return True;
}
- allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA|
- DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0;
+ allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) ?
+ GPFS_SHARE_WRITE : 0;
allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ?
GPFS_SHARE_READ : 0;
0 : GPFS_DENY_WRITE;
deny |= (share_access & (FILE_SHARE_READ)) ?
0 : GPFS_DENY_READ;
+
+ /*
+ * GPFS_DENY_DELETE can only be set together with either
+ * GPFS_DENY_WRITE or GPFS_DENY_READ.
+ */
+ if (deny & (GPFS_DENY_WRITE|GPFS_DENY_READ)) {
+ deny |= (share_access & (FILE_SHARE_DELETE)) ?
+ 0 : GPFS_DENY_DELETE;
+ }
}
DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n",
access_mask, allow, share_access, deny));
char **found_name)
{
int result;
- char *full_path;
- char real_pathname[PATH_MAX+1];
+ char *full_path = NULL;
+ char *to_free = NULL;
+ char real_pathname[PATH_MAX+1], tmpbuf[PATH_MAX];
+ size_t full_path_len;
int buflen;
bool mangled;
struct gpfs_config_data *config;
mem_ctx, found_name);
}
- full_path = talloc_asprintf(talloc_tos(), "%s/%s", path, name);
- if (full_path == NULL) {
+ full_path_len = full_path_tos(path, name, tmpbuf, sizeof(tmpbuf),
+ &full_path, &to_free);
+ if (full_path_len == -1) {
errno = ENOMEM;
return -1;
}
result = gpfswrap_get_realfilename_path(full_path, real_pathname,
&buflen);
- TALLOC_FREE(full_path);
+ TALLOC_FREE(to_free);
if ((result == -1) && (errno == ENOSYS)) {
return SMB_VFS_NEXT_GET_REAL_FILENAME(
}
static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
- const char *name,
+ const struct smb_filename *smb_fname,
SMB_ACL_TYPE_T type,
SMB_ACL_T theacl)
{
return -1);
if (!config->acl) {
- return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, type, theacl);
+ return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, smb_fname,
+ type, theacl);
}
gpfs_acl = smb2gpfs_acl(theacl, type);
return -1;
}
- result = gpfswrap_putacl(discard_const_p(char, name),
+ result = gpfswrap_putacl(discard_const_p(char, smb_fname->base_name),
GPFS_PUTACL_STRUCT|GPFS_ACL_SAMBA, gpfs_acl);
SAFE_FREE(gpfs_acl);
return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
}
- return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name->base_name,
+ return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name,
SMB_ACL_TYPE_ACCESS, theacl);
}
return winattrs;
}
+static int get_dos_attr_with_capability(struct smb_filename *smb_fname,
+ struct gpfs_winattr *attr)
+{
+ int saved_errno = 0;
+ int ret;
+
+ /*
+ * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to an
+ * Existing File" FILE_LIST_DIRECTORY on a directory implies
+ * FILE_READ_ATTRIBUTES for directory entries. Being able to stat() a
+ * file implies FILE_LIST_DIRECTORY for the directory containing the
+ * file.
+ */
+
+ if (!VALID_STAT(smb_fname->st)) {
+ /*
+ * Safety net: dos_mode() already checks this, but as we set
+ * DAC_OVERRIDE_CAPABILITY based on this, add an additional
+ * layer of defense.
+ */
+ DBG_ERR("Rejecting DAC override, invalid stat [%s]\n",
+ smb_fname_str_dbg(smb_fname));
+ errno = EACCES;
+ return -1;
+ }
+
+ set_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ ret = gpfswrap_get_winattrs_path(smb_fname->base_name, attr);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+
+ drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ return ret;
+}
+
static NTSTATUS vfs_gpfs_get_dos_attributes(struct vfs_handle_struct *handle,
struct smb_filename *smb_fname,
uint32_t *dosmode)
return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, smb_fname,
dosmode);
}
+ if (ret == -1 && errno == EACCES) {
+ ret = get_dos_attr_with_capability(smb_fname, &attrs);
+ }
- if (ret == -1) {
+ if (ret == -1 && errno == EBADF) {
+ /*
+ * Returned for directory listings in gpfs root for
+ * .. entry which steps out of gpfs.
+ */
+ DBG_DEBUG("Getting winattrs for %s returned EBADF.\n",
+ smb_fname->base_name);
+ return map_nt_error_from_unix(errno);
+ } else if (ret == -1) {
DBG_WARNING("Getting winattrs failed for %s: %s\n",
smb_fname->base_name, strerror(errno));
return map_nt_error_from_unix(errno);
return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
}
+ if (ret == -1 && errno == EACCES) {
+ int saved_errno = 0;
+
+ /*
+ * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to
+ * an Existing File" FILE_LIST_DIRECTORY on a directory implies
+ * FILE_READ_ATTRIBUTES for directory entries. Being able to
+ * open a file implies FILE_LIST_DIRECTORY.
+ */
+
+ set_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ ret = gpfswrap_get_winattrs(fsp->fh->fd, &attrs);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+
+ drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
+
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ }
+
if (ret == -1) {
DBG_WARNING("Getting winattrs failed for %s: %s\n",
fsp->fsp_name->base_name, strerror(errno));
struct gpfs_winattr attrs;
int ret;
- char *path = NULL;
- NTSTATUS status;
struct gpfs_config_data *config;
SMB_VFS_HANDLE_GET_DATA(handle, config,
struct gpfs_config_data,
return -1);
- status = get_full_smb_filename(talloc_tos(), smb_fname, &path);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
/* Try to use gpfs_set_times if it is enabled and available */
if (config->settimes) {
- ret = smbd_gpfs_set_times_path(path, ft);
+ ret = smbd_gpfs_set_times_path(smb_fname->base_name, ft);
if (ret == 0 || (ret == -1 && errno != ENOSYS)) {
return ret;
attrs.creationTime.tv_sec = ft->create_time.tv_sec;
attrs.creationTime.tv_nsec = ft->create_time.tv_nsec;
- ret = gpfswrap_set_winattrs_path(discard_const_p(char, path),
+ ret = gpfswrap_set_winattrs_path(smb_fname->base_name,
GPFS_WINATTR_SET_CREATION_TIME,
&attrs);
if(ret == -1 && errno != ENOSYS){
SMB_STRUCT_STAT *sbuf)
{
struct gpfs_winattr attrs;
- char *path = NULL;
- NTSTATUS status;
struct gpfs_config_data *config;
int ret;
return false;
}
- status = get_full_smb_filename(talloc_tos(), fname, &path);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
-
- ret = gpfswrap_get_winattrs_path(path, &attrs);
+ ret = gpfswrap_get_winattrs_path(fname->base_name, &attrs);
if (ret == -1) {
- TALLOC_FREE(path);
return false;
}
if ((attrs.winAttrs & GPFS_WINATTR_OFFLINE) != 0) {
- DEBUG(10, ("%s is offline\n", path));
- TALLOC_FREE(path);
+ DBG_DEBUG("%s is offline\n", fname->base_name);
return true;
}
- DEBUG(10, ("%s is online\n", path));
- TALLOC_FREE(path);
+
+ DBG_DEBUG("%s is online\n", fname->base_name);
return false;
}
}
}
+ /*
+ * Unless we have an async implementation of get_dos_attributes turn
+ * this off.
+ */
+ lp_do_parameter(SNUM(handle->conn), "smbd:async dosmode", "false");
+
return 0;
}
}
}
-static uint64_t vfs_gpfs_disk_free(vfs_handle_struct *handle, const char *path,
- uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
+static uint64_t vfs_gpfs_disk_free(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ uint64_t *bsize,
+ uint64_t *dfree,
+ uint64_t *dsize)
{
struct security_unix_token *utok;
struct gpfs_quotaInfo qi_user = { 0 }, qi_group = { 0 };
SMB_VFS_HANDLE_GET_DATA(handle, config, struct gpfs_config_data,
return (uint64_t)-1);
if (!config->dfreequota) {
- return SMB_VFS_NEXT_DISK_FREE(handle, path,
+ return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
bsize, dfree, dsize);
}
- err = sys_fsusage(path, dfree, dsize);
+ err = sys_fsusage(smb_fname->base_name, dfree, dsize);
if (err) {
DEBUG (0, ("Could not get fs usage, errno %d\n", errno));
- return SMB_VFS_NEXT_DISK_FREE(handle, path,
+ return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
bsize, dfree, dsize);
}
utok = handle->conn->session_info->unix_token;
- err = get_gpfs_quota(path, GPFS_USRQUOTA, utok->uid, &qi_user);
+ err = get_gpfs_quota(smb_fname->base_name,
+ GPFS_USRQUOTA, utok->uid, &qi_user);
if (err) {
- return SMB_VFS_NEXT_DISK_FREE(handle, path,
+ return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
bsize, dfree, dsize);
}
- err = get_gpfs_quota(path, GPFS_GRPQUOTA, utok->gid, &qi_group);
+ err = get_gpfs_quota(smb_fname->base_name,
+ GPFS_GRPQUOTA, utok->gid, &qi_group);
if (err) {
- return SMB_VFS_NEXT_DISK_FREE(handle, path,
+ return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname,
bsize, dfree, dsize);
}
return *dfree / 2;
}
-static int vfs_gpfs_get_quota(vfs_handle_struct *handle, const char *path,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *dq)
+static int vfs_gpfs_get_quota(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ enum SMB_QUOTA_TYPE qtype,
+ unid_t id,
+ SMB_DISK_QUOTA *dq)
{
switch(qtype) {
/*
errno = ENOSYS;
return -1;
default:
- return SMB_VFS_NEXT_GET_QUOTA(handle, path, qtype, id, dq);
+ return SMB_VFS_NEXT_GET_QUOTA(handle, smb_fname,
+ qtype, id, dq);
}
}
.linux_setlease_fn = vfs_gpfs_setlease,
.get_real_filename_fn = vfs_gpfs_get_real_filename,
.get_dos_attributes_fn = vfs_gpfs_get_dos_attributes,
+ .get_dos_attributes_send_fn = vfs_not_implemented_get_dos_attributes_send,
+ .get_dos_attributes_recv_fn = vfs_not_implemented_get_dos_attributes_recv,
.fget_dos_attributes_fn = vfs_gpfs_fget_dos_attributes,
.set_dos_attributes_fn = vfs_gpfs_set_dos_attributes,
.fset_dos_attributes_fn = vfs_gpfs_fset_dos_attributes,
.ftruncate_fn = vfs_gpfs_ftruncate
};
-NTSTATUS vfs_gpfs_init(TALLOC_CTX *);
+static_decl_vfs;
NTSTATUS vfs_gpfs_init(TALLOC_CTX *ctx)
{
int ret;