diff options
author | Andrew Tridgell <tridge@samba.org> | 1998-08-14 17:38:29 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1998-08-14 17:38:29 +0000 |
commit | b9623ab59e813131b1ed3f51616a46e719d59c21 (patch) | |
tree | a1ba04e55e67ca102b05dd22b024bab9e9d51d57 /source3/lib | |
parent | 58fb3c31c03601042fdba71501068fcaea8a821c (diff) | |
download | samba-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.c | 173 | ||||
-rw-r--r-- | source3/lib/system.c | 14 | ||||
-rw-r--r-- | source3/lib/util.c | 92 |
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 */ |