Make mkdir_internal() check the parent ACL for SEC_DIR_ADD_SUBDIR rights.
authorJeremy Allison <jra@samba.org>
Wed, 19 Oct 2011 23:56:00 +0000 (16:56 -0700)
committerJeremy Allison <jra@samba.org>
Thu, 20 Oct 2011 16:07:46 +0000 (09:07 -0700)
source3/smbd/open.c

index a56dd6bfa1e8411eda1abc15d010062617dec857..a03e41da3e470ed4ba29b8f1423d976bd89b0aa3 100644 (file)
@@ -2441,9 +2441,12 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
        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(!CAN_WRITE(conn)) {
-               DEBUG(5,("mkdir_internal: failing create on read-only share "
+       if(access_mask & ~(conn->share_access)) {
+               DEBUG(5,("mkdir_internal: failing share access "
                         "%s\n", lp_servicename(SNUM(conn))));
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -2465,6 +2468,34 @@ 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),
+                                       access_mask,
+                                       &access_granted);
+       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",
+                       parent_dir,
+                       smb_dname->base_name,
+                       access_mask,
+                       nt_errstr(status) ));
+               return status;
+       }
+
        if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) {
                return map_nt_error_from_unix(errno);
        }