summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h2
-rw-r--r--source3/libsmb/smbdes.c26
-rw-r--r--source3/smbd/reply.c4
-rw-r--r--source3/smbd/server.c44
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