From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/smbd/uid.c | 434 ++++++++++++++++++++--------------------------------- 1 file changed, 161 insertions(+), 273 deletions(-) (limited to 'source3/smbd/uid.c') diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3501879d5f..ce0631e418 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -23,53 +23,36 @@ extern int DEBUGLEVEL; -static uid_t initial_uid; -static gid_t initial_gid; -static struct uid_cache vcache; - /* what user is current? */ extern struct current_user current_user; pstring OriginalDir; /**************************************************************************** -initialise the uid routines + Initialise the uid routines. ****************************************************************************/ + void init_uid(void) { - initial_uid = current_user.uid = geteuid(); - initial_gid = current_user.gid = getegid(); - - if (initial_gid != 0 && initial_uid == 0) { -#ifdef HAVE_SETRESUID - setresgid(0,0,0); -#else - setgid(0); - setegid(0); -#endif - } + current_user.uid = geteuid(); + current_user.gid = getegid(); - initial_uid = geteuid(); - initial_gid = getegid(); + if (current_user.gid != 0 && current_user.uid == 0) { + gain_root_group_privilege(); + } current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; - vcache.entries = 0; - dos_ChDir(OriginalDir); } - /**************************************************************************** - become the specified uid + Become the specified uid. ****************************************************************************/ + static BOOL become_uid(uid_t uid) { - if (initial_uid != 0) { - return(True); - } - if (uid == (uid_t)-1 || ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) { static int done; if (!done) { @@ -78,98 +61,53 @@ static BOOL become_uid(uid_t uid) } } -#ifdef HAVE_TRAPDOOR_UID -#ifdef HAVE_SETUIDX - /* AIX3 has setuidx which is NOT a trapoor function (tridge) */ - if (setuidx(ID_EFFECTIVE, uid) != 0) { - if (seteuid(uid) != 0) { - DEBUG(1,("Can't set uid %d (setuidx)\n", (int)uid)); - return False; - } - } -#endif -#endif - -#ifdef HAVE_SETRESUID - if (setresuid(-1,uid,-1) != 0) -#else - if ((seteuid(uid) != 0) && - (setuid(uid) != 0)) -#endif - { - DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n", - (int)uid,(int)getuid(), (int)geteuid())); - if (uid > (uid_t)32000) { - DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); - } - return(False); - } - - if (((uid == (uid_t)-1) || ((sizeof(uid_t) == 2) && (uid == 65535))) && (geteuid() != uid)) { - DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); - return(False); - } + set_effective_uid(uid); - current_user.uid = uid; + current_user.uid = uid; #ifdef WITH_PROFILE - profile_p->uid_changes++; + profile_p->uid_changes++; #endif - return(True); + return(True); } /**************************************************************************** - become the specified gid + Become the specified gid. ****************************************************************************/ + static BOOL become_gid(gid_t gid) { - if (initial_uid != 0) - return(True); - - if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { - DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); - } - -#ifdef HAVE_SETRESUID - if (setresgid(-1,gid,-1) != 0) -#else - if (setgid(gid) != 0) -#endif - { - DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n", - (int)gid,(int)getgid(),(int)getegid())); - if (gid > 32000) { - DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); + if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) && (gid == (gid_t)65535))) { + DEBUG(1,("WARNING: using gid %d is a security risk\n",(int)gid)); } - return(False); - } - - current_user.gid = gid; - - return(True); + + set_effective_gid(gid); + + current_user.gid = gid; + + return(True); } /**************************************************************************** - become the specified uid and gid + Become the specified uid and gid. ****************************************************************************/ + static BOOL become_id(uid_t uid,gid_t gid) { return(become_gid(gid) && become_uid(uid)); } /**************************************************************************** -become the guest user + Become the guest user. ****************************************************************************/ + BOOL become_guest(void) { BOOL ret; - static const struct passwd *pass=NULL; - - if (initial_uid != 0) - return(True); + static struct passwd *pass=NULL; if (!pass) pass = Get_Pwnam(lp_guestaccount(-1),True); @@ -193,138 +131,43 @@ BOOL become_guest(void) } /******************************************************************* -check if a username is OK + Check if a username is OK. ********************************************************************/ -static BOOL check_vuser_ok(struct uid_cache *cache, user_struct *vuser,int snum) + +static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { int i; - for (i=0;ientries;i++) - if (cache->list[i] == vuser->uid) return(True); + for (i=0;iuid_cache.entries;i++) + if (conn->uid_cache.list[i] == vuser->uid) return(True); if (!user_ok(vuser->name,snum)) return(False); - i = cache->entries % UID_CACHE_SIZE; - cache->list[i] = vuser->uid; + i = conn->uid_cache.entries % UID_CACHE_SIZE; + conn->uid_cache.list[i] = vuser->uid; - if (cache->entries < UID_CACHE_SIZE) - cache->entries++; + if (conn->uid_cache.entries < UID_CACHE_SIZE) + conn->uid_cache.entries++; return(True); } /**************************************************************************** - become the user of a connection number -****************************************************************************/ -BOOL become_vuser(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - gid_t gid; - uid_t uid; - - unbecome_vuser(); - - if((vuser != NULL) && !check_vuser_ok(&vcache, vuser, -1)) - return False; - - if ( vuser != 0 && - current_user.vuid == vuid && - current_user.uid == vuser->uid) - { - DEBUG(4,("Skipping become_vuser - already user\n")); - return(True); - } - uid = vuser->uid; - gid = vuser->gid; - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; - - if (initial_uid == 0) - { - if (!become_gid(gid)) return(False); - -#ifdef HAVE_SETGROUPS - /* groups stuff added by ih/wreu */ - if (current_user.ngroups > 0) - { - if (setgroups(current_user.ngroups, - current_user.groups)<0) { - DEBUG(0,("setgroups call failed!\n")); - } - } -#endif - - if (!become_uid(uid)) return(False); - } - - current_user.conn = NULL; - current_user.vuid = vuid; - - DEBUG(5,("become_vuser uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - - return(True); -} - -/**************************************************************************** - unbecome a user + Become the user of a connection number. ****************************************************************************/ -BOOL unbecome_vuser(void) -{ - dos_ChDir(OriginalDir); - - if (initial_uid == 0) - { -#ifdef HAVE_SETRESUID - setresuid(-1,getuid(),-1); - setresgid(-1,getgid(),-1); -#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(); - } -#endif - current_user.uid = initial_uid; - current_user.gid = initial_gid; - - if (dos_ChDir(OriginalDir) != 0) - DEBUG( 0, ( "chdir(%s) failed in unbecome_vuser\n", OriginalDir ) ); - - DEBUG(5,("unbecome_vuser now uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; - - return(True); -} - -/**************************************************************************** - become the user of a connection number -****************************************************************************/ BOOL become_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; - gid_t gid; + gid_t gid; uid_t uid; + char group_c; + + if (!conn) { + DEBUG(2,("Connection not open\n")); + return(False); + } /* * We need a separate check in security=share mode due to vuid @@ -346,14 +189,9 @@ BOOL become_user(connection_struct *conn, uint16 vuid) unbecome_user(); - if (!conn) { - DEBUG(2,("Connection not open\n")); - return(False); - } - snum = SNUM(conn); - if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum)) + if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) return False; if (conn->force_user || @@ -369,32 +207,55 @@ BOOL become_user(connection_struct *conn, uint16 vuid) return(False); } uid = vuser->uid; - if(!*lp_force_group(snum)) { - gid = vuser->gid; + gid = vuser->gid; + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + } + + /* + * See if we should force group for this service. + * If so this overrides any group set in the force + * user code. + */ + + if((group_c = *lp_force_group(snum))) { + if(group_c == '+') { + + /* + * Only force group if the user is a member of + * the service group. Check the group memberships for + * this user (we already have this) to + * see if we should force the group. + */ + + int i; + for (i = 0; i < current_user.ngroups; i++) { + if (current_user.groups[i] == conn->gid) { + gid = conn->gid; + break; + } + } } else { gid = conn->gid; } - current_user.ngroups = vuser->n_groups; - current_user.groups = vuser->groups; } - if (initial_uid == 0) { - if (!become_gid(gid)) return(False); + if (!become_gid(gid)) + return(False); #ifdef HAVE_SETGROUPS - if (!(conn && conn->ipc)) { - /* groups stuff added by ih/wreu */ - if (current_user.ngroups > 0) - if (setgroups(current_user.ngroups, - current_user.groups)<0) { - DEBUG(0,("setgroups call failed!\n")); - } - } + if (!(conn && conn->ipc)) { + /* groups stuff added by ih/wreu */ + if (current_user.ngroups > 0) + if (sys_setgroups(current_user.ngroups, + current_user.groups)<0) { + DEBUG(0,("sys_setgroups call failed!\n")); + } + } #endif - if (!conn->admin_user && !become_uid(uid)) - return(False); - } + if (!conn->admin_user && !become_uid(uid)) + return(False); current_user.conn = conn; current_user.vuid = vuid; @@ -406,56 +267,83 @@ BOOL become_user(connection_struct *conn, uint16 vuid) } /**************************************************************************** - unbecome the user of a connection number + Unbecome the user of a connection number. ****************************************************************************/ + BOOL unbecome_user(void ) { - if (!current_user.conn) - return(False); - - dos_ChDir(OriginalDir); - - if (initial_uid == 0) - { -#ifdef HAVE_SETRESUID - setresuid(-1,getuid(),-1); - setresgid(-1,getgid(),-1); -#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(); - } -#endif + if (!current_user.conn) + return(False); + + dos_ChDir(OriginalDir); - current_user.uid = initial_uid; - current_user.gid = initial_gid; + set_effective_uid(0); + set_effective_gid(0); + + if (geteuid() != 0) { + DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); + } + if (getegid() != 0) { + DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); + } + + current_user.uid = 0; + current_user.gid = 0; - if (dos_ChDir(OriginalDir) != 0) - DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); + if (dos_ChDir(OriginalDir) != 0) + DEBUG( 0, ( "chdir(%s) failed in unbecome_user\n", OriginalDir ) ); - DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", - (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); + DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", + (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - current_user.conn = NULL; - current_user.vuid = UID_FIELD_INVALID; + current_user.conn = NULL; + current_user.vuid = UID_FIELD_INVALID; - return(True); + return(True); +} + +/**************************************************************************** + Become the user of an authenticated connected named pipe. + When this is called we are currently running as the connection + user. +****************************************************************************/ + +BOOL become_authenticated_pipe_user(pipes_struct *p) +{ + /* + * Go back to root. + */ + + if(!unbecome_user()) + return False; + + /* + * Now become the authenticated user stored in the pipe struct. + */ + + if(!become_id(p->uid, p->gid)) { + /* Go back to the connection user. */ + become_user(p->conn, p->vuid); + return False; + } + + return True; +} + +/**************************************************************************** + Unbecome the user of an authenticated connected named pipe. + When this is called we are running as the authenticated pipe + user and need to go back to being the connection user. +****************************************************************************/ + +BOOL unbecome_authenticated_pipe_user(pipes_struct *p) +{ + if(!become_id(0,0)) { + DEBUG(0,("unbecome_authenticated_pipe_user: Unable to go back to root.\n")); + return False; + } + + return become_user(p->conn, p->vuid); } static struct current_user current_user_saved; @@ -463,13 +351,14 @@ static int become_root_depth; static pstring become_root_dir; /**************************************************************************** -This is used when we need to do a privilaged operation (such as mucking +This is used when we need to do a privileged operation (such as mucking with share mode files) and temporarily need root access to do it. This call should always be paired with an unbecome_root() call immediately after the operation Set save_dir if you also need to save/restore the CWD ****************************************************************************/ + void become_root(BOOL save_dir) { if (become_root_depth) { @@ -486,10 +375,11 @@ void become_root(BOOL save_dir) } /**************************************************************************** -When the privilaged operation is over call this +When the privileged operation is over call this Set save_dir if you also need to save/restore the CWD ****************************************************************************/ + void unbecome_root(BOOL restore_dir) { if (become_root_depth != 1) { @@ -512,9 +402,9 @@ void unbecome_root(BOOL restore_dir) #ifdef HAVE_SETGROUPS if (current_user_saved.ngroups > 0) { - if (setgroups(current_user_saved.ngroups, + if (sys_setgroups(current_user_saved.ngroups, current_user_saved.groups)<0) - DEBUG(0,("ERROR: setgroups call failed!\n")); + DEBUG(0,("ERROR: sys_setgroups call failed!\n")); } #endif @@ -531,5 +421,3 @@ void unbecome_root(BOOL restore_dir) become_root_depth = 0; } - - -- cgit