client.c: Changed shadowed variable.
[kai/samba.git] / source3 / smbd / reply.c
index c1422bbcf609828162b0143ab0cd9dcec8bc5aed..fa641931eb2ddaad6230a10dd4e7ca9a871727f0 100644 (file)
@@ -42,6 +42,7 @@ extern BOOL short_case_preserve;
 extern pstring sesssetup_user;
 extern fstring myworkgroup;
 extern int Client;
+extern int global_oplock_break;
 
 /* this macro should always be used to extract an fnum (smb_fid) from
 a packet to ensure chaining works correctly */
@@ -54,7 +55,7 @@ report a possible attack via the password buffer overflow bug
 static void overflow_attack(int len)
 {
        DEBUG(0,("ERROR: Invalid password length %d\n", len));
-       DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n"));
+       DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
        DEBUG(0,("Attack was from IP=%s\n", client_addr()));
        exit_server("possible attack");
 }
@@ -388,7 +389,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   if (Protocol < PROTOCOL_NT1) {
     smb_apasslen = SVAL(inbuf,smb_vwv7);
     if (smb_apasslen > MAX_PASSWORD_LENGTH)
+    {
            overflow_attack(smb_apasslen);
+    }
 
     memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
     pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
@@ -596,7 +599,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   if (!done_sesssetup)
     max_send = MIN(max_send,smb_bufsize);
 
-  DEBUG(1,(" Client requested max send size of %d\n", max_send));
+  DEBUG(6,("Client requested max send size of %d\n", max_send));
 
   done_sesssetup = True;
 
@@ -637,6 +640,15 @@ int reply_chkpth(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+
+    /* Ugly - NT specific hack - but needed (JRA) */
+    if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
+       (get_remote_arch() == RA_WINNT))
+    {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbaddirectory;
+    }
+
     return(UNIXERROR(ERRDOS,ERRbadpath));
   }
  
@@ -1099,6 +1111,8 @@ int reply_open(char *inbuf,char *outbuf)
   int rmode=0;
   struct stat sbuf;
   BOOL bad_path = False;
+  files_struct *fsp;
+  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
   cnum = SVAL(inbuf,smb_tid);
 
@@ -1123,9 +1137,12 @@ int reply_open(char *inbuf,char *outbuf)
  
   unixmode = unix_mode(cnum,aARCH);
       
-  open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
+  open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
+                   oplock_request,&rmode,NULL);
 
-  if (!Files[fnum].open)
+  fsp = &Files[fnum];
+
+  if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path)
     {
@@ -1135,7 +1152,7 @@ int reply_open(char *inbuf,char *outbuf)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
+  if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
     close_file(fnum);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
@@ -1157,10 +1174,12 @@ int reply_open(char *inbuf,char *outbuf)
   SIVAL(outbuf,smb_vwv4,size);
   SSVAL(outbuf,smb_vwv6,rmode);
 
-  if (lp_fake_oplocks(SNUM(cnum))) {
-    CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
+  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
     
+  if(fsp->granted_oplock)
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   return(outsize);
 }
 
@@ -1175,7 +1194,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   int fnum = -1;
   int smb_mode = SVAL(inbuf,smb_vwv3);
   int smb_attr = SVAL(inbuf,smb_vwv5);
-  BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
+  BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
 #if 0
   int open_flags = SVAL(inbuf,smb_vwv2);
   int smb_sattr = SVAL(inbuf,smb_vwv4); 
@@ -1187,6 +1206,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   struct stat sbuf;
   int smb_action = 0;
   BOOL bad_path = False;
+  files_struct *fsp;
 
   /* If it's an IPC, pass off the pipe handler. */
   if (IS_IPC(cnum))
@@ -1214,9 +1234,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   unixmode = unix_mode(cnum,smb_attr | aARCH);
       
   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
-                  &rmode,&smb_action);
+                  oplock_request, &rmode,&smb_action);
       
-  if (!Files[fnum].open)
+  fsp = &Files[fnum];
+
+  if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path)
     {
@@ -1226,7 +1248,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
+  if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
     close_file(fnum);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
@@ -1240,7 +1262,13 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   }
 
   if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
-    smb_action |= (1<<15);
+    smb_action |= EXTENDED_OPLOCK_GRANTED;
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+  }
+
+  if(fsp->granted_oplock) {
+    smb_action |= EXTENDED_OPLOCK_GRANTED;
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
   set_message(outbuf,15,0,True);
@@ -1302,6 +1330,8 @@ int reply_mknew(char *inbuf,char *outbuf)
   mode_t unixmode;
   int ofun = 0;
   BOOL bad_path = False;
+  files_struct *fsp;
+  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
   com = SVAL(inbuf,smb_com);
   cnum = SVAL(inbuf,smb_tid);
@@ -1343,9 +1373,12 @@ int reply_mknew(char *inbuf,char *outbuf)
   }
 
   /* Open file in dos compatibility share mode. */
-  open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
+  open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, 
+                   oplock_request, NULL, NULL);
   
-  if (!Files[fnum].open)
+  fsp = &Files[fnum];
+
+  if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path) 
     {
@@ -1358,10 +1391,13 @@ int reply_mknew(char *inbuf,char *outbuf)
   outsize = set_message(outbuf,1,0,True);
   SSVAL(outbuf,smb_vwv0,fnum);
 
-  if (lp_fake_oplocks(SNUM(cnum))) {
-    CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
+  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
-  
+  if(fsp->granted_oplock)
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   DEBUG(2,("new file %s\n",fname));
   DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
   
@@ -1382,6 +1418,8 @@ int reply_ctemp(char *inbuf,char *outbuf)
   int createmode;
   mode_t unixmode;
   BOOL bad_path = False;
+  files_struct *fsp;
+  int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
  
   cnum = SVAL(inbuf,smb_tid);
   createmode = SVAL(inbuf,smb_vwv0);
@@ -1409,9 +1447,12 @@ int reply_ctemp(char *inbuf,char *outbuf)
 
   /* Open file in dos compatibility share mode. */
   /* We should fail if file exists. */
-  open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
+  open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, 
+                   oplock_request, NULL, NULL);
 
-  if (!Files[fnum].open)
+  fsp = &Files[fnum];
+
+  if (!fsp->open)
   {
     if((errno == ENOENT) && bad_path)
     {
@@ -1426,10 +1467,13 @@ int reply_ctemp(char *inbuf,char *outbuf)
   CVAL(smb_buf(outbuf),0) = 4;
   strcpy(smb_buf(outbuf) + 1,fname2);
 
-  if (lp_fake_oplocks(SNUM(cnum))) {
-    CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
+  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
   
+  if(fsp->granted_oplock)
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+
   DEBUG(2,("created temp file %s\n",fname2));
   DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
   
@@ -1577,6 +1621,20 @@ int reply_readbraw(char *inbuf, char *outbuf)
   int fd;
   char *fname;
 
+  /*
+   * Special check if an oplock break has been issued
+   * and the readraw request croses on the wire, we must
+   * return a zero length response here.
+   */
+
+  if(global_oplock_break)
+  {
+    _smb_setlen(header,0);
+    transfer_file(0,Client,0,header,4,0);
+    DEBUG(5,("readbraw - oplock break finished\n"));
+    return -1;
+  }
+
   cnum = SVAL(inbuf,smb_tid);
   fnum = GETFNUM(inbuf,smb_vwv0);
 
@@ -2432,7 +2490,8 @@ int reply_printopen(char *inbuf,char *outbuf)
     return(ERROR(ERRDOS,ERRnoaccess));
 
   /* Open for exclusive use, write only. */
-  open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
+  open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 
+                   0, NULL, NULL);
 
   if (!Files[fnum].open)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -3094,7 +3153,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
   fnum1 = find_free_file();
   if (fnum1<0) return(False);
   open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
-                  1,0,&Access,&action);
+                  1,0,0,&Access,&action);
 
   if (!Files[fnum1].open) return(False);
 
@@ -3107,7 +3166,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
     return(False);
   }
   open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
-                  ofun,st.st_mode,&Access,&action);
+                  ofun,st.st_mode,0,&Access,&action);
 
   if (!Files[fnum2].open) {
     close_file(fnum1);
@@ -3309,7 +3368,10 @@ int reply_setdir(char *inbuf,char *outbuf)
 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
 {
   int fnum = GETFNUM(inbuf,smb_vwv2);
-  uint16 locktype = SVAL(inbuf,smb_vwv3);
+  unsigned char locktype = CVAL(inbuf,smb_vwv3);
+#if 0
+  unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
+#endif
   uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
   uint16 num_locks = SVAL(inbuf,smb_vwv7);
   uint32 count, offset;
@@ -3326,6 +3388,48 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
   CHECK_ERROR(fnum);
 
   data = smb_buf(inbuf);
+
+  /* Check if this is an oplock break on a file
+     we have granted an oplock on.
+   */
+  if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) && 
+     (num_ulocks == 0) && (num_locks == 0) &&
+     (CVAL(inbuf,smb_vwv0) == 0xFF))
+  {
+    share_lock_token token;
+    files_struct *fsp = &Files[fnum];
+    uint32 dev = fsp->fd_ptr->dev;
+    uint32 inode = fsp->fd_ptr->inode;
+
+    DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
+              fnum));
+    /*
+     * Make sure we have granted an oplock on this file.
+     */
+    if(!fsp->granted_oplock)
+    {
+      DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
+no oplock granted on this file.\n", fnum));
+      return ERROR(ERRDOS,ERRlock);
+    }
+
+    /* Remove the oplock flag from the sharemode. */
+    lock_share_entry(fsp->cnum, dev, inode, &token);
+    if(remove_share_oplock( fnum, token)==False)
+    {
+      DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
+dev = %x, inode = %x\n", fnum, dev, inode));
+      unlock_share_entry(fsp->cnum, dev, inode, token);
+      return -1;
+    }
+    unlock_share_entry(fsp->cnum, dev, inode, token);
+
+    /* Clear the granted flag and return. */
+
+    fsp->granted_oplock = False;
+    return -1;
+  }
+
   /* Data now points at the beginning of the list
      of smb_unlkrng structs */
   for(i = 0; i < (int)num_ulocks; i++) {
@@ -3360,7 +3464,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
   set_message(outbuf,2,0,True);
   
   DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
-       timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
+       timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
 
   chain_fnum = fnum;
 
@@ -3713,8 +3817,3 @@ int reply_getattrE(char *inbuf,char *outbuf)
   
   return(outsize);
 }
-
-
-
-
-