summaryrefslogtreecommitdiff
path: root/uidswap.c
diff options
context:
space:
mode:
Diffstat (limited to 'uidswap.c')
-rw-r--r--uidswap.c101
1 files changed, 64 insertions, 37 deletions
diff --git a/uidswap.c b/uidswap.c
index bdfa484fc..7cfacd4a5 100644
--- a/uidswap.c
+++ b/uidswap.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: uidswap.c,v 1.13 2001/01/21 19:06:01 markus Exp $"); 15RCSID("$OpenBSD: uidswap.c,v 1.14 2001/04/06 21:00:16 markus Exp $");
16 16
17#include "log.h" 17#include "log.h"
18#include "uidswap.h" 18#include "uidswap.h"
@@ -26,57 +26,80 @@ RCSID("$OpenBSD: uidswap.c,v 1.13 2001/01/21 19:06:01 markus Exp $");
26 * POSIX saved uids or not. 26 * POSIX saved uids or not.
27 */ 27 */
28 28
29#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS)
30/* Lets assume that posix saved ids also work with seteuid, even though that 29/* Lets assume that posix saved ids also work with seteuid, even though that
31 is not part of the posix specification. */ 30 is not part of the posix specification. */
32#define SAVED_IDS_WORK_WITH_SETEUID 31
33/* Saved effective uid. */ 32/* Saved effective uid. */
34static uid_t saved_euid = 0; 33static int privileged = 0;
35#endif 34static int temporarily_use_uid_effective = 0;
36 35static uid_t saved_euid = 0;
36static gid_t saved_egid;
37static gid_t saved_egroups[NGROUPS_MAX], user_groups[NGROUPS_MAX];
38static int saved_egroupslen = -1, user_groupslen = -1;
39
37/* 40/*
38 * Temporarily changes to the given uid. If the effective user 41 * Temporarily changes to the given uid. If the effective user
39 * id is not root, this does nothing. This call cannot be nested. 42 * id is not root, this does nothing. This call cannot be nested.
40 */ 43 */
41void 44void
42temporarily_use_uid(uid_t uid) 45temporarily_use_uid(struct passwd *pw)
43{ 46{
44#ifdef SAVED_IDS_WORK_WITH_SETEUID 47 /* Save the current euid, and egroups. */
45 /* Save the current euid. */ 48 saved_euid = geteuid();
46 saved_euid = geteuid(); 49 debug("temporarily_use_uid: %d/%d (e=%d)",
47 50 pw->pw_uid, pw->pw_gid, saved_euid);
48 /* Set the effective uid to the given (unprivileged) uid. */ 51 if (saved_euid != 0) {
49 if (seteuid(uid) == -1) 52 privileged = 0;
50 debug("seteuid %u: %.100s", (u_int) uid, strerror(errno)); 53 return;
51#else /* SAVED_IDS_WORK_WITH_SETEUID */ 54 }
52 /* Propagate the privileged uid to all of our uids. */ 55 privileged = 1;
53 if (setuid(geteuid()) < 0) 56 temporarily_use_uid_effective = 1;
54 debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); 57 saved_egid = getegid();
55 58 saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups);
56 /* Set the effective uid to the given (unprivileged) uid. */ 59 if (saved_egroupslen < 0)
57 if (seteuid(uid) == -1) 60 fatal("getgroups: %.100s", strerror(errno));
58 debug("seteuid %u: %.100s", (u_int) uid, strerror(errno)); 61
59#endif /* SAVED_IDS_WORK_WITH_SETEUID */ 62 /* set and save the user's groups */
63 if (user_groupslen == -1) {
64 if (initgroups(pw->pw_name, pw->pw_gid) < 0)
65 fatal("initgroups: %s: %.100s", pw->pw_name,
66 strerror(errno));
67 user_groupslen = getgroups(NGROUPS_MAX, user_groups);
68 if (user_groupslen < 0)
69 fatal("getgroups: %.100s", strerror(errno));
70 }
71 /* Set the effective uid to the given (unprivileged) uid. */
72 if (setgroups(user_groupslen, user_groups) < 0)
73 fatal("setgroups: %.100s", strerror(errno));
74 pw->pw_gid = pw->pw_gid;
75 if (setegid(pw->pw_gid) < 0)
76 fatal("setegid %u: %.100s", (u_int) pw->pw_gid,
77 strerror(errno));
78 if (seteuid(pw->pw_uid) == -1)
79 fatal("seteuid %u: %.100s", (u_int) pw->pw_uid,
80 strerror(errno));
60} 81}
61 82
62/* 83/*
63 * Restores to the original uid. 84 * Restores to the original uid.
64 */ 85 */
65void 86void
66restore_uid(void) 87restore_uid(void)
67{ 88{
68#ifdef SAVED_IDS_WORK_WITH_SETEUID 89 debug("restore_uid");
90 /* it's a no-op unless privileged */
91 if (!privileged)
92 return;
93 if (!temporarily_use_uid_effective)
94 fatal("restore_uid: temporarily_use_uid not effective");
69 /* Set the effective uid back to the saved uid. */ 95 /* Set the effective uid back to the saved uid. */
70 if (seteuid(saved_euid) < 0) 96 if (seteuid(saved_euid) < 0)
71 debug("seteuid %u: %.100s", (u_int) saved_euid, strerror(errno)); 97 fatal("seteuid %u: %.100s", (u_int) saved_euid, strerror(errno));
72#else /* SAVED_IDS_WORK_WITH_SETEUID */ 98 if (setgroups(saved_egroupslen, saved_egroups) < 0)
73 /* 99 fatal("setgroups: %.100s", strerror(errno));
74 * We are unable to restore the real uid to its unprivileged value. 100 if (setegid(saved_egid) < 0)
75 * Propagate the real uid (usually more privileged) to effective uid 101 fatal("setegid %u: %.100s", (u_int) saved_egid, strerror(errno));
76 * as well. 102 temporarily_use_uid_effective = 0;
77 */
78 setuid(getuid());
79#endif /* SAVED_IDS_WORK_WITH_SETEUID */
80} 103}
81 104
82/* 105/*
@@ -84,8 +107,12 @@ restore_uid(void)
84 * called while temporarily_use_uid is effective. 107 * called while temporarily_use_uid is effective.
85 */ 108 */
86void 109void
87permanently_set_uid(uid_t uid) 110permanently_set_uid(struct passwd *pw)
88{ 111{
89 if (setuid(uid) < 0) 112 if (temporarily_use_uid_effective)
90 debug("setuid %u: %.100s", (u_int) uid, strerror(errno)); 113 fatal("restore_uid: temporarily_use_uid effective");
114 if (setuid(pw->pw_uid) < 0)
115 fatal("setuid %u: %.100s", (u_int) pw->pw_uid, strerror(errno));
116 if (setgid(pw->pw_gid) < 0)
117 fatal("setgid %u: %.100s", (u_int) pw->pw_gid, strerror(errno));
91} 118}