diff options
Diffstat (limited to 'uidswap.c')
-rw-r--r-- | uidswap.c | 43 |
1 files changed, 32 insertions, 11 deletions
@@ -16,6 +16,7 @@ RCSID("$OpenBSD: uidswap.c,v 1.24 2003/05/29 16:58:45 deraadt Exp $"); | |||
16 | 16 | ||
17 | #include "log.h" | 17 | #include "log.h" |
18 | #include "uidswap.h" | 18 | #include "uidswap.h" |
19 | #include "xmalloc.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Note: all these functions must work in all of the following cases: | 22 | * Note: all these functions must work in all of the following cases: |
@@ -38,7 +39,7 @@ static gid_t saved_egid = 0; | |||
38 | /* Saved effective uid. */ | 39 | /* Saved effective uid. */ |
39 | static int privileged = 0; | 40 | static int privileged = 0; |
40 | static int temporarily_use_uid_effective = 0; | 41 | static int temporarily_use_uid_effective = 0; |
41 | static gid_t saved_egroups[NGROUPS_MAX], user_groups[NGROUPS_MAX]; | 42 | static gid_t *saved_egroups = NULL, *user_groups = NULL; |
42 | static int saved_egroupslen = -1, user_groupslen = -1; | 43 | static int saved_egroupslen = -1, user_groupslen = -1; |
43 | 44 | ||
44 | /* | 45 | /* |
@@ -68,18 +69,38 @@ temporarily_use_uid(struct passwd *pw) | |||
68 | 69 | ||
69 | privileged = 1; | 70 | privileged = 1; |
70 | temporarily_use_uid_effective = 1; | 71 | temporarily_use_uid_effective = 1; |
71 | saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups); | 72 | |
73 | saved_egroupslen = getgroups(0, NULL); | ||
72 | if (saved_egroupslen < 0) | 74 | if (saved_egroupslen < 0) |
73 | fatal("getgroups: %.100s", strerror(errno)); | 75 | fatal("getgroups: %.100s", strerror(errno)); |
76 | if (saved_egroupslen > 0) { | ||
77 | saved_egroups = xrealloc(saved_egroups, | ||
78 | saved_egroupslen * sizeof(gid_t)); | ||
79 | if (getgroups(saved_egroupslen, saved_egroups) < 0) | ||
80 | fatal("getgroups: %.100s", strerror(errno)); | ||
81 | } else { /* saved_egroupslen == 0 */ | ||
82 | if (saved_egroups != NULL) | ||
83 | xfree(saved_egroups); | ||
84 | } | ||
74 | 85 | ||
75 | /* set and save the user's groups */ | 86 | /* set and save the user's groups */ |
76 | if (user_groupslen == -1) { | 87 | if (user_groupslen == -1) { |
77 | if (initgroups(pw->pw_name, pw->pw_gid) < 0) | 88 | if (initgroups(pw->pw_name, pw->pw_gid) < 0) |
78 | fatal("initgroups: %s: %.100s", pw->pw_name, | 89 | fatal("initgroups: %s: %.100s", pw->pw_name, |
79 | strerror(errno)); | 90 | strerror(errno)); |
80 | user_groupslen = getgroups(NGROUPS_MAX, user_groups); | 91 | |
92 | user_groupslen = getgroups(0, NULL); | ||
81 | if (user_groupslen < 0) | 93 | if (user_groupslen < 0) |
82 | fatal("getgroups: %.100s", strerror(errno)); | 94 | fatal("getgroups: %.100s", strerror(errno)); |
95 | if (user_groupslen > 0) { | ||
96 | user_groups = xrealloc(user_groups, | ||
97 | user_groupslen * sizeof(gid_t)); | ||
98 | if (getgroups(user_groupslen, user_groups) < 0) | ||
99 | fatal("getgroups: %.100s", strerror(errno)); | ||
100 | } else { /* user_groupslen == 0 */ | ||
101 | if (user_groups) | ||
102 | xfree(user_groups); | ||
103 | } | ||
83 | } | 104 | } |
84 | /* Set the effective uid to the given (unprivileged) uid. */ | 105 | /* Set the effective uid to the given (unprivileged) uid. */ |
85 | if (setgroups(user_groupslen, user_groups) < 0) | 106 | if (setgroups(user_groupslen, user_groups) < 0) |
@@ -151,7 +172,7 @@ permanently_set_uid(struct passwd *pw) | |||
151 | debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, | 172 | debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, |
152 | (u_int)pw->pw_gid); | 173 | (u_int)pw->pw_gid); |
153 | 174 | ||
154 | #if defined(HAVE_SETRESGID) | 175 | #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID) |
155 | if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) | 176 | if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) |
156 | fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); | 177 | fatal("setresgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); |
157 | #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID) | 178 | #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID) |
@@ -164,7 +185,7 @@ permanently_set_uid(struct passwd *pw) | |||
164 | fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); | 185 | fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); |
165 | #endif | 186 | #endif |
166 | 187 | ||
167 | #if defined(HAVE_SETRESUID) | 188 | #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID) |
168 | if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) | 189 | if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) |
169 | fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); | 190 | fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); |
170 | #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID) | 191 | #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID) |
@@ -180,28 +201,28 @@ permanently_set_uid(struct passwd *pw) | |||
180 | #endif | 201 | #endif |
181 | 202 | ||
182 | /* Try restoration of GID if changed (test clearing of saved gid) */ | 203 | /* Try restoration of GID if changed (test clearing of saved gid) */ |
183 | if (old_gid != pw->pw_gid && | 204 | if (old_gid != pw->pw_gid && |
184 | (setgid(old_gid) != -1 || setegid(old_gid) != -1)) | 205 | (setgid(old_gid) != -1 || setegid(old_gid) != -1)) |
185 | fatal("%s: was able to restore old [e]gid", __func__); | 206 | fatal("%s: was able to restore old [e]gid", __func__); |
186 | 207 | ||
187 | /* Verify GID drop was successful */ | 208 | /* Verify GID drop was successful */ |
188 | if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { | 209 | if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { |
189 | fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", | 210 | fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", |
190 | __func__, (u_int)getgid(), (u_int)getegid(), | 211 | __func__, (u_int)getgid(), (u_int)getegid(), |
191 | (u_int)pw->pw_gid); | 212 | (u_int)pw->pw_gid); |
192 | } | 213 | } |
193 | 214 | ||
194 | #ifndef HAVE_CYGWIN | 215 | #ifndef HAVE_CYGWIN |
195 | /* Try restoration of UID if changed (test clearing of saved uid) */ | 216 | /* Try restoration of UID if changed (test clearing of saved uid) */ |
196 | if (old_uid != pw->pw_uid && | 217 | if (old_uid != pw->pw_uid && |
197 | (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) | 218 | (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) |
198 | fatal("%s: was able to restore old [e]uid", __func__); | 219 | fatal("%s: was able to restore old [e]uid", __func__); |
199 | #endif | 220 | #endif |
200 | 221 | ||
201 | /* Verify UID drop was successful */ | 222 | /* Verify UID drop was successful */ |
202 | if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { | 223 | if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { |
203 | fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", | 224 | fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", |
204 | __func__, (u_int)getuid(), (u_int)geteuid(), | 225 | __func__, (u_int)getuid(), (u_int)geteuid(), |
205 | (u_int)pw->pw_uid); | 226 | (u_int)pw->pw_uid); |
206 | } | 227 | } |
207 | } | 228 | } |