summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/ipc.c4
-rw-r--r--source3/smbd/pipes.c4
-rw-r--r--source3/smbd/reply.c26
-rw-r--r--source3/smbd/server.c16
-rw-r--r--source3/smbd/trans2.c4
-rw-r--r--source3/smbd/uid.c74
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;
+}