s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source3 / modules / vfs_gpfs.c
index 41eace799b2c35758d97bd1abcc8711cb889cef8..a8b4e38ff88c00c61285258f92c4f4a67de152a2 100644 (file)
@@ -423,13 +423,15 @@ static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
        }
 }
 
-static int gpfs_getacl_with_capability(const char *fname, int flags, void *buf)
+static int gpfs_getacl_with_capability(struct files_struct *fsp,
+                                      int flags,
+                                      void *buf)
 {
        int ret, saved_errno;
 
        set_effective_capability(DAC_OVERRIDE_CAPABILITY);
 
-       ret = gpfswrap_getacl(fname, flags, buf);
+       ret = gpfswrap_fgetacl(fsp_get_pathref_fd(fsp), flags, buf);
        saved_errno = errno;
 
        drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
@@ -448,11 +450,11 @@ static int gpfs_getacl_with_capability(const char *fname, int flags, void *buf)
  *
  */
 static void *vfs_gpfs_getacl(TALLOC_CTX *mem_ctx,
-                        const char *fname,
+                        struct files_struct *fsp,
                         const bool raw,
                         const gpfs_aclType_t type)
 {
-
+       const char *fname = fsp->fsp_name->base_name;
        void *aclbuf;
        size_t size = 512;
        int ret, flags;
@@ -488,13 +490,13 @@ again:
        *len = size;
 
        if (use_capability) {
-               ret = gpfs_getacl_with_capability(fname, flags, aclbuf);
+               ret = gpfs_getacl_with_capability(fsp, flags, aclbuf);
        } else {
-               ret = gpfswrap_getacl(fname, flags, aclbuf);
+               ret = gpfswrap_fgetacl(fsp_get_pathref_fd(fsp), flags, aclbuf);
                if ((ret != 0) && (errno == EACCES)) {
                        DBG_DEBUG("Retry with DAC capability for %s\n", fname);
                        use_capability = true;
-                       ret = gpfs_getacl_with_capability(fname, flags, aclbuf);
+                       ret = gpfs_getacl_with_capability(fsp, flags, aclbuf);
                }
        }
 
@@ -539,7 +541,7 @@ static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx,
        DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fname));
 
        /* Get the ACL */
-       gacl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(), fname,
+       gacl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(), fsp,
                                                  false, 0);
        if (gacl == NULL) {
                DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
@@ -831,7 +833,7 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_str
        NTSTATUS result = NT_STATUS_ACCESS_DENIED;
 
        acl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(),
-                                                fsp->fsp_name->base_name,
+                                                fsp,
                                                 false, 0);
        if (acl == NULL) {
                return map_nt_error_from_unix(errno);
@@ -840,14 +842,6 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_str
        if (acl->acl_version == GPFS_ACL_VERSION_NFS4) {
                struct gpfs_config_data *config;
 
-               if (lp_parm_bool(fsp->conn->params->service, "gpfs",
-                                "refuse_dacl_protected", false)
-                   && (psd->type&SEC_DESC_DACL_PROTECTED)) {
-                       DEBUG(2, ("Rejecting unsupported ACL with DACL_PROTECTED bit set\n"));
-                       talloc_free(acl);
-                       return NT_STATUS_NOT_SUPPORTED;
-               }
-
                SMB_VFS_HANDLE_GET_DATA(handle, config,
                                        struct gpfs_config_data,
                                        return NT_STATUS_INTERNAL_ERROR);
@@ -954,15 +948,14 @@ static SMB_ACL_T gpfsacl_get_posix_acl(struct files_struct *fsp,
                                       gpfs_aclType_t type,
                                       TALLOC_CTX *mem_ctx)
 {
-       const char *path = fsp->fsp_name->base_name;
        struct gpfs_acl *pacl;
        SMB_ACL_T result = NULL;
 
-       pacl = vfs_gpfs_getacl(talloc_tos(), path, false, type);
+       pacl = vfs_gpfs_getacl(talloc_tos(), fsp, false, type);
 
        if (pacl == NULL) {
-               DEBUG(10, ("vfs_gpfs_getacl failed for %s with %s\n",
-                          path, strerror(errno)));
+               DBG_DEBUG("vfs_gpfs_getacl failed for %s with %s\n",
+                          fsp_str_dbg(fsp), strerror(errno));
                if (errno == 0) {
                        errno = EINVAL;
                }
@@ -1048,7 +1041,7 @@ static int gpfsacl_sys_acl_blob_get_fd(vfs_handle_struct *handle,
 
        errno = 0;
        acl = (struct gpfs_opaque_acl *) vfs_gpfs_getacl(mem_ctx,
-                                               fsp->fsp_name->base_name,
+                                               fsp,
                                                true,
                                                GPFS_ACL_TYPE_NFS4);
 
@@ -1453,7 +1446,7 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
 {
        struct gpfs_config_data *config;
        int fd = fsp_get_pathref_fd(fsp);
-       char buf[PATH_MAX];
+       struct sys_proc_fd_path_buf buf;
        const char *p = NULL;
        struct gpfs_iattr64 iattr = { };
        unsigned int litemask = 0;
@@ -1470,10 +1463,7 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle,
 
        if (fsp->fsp_flags.is_pathref && !config->pathref_ok.gpfs_fstat_x) {
                if (fsp->fsp_flags.have_proc_fds) {
-                       p = sys_proc_fd_path(fd, buf, sizeof(buf));
-                       if (p == NULL) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
+                       p = sys_proc_fd_path(fd, &buf);
                } else {
                        p = fsp->fsp_name->base_name;
                }
@@ -1567,20 +1557,17 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct vfs_handle_struct *handle,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
-
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
+               struct sys_proc_fd_path_buf buf;
 
-               ret = gpfswrap_set_winattrs_path(p,
+               ret = gpfswrap_set_winattrs_path(sys_proc_fd_path(fd, &buf),
                                                 GPFS_WINATTR_SET_ATTRS,
                                                 &attrs);
                if (ret == -1) {
-                       DBG_WARNING("Setting winattrs failed for [%s][%s]: %s\n",
-                                   p, fsp_str_dbg(fsp), strerror(errno));
+                       DBG_WARNING("Setting winattrs failed for "
+                                   "[%s][%s]: %s\n",
+                                   buf.buf,
+                                   fsp_str_dbg(fsp),
+                                   strerror(errno));
                        return map_nt_error_from_unix(errno);
                }
                return NT_STATUS_OK;
@@ -1601,86 +1588,27 @@ static NTSTATUS vfs_gpfs_fset_dos_attributes(struct vfs_handle_struct *handle,
        return NT_STATUS_OK;
 }
 
-static int stat_with_capability(struct vfs_handle_struct *handle,
-                               struct smb_filename *smb_fname, int flag)
+static int timespec_to_gpfs_time(
+       struct timespec ts, gpfs_timestruc_t *gt, int idx, int *flags)
 {
-       int fd = -1;
-       NTSTATUS status;
-       struct smb_filename *dir_name = NULL;
-       struct smb_filename *rel_name = NULL;
-       struct stat st;
-       int ret = -1;
-
-       status = SMB_VFS_PARENT_PATHNAME(handle->conn,
-                                        talloc_tos(),
-                                        smb_fname,
-                                        &dir_name,
-                                        &rel_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = map_errno_from_nt_status(status);
-               return -1;
+       if (is_omit_timespec(&ts)) {
+               return 0;
        }
 
-       fd = open(dir_name->base_name, O_RDONLY, 0);
-       if (fd == -1) {
-               TALLOC_FREE(dir_name);
+       if (ts.tv_sec < 0 || ts.tv_sec > UINT32_MAX) {
+               DBG_NOTICE("GPFS uses 32-bit unsigned timestamps "
+                          "and cannot handle %jd.\n",
+                          (intmax_t)ts.tv_sec);
+               errno = ERANGE;
                return -1;
        }
 
-       set_effective_capability(DAC_OVERRIDE_CAPABILITY);
-       ret = fstatat(fd, rel_name->base_name, &st, flag);
-       drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
-
-       TALLOC_FREE(dir_name);
-       close(fd);
-
-       if (ret == 0) {
-               init_stat_ex_from_stat(
-                       &smb_fname->st, &st,
-                       lp_fake_directory_create_times(SNUM(handle->conn)));
-       }
-
-       return ret;
-}
-
-static int vfs_gpfs_stat(struct vfs_handle_struct *handle,
-                        struct smb_filename *smb_fname)
-{
-       int ret;
-
-       ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
-       if (ret == -1 && errno == EACCES) {
-               DEBUG(10, ("Trying stat with capability for %s\n",
-                          smb_fname->base_name));
-               ret = stat_with_capability(handle, smb_fname, 0);
-       }
-       return ret;
-}
+       *flags |= 1 << idx;
+       gt[idx].tv_sec = ts.tv_sec;
+       gt[idx].tv_nsec = ts.tv_nsec;
+       DBG_DEBUG("Setting GPFS time %d, flags 0x%x\n", idx, *flags);
 
-static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
-                         struct smb_filename *smb_fname)
-{
-       int ret;
-
-       ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
-       if (ret == -1 && errno == EACCES) {
-               DEBUG(10, ("Trying lstat with capability for %s\n",
-                          smb_fname->base_name));
-               ret = stat_with_capability(handle, smb_fname,
-                                          AT_SYMLINK_NOFOLLOW);
-       }
-       return ret;
-}
-
-static void timespec_to_gpfs_time(struct timespec ts, gpfs_timestruc_t *gt,
-                                 int idx, int *flags)
-{
-       if (!is_omit_timespec(&ts)) {
-               *flags |= 1 << idx;
-               gt[idx].tv_sec = ts.tv_sec;
-               gt[idx].tv_nsec = ts.tv_nsec;
-               DEBUG(10, ("Setting GPFS time %d, flags 0x%x\n", idx, *flags));
-       }
+       return 0;
 }
 
 static int smbd_gpfs_set_times(struct files_struct *fsp,
@@ -1691,10 +1619,21 @@ static int smbd_gpfs_set_times(struct files_struct *fsp,
        int rc;
 
        ZERO_ARRAY(gpfs_times);
-       timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
-       timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
+       rc = timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
+       if (rc != 0) {
+               return rc;
+       }
+
+       rc = timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
+       if (rc != 0) {
+               return rc;
+       }
+
        /* No good mapping from LastChangeTime to ctime, not storing */
-       timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+       rc = timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
+       if (rc != 0) {
+               return rc;
+       }
 
        if (!flags) {
                DBG_DEBUG("nothing to do, return to avoid EINVAL\n");
@@ -1713,18 +1652,16 @@ static int smbd_gpfs_set_times(struct files_struct *fsp,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
-
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return -1;
-               }
+               struct sys_proc_fd_path_buf buf;
 
-               rc = gpfswrap_set_times_path(buf, flags, gpfs_times);
+               rc = gpfswrap_set_times_path(sys_proc_fd_path(fd, &buf),
+                                            flags,
+                                            gpfs_times);
                if (rc != 0) {
                        DBG_WARNING("gpfs_set_times_path(%s,%s) failed: %s\n",
-                                   fsp_str_dbg(fsp), p, strerror(errno));
+                                   fsp_str_dbg(fsp),
+                                   buf.buf,
+                                   strerror(errno));
                }
                return rc;
        }
@@ -1769,7 +1706,7 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct *handle,
        if (ret == -1) {
                /* don't complain if access was denied */
                if (errno != EPERM && errno != EACCES) {
-                       DBG_WARNING("SMB_VFS_NEXT_FNTIMES failed: %s",
+                       DBG_WARNING("SMB_VFS_NEXT_FNTIMES failed: %s\n",
                                    strerror(errno));
                }
                return -1;
@@ -1801,17 +1738,12 @@ static int vfs_gpfs_fntimes(struct vfs_handle_struct *handle,
 
        if (fsp->fsp_flags.have_proc_fds) {
                int fd = fsp_get_pathref_fd(fsp);
-               const char *p = NULL;
-               char buf[PATH_MAX];
+               struct sys_proc_fd_path_buf buf;
 
-               p = sys_proc_fd_path(fd, buf, sizeof(buf));
-               if (p == NULL) {
-                       return -1;
-               }
-
-               ret = gpfswrap_set_winattrs_path(p,
-                                                GPFS_WINATTR_SET_CREATION_TIME,
-                                                &attrs);
+               ret = gpfswrap_set_winattrs_path(
+                       sys_proc_fd_path(fd, &buf),
+                       GPFS_WINATTR_SET_CREATION_TIME,
+                       &attrs);
                if (ret == -1 && errno != ENOSYS) {
                        DBG_WARNING("Set GPFS ntimes failed %d\n", ret);
                        return -1;
@@ -1877,7 +1809,7 @@ static int vfs_gpfs_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
 }
 
 static bool vfs_gpfs_is_offline(struct vfs_handle_struct *handle,
-                               const struct smb_filename *fname,
+                               struct files_struct *fsp,
                                SMB_STRUCT_STAT *sbuf)
 {
        struct gpfs_winattr attrs;
@@ -1892,17 +1824,17 @@ static bool vfs_gpfs_is_offline(struct vfs_handle_struct *handle,
                return false;
        }
 
-       ret = gpfswrap_get_winattrs_path(fname->base_name, &attrs);
+       ret = gpfswrap_get_winattrs(fsp_get_pathref_fd(fsp), &attrs);
        if (ret == -1) {
                return false;
        }
 
        if ((attrs.winAttrs & GPFS_WINATTR_OFFLINE) != 0) {
-               DBG_DEBUG("%s is offline\n", fname->base_name);
+               DBG_DEBUG("%s is offline\n", fsp_str_dbg(fsp));
                return true;
        }
 
-       DBG_DEBUG("%s is online\n", fname->base_name);
+       DBG_DEBUG("%s is online\n", fsp_str_dbg(fsp));
        return false;
 }
 
@@ -1916,7 +1848,7 @@ static bool vfs_gpfs_fsp_is_offline(struct vfs_handle_struct *handle,
                /*
                 * Something bad happened, always ask.
                 */
-               return vfs_gpfs_is_offline(handle, fsp->fsp_name,
+               return vfs_gpfs_is_offline(handle, fsp,
                                           &fsp->fsp_name->st);
        }
 
@@ -1924,7 +1856,7 @@ static bool vfs_gpfs_fsp_is_offline(struct vfs_handle_struct *handle,
                /*
                 * As long as it's offline, ask.
                 */
-               ext->offline = vfs_gpfs_is_offline(handle, fsp->fsp_name,
+               ext->offline = vfs_gpfs_is_offline(handle, fsp,
                                                   &fsp->fsp_name->st);
        }
 
@@ -2026,7 +1958,24 @@ static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
                return 0;
        }
 
-       gpfswrap_lib_init(0);
+       ret = gpfswrap_init();
+       if (ret < 0) {
+               DBG_ERR("Could not load GPFS library.\n");
+               return ret;
+       }
+
+       ret = gpfswrap_lib_init(0);
+       if (ret < 0) {
+               DBG_ERR("Could not open GPFS device file: %s\n",
+                       strerror(errno));
+               return ret;
+       }
+
+       ret = gpfswrap_register_cifs_export();
+       if (ret < 0) {
+               DBG_ERR("Failed to register with GPFS: %s\n", strerror(errno));
+               return ret;
+       }
 
        config = talloc_zero(handle->conn, struct gpfs_config_data);
        if (!config) {
@@ -2331,9 +2280,9 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
                           const struct files_struct *dirfsp,
                           const struct smb_filename *smb_fname,
                           files_struct *fsp,
-                          int flags,
-                          mode_t mode)
+                          const struct vfs_open_how *_how)
 {
+       struct vfs_open_how how = *_how;
        struct gpfs_config_data *config = NULL;
        struct gpfs_fsp_extension *ext = NULL;
        int ret;
@@ -2353,7 +2302,7 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
        }
 
        if (config->syncio) {
-               flags |= O_SYNC;
+               how.flags |= O_SYNC;
        }
 
        ext = VFS_ADD_FSP_EXTENSION(handle, fsp, struct gpfs_fsp_extension,
@@ -2368,7 +2317,7 @@ static int vfs_gpfs_openat(struct vfs_handle_struct *handle,
         */
        *ext = (struct gpfs_fsp_extension) { .offline = true };
 
-       ret = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, flags, mode);
+       ret = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, &how);
        if (ret == -1) {
                VFS_REMOVE_FSP_EXTENSION(handle, fsp);
        }
@@ -2571,8 +2520,10 @@ static struct vfs_fn_pointers vfs_gpfs_fns = {
        .sys_acl_delete_def_fd_fn = gpfsacl_sys_acl_delete_def_fd,
        .fchmod_fn = vfs_gpfs_fchmod,
        .close_fn = vfs_gpfs_close,
-       .stat_fn = vfs_gpfs_stat,
-       .lstat_fn = vfs_gpfs_lstat,
+       .stat_fn = nfs4_acl_stat,
+       .fstat_fn = nfs4_acl_fstat,
+       .lstat_fn = nfs4_acl_lstat,
+       .fstatat_fn = nfs4_acl_fstatat,
        .fntimes_fn = vfs_gpfs_fntimes,
        .aio_force_fn = vfs_gpfs_aio_force,
        .sendfile_fn = vfs_gpfs_sendfile,
@@ -2590,13 +2541,6 @@ static struct vfs_fn_pointers vfs_gpfs_fns = {
 static_decl_vfs;
 NTSTATUS vfs_gpfs_init(TALLOC_CTX *ctx)
 {
-       int ret;
-
-       ret = gpfswrap_init();
-       if (ret != 0) {
-               DEBUG(1, ("Could not initialize GPFS library wrapper\n"));
-       }
-
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",
                                &vfs_gpfs_fns);
 }