diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a03e41da3e4..1e21799868e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -134,6 +134,63 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn, return status; } +static NTSTATUS check_parent_access(struct connection_struct *conn, + struct smb_filename *smb_fname, + uint32_t access_mask, + char **pp_parent_dir, + struct security_descriptor **pp_parent_sd) +{ + NTSTATUS status; + char *parent_dir = NULL; + struct security_descriptor *parent_sd = NULL; + uint32_t access_granted = 0; + + if (!parent_dirname(talloc_tos(), + smb_fname->base_name, + &parent_dir, + NULL)) { + return NT_STATUS_NO_MEMORY; + } + + status = SMB_VFS_GET_NT_ACL(conn, + parent_dir, + SECINFO_DACL, + &parent_sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("check_parent_access: SMB_VFS_GET_NT_ACL failed for " + "%s with error %s\n", + parent_dir, + nt_errstr(status))); + return status; + } + + status = smb1_file_se_access_check(conn, + parent_sd, + get_current_nttok(conn), + access_mask, + &access_granted); + if(!NT_STATUS_IS_OK(status)) { + DEBUG(5,("check_parent_access: access check " + "on directory %s for " + "path %s for mask 0x%x returned (0x%x) %s\n", + parent_dir, + smb_fname->base_name, + access_mask, + access_granted, + nt_errstr(status) )); + return status; + } + + if (pp_parent_dir) { + *pp_parent_dir = parent_dir; + } + if (pp_parent_sd) { + *pp_parent_sd = parent_sd; + } + return NT_STATUS_OK; +} + /**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -2437,13 +2494,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, uint32 file_attributes) { mode_t mode; - char *parent_dir; + char *parent_dir = NULL; NTSTATUS status; bool posix_open = false; bool need_re_stat = false; - struct security_descriptor *parent_sd = NULL; uint32_t access_mask = SEC_DIR_ADD_SUBDIR; - uint32_t access_granted = 0; if(access_mask & ~(conn->share_access)) { DEBUG(5,("mkdir_internal: failing share access " @@ -2468,30 +2523,16 @@ static NTSTATUS mkdir_internal(connection_struct *conn, mode = unix_mode(conn, FILE_ATTRIBUTE_DIRECTORY, smb_dname, parent_dir); } - status = SMB_VFS_GET_NT_ACL(conn, - parent_dir, - SECINFO_DACL, - &parent_sd); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(5,("mkdir_internal: SMB_VFS_GET_NT_ACL failed for " - "%s with error %s\n", - parent_dir, - nt_errstr(status))); - return status; - } - - status = smb1_file_se_access_check(conn, - parent_sd, - get_current_nttok(conn), + status = check_parent_access(conn, + smb_dname, access_mask, - &access_granted); + &parent_dir, + NULL); if(!NT_STATUS_IS_OK(status)) { - DEBUG(5,("mkdir_internal: access check " - "on directory %s for " - "path %s for mask 0x%x returned %s\n", + DEBUG(5,("mkdir_internal: check_parent_access " + "on directory %s for path %s returned %s\n", parent_dir, smb_dname->base_name, - access_mask, nt_errstr(status) )); return status; }