summaryrefslogtreecommitdiff
path: root/source3/smbd/uid.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/uid.c')
-rw-r--r--source3/smbd/uid.c279
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)