nttrans.c: Fix change_notify. Queue processing code wasn't changing to
authorJeremy Allison <jra@samba.org>
Tue, 4 Aug 1998 23:45:34 +0000 (23:45 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 4 Aug 1998 23:45:34 +0000 (23:45 +0000)
           the correct directory before doing the stat. Doh !
uid.c: Fix for performance in security=share mode. Invalid vuid meant
       that in security=share mode Samba was always doing the become_user/
       undebome_user pairs for *every* smb. This code fixes it, but tridge
       should review for security implications.
Jeremy.

source/smbd/nttrans.c
source/smbd/uid.c

index a30da8e6e03d358dd2347f8a62ca43a0a1c31cf9..1f724a4bfbdf70c2932aebe98515fa922868dc4e 100644 (file)
@@ -1071,6 +1071,19 @@ void process_pending_change_notify_queue(time_t t)
       continue;
     }
 
+    if(!become_service(cnum,True)) {
+      DEBUG(0,("process_pending_change_notify_queue: Unable to become service cnum=%d. \
+Error was %s.\n", cnum, strerror(errno) ));
+      /*
+       * Remove the entry and return an error to the client.
+       */
+      change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess);
+      ubi_slRemNext( &change_notify_queue, prev);
+      cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
+      unbecome_user();
+      continue;
+    }
+
     if(sys_stat(fsp->name, &st) < 0) {
       DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \
 Error was %s.\n", fsp->name, strerror(errno) ));
@@ -1135,27 +1148,39 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length,
   if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum))
     return(ERROR(ERRDOS,ERRbadfid));
 
-  /*
-   * Setup the current directory information in the
-   * directory entry in the files_struct. We will use
-   * this to check against when the timer expires.
-   */
-
-  if(sys_stat(fsp->name, &st) < 0) {
-                       DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \
-               Error was %s\n", fnum, fsp->name, strerror(errno) ));
-                       return -1;
-  }
   if(fsp->f_u.dir_ptr == NULL) {
+
+    /*
+     * No currently stored directory info - we must
+     * generate it here.
+     */
+
     if((fsp->f_u.dir_ptr = (dir_status_struct *)malloc(sizeof(dir_status_struct))) == NULL) {
       DEBUG(0,("call_nt_transact_notify_change: Malloc fail !\n" ));
       return -1;
     }
-  }
 
-  fsp->f_u.dir_ptr->modify_time = st.st_mtime;
-  fsp->f_u.dir_ptr->status_time = st.st_ctime;
+    /*
+     * Setup the current directory information in the
+     * directory entry in the files_struct. We will use
+     * this to check against when the timer expires.
+     * NB. We only do this if there is no current directory
+     * information in the directory struct - as when we start
+     * monitoring file size etc. this information will start
+     * becoming increasingly expensive to maintain, so we won't
+     * want to re-generate it for every ChangeNofity call.
+     */
+
+    if(sys_stat(fsp->name, &st) < 0) {
+      DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \
+Error was %s\n", fnum, fsp->name, strerror(errno) ));
+      return -1;
+    }
+    fsp->f_u.dir_ptr->modify_time = st.st_mtime;
+    fsp->f_u.dir_ptr->status_time = st.st_ctime;
+
+  }
 
   /*
    * Now queue an entry on the notify change stack. We timestamp
@@ -1183,8 +1208,8 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length,
 
   ubi_slAddTail(&change_notify_queue, cnbp);
 
-  DEBUG(3,("call_nt_transact_notify_change: notify change called on directory fid=%d, name = %s\n",
-        fnum, fsp->name ));
+  DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \
+fid=%d, name = %s\n", fnum, fsp->name ));
 
   return -1;
 }
index 82ff7ee7cea67d443880f3b6467707ed145bf7dd..9e669c301b904e0231bcc2198e83dc34ac2c15c3 100644 (file)
@@ -216,7 +216,18 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
   int snum,gid;
   int uid;
 
-  if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && 
+  /*
+   * We need a separate check in security=share mode due to vuid
+   * always being UID_FIELD_INVALID. If we don't do this then
+   * in share mode security we are *always* changing uid's between
+   * SMB's - this hurts performance - Badly.
+   */
+
+  if((lp_security() == SEC_SHARE) && (current_user.cnum == cnum) &&
+     (current_user.uid == conn->uid)) {
+    DEBUG(4,("Skipping become_user - already user\n"));
+    return(True);
+  } else if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) && 
       (current_user.uid == vuser->uid)) {
     DEBUG(4,("Skipping become_user - already user\n"));
     return(True);