diff options
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/libsmb/smbdes.c | 26 | ||||
-rw-r--r-- | source3/smbd/reply.c | 4 | ||||
-rw-r--r-- | source3/smbd/server.c | 44 |
4 files changed, 48 insertions, 28 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index a8471d0c2d..d0376fb9fe 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1218,7 +1218,7 @@ int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); BOOL check_name(char *name,int cnum); void sync_file(int fnum); void close_file(int fnum, BOOL normal_close); -BOOL check_file_sharing(int cnum,char *fname); +BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op); int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags); void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c index e4f8280f9b..c3cc2c7133 100644 --- a/source3/libsmb/smbdes.c +++ b/source3/libsmb/smbdes.c @@ -178,7 +178,7 @@ static void xor(char *out, char *in1, char *in2, int n) out[i] = in1[i] ^ in2[i]; } -static void dohash(char *out, char *in, char *key) +static void dohash(char *out, char *in, char *key, int forw) { int i, j, k; char pk1[56]; @@ -222,7 +222,7 @@ static void dohash(char *out, char *in, char *key) permute(er, r, perm4, 48); - xor(erk, er, ki[i], 48); + xor(erk, er, ki[forw ? i : 15 - i], 48); for (j=0;j<8;j++) for (k=0;k<6;k++) @@ -275,7 +275,7 @@ static void str_to_key(unsigned char *str,unsigned char *key) } -static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) +static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) { int i; char outb[64]; @@ -291,7 +291,7 @@ static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) outb[i] = 0; } - dohash(outb, inb, keyb); + dohash(outb, inb, keyb, forw); for (i=0;i<8;i++) { out[i] = 0; @@ -306,23 +306,23 @@ static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) void E_P16(unsigned char *p14,unsigned char *p16) { unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; - smbhash(p16, sp8, p14); - smbhash(p16+8, sp8, p14+7); + smbhash(p16, sp8, p14, 1); + smbhash(p16+8, sp8, p14+7, 1); } void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) { - smbhash(p24, c8, p21); - smbhash(p24+8, c8, p21+7); - smbhash(p24+16, c8, p21+14); + smbhash(p24, c8, p21, 1); + smbhash(p24+8, c8, p21+7, 1); + smbhash(p24+16, c8, p21+14, 1); } void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key) { unsigned char buf[8]; - smbhash(buf, in, key); - smbhash(out, buf, key+9); + smbhash(buf, in, key, 1); + smbhash(out, buf, key+9, 1); } void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key) @@ -330,8 +330,8 @@ void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key) unsigned char buf[8]; static unsigned char key2[8]; - smbhash(buf, in, key); + smbhash(buf, in, key, 1); key2[0] = key[7]; - smbhash(out, buf, key2); + smbhash(out, buf, key2, 1); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b1caee10a2..847f6e68f2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1586,7 +1586,7 @@ static BOOL can_delete(char *fname,int cnum,int dirtype) } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) return(False); - if (!check_file_sharing(cnum,fname)) return(False); + if (!check_file_sharing(cnum,fname,False)) return(False); return(True); } @@ -3039,7 +3039,7 @@ static BOOL can_rename(char *fname,int cnum) if (!CAN_WRITE(cnum)) return(False); if (sys_lstat(fname,&sbuf) != 0) return(False); - if (!check_file_sharing(cnum,fname)) return(False); + if (!check_file_sharing(cnum,fname,True)) return(False); return(True); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index aaf446bdf5..bf635fc27a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1574,7 +1574,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, check if the share mode on a file allows it to be deleted or unlinked return True if sharing doesn't prevent the operation ********************************************************************/ -BOOL check_file_sharing(int cnum,char *fname) +BOOL check_file_sharing(int cnum,char *fname, BOOL rename_op) { int i; int ret = False; @@ -1621,21 +1621,41 @@ BOOL check_file_sharing(int cnum,char *fname) if(share_entry->op_type & BATCH_OPLOCK) { - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ + /* + * It appears that the NT redirector may have a bug, in that + * it tries to do an SMBmv on a file that it has open with a + * batch oplock, and then fails to respond to the oplock break + * request. This only seems to occur when the client is doing an + * SMBmv to the smbd it is using - thus we try and detect this + * condition by checking if the file being moved is open and oplocked by + * this smbd process, and then not sending the oplock break in this + * special case. If the file was open with a deny mode that + * prevents the move the SMBmv will fail anyway with a share + * violation error. JRA. + */ + if(rename_op && (share_entry->pid == pid)) + { + DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \ +batch oplocked file %s, dev = %x, inode = %x\n", fname, dev, inode)); + } + else + { + DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ + /* Oplock break.... */ + unlock_share_entry(cnum, dev, inode, token); + if(request_oplock_break(share_entry, dev, inode) == False) + { + free((char *)old_shares); + DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - return False; + return False; + } + lock_share_entry(cnum, dev, inode, &token); + broke_oplock = True; + break; } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; } /* someone else has a share lock on it, check to see |