diff options
-rw-r--r-- | source3/modules/vfs_aixacl2.c | 2 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 4 | ||||
-rw-r--r-- | source3/modules/vfs_gpfs.c | 2 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 211 |
4 files changed, 152 insertions, 67 deletions
diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c index 756977df4f..ab7c75691c 100644 --- a/source3/modules/vfs_aixacl2.c +++ b/source3/modules/vfs_aixacl2.c @@ -170,7 +170,7 @@ static NTSTATUS aixjfs2_get_nt_acl_common(files_struct *fsp, if (retryPosix) { DEBUG(10, ("retrying with posix acl...\n")); - return get_nt_acl(fsp, security_info, ppdesc); + return posix_fget_nt_acl(fsp, security_info, ppdesc); } if (result==False) return NT_STATUS_ACCESS_DENIED; diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index cce5430493..3dd3727340 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -950,7 +950,7 @@ static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle, NTSTATUS result; START_PROFILE(fget_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); + result = posix_fget_nt_acl(fsp, security_info, ppdesc); END_PROFILE(fget_nt_acl); return result; } @@ -962,7 +962,7 @@ static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle, NTSTATUS result; START_PROFILE(get_nt_acl); - result = get_nt_acl(fsp, security_info, ppdesc); + result = posix_get_nt_acl(fsp->conn, fsp->fsp_name, security_info, ppdesc); END_PROFILE(get_nt_acl); return result; } diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index c207bbfe2d..91d38874b9 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -240,7 +240,7 @@ static NTSTATUS gpfsacl_get_nt_acl_common(files_struct *fsp, if (result > 0) { DEBUG(10, ("retrying with posix acl...\n")); - return get_nt_acl(fsp, security_info, ppdesc); + return posix_fget_nt_acl(fsp, security_info, ppdesc); } /* GPFS ACL was not read, something wrong happened, error code is set in errno */ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 57a3ff9766..d9782cfdb8 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -430,7 +430,7 @@ static struct pai_val *create_pai_val(char *buf, size_t size) Load the user.SAMBA_PAI attribute. ************************************************************************/ -static struct pai_val *load_inherited_info(files_struct *fsp) +static struct pai_val *fload_inherited_info(files_struct *fsp) { char *pai_buf; size_t pai_buf_size = 1024; @@ -490,6 +490,71 @@ static struct pai_val *load_inherited_info(files_struct *fsp) return paiv; } +/************************************************************************ + Load the user.SAMBA_PAI attribute. +************************************************************************/ + +static struct pai_val *load_inherited_info(const struct connection_struct *conn, + const char *fname) +{ + char *pai_buf; + size_t pai_buf_size = 1024; + struct pai_val *paiv = NULL; + ssize_t ret; + + if (!lp_map_acl_inherit(SNUM(conn))) { + return NULL; + } + + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) { + return NULL; + } + + do { + ret = SMB_VFS_GETXATTR(conn, fname, + SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + + if (ret == -1) { + if (errno != ERANGE) { + break; + } + /* Buffer too small - enlarge it. */ + pai_buf_size *= 2; + SAFE_FREE(pai_buf); + if (pai_buf_size > 1024*1024) { + return NULL; /* Limit malloc to 1mb. */ + } + if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) + return NULL; + } + } while (ret == -1); + + DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname)); + + if (ret == -1) { + /* No attribute or not supported. */ +#if defined(ENOATTR) + if (errno != ENOATTR) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#else + if (errno != ENOSYS) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#endif + SAFE_FREE(pai_buf); + return NULL; + } + + paiv = create_pai_val(pai_buf, ret); + + if (paiv && paiv->pai_protected) { + DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fname)); + } + + SAFE_FREE(pai_buf); + return paiv; +} + /**************************************************************************** Functions to manipulate the internal ACE format. ****************************************************************************/ @@ -2724,6 +2789,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) return num_aces; } + /**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns the size needed to return the @@ -2731,11 +2797,15 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) the UNIX style get ACL. ****************************************************************************/ -NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) +static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, + const char *name, + const SMB_STRUCT_STAT *sbuf, + struct pai_val *pal, + SMB_ACL_T posix_acl, + SMB_ACL_T def_acl, + uint32_t security_info, + SEC_DESC **ppdesc) { - connection_struct *conn = fsp->conn; - SMB_STRUCT_STAT sbuf; - SEC_ACE *nt_ace_list = NULL; DOM_SID owner_sid; DOM_SID group_sid; size_t sd_size = 0; @@ -2743,57 +2813,12 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) size_t num_acls = 0; size_t num_def_acls = 0; size_t num_aces = 0; - SMB_ACL_T posix_acl = NULL; - SMB_ACL_T def_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; + SEC_ACE *nt_ace_list = NULL; size_t num_profile_acls = 0; - struct pai_val *pal = NULL; SEC_DESC *psd = NULL; - *ppdesc = NULL; - - DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); - - if(fsp->is_directory || fsp->fh->fd == -1) { - - /* Get the stat struct for the owner info. */ - if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { - return map_nt_error_from_unix(errno); - } - /* - * Get the ACL from the path. - */ - - posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); - - /* - * If it's a directory get the default POSIX ACL. - */ - - if(fsp->is_directory) { - def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); - def_acl = free_empty_sys_acl(conn, def_acl); - } - - } else { - - /* Get the stat struct for the owner info. */ - if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { - return map_nt_error_from_unix(errno); - } - /* - * Get the ACL from the fd. - */ - posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); - } - - DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", - posix_acl ? "present" : "absent", - def_acl ? "present" : "absent" )); - - pal = load_inherited_info(fsp); - /* * Get the owner, group and world SIDs. */ @@ -2804,7 +2829,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) sid_copy(&group_sid, &global_sid_Builtin_Users); num_profile_acls = 2; } else { - create_file_sids(&sbuf, &owner_sid, &group_sid); + create_file_sids(sbuf, &owner_sid, &group_sid); } if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) { @@ -2819,22 +2844,20 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ /* Create the canon_ace lists. */ - file_ace = canonicalise_acl(fsp->conn, - fsp->fsp_name, posix_acl, &sbuf, + file_ace = canonicalise_acl(conn, name, posix_acl, sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS); /* We must have *some* ACLS. */ if (count_canon_ace_list(file_ace) == 0) { - DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); + DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name)); goto done; } - if (fsp->is_directory && def_acl) { - dir_ace = canonicalise_acl(fsp->conn, - fsp->fsp_name, def_acl, - &sbuf, + if (S_ISDIR(sbuf->st_mode) && def_acl) { + dir_ace = canonicalise_acl(conn, name, def_acl, + sbuf, &global_sid_Creator_Owner, &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT); @@ -2921,7 +2944,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - fsp->is_directory); + S_ISDIR(sbuf->st_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -2950,7 +2973,7 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - fsp->is_directory); + S_ISDIR(sbuf->st_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -3039,6 +3062,69 @@ NTSTATUS get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) return NT_STATUS_OK; } +NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, + SEC_DESC **ppdesc) +{ + SMB_STRUCT_STAT sbuf; + SMB_ACL_T posix_acl = NULL; + struct pai_val *pal; + + *ppdesc = NULL; + + DEBUG(10,("posix_fget_nt_acl: called for file %s\n", fsp->fsp_name )); + + /* can it happen that fsp_name == NULL ? */ + if (fsp->is_directory || fsp->fh->fd == -1) { + return posix_get_nt_acl(fsp->conn, fsp->fsp_name, + security_info, ppdesc); + } + + /* Get the stat struct for the owner info. */ + if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { + return map_nt_error_from_unix(errno); + } + + /* Get the ACL from the fd. */ + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd); + + pal = fload_inherited_info(fsp); + + return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name, &sbuf, pal, + posix_acl, NULL, security_info, ppdesc); +} + +NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, + uint32_t security_info, SEC_DESC **ppdesc) +{ + SMB_STRUCT_STAT sbuf; + SMB_ACL_T posix_acl = NULL; + SMB_ACL_T def_acl = NULL; + struct pai_val *pal; + + *ppdesc = NULL; + + DEBUG(10,("posix_get_nt_acl: called for file %s\n", name )); + + /* Get the stat struct for the owner info. */ + if(SMB_VFS_STAT(conn, name, &sbuf) != 0) { + return map_nt_error_from_unix(errno); + } + + /* Get the ACL from the path. */ + posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS); + + /* If it's a directory get the default POSIX ACL. */ + if(S_ISDIR(sbuf.st_mode)) { + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT); + def_acl = free_empty_sys_acl(conn, def_acl); + } + + pal = load_inherited_info(conn, name); + + return posix_get_nt_acl_common(conn, name, &sbuf, pal, posix_acl, + def_acl, security_info, ppdesc); +} + /**************************************************************************** Try to chown a file. We will be able to chown it under the following conditions. @@ -4182,8 +4268,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); - if (!NT_STATUS_IS_OK(get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, - &psd ))) { + if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( &conn ); return NULL; |