diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/ipc.c | 4 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 26 | ||||
-rw-r--r-- | source3/smbd/server.c | 16 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 4 | ||||
-rw-r--r-- | source3/smbd/uid.c | 74 |
6 files changed, 106 insertions, 22 deletions
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index c29e8656b1..142f139d26 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -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; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index bf53fa84bc..8c7e6c69c5 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -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)); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dffb6f05bd..56288df073 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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); } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1c31f69389..be24ad7781 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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); } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a56df9cb9c..e484b3b2e1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -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)); } diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 78614a5b5c..42ade7e4da 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -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; +} |