r5324: In order to process DELETE_ACCESS correctly and return access denied
authorJeremy Allison <jra@samba.org>
Fri, 11 Feb 2005 02:14:49 +0000 (02:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:55:37 +0000 (10:55 -0500)
to a WXPSP2 client we must do permission checking in userspace first
(this is a race condition but what can you do...). Needed for bugid #2227.
Jeremy.

source/smbd/nttrans.c
source/smbd/posix_acls.c
source/smbd/reply.c

index 5758b9d71622f685228e09b0e8ad1da921ac0645..ea155a8edb1ffeffb89b3e5b3f075204e64c5177 100644 (file)
@@ -780,6 +780,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                }
        }
 
+       if (desired_access & DELETE_ACCESS) {
+               status = can_delete(conn, fname, file_attributes, bad_path, True);
+               if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(status);
+               }
+       }
+
        /* 
         * If it's a request for a directory open, deal with it separately.
         */
@@ -1319,6 +1328,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
        }
     
+       if (desired_access & DELETE_ACCESS) {
+               status = can_delete(conn, fname, file_attributes, bad_path, True);
+               if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_IS_A_DIRECTORY)) {
+                       restore_case_semantics(conn, file_attributes);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(status);
+               }
+       }
+
        /*
         * If it's a request for a directory open, deal with it separately.
         */
index 903b9435225f5ae06d5aaed98604d371416046c2..b3976fdecb5b68f28298eb8c942345f0e57825cf 100644 (file)
@@ -3753,3 +3753,14 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
        return True;
 }
+
+/****************************************************************************
+ Actually emulate the in-kernel access checking for write access. We need
+ this to successfully return ACCESS_DENIED on a file open for delete access.
+****************************************************************************/
+
+BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
+{
+       /* Add acl check here... JRA */
+       return True;
+}
index 748d9958bcdb5a48e5585660db095bc9b6e33cab..68705a8aea8addf759a9d5e0775ffa827fa559c1 100644 (file)
@@ -1438,7 +1438,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  Check if a user is allowed to rename a file.
 ********************************************************************/
 
-static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
 {
        int smb_action;
        int access_mode;
@@ -1479,7 +1479,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype,
  Check if a user is allowed to delete a file.
 ********************************************************************/
 
-static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
+NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
 {
        SMB_STRUCT_STAT sbuf;
        int fmode;
@@ -1520,6 +1520,10 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO
        if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
                return NT_STATUS_NO_SUCH_FILE;
 
+       if (check_is_at_open && !can_delete_file_in_directory(conn, fname)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* We need a better way to return NT status codes from open... */
        unix_ERR_class = 0;
        unix_ERR_code = 0;
@@ -1598,7 +1602,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
        if (!has_wild) {
                pstrcat(directory,"/");
                pstrcat(directory,mask);
-               error = can_delete(directory,conn,dirtype,bad_path);
+               error = can_delete(conn,directory,dirtype,bad_path,False);
                if (!NT_STATUS_IS_OK(error))
                        return error;
 
@@ -1656,7 +1660,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                }
 
                                slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                               error = can_delete(fname,conn,dirtype,bad_path);
+                               error = can_delete(conn,fname,dirtype,bad_path,False);
                                if (!NT_STATUS_IS_OK(error)) {
                                        continue;
                                }
@@ -3744,7 +3748,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       error = can_rename(newname,conn,attrs,&sbuf);
+       error = can_rename(conn,newname,attrs,&sbuf);
 
        if (dest_exists && !NT_STATUS_IS_OK(error)) {
                DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3950,7 +3954,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                        return NT_STATUS_OBJECT_PATH_NOT_FOUND;
                }
 
-               error = can_rename(directory,conn,attrs,&sbuf1);
+               error = can_rename(conn,directory,attrs,&sbuf1);
 
                if (!NT_STATUS_IS_OK(error)) {
                        DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -4045,7 +4049,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                        DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
                                        continue;
                                }
-                               error = can_rename(fname,conn,attrs,&sbuf1);
+                               error = can_rename(conn,fname,attrs,&sbuf1);
                                if (!NT_STATUS_IS_OK(error)) {
                                        DEBUG(6,("rename %s refused\n", fname));
                                        continue;