diff options
-rw-r--r-- | source3/include/trans2.h | 6 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 56 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 67 |
3 files changed, 74 insertions, 55 deletions
diff --git a/source3/include/trans2.h b/source3/include/trans2.h index 55b28ae937..b1fe2d9d83 100644 --- a/source3/include/trans2.h +++ b/source3/include/trans2.h @@ -506,6 +506,10 @@ In the same format as the uid/gid fields in the other UNIX extensions definitions. Use 0xFFFFFFFFFFFFFFFF for the MASK and OTHER entry types. +If the Number of ACE entries for either file or default ACE's +is set to 0xFFFF this means ignore this kind of ACE (and the +number of entries sent will be zero. + */ /* The query/set info levels for POSIX ACLs. */ @@ -530,4 +534,6 @@ the MASK and OTHER entry types. #define SMB_POSIX_ACL_HEADER_SIZE 6 #define SMB_POSIX_ACL_ENTRY_SIZE 10 + +#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF #endif diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 9b7c39c00e..7e20313b76 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2638,10 +2638,10 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) size_t sd_size = 0; SEC_ACL *psa = NULL; size_t num_acls = 0; - size_t num_dir_acls = 0; + size_t num_def_acls = 0; size_t num_aces = 0; SMB_ACL_T posix_acl = NULL; - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; size_t num_profile_acls = 0; @@ -2669,8 +2669,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) */ if(fsp->is_directory) { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); - dir_acl = free_empty_sys_acl(conn, dir_acl); + 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 { @@ -2687,7 +2687,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", posix_acl ? "present" : "absent", - dir_acl ? "present" : "absent" )); + def_acl ? "present" : "absent" )); pal = load_inherited_info(fsp); @@ -2725,8 +2725,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) return 0; } - if (fsp->is_directory && dir_acl) { - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, + if (fsp->is_directory && def_acl) { + dir_ace = canonicalise_acl(fsp, def_acl, &sbuf, &global_sid_Creator_Owner, &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT ); } @@ -2790,15 +2790,15 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) } num_acls = count_canon_ace_list(file_ace); - num_dir_acls = count_canon_ace_list(dir_ace); + num_def_acls = count_canon_ace_list(dir_ace); /* Allocate the ace list. */ - if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) { + if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_def_acls)* sizeof(SEC_ACE))) == NULL) { DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n")); goto done; } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) ); /* * Create the NT ACE list from the canonical ace lists. @@ -2824,7 +2824,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) ace = dir_ace; - for (i = 0; i < num_dir_acls; i++, ace = ace->next) { + for (i = 0; i < num_def_acls; i++, ace = ace->next) { SEC_ACCESS acc; acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); @@ -2894,8 +2894,8 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) if (posix_acl) SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); - if (dir_acl) - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); free_inherited_info(pal); @@ -3373,16 +3373,16 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { + if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) { has_acl = True; } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return has_acl; } @@ -3532,23 +3532,23 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ /**************************************************************************** Calls from UNIX extensions - Default POSIX ACL set. - If num_dir_acls == 0 and not a directory just return. If it is a directory - and num_dir_acls == 0 then remove the default acl. Else set the default acl + If num_def_acls == 0 and not a directory just return. If it is a directory + and num_def_acls == 0 then remove the default acl. Else set the default acl on the directory. ****************************************************************************/ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, - uint16 num_dir_acls, const char *pdata) + uint16 num_def_acls, const char *pdata) { - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; - if (num_dir_acls && !S_ISDIR(psbuf->st_mode)) { + if (num_def_acls && !S_ISDIR(psbuf->st_mode)) { DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname )); errno = EISDIR; return False; } - if (!num_dir_acls) { + if (!num_def_acls) { /* Remove the default ACL. */ if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) { DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n", @@ -3558,19 +3558,19 @@ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_ return True; } - if ((dir_acl = create_posix_acl_from_wire(conn, num_dir_acls, pdata)) == NULL) { + if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) { return False; } - if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, dir_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) { DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n", fname, strerror(errno) )); - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); return False; } DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname )); - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); return True; } @@ -3701,7 +3701,7 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c /**************************************************************************** Calls from UNIX extensions - POSIX ACL set. - If num_dir_acls == 0 then read/modify/write acl after removing all entries + If num_def_acls == 0 then read/modify/write acl after removing all entries except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER. ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index afe4d352ff..b4140eeafe 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2927,9 +2927,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * case SMB_QUERY_POSIX_ACL: { SMB_ACL_T file_acl = NULL; - SMB_ACL_T dir_acl = NULL; + SMB_ACL_T def_acl = NULL; uint16 num_file_acls = 0; - uint16 num_dir_acls = 0; + uint16 num_def_acls = 0; if (fsp && !fsp->is_directory && (fsp->fd != -1)) { file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); @@ -2945,48 +2945,48 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (S_ISDIR(sbuf.st_mode)) { if (fsp && fsp->is_directory) { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); } else { - dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); + def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); } - dir_acl = free_empty_sys_acl(conn, dir_acl); + def_acl = free_empty_sys_acl(conn, def_acl); } num_file_acls = count_acl_entries(conn, file_acl); - num_dir_acls = count_acl_entries(conn, dir_acl); + num_def_acls = count_acl_entries(conn, def_acl); - if ( data_size < (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { + if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n", data_size, - (unsigned int)((num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + + (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) )); if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); } SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); SSVAL(pdata,2,num_file_acls); - SSVAL(pdata,4,num_dir_acls); + SSVAL(pdata,4,num_def_acls); if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_INTERNAL_ERROR); } - if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, dir_acl)) { + if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) { if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } return ERROR_NT(NT_STATUS_INTERNAL_ERROR); } @@ -2994,10 +2994,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * if (file_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl); } - if (dir_acl) { - SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); + if (def_acl) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - data_size = (num_file_acls + num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; + data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE; break; } @@ -3813,34 +3813,47 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", { uint16 posix_acl_version; uint16 num_file_acls; - uint16 num_dir_acls; + uint16 num_def_acls; + BOOL valid_file_acls = True; + BOOL valid_def_acls = True; if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } posix_acl_version = SVAL(pdata,0); num_file_acls = SVAL(pdata,2); - num_dir_acls = SVAL(pdata,4); + num_def_acls = SVAL(pdata,4); + + if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_file_acls = False; + num_file_acls = 0; + } + + if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) { + valid_def_acls = False; + num_def_acls = 0; + } if (posix_acl_version != SMB_POSIX_ACL_VERSION) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } if (total_data < SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls+num_dir_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { return(ERROR_DOS(ERRDOS,ERRinvalidparam)); } - if (!set_unix_posix_default_acl(conn, fname, &sbuf, num_dir_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { + if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE)) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (!set_unix_posix_acl(conn, fsp, fname, num_file_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE)) { + if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); return(-1); |