summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1998-08-14 17:38:29 +0000
committerAndrew Tridgell <tridge@samba.org>1998-08-14 17:38:29 +0000
commitb9623ab59e813131b1ed3f51616a46e719d59c21 (patch)
treea1ba04e55e67ca102b05dd22b024bab9e9d51d57 /source3/lib
parent58fb3c31c03601042fdba71501068fcaea8a821c (diff)
downloadsamba-b9623ab59e813131b1ed3f51616a46e719d59c21.tar.gz
samba-b9623ab59e813131b1ed3f51616a46e719d59c21.tar.bz2
samba-b9623ab59e813131b1ed3f51616a46e719d59c21.zip
this is the bug change to using connection_struct* instead of cnum.
Connections[] is now a local array in server.c I might have broken something with this change. In particular the oplock code is suspect and some .dll files aren't being oplocked when I expected them to be. I'll look at it after I've got some sleep. (This used to be commit c7ee025ead4a85b6fa44a832047b878451845fb6)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/smbrun.c173
-rw-r--r--source3/lib/system.c14
-rw-r--r--source3/lib/util.c92
3 files changed, 269 insertions, 10 deletions
diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c
new file mode 100644
index 0000000000..0388b3f1bd
--- /dev/null
+++ b/source3/lib/smbrun.c
@@ -0,0 +1,173 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ run a command as a specified user
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/* need to move this from here!! need some sleep ... */
+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 privilaged state.
+****************************************************************************/
+static BOOL setup_stdout_file(char *outfile,BOOL shared)
+{
+ int fd;
+ struct stat st;
+ mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH;
+ int flags = O_RDWR|O_CREAT|O_TRUNC|O_EXCL;
+
+ close(1);
+
+ if (shared) {
+ /* become root - unprivilaged users can't delete these files */
+#ifdef HAVE_SETRESUID
+ setresgid(0,0,0);
+ setresuid(0,0,0);
+#else
+ setuid(0);
+ seteuid(0);
+#endif
+ }
+
+ if(stat(outfile, &st) == 0) {
+ /* Check we're not deleting a device file. */
+ if(st.st_mode & S_IFREG)
+ unlink(outfile);
+ else
+ flags = O_RDWR;
+ }
+ /* now create the file */
+ fd = open(outfile,flags,mode);
+
+ if (fd == -1) return False;
+
+ if (fd != 1) {
+ if (dup2(fd,1) != 0) {
+ DEBUG(2,("Failed to create stdout file descriptor\n"));
+ close(fd);
+ return False;
+ }
+ close(fd);
+ }
+ return True;
+}
+
+
+/****************************************************************************
+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
+****************************************************************************/
+int smbrun(char *cmd,char *outfile,BOOL shared)
+{
+ extern struct current_user current_user;
+ int fd,pid;
+ int uid = current_user.uid;
+ int gid = current_user.gid;
+
+#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);
+ }
+
+ slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"",
+ path,uid,gid,cmd,
+ outfile?outfile:"/dev/null");
+
+ DEBUG(5,("smbrun - running %s ",syscmd));
+ ret = system(syscmd);
+ DEBUG(5,("gave %d\n",ret));
+ return(ret);
+#else
+ /* in this newer method we will exec /bin/sh with the correct
+ arguments, after first setting stdout to point at the file */
+
+ if ((pid=fork())) {
+ int status=0;
+ /* the parent just waits for the child to exit */
+ if (sys_waitpid(pid,&status,0) != pid) {
+ DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno)));
+ return -1;
+ }
+ return status;
+ }
+
+
+ /* we are in the child. we exec /bin/sh to do the work for us. we
+ don't directly exec the command we want because it may be a
+ 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);
+ }
+
+ /* now completely lose our privilages. This is a fairly paranoid
+ way of doing it, but it does work on all systems that I know of */
+#ifdef HAVE_SETRESUID
+ setresgid(0,0,0);
+ setresuid(0,0,0);
+ setresgid(gid,gid,gid);
+ setresuid(uid,uid,uid);
+#else
+ setuid(0);
+ seteuid(0);
+ setgid(gid);
+ setegid(gid);
+ setuid(uid);
+ seteuid(uid);
+#endif
+
+ if (getuid() != uid || geteuid() != uid ||
+ getgid() != gid || getegid() != gid) {
+ /* we failed to lose our privilages - do not execute
+ the command */
+ exit(81); /* we can't print stuff at this stage,
+ instead use exit codes for debugging */
+ }
+
+ /* close all other file descriptors, leaving only 0, 1 and 2. 0 and
+ 2 point to /dev/null from the startup code */
+ for (fd=3;fd<256;fd++) close(fd);
+
+ execl("/bin/sh","sh","-c",cmd,NULL);
+
+ /* not reached */
+ exit(82);
+#endif
+ return 1;
+}
diff --git a/source3/lib/system.c b/source3/lib/system.c
index ab65339f6e..255b1c7b49 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -129,7 +129,7 @@ a simple opendir() wrapper
********************************************************************/
DIR *sys_opendir(char *dname)
{
- return(opendir(dos_to_unix(dname,False)));
+ return(opendir(dos_to_unix(dname,False)));
}
@@ -342,15 +342,15 @@ for getwd
********************************************************************/
char *sys_getwd(char *s)
{
- char *wd;
+ char *wd;
#ifdef HAVE_GETCWD
- wd = (char *)getcwd(s, sizeof (pstring));
+ wd = (char *)getcwd(s, sizeof (pstring));
#else
- wd = (char *)getwd(s);
+ wd = (char *)getwd(s);
#endif
- if (wd)
- unix_to_dos (wd, True);
- return wd;
+ if (wd)
+ unix_to_dos(wd, True);
+ return wd;
}
/*******************************************************************
diff --git a/source3/lib/util.c b/source3/lib/util.c
index fb2a6fa119..863e2d94af 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2752,7 +2752,7 @@ static BOOL unix_do_match(char *str, char *regexp, int case_sig)
while(*str) {
while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
str++;
- if(do_match(str,p,case_sig))
+ if(unix_do_match(str,p,case_sig))
return True;
if(!*str)
return False;
@@ -2846,8 +2846,8 @@ static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
}
}
- matched = do_match(sbase,ebase,case_sig) &&
- (trans2 || do_match(sext,eext,case_sig));
+ matched = unix_do_match(sbase,ebase,case_sig) &&
+ (trans2 || unix_do_match(sext,eext,case_sig));
DEBUG(8,("unix_mask_match returning %d\n", matched));
@@ -4134,6 +4134,67 @@ void standard_sub_basic(char *str)
return;
}
+
+/****************************************************************************
+do some standard substitutions in a string
+****************************************************************************/
+void standard_sub(connection_struct *conn,char *str)
+{
+ char *p, *s, *home;
+
+ for (s=str; (p=strchr(s, '%'));s=p) {
+ switch (*(p+1)) {
+ case 'H':
+ if ((home = get_home_dir(conn->user))) {
+ string_sub(p,"%H",home);
+ } else {
+ p += 2;
+ }
+ break;
+
+ case 'P':
+ string_sub(p,"%P",conn->connectpath);
+ break;
+
+ case 'S':
+ string_sub(p,"%S",
+ lp_servicename(SNUM(conn)));
+ break;
+
+ case 'g':
+ string_sub(p,"%g",
+ gidtoname(conn->gid));
+ break;
+ case 'u':
+ string_sub(p,"%u",conn->user);
+ break;
+
+ /* Patch from jkf@soton.ac.uk Left the %N (NIS
+ * server name) in standard_sub_basic as it is
+ * a feature for logon servers, hence uses the
+ * username. The %p (NIS server path) code is
+ * here as it is used instead of the default
+ * "path =" string in [homes] and so needs the
+ * service name, not the username. */
+ case 'p':
+ string_sub(p,"%p",
+ automount_path(lp_servicename(SNUM(conn))));
+ break;
+ case '\0':
+ p++;
+ break; /* don't run off the end of the string
+ */
+
+ default: p+=2;
+ break;
+ }
+ }
+
+ standard_sub_basic(str);
+}
+
+
+
/*******************************************************************
are two IPs on the same subnet?
********************************************************************/
@@ -5064,3 +5125,28 @@ BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
return True;
}
+
+/*****************************************************************************
+ * Provide a checksum on a string
+ *
+ * Input: s - the nul-terminated character string for which the checksum
+ * will be calculated.
+ *
+ * Output: The checksum value calculated for s.
+ *
+ * ****************************************************************************
+ */
+int str_checksum(char *s)
+{
+ int res = 0;
+ int c;
+ int i=0;
+
+ while(*s) {
+ c = *s;
+ res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
+ s++;
+ i++;
+ }
+ return(res);
+} /* str_checksum */