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.c434
1 files changed, 161 insertions, 273 deletions
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;i<cache->entries;i++)
- if (cache->list[i] == vuser->uid) return(True);
+ for (i=0;i<conn->uid_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;
}
-
-