diff options
author | Andrew Tridgell <tridge@samba.org> | 1998-07-29 03:08:05 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1998-07-29 03:08:05 +0000 |
commit | 64578c0589a3a741f81fb55c16eeb882128da00b (patch) | |
tree | 8b650156e44e4d39af8625185d857a88789b8074 /source3/smbd/uid.c | |
parent | c48b3fce6be6d5d952cbcda0ddae223dda5a576f (diff) | |
download | samba-64578c0589a3a741f81fb55c16eeb882128da00b.tar.gz samba-64578c0589a3a741f81fb55c16eeb882128da00b.tar.bz2 samba-64578c0589a3a741f81fb55c16eeb882128da00b.zip |
merge from the autoconf2 branch to the main branch
(This used to be commit 3bda7ac417107a7b01d91805ca71c4330657ed21)
Diffstat (limited to 'source3/smbd/uid.c')
-rw-r--r-- | source3/smbd/uid.c | 279 |
1 files changed, 75 insertions, 204 deletions
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 2a75b660b5..a8e0bf0d03 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -36,26 +36,25 @@ initialise the uid routines ****************************************************************************/ void init_uid(void) { - initial_uid = current_user.uid = geteuid(); - initial_gid = current_user.gid = getegid(); + initial_uid = current_user.uid = geteuid(); + initial_gid = current_user.gid = getegid(); - if (initial_gid != 0 && initial_uid == 0) - { -#ifdef HPUX - setresgid(0,0,0); + if (initial_gid != 0 && initial_uid == 0) { +#ifdef HAVE_SETRESUID + setresgid(0,0,0); #else - setgid(0); - setegid(0); + setgid(0); + setegid(0); #endif - } - - initial_uid = geteuid(); - initial_gid = getegid(); + } - current_user.cnum = -1; - current_user.vuid = UID_FIELD_INVALID; + initial_uid = geteuid(); + initial_gid = getegid(); - ChDir(OriginalDir); + current_user.cnum = -1; + current_user.vuid = UID_FIELD_INVALID; + + ChDir(OriginalDir); } @@ -64,141 +63,33 @@ void init_uid(void) ****************************************************************************/ static BOOL become_uid(int uid) { - if (initial_uid != 0) - return(True); - - if (uid == -1 || uid == 65535) { - DEBUG(1,("WARNING: using uid %d is a security risk\n",uid)); - } - -#ifdef AIX - { - /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */ - /* MWW: This is all undocumented, of course. There's a patch to WU-ftpd - in the AIX FAQ which does the setpriv, then sets the gid stuff, then - sets uid. Since Samba separates setting the gid and setting the uid, - I've duplicated the setpriv code in become_gid. I've also made the - requisite changes to become_gid to match the WU-ftpd patch. - - I believe we'll still get errors in the Samba logs. This setpriv - call is supposed to disable "trapdooring" on AIX - ie. normally - once a seteuid / setegid is done, the effective ID can't be set back - to what it was before. See the comments in become_root / unbecome_root. - I *think* that we may have to do something additional here to prevent - the "Can't set uid (AIX3)" messages, though - possibly change the - values of priv.pv_priv to keep the SET_PROC_DAC privilege, and - possibly SET_OBJ_DAC and SET_OBJ_STAT as well. - - The pv_priv array is two longwords, and the constants in sys/priv.h - have values between 1 and 64, according to the comments in priv.h. - This strongly suggests a bit vector - but does BYPASS_DAC_WRITE - (#define'd to 1) mean 1<<0 or 1<<1? Unfortunately, nothing's - defined to 0 or 64, which would be a dead giveaway. Also, what's the - fullword-boundary endianness? That is, is pv_priv[0] the high or - the low 32 bits? Fortunately, the values used by "su" (see below) - don't make much sense if pv_priv[0] is the high bits. Also, based - on analysis of the values used by su, I concluded that, for example, - BYPASS_DAC_READ (defined to 2) is bit "2" counting from 1 - ie. - if (pv_priv[0] & (1 << (BYPASS_DAC_READ - 1))) then BYPASS_DAC_READ - is on. That's a bit odd, but it makes more sense than if the - privilege constants are meant to be taken as exponents of 2. - - For analysis, I ran "su" as root under dbx, and stopped in setpriv. - The first argument to setpriv can be examined using - - print $r3 (eg. "0x30009" = PRIV_SET|PRIV_MAXIMUM|PRIV_EFFECTIV) - - the contents of the pv_priv array can be examined using - - ($r4)/2X - - Here's what su does: - - setpriv(PRIV_SET | PRIV_INHERITED | PRIV_BEQUEATH, {0,0}) - setpriv(PRIV_SET | PRIV_EFFECTIVE | PRIV_MAXIMUM, - {0x02800006, 0x00040000}) - 0x02800006 = SET_PROC_AUDIT | SET_PROC_ENV | - BYPASS_DAC_EXEC | BYPASS_DAC_READ - 0x00040000 = TPATH_CONFIG - setpriv(PRIV_SET | PRIV_EFFECTIVE, {0, 0}) - - Analysis: - - Reduce inherited privileges to none, so the child doesn't inherit - anything special. - Change su's privileges so it can execute the shell even if someone - has goofed up the permissions to it or to directories on the - search path; so it can set the process auditing characteristics - and privileged environment (stuff in /etc/security/environ with - the sysenv attribute); and so that it can set the trusted path - characteristics for this login. - Zap those privileges back off when we don't need them any more. - - I'm guessing we want to keep SET_PROC_DAC in the current priv set, - but not in the inherited one. That is, set PRIV_INHERITED and - PRIV_BEQUEATH to 0. We also probably want to set PRIV_MAXIMUM and - PRIV_EFFECTIVE to only the privs we need, which at this point would - appear to be just SET_PROC_DAC. *Note*: setting PRIV_MAXIMUM - with any of the privilege sets higher than what you're trying to - set the maximum to will produce an EINVAL. For example, if we - try to set PRIV_MAXIMUM to SET_PROC_DAC *before* we reduce - PRIV_INHERITED and PRIV_BEQUEATH, it won't work. Zero out the - inherited privileges first. - - Some experimentation with simple programs confirms that if we're - running with an EUID of 0 we can switch our UID/EUID back and - forth with setuidx - *unless* we call setpriv({0,0}, ...) first. - In other words, by default root has SET_PROC_DAT set, but we can - remove it from our privilege set. This is what we want to do for - child processes, I believe. - - Also, calling setpriv(PRIV_SUB|PRIV_EFFECTIVE,...) with pv_priv[0] - set to SET_PROC_DAC (1 << (SET_PROC_DAC - 1)) will prevent an - EUID-root process from switching its EUID back with setuidx. - - In other words, setuidx on AIX is *not* trapdoor. setuid is - trapdoor. We need a non-trapdoor setuid function, but we don't - want processes we fork to have access to it. Thus we use setuidx - but first we disable it for our children. - - Note, however, that we can only increase our privileges (as we - do in the first call to setpriv) if we're EUID-root. If we - started out as root, and then switched to a non-root user ID, - that's OK; we've already set them. Just don't try to set them - again. - - Also, I suspect that after using setpriv / setuidx / etc. here in - the AIX-specific code we DON'T want to fall through to the code that - calls setuid, etc. However, I haven't noticed any more problems with - the code the way it is here. - */ - - priv_t priv; - - priv.pv_priv[0] = 0; - priv.pv_priv[1] = 0; - if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_BEQUEATH, - &priv, sizeof(priv_t)) < 0) { - DEBUG(1, ("Can't set child privileges (AIX3): %s\n", strerror(errno))); - } - - priv.pv_priv[0] = (1 << (SET_PROC_DAC - 1)); - if (setpriv(PRIV_SET|PRIV_EFFECTIVE|PRIV_MAXIMUM, - &priv, sizeof(priv_t)) < 0) { - DEBUG(1, ("Can't set own privileges (AIX3): %s\n", strerror(errno))); - } + if (initial_uid != 0) { + return(True); + } + + if (uid == -1 || uid == 65535) { + static int done; + if (!done) { + DEBUG(1,("WARNING: using uid %d is a security risk\n", + uid)); + done=1; + } + } - if (setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 || - seteuid((uid_t)uid) < 0) { - DEBUG(1,("Can't set uid (AIX3)\n")); - } - } +#ifdef HAVE_TRAPDOOR_UID +#ifdef HAVE_SETUIDX + /* AIX3 has setuidx which is NOT a trapoor function (tridge) */ + if (setuidx(ID_EFFECTIVE, (uid_t)uid) != 0) { + if (seteuid((uid_t)uid) != 0) { + DEBUG(1,("Can't set uid (setuidx)\n")); + return False; + } + } +#endif #endif -#ifdef USE_SETRES - if (setresuid(-1,uid,-1) != 0) -#elif defined(USE_SETFS) - if (setfsuid(uid) != 0) +#ifdef HAVE_SETRESUID + if (setresuid(-1,uid,-1) != 0) #else if ((seteuid(uid) != 0) && (setuid(uid) != 0)) @@ -206,19 +97,20 @@ static BOOL become_uid(int uid) { DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n", uid,getuid(), geteuid())); - if (uid > 32000) - DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); + if (uid > 32000) { + DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); + } return(False); } - if (((uid == -1) || (uid == 65535)) && geteuid() != uid) { - DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); - return(False); - } + if (((uid == -1) || (uid == 65535)) && geteuid() != uid) { + DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); + return(False); + } - current_user.uid = uid; + current_user.uid = uid; - return(True); + return(True); } @@ -234,36 +126,17 @@ static BOOL become_gid(int gid) DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); } -#ifdef AIX - { - /* MWW: See comment above in become_uid. */ - priv_t priv; - - priv.pv_priv[0] = 0; - priv.pv_priv[1] = 0; - if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH, - &priv, sizeof(priv_t)) < 0) { - DEBUG(1, ("Can't set privilege (AIX3)\n")); - } - if (setgidx(ID_REAL|ID_EFFECTIVE, (gid_t)gid) < 0 || - setegid((gid_t)gid) < 0) { - DEBUG(1,("Can't set gid (AIX3)\n")); - } - } -#endif - -#ifdef USE_SETRES +#ifdef HAVE_SETRESUID if (setresgid(-1,gid,-1) != 0) -#elif defined(USE_SETFS) - if (setfsgid(gid) != 0) #else if (setgid(gid) != 0) #endif { DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n", gid,getgid(),getegid())); - if (gid > 32000) - DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); + if (gid > 32000) { + DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); + } return(False); } @@ -278,7 +151,7 @@ static BOOL become_gid(int gid) ****************************************************************************/ static BOOL become_id(int uid,int gid) { - return(become_gid(gid) && become_uid(uid)); + return(become_gid(gid) && become_uid(uid)); } /**************************************************************************** @@ -300,10 +173,12 @@ BOOL become_guest(void) /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before setting IDs */ initgroups(pass->pw_name, (gid_t)pass->pw_gid); #endif + ret = become_id(pass->pw_uid,pass->pw_gid); - if (!ret) + if (!ret) { DEBUG(1,("Failed to become guest. Invalid guest account?\n")); + } current_user.cnum = -2; current_user.vuid = UID_FIELD_INVALID; @@ -390,7 +265,7 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid) { if (!become_gid(gid)) return(False); -#ifndef NO_SETGROUPS +#ifdef HAVE_SETGROUPS if (!(VALID_CNUM(cnum) && conn->ipc)) { /* groups stuff added by ih/wreu */ if (current_user.ngroups > 0) @@ -424,34 +299,30 @@ BOOL unbecome_user(void ) if (initial_uid == 0) { -#ifdef USE_SETRES +#ifdef HAVE_SETRESUID setresuid(-1,getuid(),-1); setresgid(-1,getgid(),-1); -#elif defined(USE_SETFS) - setfsuid(initial_uid); - setfsgid(initial_gid); #else if (seteuid(initial_uid) != 0) setuid(initial_uid); setgid(initial_gid); #endif } + #ifdef NO_EID if (initial_uid == 0) DEBUG(2,("Running with no EID\n")); initial_uid = getuid(); initial_gid = getgid(); #else - if (geteuid() != initial_uid) - { - DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); - initial_uid = geteuid(); - } - if (getegid() != initial_gid) - { - DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); - initial_gid = getegid(); - } + if (geteuid() != initial_uid) { + DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); + initial_uid = geteuid(); + } + if (getegid() != initial_gid) { + DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); + initial_gid = getegid(); + } #endif current_user.uid = initial_uid; @@ -485,13 +356,13 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared) close(1); if (shared) { - /* become root - unprivilaged users can't delete these files */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); + /* 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); + setuid(0); + seteuid(0); #endif } @@ -534,7 +405,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) int uid = current_user.uid; int gid = current_user.gid; -#if USE_SYSTEM +#ifndef HAVE_EXECL int ret; pstring syscmd; char *path = lp_smbrun(); @@ -583,7 +454,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared) /* 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 USE_SETRES +#ifdef HAVE_SETRESUID setresgid(0,0,0); setresuid(0,0,0); setresgid(gid,gid,gid); @@ -668,7 +539,7 @@ void unbecome_root(BOOL restore_dir) exit_server("Failed to restore gid"); } -#ifndef NO_SETGROUPS +#ifdef HAVE_SETGROUPS if (current_user_saved.ngroups > 0) { if (setgroups(current_user_saved.ngroups, current_user_saved.groups)<0) |