Author: jra Date: 2005-02-11 02:14:39 +0000 (Fri, 11 Feb 2005) New Revision: 5323
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=5323 Log: In order to process DELETE_ACCESS correctly and return access denied 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. Modified: trunk/source/smbd/nttrans.c trunk/source/smbd/posix_acls.c trunk/source/smbd/reply.c Changeset: Modified: trunk/source/smbd/nttrans.c =================================================================== --- trunk/source/smbd/nttrans.c 2005-02-11 02:08:39 UTC (rev 5322) +++ trunk/source/smbd/nttrans.c 2005-02-11 02:14:39 UTC (rev 5323) @@ -782,6 +782,15 @@ } } + 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. */ @@ -1321,6 +1330,15 @@ 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. */ Modified: trunk/source/smbd/posix_acls.c =================================================================== --- trunk/source/smbd/posix_acls.c 2005-02-11 02:08:39 UTC (rev 5322) +++ trunk/source/smbd/posix_acls.c 2005-02-11 02:14:39 UTC (rev 5323) @@ -3753,3 +3753,14 @@ 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; +} Modified: trunk/source/smbd/reply.c =================================================================== --- trunk/source/smbd/reply.c 2005-02-11 02:08:39 UTC (rev 5322) +++ trunk/source/smbd/reply.c 2005-02-11 02:14:39 UTC (rev 5323) @@ -1438,7 +1438,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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;