ipc.c: Adding Andrews become_root code to the main branch.
authorJeremy Allison <jra@samba.org>
Wed, 15 Oct 1997 21:53:59 +0000 (21:53 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 15 Oct 1997 21:53:59 +0000 (21:53 +0000)
locking.c: Adding Andrews become_root code to the main branch.
pipes.c: Fixing the close_file issue.
proto.h: The usual.
reply.c: Move smb_pass into NTDOMAIN defined code. Fixing the close_file issue.
server.c: Fixing the close_file issue.
trans2.c: Fixing the close_file issue.
uid.c: Adding Andrews become_root code to the main branch.
Jeremy (jallison@whistle.com)

source/include/proto.h
source/locking/locking.c
source/smbd/ipc.c
source/smbd/pipes.c
source/smbd/reply.c
source/smbd/server.c
source/smbd/trans2.c
source/smbd/uid.c

index 70a9873d34043c2ab674f1ab63ea5a8674a39551..85ef0943400d77a36e23e29af5fc9d7d95ad326d 100644 (file)
@@ -776,7 +776,7 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize);
 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);
+void close_file(int fnum, BOOL normal_close);
 BOOL check_file_sharing(int cnum,char *fname);
 int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
                       BOOL fcbopen, int *flags);
@@ -957,6 +957,8 @@ BOOL become_guest(void);
 BOOL become_user(int cnum, uint16 vuid);
 BOOL unbecome_user(void );
 int smbrun(char *cmd,char *outfile,BOOL shared);
+void become_root(BOOL save_dir) ;
+void unbecome_root(BOOL restore_dir);
 
 /*The following definitions come from  username.c  */
 
index 04c198afeac8c5505347768e0c384c9fcfa9db07..5071121bed0fd41db7f95ec665b975d9bb4a886f 100644 (file)
@@ -729,10 +729,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok
   if(!share_name(cnum, dev, inode, fname))
     return False;
 
+  /* we need to do this as root */
+  become_root(False);
+
   {
     int old_umask;
     BOOL gotlock = False;
-    unbecome_user();
     old_umask = umask(0);
 
     /*
@@ -801,23 +803,13 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok
      */
 
     umask(old_umask);
-    if(!become_user(cnum,Connections[cnum].vuid))
-    {
-      DEBUG(0,("lock_share_entry: Can't become connected user!\n"));
-      close(fd);
-      ret = False;
-    }
-    /* We need to change directory back to the connection root. */
-    if (ChDir(Connections[cnum].connectpath) != 0)
-    {
-      DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n",
-              Connections[cnum].connectpath, strerror(errno)));
-      close(fd);
-      ret = False;  
-    }
   }
 
   *ptok = (share_lock_token)fd;
+
+  /* return to our previous privilage level */
+  unbecome_root(False);
+
   return ret;
 }
 
@@ -848,27 +840,22 @@ Force a share file to be deleted.
 
 static int delete_share_file( int cnum, char *fname )
 {
-  unbecome_user();
+  /* the share file could be owned by anyone, so do this as root */
+  become_root(False);
+
   if(unlink(fname) != 0)
   {
     DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
             fname, strerror(errno)));
+  } 
+  else 
+  {
+    DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
   }
 
-  DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
+  /* return to our previous privilage level */
+  unbecome_root(False);
 
-  if(!become_user(cnum,Connections[cnum].vuid))
-  {
-    DEBUG(0,("delete_share_file: Can't become connected user!\n"));
-    return -1;
-  }
-  /* We need to change directory back to the connection root. */
-  if (ChDir(Connections[cnum].connectpath) != 0)
-  {
-    DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n",
-            Connections[cnum].connectpath, strerror(errno)));
-    return -1;  
-  }
   return 0;
 }
 
index c29e8656b17934a93f4c12f8bd82767bfb17716f..142f139d2609efbae7691f40b08059510495ed7c 100644 (file)
@@ -1602,6 +1602,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
        
        DEBUG(3,("Setting print name to %s\n",name));
        
+        become_root(True);
+
        for (i=0;i<MAX_OPEN_FILES;i++)
          if (Files[i].open && Files[i].print_file)
            {
@@ -1617,6 +1619,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
                string_set(&Files[i].name,name);
              break;
            }
+
+         unbecome_root(True);
       }
     desc.errcode=NERR_Success;
   
index bf53fa84bc25ff0fb5d7584a5f033919a474d648..8c7e6c69c5cc90315b287074ef5064de32528dfa 100644 (file)
@@ -147,7 +147,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   }
 
   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -155,7 +155,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   fmode = dos_mode(cnum,fname,&sbuf);
   mtime = sbuf.st_mtime;
   if (fmode & aDIR) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
index dffb6f05bd44fdc8391af5141c82fb701cb15ce8..56288df073919609e20db501d300c0aacbc5f5ac 100644 (file)
@@ -479,8 +479,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   /* computer with that name (minus the $) has access. For now */
   /* say yes to everything ending in $. */
   if (user[strlen(user) - 1] == '$') {
-    struct smb_passwd *smb_pass; /* To check if machine account exists */
 #ifdef NTDOMAIN
+    struct smb_passwd *smb_pass; /* To check if machine account exists */
 /* 
    PAXX: Ack. We don't want to do this. The workstation trust account
    with a $ on the end should exist in the local password database
@@ -1178,7 +1178,7 @@ int reply_open(char *inbuf,char *outbuf)
   }
 
   if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
     
@@ -1188,7 +1188,7 @@ int reply_open(char *inbuf,char *outbuf)
 
   if (fmode & aDIR) {
     DEBUG(3,("attempt to open a directory %s\n",fname));
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
   
@@ -1274,7 +1274,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   }
 
   if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1282,7 +1282,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   fmode = dos_mode(cnum,fname,&sbuf);
   mtime = sbuf.st_mtime;
   if (fmode & aDIR) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1328,7 +1328,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
     int i;
     for (i=0;i<MAX_OPEN_FILES;i++)
       if (Files[i].uid == vuser->uid && Files[i].open) {
-       close_file(i);
+       close_file(i,False);
       }
   }
 
@@ -2271,7 +2271,7 @@ int reply_close(char *inbuf,char *outbuf)
   /* try and set the date */
   set_filetime(Files[fnum].name,mtime);
 
-  close_file(fnum);
+  close_file(fnum,True);
 
   /* We have a cached error */
   if(eclass || err)
@@ -2318,7 +2318,7 @@ int reply_writeclose(char *inbuf,char *outbuf)
 
   set_filetime(Files[fnum].name,mtime);
   
-  close_file(fnum);
+  close_file(fnum,True);
 
   DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
           timestring(),fnum,cnum,numtowrite,nwritten,
@@ -2550,7 +2550,7 @@ int reply_printclose(char *inbuf,char *outbuf)
   if (!CAN_PRINT(cnum))
     return(ERROR(ERRDOS,ERRnoaccess));
   
-  close_file(fnum);
+  close_file(fnum,True);
   
   DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
   
@@ -3187,14 +3187,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
 
   fnum2 = find_free_file();
   if (fnum2<0) {
-    close_file(fnum1);
+    close_file(fnum1,False);
     return(False);
   }
   open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
                   ofun,st.st_mode,0,&Access,&action);
 
   if (!Files[fnum2].open) {
-    close_file(fnum1);
+    close_file(fnum1,False);
     return(False);
   }
 
@@ -3205,8 +3205,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
   if (st.st_size)
     ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
 
-  close_file(fnum1);
-  close_file(fnum2);
+  close_file(fnum1,False);
+  close_file(fnum2,False);
 
   return(ret == st.st_size);
 }
index 1c31f69389db69869e93b004d4653d870b306625..be24ad7781a309a131ba5971f0e122063ca21d20 100644 (file)
@@ -1361,8 +1361,13 @@ static void check_magic(int fnum,int cnum)
 
 /****************************************************************************
 close a file - possibly invalidating the read prediction
+
+If normal_close is 1 then this came from a normal SMBclose (or equivalent)
+operation otherwise it came as the result of some other operation such as
+the closing of the connection. In the latter case printing and
+magic scripts are not run
 ****************************************************************************/
-void close_file(int fnum)
+void close_file(int fnum, BOOL normal_close)
 {
   files_struct *fs_p = &Files[fnum];
   int cnum = fs_p->cnum;
@@ -1399,11 +1404,12 @@ void close_file(int fnum)
     unlock_share_entry( cnum, dev, inode, token);
 
   /* NT uses smbclose to start a print - weird */
-  if (fs_p->print_file)
+  if (normal_close && fs_p->print_file)
     print_file(fnum);
 
   /* check for magic scripts */
-  check_magic(fnum,cnum);
+  if (normal_close)
+    check_magic(fnum,cnum);
 
   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
           timestring(),Connections[cnum].user,fs_p->name,
@@ -1575,7 +1581,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
       if (*share_locked && lp_share_modes(SNUM(cnum)))
         unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, 
                             Files[fnum].fd_ptr->inode, token);
-      close_file(fnum);   
+      close_file(fnum,False);   
       /* Share mode no longer locked. */
       *share_locked = False;
       errno = EACCES;
@@ -3847,7 +3853,7 @@ static void close_open_files(int cnum)
   int i;
   for (i=0;i<MAX_OPEN_FILES;i++)
     if( Files[i].cnum == cnum && Files[i].open) {
-      close_file(i);
+      close_file(i,False);
     }
 }
 
index a56df9cb9cc68f03a4ed6017eb289f8bf4a2c4fe..e484b3b2e1a767eaa6a8cff4132c65a88b39b72c 100644 (file)
@@ -226,7 +226,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
   }
 
   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
     
@@ -235,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
   mtime = sbuf.st_mtime;
   inode = sbuf.st_ino;
   if (fmode & aDIR) {
-    close_file(fnum);
+    close_file(fnum,False);
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
index 78614a5b5c49ca3f942672bdac8419e8790454ca..42ade7e4da1f075c9b183d70064df7337c93d8c9 100644 (file)
@@ -481,3 +481,77 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
 #endif
   return 1;
 }
+
+static struct current_user current_user_saved;
+static int become_root_depth;
+static pstring become_root_dir;
+
+/****************************************************************************
+This is used when we need to do a privilaged operation (such as mucking
+with share mode files) and temporarily need root access to do it. This
+call should always be paired with an unbecome_root() call immediately
+after the operation
+
+Set save_dir if you also need to save/restore the CWD 
+****************************************************************************/
+void become_root(BOOL save_dir) 
+{
+       if (become_root_depth) {
+               DEBUG(0,("ERROR: become root depth is non zero\n"));
+       }
+       if (save_dir)
+               GetWd(become_root_dir);
+
+       current_user_saved = current_user;
+       become_root_depth = 1;
+
+       become_gid(0);
+       become_uid(0);
+}
+
+/****************************************************************************
+When the privilaged operation is over call this
+
+Set save_dir if you also need to save/restore the CWD 
+****************************************************************************/
+void unbecome_root(BOOL restore_dir)
+{
+       if (become_root_depth != 1) {
+               DEBUG(0,("ERROR: unbecome root depth is %d\n",
+                        become_root_depth));
+       }
+
+       /* we might have done a become_user() while running as root,
+          if we have then become root again in order to become 
+          non root! */
+       if (current_user.uid != 0) {
+               become_uid(0);
+       }
+
+       /* restore our gid first */
+       if (!become_gid(current_user_saved.gid)) {
+               DEBUG(0,("ERROR: Failed to restore gid\n"));
+               exit_server("Failed to restore gid");
+       }
+
+#ifndef NO_SETGROUPS      
+       if (current_user_saved.ngroups > 0) {
+               if (setgroups(current_user_saved.ngroups,
+                             current_user_saved.groups)<0)
+                       DEBUG(0,("ERROR: setgroups call failed!\n"));
+       }
+#endif
+
+       /* now restore our uid */
+       if (!become_uid(current_user_saved.uid)) {
+               DEBUG(0,("ERROR: Failed to restore uid\n"));
+               exit_server("Failed to restore uid");
+       }
+
+       if (restore_dir)
+               ChDir(become_root_dir);
+
+       current_user = current_user_saved;
+
+       become_root_depth = 0;
+}