summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/smbrun.c116
-rw-r--r--source3/lib/util.c5
-rw-r--r--source3/lib/util_file.c52
3 files changed, 96 insertions, 77 deletions
diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c
index e039f222fc..a543ff5eee 100644
--- a/source3/lib/smbrun.c
+++ b/source3/lib/smbrun.c
@@ -27,54 +27,41 @@ struct current_user current_user;
extern int DEBUGLEVEL;
/****************************************************************************
-This is a utility function of smbrun(). It must be called only from
-the child as it may leave the caller in a privileged state.
+This is a utility function of smbrun().
****************************************************************************/
-static BOOL setup_stdout_file(char *outfile,BOOL shared)
-{
- int fd;
- mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH;
- int flags = O_RDWR|O_CREAT|O_EXCL;
- close(1);
+static BOOL setup_out_fd(char *template)
+{
+ int fd;
+ pstring path;
- if (shared) {
- /* become root - unprivileged users can't delete these files */
- gain_root_privilege();
- gain_root_group_privilege();
- }
+ pstrcpy( path, template);
+ pstrcat( path, generate_random_str(17));
+ pstrcat( path, ".XXXXXX");
- unlink(outfile);
+ /* now create the file */
+ fd = smb_mkstemp(path);
- /* now create the file */
- fd = sys_open(outfile,flags,mode);
+ if (fd == -1) {
+ DEBUG(0,("setup_out_fd: Failed to create file %s. (%s)\n",
+ path, strerror(errno) ));
+ return -1;
+ }
- if (fd == -1) return False;
+ DEBUG(10,("setup_out_fd: Created tmp file %s\n", path ));
- if (fd != 1) {
- if (dup2(fd,1) != 1) {
- DEBUG(2,("Failed to create stdout file descriptor\n"));
- close(fd);
- return False;
- }
- close(fd);
- }
- return True;
+ /* Ensure file only kept around by open fd. */
+ unlink(path);
+ return fd;
}
-
/****************************************************************************
run a command being careful about uid/gid handling and putting the output in
-outfile (or discard it if outfile is NULL).
-
-if shared is True then ensure the file will be writeable by all users
-but created such that its owned by root. This overcomes a security hole.
-
-if shared is not set then open the file with O_EXCL set
+outfd (or discard it if outfd is NULL).
****************************************************************************/
-int smbrun(char *cmd,char *outfile,BOOL shared)
+
+int smbrun(char *cmd, int *outfd, char *template)
{
- int fd;
pid_t pid;
uid_t uid = current_user.uid;
gid_t gid = current_user.gid;
@@ -84,32 +71,13 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
*/
oplock_set_capability(False, False);
-#ifndef HAVE_EXECL
- {
- int ret;
- pstring syscmd;
- char *path = lp_smbrun();
-
- /* in the old method we use system() to execute smbrun which then
- executes the command (using system() again!). This involves lots
- of shell launches and is very slow. It also suffers from a
- potential security hole */
- if (!file_exist(path,NULL)) {
- DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",path));
- return(1);
- }
+ /* point our stdout at the file we want output to go into */
- slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"",
- path,(int)uid,(int)gid,cmd,
- outfile?outfile:"/dev/null");
-
- DEBUG(5,("smbrun - running %s ",syscmd));
- ret = system(syscmd);
- DEBUG(5,("gave %d\n",ret));
- return(ret);
+ if (outfd && ((*outfd = setup_out_fd(template)) == -1)) {
+ return -1;
}
-#else
- /* in this newer method we will exec /bin/sh with the correct
+
+ /* in this method we will exec /bin/sh with the correct
arguments, after first setting stdout to point at the file */
/*
@@ -122,6 +90,10 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
if ((pid=sys_fork()) < 0) {
DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) ));
CatchChild();
+ if (outfd) {
+ close(*outfd);
+ *outfd = -1;
+ }
return errno;
}
@@ -146,13 +118,24 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
if (wpid != pid) {
DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno)));
+ if (outfd) {
+ close(*outfd);
+ *outfd = -1;
+ }
return -1;
}
+
+ /* Reset the seek pointer. */
+ if (outfd) {
+ sys_lseek(*outfd, 0, SEEK_SET);
+ }
+
#if defined(WIFEXITED) && defined(WEXITSTATUS)
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
}
#endif
+
return status;
}
@@ -163,10 +146,15 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
pipeline or anything else the config file specifies */
/* point our stdout at the file we want output to go into */
- if (outfile && !setup_stdout_file(outfile,shared)) {
- exit(80);
+ if (outfd) {
+ close(1);
+ if (dup2(*outfd,1) != 1) {
+ DEBUG(2,("Failed to create stdout file descriptor\n"));
+ close(*outfd);
+ exit(80);
+ }
}
-
+
/* now completely lose our privileges. This is a fairly paranoid
way of doing it, but it does work on all systems that I know of */
@@ -183,13 +171,15 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
#ifndef __INSURE__
/* close all other file descriptors, leaving only 0, 1 and 2. 0 and
2 point to /dev/null from the startup code */
+ {
+ int fd;
for (fd=3;fd<256;fd++) close(fd);
+ }
#endif
execl("/bin/sh","sh","-c",cmd,NULL);
/* not reached */
exit(82);
-#endif
return 1;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 42a9617077..506a0334d1 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -1752,8 +1752,9 @@ int smb_mkstemp(char *template)
#else
/* have a reasonable go at emulating it. Hope that
the system mktemp() isn't completly hopeless */
- if (!mktemp(template)) return -1;
- return open(template, O_CREAT|O_EXCL|O_RDWR, 0600);
+ char *p = smbd_mktemp(template);
+ if (!p) return -1;
+ return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
#endif
}
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 023f3e131c..4e2adc97bc 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -368,21 +368,15 @@ char *file_pload(char *syscmd, size_t *size)
return p;
}
-
/****************************************************************************
-load a file into memory
-****************************************************************************/
-char *file_load(char *fname, size_t *size)
+load a file into memory from a fd.
+****************************************************************************/
+
+char *fd_load(int fd, size_t *size)
{
- int fd;
SMB_STRUCT_STAT sbuf;
char *p;
- if (!fname || !*fname) return NULL;
-
- fd = open(fname,O_RDONLY);
- if (fd == -1) return NULL;
-
if (sys_fstat(fd, &sbuf) != 0) return NULL;
p = (char *)malloc(sbuf.st_size+1);
@@ -394,13 +388,31 @@ char *file_load(char *fname, size_t *size)
}
p[sbuf.st_size] = 0;
- close(fd);
-
if (size) *size = sbuf.st_size;
return p;
}
+/****************************************************************************
+load a file into memory
+****************************************************************************/
+char *file_load(char *fname, size_t *size)
+{
+ int fd;
+ char *p;
+
+ if (!fname || !*fname) return NULL;
+
+ fd = open(fname,O_RDONLY);
+ if (fd == -1) return NULL;
+
+ p = fd_load(fd, size);
+
+ close(fd);
+
+ return p;
+}
+
/****************************************************************************
parse a buffer into lines
@@ -459,6 +471,22 @@ char **file_lines_load(char *fname, int *numlines, BOOL convert)
return file_lines_parse(p, size, numlines, convert);
}
+/****************************************************************************
+load a fd into memory and return an array of pointers to lines in the file
+must be freed with file_lines_free(). If convert is true calls unix_to_dos on
+the list.
+****************************************************************************/
+char **fd_lines_load(int fd, int *numlines, BOOL convert)
+{
+ char *p;
+ size_t size;
+
+ p = fd_load(fd, &size);
+ if (!p) return NULL;
+
+ return file_lines_parse(p, size, numlines, convert);
+}
+
/****************************************************************************
load a pipe into memory and return an array of pointers to lines in the data