Fixed an apparent typo:
[samba.git] / source3 / smbd / server.c
index be24ad7781a309a131ba5971f0e122063ca21d20..29a0d462f3d4df82eb143fd48b2d2cd8f4480f0e 100644 (file)
@@ -48,7 +48,7 @@ extern BOOL case_preserve;
 extern BOOL use_mangled_map;
 extern BOOL short_case_preserve;
 extern BOOL case_mangle;
-extern time_t smb_last_time;
+time_t smb_last_time=(time_t)0;
 
 extern int smb_read_error;
 
@@ -94,7 +94,7 @@ BOOL global_oplock_break = False;
 
 extern fstring remote_machine;
 
-pstring OriginalDir;
+extern pstring OriginalDir;
 
 /* these can be set by some functions to override the error codes */
 int unix_ERR_class=SUCCESS;
@@ -254,7 +254,6 @@ int dos_mode(int cnum,char *path,struct stat *sbuf)
   return(result);
 }
 
-
 /*******************************************************************
 chmod a file - but preserve some bits
 ********************************************************************/
@@ -308,6 +307,73 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
   return(sys_chmod(fname,unixmode));
 }
 
+/*******************************************************************
+Wrapper around sys_utime that possibly allows DOS semantics rather
+than POSIX.
+*******************************************************************/
+
+int file_utime(int cnum, char *fname, struct utimbuf *times)
+{
+  extern struct current_user current_user;
+  struct stat sb;
+  int ret = -1;
+
+  errno = 0;
+
+  if(sys_utime(fname, times) == 0)
+    return 0;
+
+  if((errno != EPERM) && (errno != EACCES))
+    return -1;
+
+  if(!lp_dos_filetimes(SNUM(cnum)))
+    return -1;
+
+  /* We have permission (given by the Samba admin) to
+     break POSIX semantics and allow a user to change
+     the time on a file they don't own but can write to
+     (as DOS does).
+   */
+
+  if(sys_stat(fname,&sb) != 0)
+    return -1;
+
+  /* Check if we have write access. */
+  if (CAN_WRITE(cnum)) {
+         if (((sb.st_mode & S_IWOTH) ||
+              Connections[cnum].admin_user ||
+              ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
+              ((sb.st_mode & S_IWGRP) &&
+               in_group(sb.st_gid,current_user.gid,
+                        current_user.ngroups,current_user.igroups)))) {
+                 /* We are allowed to become root and change the filetime. */
+                 become_root(False);
+                 ret = sys_utime(fname, times);
+                 unbecome_root(False);
+         }
+  }
+
+  return ret;
+}
+  
+/*******************************************************************
+Change a filetime - possibly allowing DOS semantics.
+*******************************************************************/
+
+BOOL set_filetime(int cnum, char *fname, time_t mtime)
+{
+  struct utimbuf times;
+
+  if (null_mtime(mtime)) return(True);
+
+  times.modtime = times.actime = mtime;
+
+  if (file_utime(cnum, fname, &times)) {
+    DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
+  }
+  
+  return(True);
+} 
 
 /****************************************************************************
 check if two filenames are equal
@@ -386,8 +452,20 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
     return(True);
   }      
 
+#if 0 
+  /* 
+   * This code I believe is incorrect - and commenting it out
+   * is the correct fix for the bug mentioned below in the
+   * comment 'name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra)'.
+   * The incoming name can be mangled, and if we de-mangle it
+   * here it will not compare correctly against the filename (name2)
+   * read from the directory and then mangled by the name_map_mangle()
+   * call. We need to mangle both names or neither.
+   * (JRA).
+   */
   if (mangled)
     check_mangled_stack(name);
+#endif 
 
   /* open the directory */
   if (!(cur_dir = OpenDir(cnum, path, True))) 
@@ -1073,6 +1151,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
   struct stat statbuf;
   file_fd_struct *fd_ptr;
   files_struct *fsp = &Files[fnum];
+  int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
 
   fsp->open = False;
   fsp->fd_ptr = 0;
@@ -1082,12 +1161,32 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
   pstrcpy(fname,fname1);
 
   /* check permissions */
-  if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
-    {
+
+  /*
+   * This code was changed after seeing a client open request 
+   * containing the open mode of (DENY_WRITE/read-only) with
+   * the 'create if not exist' bit set. The previous code
+   * would fail to open the file read only on a read-only share
+   * as it was checking the flags parameter  directly against O_RDONLY,
+   * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
+   * JRA.
+   */
+
+  if (!CAN_WRITE(cnum) && !Connections[cnum].printer) {
+    /* It's a read-only share - fail if we wanted to write. */
+    if(accmode != O_RDONLY) {
       DEBUG(3,("Permission denied opening %s\n",fname));
       check_for_pipe(fname);
       return;
     }
+    else if(flags & O_CREAT) {
+      /* We don't want to write - but we must make sure that O_CREAT
+         doesn't create the file if we have write access into the
+         directory.
+       */
+      flags &= ~O_CREAT;
+    }
+  }
 
   /* this handles a bug in Win95 - it doesn't say to create the file when it 
      should */
@@ -1099,13 +1198,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
 */
 
-#if UTIME_WORKAROUND
-  /* XXXX - is this OK?? */
-  /* this works around a utime bug but can cause other problems */
-  if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
-    sys_unlink(fname);
-#endif
-
   /*
    * Ensure we have a valid struct stat so we can search the
    * open fd table.
@@ -1132,8 +1224,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
    */
   if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
 
-    int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
-
     /* File was already open. */
     if((flags & O_CREAT) && (flags & O_EXCL)) {
       fd_ptr->ref_count--;
@@ -1267,6 +1357,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
       fsp->print_file = Connections[cnum].printer;
       fsp->modified = False;
       fsp->granted_oplock = False;
+      fsp->sent_oplock_break = False;
       fsp->cnum = cnum;
       string_set(&fsp->name,dos_to_unix(fname,False));
       fsp->wbmpx_ptr = NULL;      
@@ -1373,9 +1464,12 @@ void close_file(int fnum, BOOL normal_close)
   int cnum = fs_p->cnum;
   uint32 dev = fs_p->fd_ptr->dev;
   uint32 inode = fs_p->fd_ptr->inode;
-  share_lock_token token;
+  int token;
 
+#if USE_READ_PREDICTION
   invalidate_read_prediction(fs_p->fd_ptr->fd);
+#endif
+
   fs_p->open = False;
   Connections[cnum].num_files_open--;
   if(fs_p->wbmpx_ptr) 
@@ -1411,6 +1505,11 @@ void close_file(int fnum, BOOL normal_close)
   if (normal_close)
     check_magic(fnum,cnum);
 
+  if(fs_p->granted_oplock == True)
+    global_oplocks_open--;
+
+  fs_p->sent_oplock_break = False;
+
   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
           timestring(),Connections[cnum].user,fs_p->name,
           Connections[cnum].num_files_open));
@@ -1477,10 +1576,10 @@ BOOL check_file_sharing(int cnum,char *fname)
 {
   int i;
   int ret = False;
-  min_share_mode_entry *old_shares = 0;
+  share_mode_entry *old_shares = 0;
   int num_share_modes;
   struct stat sbuf;
-  share_lock_token token;
+  int token;
   int pid = getpid();
   uint32 dev, inode;
 
@@ -1509,7 +1608,7 @@ BOOL check_file_sharing(int cnum,char *fname)
       broke_oplock = False;
       for(i = 0; i < num_share_modes; i++)
       {
-        min_share_mode_entry *share_entry = &old_shares[i];
+        share_mode_entry *share_entry = &old_shares[i];
 
         /* 
          * Break oplocks before checking share modes. See comment in
@@ -1571,8 +1670,8 @@ free_and_exit:
   Helper for open_file_shared. 
   Truncate a file after checking locking; close file if locked.
   **************************************************************************/
-static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, 
-       BOOL *share_locked)
+static void truncate_unless_locked(int fnum, int cnum, int token, 
+                                  BOOL *share_locked)
 {
   if (Files[fnum].can_write){
     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
@@ -1596,7 +1695,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
 /****************************************************************************
 check if we can open a file with a share mode
 ****************************************************************************/
-int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
+int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
                       BOOL fcbopen, int *flags)
 {
   int old_open_mode = share->share_mode &0xF;
@@ -1618,9 +1717,9 @@ int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
         (access_allowed == AREAD && *flags == O_WRONLY) ||
         (access_allowed == AWRITE && *flags == O_RDONLY))
     {
-      DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
+      DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
                 deny_mode,old_deny_mode,old_open_mode,
-                share->pid,fname, access_allowed));
+                share->pid,fname, fcbopen, *flags, access_allowed));
       return False;
     }
 
@@ -1648,7 +1747,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
   BOOL file_existed = file_exist(fname,&sbuf);
   BOOL share_locked = False;
   BOOL fcbopen = False;
-  share_lock_token token;
+  int token;
   uint32 dev = 0;
   uint32 inode = 0;
   int num_share_modes = 0;
@@ -1724,7 +1823,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
   if (lp_share_modes(SNUM(cnum))) 
   {
     int i;
-    min_share_mode_entry *old_shares = 0;
+    share_mode_entry *old_shares = 0;
 
     if (file_existed)
     {
@@ -1749,7 +1848,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
         broke_oplock = False;
         for(i = 0; i < num_share_modes; i++)
         {
-          min_share_mode_entry *share_entry = &old_shares[i];
+          share_mode_entry *share_entry = &old_shares[i];
 
           /* 
            * By observation of NetBench, oplocks are broken *before* share
@@ -1866,9 +1965,11 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
          be extended to level II oplocks (multiple reader
          oplocks). */
 
-      if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)))
+      if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)) && 
+             !IS_VETO_OPLOCK_PATH(cnum,fname))
       {
         fs_p->granted_oplock = True;
+        fs_p->sent_oplock_break = False;
         global_oplocks_open++;
         port = oplock_port;
 
@@ -1913,6 +2014,7 @@ int read_file(int fnum,char *data,uint32 pos,int n)
 {
   int ret=0,readret;
 
+#if USE_READ_PREDICTION
   if (!Files[fnum].can_write)
     {
       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
@@ -1921,6 +2023,7 @@ int read_file(int fnum,char *data,uint32 pos,int n)
       n -= ret;
       pos += ret;
     }
+#endif
 
 #if USE_MMAP
   if (Files[fnum].mmap_ptr)
@@ -2264,22 +2367,21 @@ static int sig_cld()
   **************************************************************************/
 static int sig_pipe()
 {
-  extern int password_client;
-  BlockSignals(True,SIGPIPE);
+       struct cli_state *cli;
+       BlockSignals(True,SIGPIPE);
 
-  if (password_client != -1) {
-    DEBUG(3,("lost connection to password server\n"));
-    close(password_client);
-    password_client = -1;
+       if ((cli = server_client()) && cli->initialised) {
+               DEBUG(3,("lost connection to password server\n"));
+               cli_shutdown(cli);
 #ifndef DONT_REINSTALL_SIG
-    signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
 #endif
-    BlockSignals(False,SIGPIPE);
-    return 0;
-  }
+               BlockSignals(False,SIGPIPE);
+               return 0;
+       }
 
-  exit_server("Got sigpipe\n");
-  return(0);
+       exit_server("Got sigpipe\n");
+       return(0);
 }
 
 /****************************************************************************
@@ -2290,100 +2392,182 @@ static BOOL open_sockets(BOOL is_daemon,int port)
   extern int Client;
 
   if (is_daemon)
-    {
-      int s;
-      struct sockaddr addr;
-      int in_addrlen = sizeof(addr);
-       
-      /* Stop zombies */
+  {
+    int num_interfaces = iface_count();
+    int fd_listenset[FD_SETSIZE];
+    fd_set listen_set;
+    int s;
+    int i;
+
+    /* Stop zombies */
 #ifdef SIGCLD_IGNORE
-      signal(SIGCLD, SIG_IGN);
+    signal(SIGCLD, SIG_IGN);
 #else
-      signal(SIGCLD, SIGNAL_CAST sig_cld);
+    signal(SIGCLD, SIGNAL_CAST sig_cld);
 #endif
 
+    if(atexit_set == 0)
+      atexit(killkids);
+
+    FD_ZERO(&listen_set);
+
+    if(lp_interfaces() && lp_bind_interfaces_only())
+    {
+       /* We have been given an interfaces line, and been 
+          told to only bind to those interfaces. Create a
+          socket per interface and bind to only these.
+        */
+
+      if(num_interfaces > FD_SETSIZE)
+      {
+        DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \
+max can be %d\n", num_interfaces, FD_SETSIZE));
+        return False;
+      }
+
+      /* Now open a listen socket for each of the interfaces. */
+      for(i = 0; i < num_interfaces; i++)
+      {
+        struct in_addr *ifip = iface_n_ip(i);
+
+        if(ifip == NULL)
+        {
+          DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i));
+          continue;
+        }
+        s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr);
+        if(s == -1)
+          return False;
+        /* ready to listen */
+        if (listen(s, 5) == -1) 
+        {
+          DEBUG(0,("listen: %s\n",strerror(errno)));
+          close(s);
+          return False;
+        }
+        FD_SET(s,&listen_set);
+      }
+    }
+    else
+    {
+      /* Just bind to 0.0.0.0 - accept connections from anywhere. */
+      num_interfaces = 1;
+
       /* open an incoming socket */
       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
       if (s == -1)
-       return(False);
+        return(False);
 
       /* ready to listen */
       if (listen(s, 5) == -1) 
-       {
-         DEBUG(0,("listen: %s\n",strerror(errno)));
-         close(s);
-         return False;
-       }
-      
-      if(atexit_set == 0)
-        atexit(killkids);
+      {
+        DEBUG(0,("open_sockets: listen: %s\n",strerror(errno)));
+        close(s);
+        return False;
+      }
 
-      /* now accept incoming connections - forking a new process
-        for each incoming connection */
-      DEBUG(2,("waiting for a connection\n"));
-      while (1)
-       {
-         Client = accept(s,&addr,&in_addrlen);
+      fd_listenset[0] = s;
+      FD_SET(s,&listen_set);
+    }      
 
-         if (Client == -1 && errno == EINTR)
-           continue;
+    /* now accept incoming connections - forking a new process
+       for each incoming connection */
+    DEBUG(2,("waiting for a connection\n"));
+    while (1)
+    {
+      fd_set lfds;
+      int num;
 
-         if (Client == -1)
-           {
-             DEBUG(0,("accept: %s\n",strerror(errno)));
-             continue;
-           }
+      memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set));
+
+      num = sys_select(&lfds,NULL);
+
+      if (num == -1 && errno == EINTR)
+        continue;
+
+      /* Find the sockets that are read-ready - accept on these. */
+      for( ; num > 0; num--)
+      {
+        struct sockaddr addr;
+        int in_addrlen = sizeof(addr);
+
+        s = -1;
+        for(i = 0; i < num_interfaces; i++)
+        {
+          if(FD_ISSET(fd_listenset[i],&lfds))
+          {
+            s = fd_listenset[i];
+            /* Clear this so we don't look at it again. */
+            FD_CLR(fd_listenset[i],&lfds);
+            break;
+          }
+        }
+
+        Client = accept(s,&addr,&in_addrlen);
+
+        if (Client == -1 && errno == EINTR)
+          continue;
+
+        if (Client == -1)
+        {
+          DEBUG(0,("open_sockets: accept: %s\n",strerror(errno)));
+          continue;
+        }
 
 #ifdef NO_FORK_DEBUG
+#ifndef NO_SIGNAL_TEST
+        signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+        signal(SIGCLD, SIGNAL_CAST SIG_DFL);
+#endif /* NO_SIGNAL_TEST */
+        return True;
+#else /* NO_FORK_DEBUG */
+        if (Client != -1 && fork()==0)
+        {
+          /* Child code ... */
+
 #ifndef NO_SIGNAL_TEST
           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
-#endif
-         return True;
-#else
-         if (Client != -1 && fork()==0)
-           {
-              /* Child code ... */
-#ifndef NO_SIGNAL_TEST
-             signal(SIGPIPE, SIGNAL_CAST sig_pipe);
-             signal(SIGCLD, SIGNAL_CAST SIG_DFL);
-#endif
-             /* close the listening socket */
-             close(s);
-
-             /* close our standard file descriptors */
-             close_low_fds();
-              am_parent = 0;
+#endif /* NO_SIGNAL_TEST */
+          /* close the listening socket(s) */
+          for(i = 0; i < num_interfaces; i++)
+            close(fd_listenset[i]);
+
+          /* close our standard file descriptors */
+          close_low_fds();
+          am_parent = 0;
   
-             set_socket_options(Client,"SO_KEEPALIVE");
-             set_socket_options(Client,user_socket_options);
-
-              /* Reset global variables in util.c so that
-                 client substitutions will be done correctly
-                 in the process.
-               */
-              reset_globals_after_fork();
-             return True; 
-           }
-          close(Client); /* The parent doesn't need this socket */
-#endif
-       }
-    }
+          set_socket_options(Client,"SO_KEEPALIVE");
+          set_socket_options(Client,user_socket_options);
+
+          /* Reset global variables in util.c so that
+             client substitutions will be done correctly
+             in the process.
+           */
+          reset_globals_after_fork();
+          return True; 
+        }
+        close(Client); /* The parent doesn't need this socket */
+#endif /* NO_FORK_DEBUG */
+      } /* end for num */
+    } /* end while 1 */
+  } /* end if is_daemon */
   else
-    {
-      /* We will abort gracefully when the client or remote system 
-        goes away */
+  {
+    /* Started from inetd. fd 0 is the socket. */
+    /* We will abort gracefully when the client or remote system 
+       goes away */
 #ifndef NO_SIGNAL_TEST
-      signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+    signal(SIGPIPE, SIGNAL_CAST sig_pipe);
 #endif
-      Client = dup(0);
+    Client = dup(0);
 
-      /* close our standard file descriptors */
-      close_low_fds();
+    /* close our standard file descriptors */
+    close_low_fds();
 
-      set_socket_options(Client,"SO_KEEPALIVE");
-      set_socket_options(Client,user_socket_options);
-    }
+    set_socket_options(Client,"SO_KEEPALIVE");
+    set_socket_options(Client,user_socket_options);
+  }
 
   return True;
 }
@@ -2430,6 +2614,8 @@ static void process_smb(char *inbuf, char *outbuf)
 
   if (msg_type == 0)
     show_msg(inbuf);
+  else if(msg_type == 0x85)
+    return; /* Keepalive packet. */
 
   nread = construct_reply(inbuf,outbuf,nread,max_send);
       
@@ -2493,7 +2679,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
 static BOOL process_local_message(int sock, char *buffer, int buf_size)
 {
   int32 msg_len;
-  int16 from_port;
+  uint16 from_port;
   char *msg_start;
 
   msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
@@ -2620,24 +2806,8 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
   time_t start_time;
   BOOL shutdown_server = False;
 
-  DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \
-global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
-
-  if(inbuf == NULL)
-  {
-    inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-    if(inbuf == NULL) {
-      DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
-      return False;
-    } 
-    outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-    if(outbuf == NULL) {
-      DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
-      free(inbuf);
-      inbuf = NULL;
-      return False;
-    }
-  } 
+  DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \
+global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open));
 
   /* We need to search the file open table for the
      entry containing this dev and inode, and ensure
@@ -2646,19 +2816,20 @@ global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
   {
     if(OPEN_FNUM(fnum))
     {
-      fsp = &Files[fnum];
-      if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) &&
-         (fsp->open_time.tv_sec == tval->tv_sec) && 
-         (fsp->open_time.tv_usec == tval->tv_usec))
-        break;
+      if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) &&
+         (Files[fnum].open_time.tv_sec == tval->tv_sec) && 
+         (Files[fnum].open_time.tv_usec == tval->tv_usec)) {
+             fsp = &Files[fnum];
+             break;
+      }
     }
   }
 
   if(fsp == NULL)
   {
     /* The file could have been closed in the meantime - return success. */
-    DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
-allowing break to succeed.\n", dev, inode, fnum));
+    DEBUG(0,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
+allowing break to succeed.\n", timestring(), dev, inode, fnum));
     return True;
   }
 
@@ -2673,15 +2844,42 @@ allowing break to succeed.\n", dev, inode, fnum));
 
   if(!fsp->granted_oplock)
   {
-    DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \
-Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
+    DEBUG(0,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode));
     return True;
   }
 
+  /* mark the oplock break as sent - we don't want to send twice! */
+  if (fsp->sent_oplock_break)
+  {
+    DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode));
+
+    /* We have to fail the open here as we cannot send another oplock break on this
+       file whilst we are awaiting a response from the client - neither can we
+       allow another open to succeed while we are waiting for the client. */
+    return False;
+  }
+
   /* Now comes the horrid part. We must send an oplock break to the client,
      and then process incoming messages until we get a close or oplock release.
+     At this point we know we need a new inbuf/outbuf buffer pair.
+     We cannot use these staticaly as we may recurse into here due to
+     messages crossing on the wire.
    */
 
+  if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  {
+    DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
+    return False;
+  }
+
+  if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  {
+    DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
+    free(inbuf);
+    inbuf = NULL;
+    return False;
+  }
+
   /* Prepare the SMBlockingX message. */
   bzero(outbuf,smb_size);
   set_message(outbuf,8,0,True);
@@ -2699,6 +2897,10 @@ Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
  
   send_smb(Client, outbuf);
 
+  /* Remember we just sent an oplock break on this file. */
+  fsp->sent_oplock_break = True;
+
+  /* We need this in case a readraw crosses on the wire. */
   global_oplock_break = True;
  
   /* Process incoming messages. */
@@ -2717,49 +2919,54 @@ Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
        */
 
       if (smb_read_error == READ_EOF)
-        DEBUG(0,("oplock_break: end of file from client\n"));
+        DEBUG(0,("%s oplock_break: end of file from client\n", timestring()));
  
       if (smb_read_error == READ_ERROR)
-        DEBUG(0,("oplock_break: receive_smb error (%s)\n",
-                  strerror(errno)));
+        DEBUG(0,("%s oplock_break: receive_smb error (%s)\n",
+                  timestring(), strerror(errno)));
 
       if (smb_read_error == READ_TIMEOUT)
-        DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n",
-                  OPLOCK_BREAK_TIMEOUT));
+        DEBUG(0,("%s oplock_break: receive_smb timed out after %d seconds.\n",
+                  timestring(), OPLOCK_BREAK_TIMEOUT));
 
-      DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
-inode = %x).\n", fsp->name, fnum, dev, inode));
+      DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \
+inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
       shutdown_server = True;
       break;
     }
     process_smb(inbuf, outbuf);
 
-    /* We only need this in case a readraw crossed on the wire. */
-    if(global_oplock_break)
-      global_oplock_break = False;
-
     /*
      * Die if we go over the time limit.
      */
 
     if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT)
     {
-      DEBUG(0,("oplock_break: no break received from client within \
-%d seconds.\n", OPLOCK_BREAK_TIMEOUT));
-      DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
-inode = %x).\n", fsp->name, fnum, dev, inode));
+      DEBUG(0,("%s oplock_break: no break received from client within \
+%d seconds.\n", timestring(), OPLOCK_BREAK_TIMEOUT));
+      DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \
+inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
       shutdown_server = True;
       break;
     }
   }
 
+  /* Free the buffers we've been using to recurse. */
+  free(inbuf);
+  free(outbuf);
+
+  /* We need this in case a readraw crossed on the wire. */
+  if(global_oplock_break)
+    global_oplock_break = False;
+
   /*
    * If the client did not respond we must die.
    */
 
   if(shutdown_server)
   {
-    DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n"));
+    DEBUG(0,("%s oplock_break: client failure in break - shutting down this smbd.\n",
+          timestring()));
     close_sockets();
     close(oplock_sock);
     exit_server("oplock break failure");
@@ -2771,10 +2978,10 @@ inode = %x).\n", fsp->name, fnum, dev, inode));
        from the sharemode. */
     /* Paranoia.... */
     fsp->granted_oplock = False;
+    fsp->sent_oplock_break = False;
+    global_oplocks_open--;
   }
 
-  global_oplocks_open--;
-
   /* Santity check - remove this later. JRA */
   if(global_oplocks_open < 0)
   {
@@ -2783,8 +2990,8 @@ inode = %x).\n", fsp->name, fnum, dev, inode));
     exit_server("oplock_break: global_oplocks_open < 0");
   }
 
-  DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
-global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open));
+  DEBUG(3,("%s oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
+global_oplocks_open = %d\n", timestring(), fnum, dev, inode, global_oplocks_open));
 
   return True;
 }
@@ -2794,7 +3001,7 @@ Send an oplock break message to another smbd process. If the oplock is held
 by the local smbd then call the oplock break function directly.
 ****************************************************************************/
 
-BOOL request_oplock_break(min_share_mode_entry *share_entry, 
+BOOL request_oplock_break(share_mode_entry *share_entry, 
                           uint32 dev, uint32 inode)
 {
   char op_break_msg[OPLOCK_BREAK_MSG_LEN];
@@ -2833,15 +3040,15 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
   addr_out.sin_port = htons( share_entry->op_port );
   addr_out.sin_family = AF_INET;
    
-  DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \
-for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode));
+  DEBUG(3,("%s request_oplock_break: sending a oplock break message to pid %d on port %d \
+for dev = %x, inode = %x\n", timestring(), share_entry->pid, share_entry->op_port, dev, inode));
 
   if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
          (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
   {
-    DEBUG(0,("request_oplock_break: failed when sending a oplock break message \
+    DEBUG(0,("%s request_oplock_break: failed when sending a oplock break message \
 to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
-         share_entry->pid, share_entry->op_port, dev, inode,
+         timestring(), share_entry->pid, share_entry->op_port, dev, inode,
          strerror(errno)));
     return False;
   }
@@ -2849,7 +3056,7 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
   /*
    * Now we must await the oplock broken message coming back
    * from the target smbd process. Timeout if it fails to
-   * return in OPLOCK_BREAK_TIMEOUT seconds.
+   * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds.
    * While we get messages that aren't ours, loop.
    */
 
@@ -2857,19 +3064,29 @@ to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
   {
     char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
     int32 reply_msg_len;
-    int16 reply_from_port;
+    uint16 reply_from_port;
     char *reply_msg_start;
 
     if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
-                             OPLOCK_BREAK_TIMEOUT * 1000) == False)
+               (OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) * 1000) == False)
     {
       if(smb_read_error == READ_TIMEOUT)
-        DEBUG(0,("request_oplock_break: no response received to oplock break request to \
-pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, 
+      {
+        DEBUG(0,("%s request_oplock_break: no response received to oplock break request to \
+pid %d on port %d for dev = %x, inode = %x\n", timestring(), share_entry->pid, 
                            share_entry->op_port, dev, inode));
+        /*
+         * This is a hack to make handling of failing clients more robust.
+         * If a oplock break response message is not received in the timeout
+         * period we may assume that the smbd servicing that client holding
+         * the oplock has died and the client changes were lost anyway, so
+         * we should continue to try and open the file.
+         */
+        break;
+      }
       else
-        DEBUG(0,("request_oplock_break: error in response received to oplock break request to \
-pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, 
+        DEBUG(0,("%s request_oplock_break: error in response received to oplock break request to \
+pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, share_entry->pid, 
                          share_entry->op_port, dev, inode, strerror(errno)));
       return False;
     }
@@ -2899,7 +3116,8 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid
     if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
     {
       /* Ignore it. */
-      DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n"));
+      DEBUG(0,("%s request_oplock_break: invalid message length received. Ignoring\n",
+             timestring()));
       continue;
     }
 
@@ -2909,9 +3127,9 @@ pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid
                &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
                OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0))
     {
-      DEBUG(3,("request_oplock_break: received other message whilst awaiting \
+      DEBUG(3,("%s request_oplock_break: received other message whilst awaiting \
 oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
-             share_entry->pid, share_entry->op_port, dev, inode));
+             timestring(), share_entry->pid, share_entry->op_port, dev, inode));
       if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False)
         return False;
       continue;
@@ -2920,11 +3138,44 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
     break;
   }
 
-  DEBUG(3,("request_oplock_break: broke oplock.\n"));
+  DEBUG(3,("%s request_oplock_break: broke oplock.\n", timestring()));
 
   return True;
 }
 
+/****************************************************************************
+Get the next SMB packet, doing the local message processing automatically.
+****************************************************************************/
+
+BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout)
+{
+  BOOL got_smb = False;
+  BOOL ret;
+
+  do
+  {
+    ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize,
+                                 timeout,&got_smb);
+
+    if(ret && !got_smb)
+    {
+      /* Deal with oplock break requests from other smbd's. */
+      process_local_message(oplock_sock, inbuf, bufsize);
+      continue;
+    }
+
+    if(ret && (CVAL(inbuf,0) == 0x85))
+    {
+      /* Keepalive packet. */
+      got_smb = False;
+    }
+
+  }
+  while(ret && !got_smb);
+
+  return ret;
+}
+
 /****************************************************************************
 check if a snum is in use
 ****************************************************************************/
@@ -2980,7 +3231,7 @@ BOOL reload_services(BOOL test)
     }
   }
 
-  create_mangled_stack(lp_mangledstack());
+  reset_mangled_stack( lp_mangledstack() );
 
   /* this forces service parameters to be flushed */
   become_service(-1,True);
@@ -3233,6 +3484,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
   pcon->dirptr = NULL;
   pcon->veto_list = NULL;
   pcon->hide_list = NULL;
+  pcon->veto_oplock_list = NULL;
   string_set(&pcon->dirpath,"");
   string_set(&pcon->user,user);
 
@@ -3322,7 +3574,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
       smbrun(cmd,NULL,False);
     }
 
-  if (!become_user(cnum,pcon->vuid))
+  if (!become_user(&Connections[cnum], cnum,pcon->vuid))
     {
       DEBUG(0,("Can't become connected user!\n"));
       pcon->open = False;
@@ -3383,6 +3635,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
   {
     set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
     set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
+    set_namearray( &pcon->veto_oplock_list, lp_veto_oplocks(SNUM(cnum)));
   }
 
   {
@@ -3405,14 +3658,35 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
 ****************************************************************************/
 int find_free_file(void )
 {
-  int i;
-  /* we start at 1 here for an obscure reason I can't now remember,
-     but I think is important :-) */
-  for (i=1;i<MAX_OPEN_FILES;i++)
-    if (!Files[i].open)
-      return(i);
-  DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
-  return(-1);
+       int i;
+       static int first_file;
+
+       /* we want to give out file handles differently on each new
+          connection because of a common bug in MS clients where they try to
+          reuse a file descriptor from an earlier smb connection. This code
+          increases the chance that the errant client will get an error rather
+          than causing corruption */
+       if (first_file == 0) {
+               first_file = (getpid() ^ (int)time(NULL)) % MAX_OPEN_FILES;
+               if (first_file == 0) first_file = 1;
+       }
+
+       for (i=first_file;i<MAX_OPEN_FILES;i++)
+               if (!Files[i].open) {
+                       memset(&Files[i], 0, sizeof(Files[i]));
+                       return(i);
+               }
+
+       /* returning a file handle of 0 is a bad idea - so we start at 1 */
+       for (i=1;i<first_file;i++)
+               if (!Files[i].open) {
+                       memset(&Files[i], 0, sizeof(Files[i]));
+                       return(i);
+               }
+
+
+       DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
+       return(-1);
 }
 
 /****************************************************************************
@@ -3491,11 +3765,6 @@ int reply_lanman1(char *outbuf)
   int secword=0;
   BOOL doencrypt = SMBENCRYPT();
   time_t t = time(NULL);
-  /* We need to save and restore this as it can be destroyed
-     if we call another server if security=server
-     Thanks to Paul Nelson @ Thursby for pointing this out.
-   */
-  uint16 mid = SVAL(outbuf, smb_mid);
 
   if (lp_security()>=SEC_USER) secword |= 1;
   if (doencrypt) secword |= 2;
@@ -3508,13 +3777,7 @@ int reply_lanman1(char *outbuf)
 
   Protocol = PROTOCOL_LANMAN1;
 
-  if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
-    DEBUG(3,("using password server validation\n"));
-  if (doencrypt) set_challenge(smb_buf(outbuf));    
-  }
-
   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
-  SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
   SSVAL(outbuf,smb_vwv2,max_recv);
   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
   SSVAL(outbuf,smb_vwv4,1);
@@ -3538,32 +3801,41 @@ int reply_lanman2(char *outbuf)
   int secword=0;
   BOOL doencrypt = SMBENCRYPT();
   time_t t = time(NULL);
-  /* We need to save and restore this as it can be destroyed
-     if we call another server if security=server
-     Thanks to Paul Nelson @ Thursby for pointing this out.
-   */
-  uint16 mid = SVAL(outbuf, smb_mid);
+  struct cli_state *cli = NULL;
+  char cryptkey[8];
+  char crypt_len = 0;
+
+  if (lp_security() == SEC_SERVER) {
+         cli = server_cryptkey();
+  }
+
+  if (cli) {
+         DEBUG(3,("using password server validation\n"));
+         doencrypt = ((cli->sec_mode & 2) != 0);
+  }
 
   if (lp_security()>=SEC_USER) secword |= 1;
   if (doencrypt) secword |= 2;
 
-  set_message(outbuf,13,doencrypt?8:0,True);
-  SSVAL(outbuf,smb_vwv1,secword); 
-  /* Create a token value and add it to the outgoing packet. */
-  if (doencrypt) 
-    generate_next_challenge(smb_buf(outbuf));
+  if (doencrypt) {
+         crypt_len = 8;
+         if (!cli) {
+                 generate_next_challenge(cryptkey);
+         } else {
+                 memcpy(cryptkey, cli->cryptkey, 8);
+                 set_challenge(cli->cryptkey);
+         }
+  }
 
+  set_message(outbuf,13,crypt_len,True);
+  SSVAL(outbuf,smb_vwv1,secword); 
   SIVAL(outbuf,smb_vwv6,getpid());
+  if (doencrypt) 
+         memcpy(smb_buf(outbuf), cryptkey, 8);
 
   Protocol = PROTOCOL_LANMAN2;
 
-  if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
-    DEBUG(3,("using password server validation\n"));
-    if (doencrypt) set_challenge(smb_buf(outbuf));    
-  }
-
   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
-  SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
   SSVAL(outbuf,smb_vwv2,max_recv);
   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
   SSVAL(outbuf,smb_vwv4,1);
@@ -3585,67 +3857,58 @@ int reply_nt1(char *outbuf)
 /*
   other valid capabilities which we may support at some time...
                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
-                     CAP_LARGE_FILES|CAP_LARGE_READX|
-                     CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
+                     CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
  */
 
   int secword=0;
   BOOL doencrypt = SMBENCRYPT();
   time_t t = time(NULL);
   int data_len;
-  int encrypt_len;
-  char challenge_len = 8;
-  /* We need to save and restore this as it can be destroyed
-     if we call another server if security=server
-     Thanks to Paul Nelson @ Thursby for pointing this out.
-   */
-  uint16 mid = SVAL(outbuf, smb_mid);
+  struct cli_state *cli = NULL;
+  char cryptkey[8];
+  char crypt_len = 0;
 
-  if (lp_readraw() && lp_writeraw())
-  {
-    capabilities |= CAP_RAW_MODE;
+  if (lp_security() == SEC_SERVER) {
+         cli = server_cryptkey();
   }
 
-  if (lp_security()>=SEC_USER) secword |= 1;
+  if (cli) {
+         DEBUG(3,("using password server validation\n"));
+         doencrypt = ((cli->sec_mode & 2) != 0);
+  }
+
+  if (doencrypt) {
+         crypt_len = 8;
+         if (!cli) {
+                 generate_next_challenge(cryptkey);
+         } else {
+                 memcpy(cryptkey, cli->cryptkey, 8);
+                 set_challenge(cli->cryptkey);
+         }
+  }
+
+  if (lp_readraw() && lp_writeraw()) {
+         capabilities |= CAP_RAW_MODE;
+  }
+
+  if (lp_security() >= SEC_USER) secword |= 1;
   if (doencrypt) secword |= 2;
 
   /* decide where (if) to put the encryption challenge, and
      follow it with the OEM'd domain name
    */
-  encrypt_len = doencrypt?challenge_len:0;
-#if UNICODE
-  data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
-#else
-  data_len = encrypt_len + strlen(myworkgroup) + 1;
-#endif
+  data_len = crypt_len + strlen(myworkgroup) + 1;
 
   set_message(outbuf,17,data_len,True);
-
-#if UNICODE
-  /* put the OEM'd domain name */
-  PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
-#else
-  strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
-#endif
+  strcpy(smb_buf(outbuf)+crypt_len, myworkgroup);
 
   CVAL(outbuf,smb_vwv1) = secword;
-  /* Create a token value and add it to the outgoing packet. */
-  if (doencrypt)
-  {
-    generate_next_challenge(smb_buf(outbuf));
-
-    /* Tell the nt machine how long the challenge is. */
-    SSVALS(outbuf,smb_vwv16+1,challenge_len);
-  }
+  SSVALS(outbuf,smb_vwv16+1,crypt_len);
+  if (doencrypt) 
+         memcpy(smb_buf(outbuf), cryptkey, 8);
 
   Protocol = PROTOCOL_NT1;
 
-  if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
-    DEBUG(3,("using password server validation\n"));
-    if (doencrypt) set_challenge(smb_buf(outbuf));    
-  }
-
-  SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
@@ -3890,7 +4153,7 @@ void close_cnum(int cnum, uint16 vuid)
   dptr_closecnum(cnum);
 
   /* execute any "postexec = " line */
-  if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
+  if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid))
     {
       pstring cmd;
       strcpy(cmd,lp_postexec(SNUM(cnum)));
@@ -3923,6 +4186,7 @@ void close_cnum(int cnum, uint16 vuid)
 
   free_namearray(Connections[cnum].veto_list);
   free_namearray(Connections[cnum].hide_list);
+  free_namearray(Connections[cnum].veto_oplock_list);
 
   string_set(&Connections[cnum].user,"");
   string_set(&Connections[cnum].dirpath,"");
@@ -4177,9 +4441,7 @@ void exit_server(char *reason)
 #endif
   }    
 
-#ifdef FAST_SHARE_MODES
-  stop_share_mode_mgmt();
-#endif /* FAST_SHARE_MODES */
+  locking_end();
 
   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
   exit(0);
@@ -4408,14 +4670,15 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
        {
          int cnum = SVAL(inbuf,smb_tid);
          int flags = smb_messages[match].flags;
-         uint16 session_tag = SVAL(inbuf,smb_uid);
+          /* In share mode security we must ignore the vuid. */
+         uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
 
          /* does this protocol need to be run as root? */
          if (!(flags & AS_USER))
            unbecome_user();
 
          /* does this protocol need to be run as the connected user? */
-         if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
+         if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) {
            if (flags & AS_GUEST) 
              flags &= ~AS_USER;
            else
@@ -4588,6 +4851,7 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
 
   chain_size = 0;
   chain_fnum = -1;
+  reset_chain_pnum();
 
   bzero(outbuf,smb_size);
 
@@ -4644,6 +4908,9 @@ static void process(void)
   }
 #endif    
 
+  /* re-initialise the timezone */
+  TimeInit();
+
   while (True)
   {
     int deadtime = lp_deadtime()*60;
@@ -4655,8 +4922,10 @@ static void process(void)
     if (deadtime <= 0)
       deadtime = DEFAULT_SMBD_TIMEOUT;
 
+#if USE_READ_PREDICTION
     if (lp_readprediction())
       do_read_prediction();
+#endif
 
     errno = 0;      
 
@@ -4712,17 +4981,16 @@ static void process(void)
 
       if (keepalive && (counter-last_keepalive)>keepalive) 
       {
-        extern int password_client;
-        if (!send_keepalive(Client))
-        { 
-          DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
-          return;
-        }          
-        /* also send a keepalive to the password server if its still
-           connected */
-        if (password_client != -1)
-          send_keepalive(password_client);
-        last_keepalive = counter;
+             struct cli_state *cli = server_client();
+             if (!send_keepalive(Client)) { 
+                     DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
+                     return;
+             }     
+             /* also send a keepalive to the password server if its still
+                connected */
+             if (cli && cli->initialised)
+                     send_keepalive(cli->fd);
+             last_keepalive = counter;
       }
 
       /* check for connection timeouts */
@@ -4792,6 +5060,14 @@ static void init_structs(void )
       fd_ptr->real_open_flags = -1;
     }
 
+  /* for RPC pipes */
+  init_rpc_pipe_hnd();
+
+#ifdef NTDOMAIN
+  /* for LSA handles */
+  init_lsa_policy_hnd();
+#endif
+
   init_dptrs();
 }
 
@@ -4826,7 +5102,9 @@ static void usage(char *pname)
   int port = SMB_PORT;
   int opt;
   extern char *optarg;
-  char pidFile[100] = { 0 };
+  char pidFile[100];
+
+  *pidFile = '\0';
 
 #ifdef NEED_AUTH_PARAMETERS
   set_auth_parameters(argc,argv);
@@ -4966,7 +5244,18 @@ static void usage(char *pname)
 #ifndef NO_SIGNAL_TEST
   signal(SIGHUP,SIGNAL_CAST sig_hup);
 #endif
-  
+
+  /* Setup the signals that allow the debug log level
+     to by dynamically changed. */
+#if defined(SIGUSR1)
+  signal( SIGUSR1, SIGNAL_CAST sig_usr1 );
+#endif /* SIGUSR1 */
+   
+#if defined(SIGUSR2)
+  signal( SIGUSR2, SIGNAL_CAST sig_usr2 );
+#endif /* SIGUSR2 */
+
   DEBUG(3,("%s loaded services\n",timestring()));
 
   if (!is_daemon && !is_a_socket(0))
@@ -4981,6 +5270,10 @@ static void usage(char *pname)
       become_daemon();
     }
 
+  if (!directory_exist(lp_lockdir(), NULL)) {
+         mkdir(lp_lockdir(), 0755);
+  }
+
   if (*pidFile)
     {
       int     fd;
@@ -5012,10 +5305,8 @@ static void usage(char *pname)
   if (!open_sockets(is_daemon,port))
     exit(1);
 
-#ifdef FAST_SHARE_MODES
-  if (!start_share_mode_mgmt())
+  if (!locking_init(0))
     exit(1);
-#endif /* FAST_SHARE_MODES */
 
   /* possibly reload the services file. */
   reload_services(True);