diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/nttrans.c | 10 | ||||
-rw-r--r-- | source3/smbd/open.c | 59 |
2 files changed, 53 insertions, 16 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 694cfb92a3..501f0e9ab0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -717,8 +717,11 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode, - smb_ofun,unixmode, oplock_request,&rmode,&smb_action); + fsp = open_file_shared1(conn,fname,&sbuf, + desired_access, + smb_open_mode, + smb_ofun,unixmode, oplock_request, + &rmode,&smb_action); if (!fsp) { /* We cheat here. There are two cases we @@ -1213,7 +1216,8 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared1(conn,fname,&sbuf,desired_access, + smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); if (!fsp) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index aab7b5079e..7396233c26 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -437,8 +437,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i ****************************************************************************/ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request, - BOOL *p_all_current_opens_are_level_II) + SMB_INO_T inode, + uint32 desired_access, + int share_mode, int *p_flags, int *p_oplock_request, + BOOL *p_all_current_opens_are_level_II) { int i; int num_share_modes; @@ -510,13 +512,27 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou *p_all_current_opens_are_level_II = False; } - /* someone else has a share lock on it, check to see - if we can too */ - - if(check_share_mode(conn, share_entry, share_mode, fname, fcbopen, p_flags) == False) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + /* this is a nasty hack, but necessary until we rewrite our open + handling to use a NTCreateX call as the basic call. + NT may open a file with neither read nor write access, and in + this case it expects the open not to conflict with any + existing deny modes. This happens (for example) during a + "xcopy /o" where the second file descriptor is used for + ACL sets + This code should be removed once we have a propoer ntcreateX + open functions + (tridge) + */ + if (desired_access == 0 || + (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) { + /* someone else has a share lock on it, check to see + if we can too */ + if (!check_share_mode(conn, share_entry, share_mode, + fname, fcbopen, p_flags)) { + SAFE_FREE(old_shares); + errno = EACCES; + return -1; + } } } /* end for */ @@ -609,6 +625,19 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action) { + return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode, + oplock_request, Access, action); +} + +/**************************************************************************** + Open a file with a share mode. On output from this open we are guarenteeing + that +****************************************************************************/ +files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, + uint32 desired_access, + int share_mode,int ofun, mode_t mode,int oplock_request, + int *Access,int *action) +{ int flags=0; int flags2=0; int deny_mode = GET_DENY_MODE(share_mode); @@ -736,8 +765,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S lock_share_entry(conn, dev, inode); - num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + desired_access, + share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { /* @@ -801,8 +832,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", lock_share_entry_fsp(fsp); - num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode, - &flags, &oplock_request, &all_current_opens_are_level_II); + num_share_modes = open_mode_check(conn, fname, dev, inode, + desired_access, + share_mode, + &flags, &oplock_request, &all_current_opens_are_level_II); if(num_share_modes == -1) { unlock_share_entry_fsp(fsp); |