summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-12-22 02:53:06 +0000
committerJeremy Allison <jra@samba.org>1998-12-22 02:53:06 +0000
commit80810371e6ee2ed33cb22a3629373131e92a7ab4 (patch)
treeaddea2df3e938f8c84c27481715c02570930f06a
parenta26d050828ede44d2beeb01edfa7bddd0c6deac0 (diff)
downloadsamba-80810371e6ee2ed33cb22a3629373131e92a7ab4.tar.gz
samba-80810371e6ee2ed33cb22a3629373131e92a7ab4.tar.xz
samba-80810371e6ee2ed33cb22a3629373131e92a7ab4.zip
Rather large (I'm afraid) tidyup of the setuid handling code.
All setuid code now resides in the one module lib/util_sec.c. The interfaces this module exports are : void gain_root_privilage(void); - Set real/eff/saved uid's to 0. void gain_root_group_privilage(void); - Set real/eff/saved gid's to 0. int set_effective_uid(uid_t uid); - Set eff uid *only* to given value. int set_effective_gid(gid_t gid); - Set eff gid *only* to given value. BOOL become_user_permanently(uid_t uid, gid_t gid); - Set real/eff/saved uid's and gid's to uid and gid permanently - with no way back to root. Most of the quota code now uses these calls (except for a few special cases). smbd/chgpasswd.c: Ensured the dochild exits in the fork()'d child. libsmb/nmblib.c: Fix from Jasper for memory leak. Jeremy.
-rw-r--r--source/Makefile.in4
-rw-r--r--source/auth/pass_check.c60
-rwxr-xr-xsource/configure2
-rw-r--r--source/configure.in2
-rw-r--r--source/include/config.h.in12
-rw-r--r--source/include/proto.h9
-rw-r--r--source/lib/smbrun.c34
-rw-r--r--source/lib/util.c53
-rw-r--r--source/libsmb/nmblib.c4
-rw-r--r--source/passdb/pass_check.c60
-rw-r--r--source/smbd/chgpasswd.c32
-rw-r--r--source/smbd/quotas.c37
-rw-r--r--source/smbd/server.c10
-rw-r--r--source/smbd/uid.c222
-rw-r--r--source/tests/trapdoor.c18
-rw-r--r--source/utils/smbrun.c28
16 files changed, 218 insertions, 369 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index 190968cff18..c17b618e26e 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -98,7 +98,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/bitmap.o lib/crc32.o lib/snprintf.o \
lib/util_str.o lib/util_sid.o \
lib/util_unistr.o lib/util_file.o \
- lib/util.o lib/util_sock.o
+ lib/util.o lib/util_sock.o lib/util_sec.o
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o ubiqx/debugparse.o
@@ -176,7 +176,7 @@ SWAT_OBJ = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
$(PARAM_OBJ) $(PASSDB_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ) $(PRINTING_OBJ)
-SMBRUN_OBJ = utils/smbrun.o
+SMBRUN_OBJ = utils/smbrun.o lib/util_sec.o
SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
diff --git a/source/auth/pass_check.c b/source/auth/pass_check.c
index cdbb9369688..a5a73d94f36 100644
--- a/source/auth/pass_check.c
+++ b/source/auth/pass_check.c
@@ -202,6 +202,7 @@ static BOOL dfs_auth(char *user,char *password)
sec_passwd_rec_t passwd_rec;
sec_login_auth_src_t auth_src = sec_login_auth_src_network;
unsigned char dce_errstr[dce_c_error_string_len];
+ gid_t egid;
if (dcelogin_atmost_once) return(False);
@@ -329,14 +330,16 @@ static BOOL dfs_auth(char *user,char *password)
* back to being root on error though. JRA.
*/
- if (setregid(-1, pw->pw_gid) != 0) {
+ egid = getegid();
+
+ if (set_effective_gid(pw->pw_gid) != 0) {
DEBUG(0,("Can't set egid to %d (%s)\n",
pw->pw_gid, strerror(errno)));
return False;
}
- if (setreuid(-1, pw->pw_uid) != 0) {
- setgid(0);
+ if (set_effective_uid(pw->pw_uid) != 0) {
+ set_effective_gid(egid);
DEBUG(0,("Can't set euid to %d (%s)\n",
pw->pw_uid, strerror(errno)));
return False;
@@ -347,24 +350,17 @@ static BOOL dfs_auth(char *user,char *password)
&my_dce_sec_context,
&err) == 0) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
user,dce_errstr));
- return(False);
+ goto err;
}
sec_login_get_pwent(my_dce_sec_context,
(sec_login_passwd_t*)&pw, &err);
if (err != error_status_ok ) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
passwd_rec.version_number = sec_passwd_c_version_none;
@@ -377,24 +373,16 @@ static BOOL dfs_auth(char *user,char *password)
&auth_src, &err);
if (err != error_status_ok ) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
user,dce_errstr));
-
- return(False);
+ goto err;
}
sec_login_certify_identity(my_dce_sec_context, &err);
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE certify identity failed: %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
if (auth_src != sec_login_auth_src_network) {
@@ -408,10 +396,7 @@ static BOOL dfs_auth(char *user,char *password)
user,dce_errstr));
sec_login_purge_context(&my_dce_sec_context, &err);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
- return(False);
+ goto err;
}
sec_login_get_pwent(my_dce_sec_context,
@@ -419,11 +404,7 @@ static BOOL dfs_auth(char *user,char *password)
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr));
-
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
- return(False);
+ goto err;
}
DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
@@ -441,21 +422,24 @@ static BOOL dfs_auth(char *user,char *password)
sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
- setuid(0);
- setgid(0);
+ set_effective_uid(0);
+ set_effective_gid(0);
DEBUG(0,("DCE context expires: %s",asctime(localtime(&expire_time))));
dcelogin_atmost_once = 1;
return (True);
+
+err:
+
+ /* Go back to root, JRA. */
+ set_effective_uid(0);
+ set_effective_gid(egid);
+ return(False);
}
void dfs_unlogin(void)
diff --git a/source/configure b/source/configure
index 7b871a23cdf..641ce71a727 100755
--- a/source/configure
+++ b/source/configure
@@ -3893,7 +3893,7 @@ else
fi
done
-for ac_func in initgroups select rdchk getgrnam pathconf
+for ac_func in initgroups select rdchk getgrnam pathconf setreuid setregid seteuid setegid
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:3900: checking for $ac_func" >&5
diff --git a/source/configure.in b/source/configure.in
index 5dc298a0dd4..347dcb26763 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -267,7 +267,7 @@ AC_CHECK_FUNCS(waitpid getcwd strdup strtoul strerror chown chmod chroot)
AC_CHECK_FUNCS(fstat strchr utime utimes getrlimit fsync execl bzero memset)
AC_CHECK_FUNCS(memmove vsnprintf snprintf setsid glob strpbrk pipe crypt16 getauthuid)
AC_CHECK_FUNCS(strftime sigprocmask sigblock sigaction innetgr setnetgrent getnetgrent endnetgrent)
-AC_CHECK_FUNCS(initgroups select rdchk getgrnam pathconf )
+AC_CHECK_FUNCS(initgroups select rdchk getgrnam pathconf setreuid setregid seteuid setegid)
AC_CHECK_FUNCS(setuidx setgroups mktime rename ftruncate stat64 fstat64 lstat64 fopen64)
AC_CHECK_FUNCS(atexit grantpt dup2 lseek64 ftruncate64 readdir64)
AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid yp_get_default_domain getpwanam)
diff --git a/source/include/config.h.in b/source/include/config.h.in
index 7b40cea96a4..c71ed429539 100644
--- a/source/include/config.h.in
+++ b/source/include/config.h.in
@@ -552,9 +552,15 @@
/* Define if you have the set_auth_parameters function. */
#undef HAVE_SET_AUTH_PARAMETERS
+/* Define if you have the setegid function. */
+#undef HAVE_SETEGID
+
/* Define if you have the setenv function. */
#undef HAVE_SETENV
+/* Define if you have the seteuid function. */
+#undef HAVE_SETEUID
+
/* Define if you have the setgroups function. */
#undef HAVE_SETGROUPS
@@ -564,6 +570,12 @@
/* Define if you have the setnetgrent function. */
#undef HAVE_SETNETGRENT
+/* Define if you have the setregid function. */
+#undef HAVE_SETREGID
+
+/* Define if you have the setreuid function. */
+#undef HAVE_SETREUID
+
/* Define if you have the setsid function. */
#undef HAVE_SETSID
diff --git a/source/include/proto.h b/source/include/proto.h
index 015edd8fbed..77228036ec2 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -296,7 +296,6 @@ void zero_free(void *p, size_t size);
int set_maxfiles(int requested_max);
void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name);
BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name);
-BOOL become_user_permanently(uid_t uid, gid_t gid);
/*The following definitions come from lib/util_file.c */
@@ -311,6 +310,14 @@ BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok);
int getfileline(void *vp, char *linebuf, int linebuf_size);
char *fgets_slash(char *s2,int maxlen,FILE *f);
+/*The following definitions come from lib/util_sec.c */
+
+void gain_root_privilage(void);
+void gain_root_group_privilage(void);
+int set_effective_uid(uid_t uid);
+int set_effective_gid(gid_t gid);
+BOOL become_user_permanently(uid_t uid, gid_t gid);
+
/*The following definitions come from lib/util_sid.c */
char *sid_to_string(pstring sidstr_out, DOM_SID *sid);
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 2257fa09e41..ad262c775a8 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -40,14 +40,9 @@ static BOOL setup_stdout_file(char *outfile,BOOL shared)
close(1);
if (shared) {
- /* become root - unprivilaged users can't delete these files */
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- setresgid(0,0,0);
- setresuid(0,0,0);
-#else
- setuid(0);
- seteuid(0);
-#endif
+ /* become root - unprivilaged users can't delete these files */
+ gain_root_privilage();
+ gain_root_group_privilage();
}
if(sys_stat(outfile, &st) == 0) {
@@ -86,8 +81,8 @@ if shared is not set then open the file with O_EXCL set
int smbrun(char *cmd,char *outfile,BOOL shared)
{
int fd,pid;
- int uid = current_user.uid;
- int gid = current_user.gid;
+ uid_t uid = current_user.uid;
+ gid_t gid = current_user.gid;
/*
* Lose any kernel oplock capabilities we may have.
@@ -110,7 +105,7 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
}
slprintf(syscmd,sizeof(syscmd)-1,"%s %d %d \"(%s 2>&1) > %s\"",
- path,uid,gid,cmd,
+ path,(int)uid,(int)gid,cmd,
outfile?outfile:"/dev/null");
DEBUG(5,("smbrun - running %s ",syscmd));
@@ -143,20 +138,9 @@ 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 */
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- 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
-
+
+ become_user_permanently(uid, gid);
+
if (getuid() != uid || geteuid() != uid ||
getgid() != gid || getegid() != gid) {
/* we failed to lose our privilages - do not execute
diff --git a/source/lib/util.c b/source/lib/util.c
index 9c8e6e92f01..3bf0a42c52a 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -2972,56 +2972,3 @@ BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
return True;
}
-
-/****************************************************************************
- become the specified uid - permanently !
-****************************************************************************/
-BOOL become_user_permanently(uid_t uid, gid_t gid)
-{
- /* 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 */
-
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- /*
- * Firstly ensure all our uids are set to root.
- */
- setresgid(0,0,0);
- setresuid(0,0,0);
-
- /*
- * Now ensure we change all our gids.
- */
- setresgid(gid,gid,gid);
-
- /*
- * Now ensure all the uids are the user.
- */
- setresuid(uid,uid,uid);
-#else
- /*
- * Firstly ensure all our uids are set to root.
- */
- setuid(0);
- seteuid(0);
-
- /*
- * Now ensure we change all our gids.
- */
- setgid(gid);
- setegid(gid);
-
- /*
- * Now ensure all the uids are the user.
- */
- setuid(uid);
- seteuid(uid);
-#endif
-
- if (getuid() != uid || geteuid() != uid ||
- getgid() != gid || getegid() != gid) {
- /* We failed to lose our privilages. */
- return False;
- }
-
- return(True);
-}
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index e0b6056c85a..06ef935e167 100644
--- a/source/libsmb/nmblib.c
+++ b/source/libsmb/nmblib.c
@@ -673,9 +673,9 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
break;
}
if (!ok) {
- DEBUG(10,("parse_nmb: discarding packet id = %d\n",
+ DEBUG(10,("read_packet: discarding packet id = %d\n",
packet->packet.nmb.header.name_trn_id));
- free(packet);
+ free_packet(packet);
return(NULL);
}
diff --git a/source/passdb/pass_check.c b/source/passdb/pass_check.c
index cdbb9369688..a5a73d94f36 100644
--- a/source/passdb/pass_check.c
+++ b/source/passdb/pass_check.c
@@ -202,6 +202,7 @@ static BOOL dfs_auth(char *user,char *password)
sec_passwd_rec_t passwd_rec;
sec_login_auth_src_t auth_src = sec_login_auth_src_network;
unsigned char dce_errstr[dce_c_error_string_len];
+ gid_t egid;
if (dcelogin_atmost_once) return(False);
@@ -329,14 +330,16 @@ static BOOL dfs_auth(char *user,char *password)
* back to being root on error though. JRA.
*/
- if (setregid(-1, pw->pw_gid) != 0) {
+ egid = getegid();
+
+ if (set_effective_gid(pw->pw_gid) != 0) {
DEBUG(0,("Can't set egid to %d (%s)\n",
pw->pw_gid, strerror(errno)));
return False;
}
- if (setreuid(-1, pw->pw_uid) != 0) {
- setgid(0);
+ if (set_effective_uid(pw->pw_uid) != 0) {
+ set_effective_gid(egid);
DEBUG(0,("Can't set euid to %d (%s)\n",
pw->pw_uid, strerror(errno)));
return False;
@@ -347,24 +350,17 @@ static BOOL dfs_auth(char *user,char *password)
&my_dce_sec_context,
&err) == 0) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
user,dce_errstr));
- return(False);
+ goto err;
}
sec_login_get_pwent(my_dce_sec_context,
(sec_login_passwd_t*)&pw, &err);
if (err != error_status_ok ) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
passwd_rec.version_number = sec_passwd_c_version_none;
@@ -377,24 +373,16 @@ static BOOL dfs_auth(char *user,char *password)
&auth_src, &err);
if (err != error_status_ok ) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
user,dce_errstr));
-
- return(False);
+ goto err;
}
sec_login_certify_identity(my_dce_sec_context, &err);
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE certify identity failed: %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
if (auth_src != sec_login_auth_src_network) {
@@ -408,10 +396,7 @@ static BOOL dfs_auth(char *user,char *password)
user,dce_errstr));
sec_login_purge_context(&my_dce_sec_context, &err);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
- return(False);
+ goto err;
}
sec_login_get_pwent(my_dce_sec_context,
@@ -419,11 +404,7 @@ static BOOL dfs_auth(char *user,char *password)
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr));
-
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
- return(False);
+ goto err;
}
DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
@@ -441,21 +422,24 @@ static BOOL dfs_auth(char *user,char *password)
sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
if (err != error_status_ok) {
dce_error_inq_text(err, dce_errstr, &err2);
- /* Go back to root, JRA. */
- setuid(0);
- setgid(0);
DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr));
-
- return(False);
+ goto err;
}
- setuid(0);
- setgid(0);
+ set_effective_uid(0);
+ set_effective_gid(0);
DEBUG(0,("DCE context expires: %s",asctime(localtime(&expire_time))));
dcelogin_atmost_once = 1;
return (True);
+
+err:
+
+ /* Go back to root, JRA. */
+ set_effective_uid(0);
+ set_effective_gid(egid);
+ return(False);
}
void dfs_unlogin(void)
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 1e36f34c032..d1562466ba1 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -120,11 +120,8 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram,
gid = pass->pw_gid;
uid = pass->pw_uid;
-#ifdef HAVE_SETRESUID
- setresuid(0,0,0);
-#else
- setuid(0);
-#endif
+
+ gain_root_privilage();
/* Start new session - gets rid of controlling terminal. */
if (setsid() < 0) {
@@ -184,19 +181,10 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram,
/* make us completely into the right uid */
if (!as_root) {
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- 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(!become_user_permanently(uid, gid)) {
+ DEBUG(0,("dochild: unable to permanently become uid %d, gid %d\n", (int)uid, (int)gid));
+ return False;
+ }
}
DEBUG(10, ("Invoking '%s' as password change program.\n", passwordprogram));
@@ -360,8 +348,12 @@ static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequenc
DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
chstat = dochild(master, slavedev, name, passwordprogram, as_root);
- if (as_root)
- unbecome_root(False);
+ /*
+ * The child should never return from dochild() ....
+ */
+
+ DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat ));
+ exit(1);
}
if (chstat)
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index afabb1befdf..93ec0ef3157 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -82,9 +82,9 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
}
euser_id=geteuid();
- seteuid(0);
+ set_effective_uid(0);
r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D);
- seteuid(euser_id);
+ set_effective_uid(euser_id);
/* Use softlimit to determine disk space, except when it has been exceeded */
*bsize = 1024;
@@ -313,16 +313,12 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
}
euser_id = geteuid();
- user_id = getuid();
-
- setuid(0); /* Solaris seems to want to give info only to super-user */
- seteuid(0);
+ set_effective_uid(0);
#if defined(SUNOS5)
DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
if((file=sys_open(name, O_RDONLY,0))<0) {
- setuid(user_id); /* Restore the original UID status */
- seteuid(euser_id);
+ set_effective_uid(euser_id);
return(False);
}
command.op = Q_GETQUOTA;
@@ -335,8 +331,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif
- setuid(user_id); /* Restore the original uid status. */
- seteuid(euser_id);
+ set_effective_uid(euser_id);
if (ret < 0) {
DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
@@ -383,6 +378,12 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
struct dqblk D;
SMB_STRUCT_STAT S;
+ /*
+ * This code presumes that OSF1 will only
+ * give out quota info when the real uid
+ * matches the effective uid. JRA.
+ */
+
euser_id = geteuid();
user_id = getuid();
@@ -469,7 +470,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
}
euser_id=geteuid();
- seteuid(0);
+ set_effective_uid(0);
/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -479,7 +480,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
{
r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
- seteuid(euser_id); /* Restore the original uid status. */
+ set_effective_uid(euser_id); /* Restore the original uid status. */
if (r==-1)
return(False);
@@ -510,7 +511,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
{
r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
- seteuid(euser_id); /* Restore the original uid status. */
+ set_effective_uid(euser_id); /* Restore the original uid status. */
if (r==-1)
return(False);
@@ -539,7 +540,7 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
}
else
{
- seteuid(euser_id); /* Restore the original uid status. */
+ set_effective_uid(euser_id); /* Restore the original uid status. */
return(False);
}
@@ -601,19 +602,15 @@ BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_U
uid_t user_id;
gid_t egrp_id;
- /* Need to be root to get quotas in FreeBSD */
- user_id = getuid();
egrp_id = getegid();
- setuid(0);
- seteuid(0);
+ set_effective_uid(0);
r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
/* As FreeBSD has group quotas, if getting the user
quota fails, try getting the group instead. */
if (r)
r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
- setuid(user_id);
- seteuid(euser_id);
+ set_effective_uid(euser_id);
}
#elif defined(AIX)
/* AIX has both USER and GROUP quotas:
diff --git a/source/smbd/server.c b/source/smbd/server.c
index e016c817aa1..30ffc4b8544 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -526,14 +526,8 @@ static void usage(char *pname)
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */
-#ifdef HAVE_SETRESUID
- setresuid(0,0,0);
-#else
- setuid(0);
- seteuid(0);
- setuid(0);
- seteuid(0);
-#endif
+
+ gain_root_privilage();
fault_setup((void (*)(void *))exit_server);
CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index 767fc2cdb7a..90e3eafcf13 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -23,33 +23,23 @@
extern int DEBUGLEVEL;
-static uid_t initial_uid;
-static gid_t initial_gid;
-
/* 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_SETRESGID
- 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_privilage();
+ }
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
@@ -57,16 +47,14 @@ void init_uid(void)
dos_ChDir(OriginalDir);
}
-
/****************************************************************************
- become the specified uid
+ Become the specified uid.
****************************************************************************/
+
static BOOL become_uid(uid_t uid)
{
- if (initial_uid != 0) {
- return(True);
- }
-
+ uid_t euid;
+
if (uid == (uid_t)-1 || ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) {
static int done;
if (!done) {
@@ -75,95 +63,76 @@ 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
+ if(set_effective_uid(uid) != 0) {
+ DEBUG(0,("Couldn't set effective uid to %d. Currently set to (real=%d,eff=%d). \
+Error was %s\n", (int)uid,(int)getuid(), (int)geteuid(), strerror(errno) ));
-#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"));
+ if (uid > (uid_t)32000)
+ DEBUG(0,("Could be your OS doesn't like high uid values - \
+try using a different account\n"));
+ return(False);
}
- 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"));
+ /* Paranioa.... JRA. */
+
+ euid = geteuid();
+
+ if(euid != uid) {
+ DEBUG(0,("become_uid: Unable to become uid %d.\n", (int)uid ));
+
+ if ((uid == (uid_t)-1) || ((sizeof(uid_t) == 2) && (uid == 65535)))
+ DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
+
return(False);
}
-
current_user.uid = uid;
-
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));
- }
+ 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_SETRESGID
- 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(set_effective_gid(gid) != 0) {
+ DEBUG(0,("Couldn't set effective gid to %d currently set to (real=%d,eff=%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"));
+ }
+ return(False);
}
- return(False);
- }
- current_user.gid = gid;
+ current_user.gid = gid;
- return(True);
+ 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 struct passwd *pass=NULL;
- if (initial_uid != 0)
- return(True);
-
if (!pass)
pass = Get_Pwnam(lp_guestaccount(-1),True);
if (!pass) return(False);
@@ -186,8 +155,9 @@ BOOL become_guest(void)
}
/*******************************************************************
-check if a username is OK
+ Check if a username is OK.
********************************************************************/
+
static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
{
int i;
@@ -207,8 +177,9 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
/****************************************************************************
- become the user of a connection number
+ Become the user of a connection number.
****************************************************************************/
+
BOOL become_user(connection_struct *conn, uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
@@ -268,23 +239,21 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
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 (setgroups(current_user.ngroups,
+ current_user.groups)<0) {
+ DEBUG(0,("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;
@@ -296,56 +265,39 @@ 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)
- {
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- setresuid(-1,getuid(),-1);
- setresgid(-1,getgid(),-1);
-#else
- if (seteuid(initial_uid) != 0)
- setuid(initial_uid);
- setgid(initial_gid);
-#endif
- }
+ if (!current_user.conn)
+ return(False);
-#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
+ dos_ChDir(OriginalDir);
+
+ 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 = initial_uid;
- current_user.gid = initial_gid;
+ 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);
}
static struct current_user current_user_saved;
@@ -360,6 +312,7 @@ 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) {
@@ -380,6 +333,7 @@ When the privilaged 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) {
@@ -421,5 +375,3 @@ void unbecome_root(BOOL restore_dir)
become_root_depth = 0;
}
-
-
diff --git a/source/tests/trapdoor.c b/source/tests/trapdoor.c
index 974db257a4e..75e04a6a927 100644
--- a/source/tests/trapdoor.c
+++ b/source/tests/trapdoor.c
@@ -12,13 +12,20 @@ non-trapdoor system\n");
exit(0);
}
-#ifdef HAVE_SETRESUID
+#if defined(HAVE_SETRESUID)
if (setresuid(1,1,-1) != 0) exit(1);
if (getuid() != 1) exit(1);
if (geteuid() != 1) exit(1);
if (setresuid(0,0,0) != 0) exit(1);
if (getuid() != 0) exit(1);
if (geteuid() != 0) exit(1);
+#elif defined(HAVE_SETREUID) && !defined(HAVE_SETEUID)
+ if (setreuid(1,1) != 0) exit(1);
+ if (getuid() != 1) exit(1);
+ if (geteuid() != 1) exit(1);
+ if (setreuid(0,0) != 0) exit(1);
+ if (getuid() != 0) exit(1);
+ if (geteuid() != 0) exit(1);
#else
if (seteuid(1) != 0) exit(1);
if (geteuid() != 1) exit(1);
@@ -26,13 +33,20 @@ non-trapdoor system\n");
if (geteuid() != 0) exit(1);
#endif
-#ifdef HAVE_SETRESGID
+#if defined(HAVE_SETRESGID)
if (setresgid(1,1,1) != 0) exit(1);
if (getgid() != 1) exit(1);
if (getegid() != 1) exit(1);
if (setresgid(0,0,0) != 0) exit(1);
if (getgid() != 0) exit(1);
if (getegid() != 0) exit(1);
+#elif defined(HAVE_SETREGID) && !defined(HAVE_SETEGID)
+ if (setresgid(1,1) != 0) exit(1);
+ if (getgid() != 1) exit(1);
+ if (getegid() != 1) exit(1);
+ if (setregid(0,0) != 0) exit(1);
+ if (getgid() != 0) exit(1);
+ if (getegid() != 0) exit(1);
#else
if (setegid(1) != 0) exit(1);
if (getegid() != 1) exit(1);
diff --git a/source/utils/smbrun.c b/source/utils/smbrun.c
index effc4d01bfb..b7c678411c6 100644
--- a/source/utils/smbrun.c
+++ b/source/utils/smbrun.c
@@ -48,35 +48,17 @@ It takes 3 arguments as uid,gid,command and runs command after
becoming a non-root user */
int main(int argc,char *argv[])
{
- int uid,gid;
+ uid_t uid;
+ gid_t gid;
close_fds();
if (argc != 4) exit(2);
- uid = atoi(argv[1]);
- gid = atoi(argv[2]);
-
- /* first become root - we may need to do this in order to lose
- our privilages! */
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- setresgid(0,0,0);
- setresuid(0,0,0);
-#else
- setuid(0);
- seteuid(0);
-#endif
-
-#if defined(HAVE_SETRESUID) && defined(HAVE_SETRESGID)
- setresgid(gid,gid,gid);
- setresuid(uid,uid,uid);
-#else
- setgid(gid);
- setegid(gid);
- setuid(uid);
- seteuid(uid);
-#endif
+ uid = (uid_t)atoi(argv[1]);
+ gid = (gid_t)atoi(argv[2]);
+ become_user_permanently( uid, gid);
/* paranoia :-) */
if (getuid() != uid)