1: /*
2: * Copyright (c) 1994-1996,1998-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: *
16: * Sponsored in part by the Defense Advanced Research Projects
17: * Agency (DARPA) and Air Force Research Laboratory, Air Force
18: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
19: */
20:
21: #include <config.h>
22:
23: #include <sys/types.h>
24: #include <sys/stat.h>
25: #include <stdio.h>
26: #ifdef STDC_HEADERS
27: # include <stdlib.h>
28: # include <stddef.h>
29: #else
30: # ifdef HAVE_STDLIB_H
31: # include <stdlib.h>
32: # endif
33: #endif /* STDC_HEADERS */
34: #ifdef HAVE_STRING_H
35: # include <string.h>
36: #endif /* HAVE_STRING_H */
37: #ifdef HAVE_STRINGS_H
38: # include <strings.h>
39: #endif /* HAVE_STRINGS_H */
40: #ifdef HAVE_UNISTD_H
41: # include <unistd.h>
42: #endif /* HAVE_UNISTD_H */
43: #ifdef _AIX
44: # include <sys/id.h>
45: #endif
46: #include <pwd.h>
47: #include <errno.h>
48: #include <grp.h>
49:
50: #include "sudoers.h"
51:
52: /*
53: * Prototypes
54: */
55: #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
56: static struct group_list *runas_setgroups(void);
57: #endif
58:
59: /*
60: * We keep track of the current permisstions and use a stack to restore
61: * the old permissions. A depth of 16 is overkill.
62: */
63: struct perm_state {
64: uid_t ruid;
65: uid_t euid;
66: #if defined(HAVE_SETRESUID) || defined(ID_SAVED)
67: uid_t suid;
68: #endif
69: gid_t rgid;
70: gid_t egid;
71: #if defined(HAVE_SETRESUID) || defined(ID_SAVED)
72: gid_t sgid;
73: #endif
74: struct group_list *grlist;
75: };
76:
77: #define PERM_STACK_MAX 16
78: static struct perm_state perm_stack[PERM_STACK_MAX];
79: static int perm_stack_depth = 0;
80:
81: #undef ID
82: #define ID(x) (state->x == ostate->x ? (uid_t)-1 : state->x)
83: #undef OID
84: #define OID(x) (ostate->x == state->x ? (uid_t)-1 : ostate->x)
85:
86: void
87: rewind_perms(void)
88: {
89: debug_decl(rewind_perms, SUDO_DEBUG_PERMS)
90:
91: if (perm_stack_depth != 0) {
92: while (perm_stack_depth > 1)
93: restore_perms();
94: sudo_grlist_delref(perm_stack[0].grlist);
95: }
96:
97: debug_return;
98: }
99:
100: #if defined(HAVE_SETRESUID)
101:
102: #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
103: #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
104:
105: /*
106: * Set real and effective and saved uids and gids based on perm.
107: * We always retain a saved uid of 0 unless we are headed for an exec().
108: * We only flip the effective gid since it only changes for PERM_SUDOERS.
109: * This version of set_perms() works fine with the "stay_setuid" option.
110: */
111: int
112: set_perms(int perm)
113: {
114: struct perm_state *state, *ostate = NULL;
115: char errbuf[1024];
116: const char *errstr = errbuf;
117: int noexit;
118: debug_decl(set_perms, SUDO_DEBUG_PERMS)
119:
120: noexit = ISSET(perm, PERM_NOEXIT);
121: CLR(perm, PERM_MASK);
122:
123: if (perm_stack_depth == PERM_STACK_MAX) {
124: errstr = N_("perm stack overflow");
125: errno = EINVAL;
126: goto bad;
127: }
128:
129: state = &perm_stack[perm_stack_depth];
130: if (perm != PERM_INITIAL) {
131: if (perm_stack_depth == 0) {
132: errstr = N_("perm stack underflow");
133: errno = EINVAL;
134: goto bad;
135: }
136: ostate = &perm_stack[perm_stack_depth - 1];
137: }
138:
139: switch (perm) {
140: case PERM_INITIAL:
141: /* Stash initial state */
142: #ifdef HAVE_GETRESUID
143: if (getresuid(&state->ruid, &state->euid, &state->suid)) {
144: errstr = "PERM_INITIAL: getresuid";
145: goto bad;
146:
147: }
148: if (getresgid(&state->rgid, &state->egid, &state->sgid)) {
149: errstr = "PERM_INITIAL: getresgid";
150: goto bad;
151: }
152: #else
153: state->ruid = getuid();
154: state->euid = geteuid();
155: state->suid = state->euid; /* in case we are setuid */
156:
157: state->rgid = getgid();
158: state->egid = getegid();
159: state->sgid = state->egid; /* in case we are setgid */
160: #endif
161: state->grlist = user_group_list;
162: sudo_grlist_addref(state->grlist);
163: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
164: "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
165: __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
166: (int)state->rgid, (int)state->egid, (int)state->sgid);
167: break;
168:
169: case PERM_ROOT:
170: state->ruid = ROOT_UID;
171: state->euid = ROOT_UID;
172: state->suid = ROOT_UID;
173: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
174: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
175: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
176: (int)state->ruid, (int)state->euid, (int)state->suid);
177: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
178: snprintf(errbuf, sizeof(errbuf),
179: "PERM_ROOT: setresuid(%d, %d, %d)",
180: ID(ruid), ID(euid), ID(suid));
181: goto bad;
182: }
183: state->rgid = ostate->rgid;
184: state->egid = ROOT_GID;
185: state->sgid = ostate->sgid;
186: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
187: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
188: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
189: (int)state->rgid, (int)state->egid, (int)state->sgid);
190: if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
191: errstr = N_("unable to change to root gid");
192: goto bad;
193: }
194: state->grlist = ostate->grlist;
195: sudo_grlist_addref(state->grlist);
196: break;
197:
198: case PERM_USER:
199: state->rgid = ostate->rgid;
200: state->egid = user_gid;
201: state->sgid = ostate->sgid;
202: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
203: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
204: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
205: (int)state->rgid, (int)state->egid, (int)state->sgid);
206: if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
207: snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresgid(%d, %d, %d)",
208: ID(rgid), ID(egid), ID(sgid));
209: goto bad;
210: }
211: state->grlist = user_group_list;
212: sudo_grlist_addref(state->grlist);
213: if (state->grlist != ostate->grlist) {
214: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
215: errstr = "PERM_USER: setgroups";
216: goto bad;
217: }
218: }
219: state->ruid = user_uid;
220: state->euid = user_uid;
221: state->suid = ROOT_UID;
222: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
223: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
224: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
225: (int)state->ruid, (int)state->euid, (int)state->suid);
226: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
227: snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresuid(%d, %d, %d)",
228: ID(ruid), ID(euid), ID(suid));
229: goto bad;
230: }
231: break;
232:
233: case PERM_FULL_USER:
234: /* headed for exec() */
235: state->rgid = user_gid;
236: state->egid = user_gid;
237: state->sgid = user_gid;
238: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
239: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
240: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
241: (int)state->rgid, (int)state->egid, (int)state->sgid);
242: if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
243: snprintf(errbuf, sizeof(errbuf),
244: "PERM_FULL_USER: setresgid(%d, %d, %d)",
245: ID(rgid), ID(egid), ID(sgid));
246: goto bad;
247: }
248: state->grlist = user_group_list;
249: sudo_grlist_addref(state->grlist);
250: if (state->grlist != ostate->grlist) {
251: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
252: errstr = "PERM_FULL_USER: setgroups";
253: goto bad;
254: }
255: }
256: state->ruid = user_uid;
257: state->euid = user_uid;
258: state->suid = user_uid;
259: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
260: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
261: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
262: (int)state->ruid, (int)state->euid, (int)state->suid);
263: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
264: snprintf(errbuf, sizeof(errbuf),
265: "PERM_FULL_USER: setresuid(%d, %d, %d)",
266: ID(ruid), ID(euid), ID(suid));
267: goto bad;
268: }
269: break;
270:
271: case PERM_RUNAS:
272: state->rgid = ostate->rgid;
273: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
274: state->sgid = ostate->sgid;
275: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
276: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
277: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
278: (int)state->rgid, (int)state->egid, (int)state->sgid);
279: if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
280: errstr = N_("unable to change to runas gid");
281: goto bad;
282: }
283: state->grlist = runas_setgroups();
284: state->ruid = ostate->ruid;
285: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
286: state->suid = ostate->suid;
287: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
288: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
289: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
290: (int)state->ruid, (int)state->euid, (int)state->suid);
291: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
292: errstr = N_("unable to change to runas uid");
293: goto bad;
294: }
295: break;
296:
297: case PERM_SUDOERS:
298: state->grlist = ostate->grlist;
299: sudo_grlist_addref(state->grlist);
300:
301: /* assumes euid == ROOT_UID, ruid == user */
302: state->rgid = ostate->rgid;
303: state->egid = sudoers_gid;
304: state->sgid = ostate->sgid;
305: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
306: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
307: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
308: (int)state->rgid, (int)state->egid, (int)state->sgid);
309: if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
310: errstr = N_("unable to change to sudoers gid");
311: goto bad;
312: }
313:
314: state->ruid = ROOT_UID;
315: /*
316: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
317: * we use a non-zero uid in order to avoid NFS lossage.
318: * Using uid 1 is a bit bogus but should work on all OS's.
319: */
320: if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
321: state->euid = 1;
322: else
323: state->euid = sudoers_uid;
324: state->suid = ROOT_UID;
325: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
326: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
327: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
328: (int)state->ruid, (int)state->euid, (int)state->suid);
329: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
330: snprintf(errbuf, sizeof(errbuf),
331: "PERM_SUDOERS: setresuid(%d, %d, %d)",
332: ID(ruid), ID(euid), ID(suid));
333: goto bad;
334: }
335: break;
336:
337: case PERM_TIMESTAMP:
338: state->grlist = ostate->grlist;
339: sudo_grlist_addref(state->grlist);
340: state->rgid = ostate->rgid;
341: state->egid = ostate->egid;
342: state->sgid = ostate->sgid;
343: state->ruid = ROOT_UID;
344: state->euid = timestamp_uid;
345: state->suid = ROOT_UID;
346: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
347: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
348: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
349: (int)state->ruid, (int)state->euid, (int)state->suid);
350: if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
351: snprintf(errbuf, sizeof(errbuf),
352: "PERM_TIMESTAMP: setresuid(%d, %d, %d)",
353: ID(ruid), ID(euid), ID(suid));
354: goto bad;
355: }
356: break;
357: }
358:
359: perm_stack_depth++;
360: debug_return_bool(1);
361: bad:
362: if (errno == EAGAIN)
363: warningx(U_("%s: %s"), U_(errstr), U_("too many processes"));
364: else
365: warning("%s", U_(errstr));
366: if (noexit)
367: debug_return_bool(0);
368: exit(1);
369: }
370:
371: void
372: restore_perms(void)
373: {
374: struct perm_state *state, *ostate;
375: debug_decl(restore_perms, SUDO_DEBUG_PERMS)
376:
377: if (perm_stack_depth < 2)
378: debug_return;
379:
380: state = &perm_stack[perm_stack_depth - 1];
381: ostate = &perm_stack[perm_stack_depth - 2];
382: perm_stack_depth--;
383:
384: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
385: __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
386: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
387: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
388: __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
389: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
390:
391: /* XXX - more cases here where euid != ruid */
392: if (OID(euid) == ROOT_UID) {
393: if (setresuid(-1, ROOT_UID, -1)) {
394: warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
395: (int)state->ruid, (int)state->euid, (int)state->suid,
396: -1, ROOT_UID, -1);
397: goto bad;
398: }
399: }
400: if (setresuid(OID(ruid), OID(euid), OID(suid))) {
401: warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
402: (int)state->ruid, (int)state->euid, (int)state->suid,
403: (int)OID(ruid), (int)OID(euid), (int)OID(suid));
404: goto bad;
405: }
406: if (setresgid(OID(rgid), OID(egid), OID(sgid))) {
407: warning("setresgid() [%d, %d, %d] -> [%d, %d, %d]",
408: (int)state->rgid, (int)state->egid, (int)state->sgid,
409: (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
410: goto bad;
411: }
412: if (state->grlist != ostate->grlist) {
413: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
414: warning("setgroups()");
415: goto bad;
416: }
417: }
418: sudo_grlist_delref(state->grlist);
419: debug_return;
420:
421: bad:
422: exit(1);
423: }
424:
425: #elif defined(_AIX) && defined(ID_SAVED)
426:
427: #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
428: #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
429:
430: /*
431: * Set real and effective and saved uids and gids based on perm.
432: * We always retain a saved uid of 0 unless we are headed for an exec().
433: * We only flip the effective gid since it only changes for PERM_SUDOERS.
434: * This version of set_perms() works fine with the "stay_setuid" option.
435: */
436: int
437: set_perms(int perm)
438: {
439: struct perm_state *state, *ostate = NULL;
440: char errbuf[1024];
441: const char *errstr = errbuf;
442: int noexit;
443: debug_decl(set_perms, SUDO_DEBUG_PERMS)
444:
445: noexit = ISSET(perm, PERM_NOEXIT);
446: CLR(perm, PERM_MASK);
447:
448: if (perm_stack_depth == PERM_STACK_MAX) {
449: errstr = N_("perm stack overflow");
450: errno = EINVAL;
451: goto bad;
452: }
453:
454: state = &perm_stack[perm_stack_depth];
455: if (perm != PERM_INITIAL) {
456: if (perm_stack_depth == 0) {
457: errstr = N_("perm stack underflow");
458: errno = EINVAL;
459: goto bad;
460: }
461: ostate = &perm_stack[perm_stack_depth - 1];
462: }
463:
464: switch (perm) {
465: case PERM_INITIAL:
466: /* Stash initial state */
467: state->ruid = getuidx(ID_REAL);
468: state->euid = getuidx(ID_EFFECTIVE);
469: state->suid = getuidx(ID_SAVED);
470: state->rgid = getgidx(ID_REAL);
471: state->egid = getgidx(ID_EFFECTIVE);
472: state->sgid = getgidx(ID_SAVED);
473: state->grlist = user_group_list;
474: sudo_grlist_addref(state->grlist);
475: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
476: "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
477: __func__, (unsigned int)state->ruid, (unsigned int)state->euid,
478: (unsigned int)state->suid, (unsigned int)state->rgid,
479: (unsigned int)state->egid, (unsigned int)state->sgid);
480: break;
481:
482: case PERM_ROOT:
483: state->ruid = ROOT_UID;
484: state->euid = ROOT_UID;
485: state->suid = ROOT_UID;
486: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
487: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
488: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
489: (int)state->ruid, (int)state->euid, (int)state->suid);
490: if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
491: snprintf(errbuf, sizeof(errbuf),
492: "PERM_ROOT: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
493: ROOT_UID);
494: goto bad;
495: }
496: state->rgid = ostate->rgid;
497: state->egid = ROOT_GID;
498: state->sgid = ostate->sgid;
499: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
500: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
501: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
502: (int)state->rgid, (int)state->egid, (int)state->sgid);
503: if (GID_CHANGED && setgidx(ID_EFFECTIVE, ROOT_GID)) {
504: errstr = N_("unable to change to root gid");
505: goto bad;
506: }
507: state->grlist = ostate->grlist;
508: sudo_grlist_addref(state->grlist);
509: break;
510:
511: case PERM_USER:
512: state->rgid = ostate->rgid;
513: state->egid = user_gid;
514: state->sgid = ostate->sgid;
515: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
516: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
517: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
518: (int)state->rgid, (int)state->egid, (int)state->sgid);
519: if (GID_CHANGED && setgidx(ID_EFFECTIVE, user_gid)) {
520: snprintf(errbuf, sizeof(errbuf),
521: "PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid);
522: goto bad;
523: }
524: state->grlist = user_group_list;
525: sudo_grlist_addref(state->grlist);
526: if (state->grlist != ostate->grlist) {
527: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
528: errstr = "PERM_USER: setgroups";
529: goto bad;
530: }
531: }
532: state->ruid = user_uid;
533: state->euid = user_uid;
534: state->suid = ROOT_UID;
535: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
536: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
537: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
538: (int)state->ruid, (int)state->euid, (int)state->suid);
539: if (ostate->euid != ROOT_UID || ostate->suid != ROOT_UID) {
540: if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
541: snprintf(errbuf, sizeof(errbuf),
542: "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
543: ROOT_UID);
544: goto bad;
545: }
546: }
547: if (setuidx(ID_EFFECTIVE|ID_REAL, user_uid)) {
548: snprintf(errbuf, sizeof(errbuf),
549: "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL, %d)", user_uid);
550: goto bad;
551: }
552: break;
553:
554: case PERM_FULL_USER:
555: /* headed for exec() */
556: state->rgid = user_gid;
557: state->egid = user_gid;
558: state->sgid = user_gid;
559: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
560: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
561: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
562: (int)state->rgid, (int)state->egid, (int)state->sgid);
563: if (GID_CHANGED && setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_gid)) {
564: snprintf(errbuf, sizeof(errbuf),
565: "PERM_FULL_USER: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
566: user_gid);
567: goto bad;
568: }
569: state->grlist = user_group_list;
570: sudo_grlist_addref(state->grlist);
571: if (state->grlist != ostate->grlist) {
572: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
573: errstr = "PERM_FULL_USER: setgroups";
574: goto bad;
575: }
576: }
577: state->ruid = user_uid;
578: state->euid = user_uid;
579: state->suid = user_uid;
580: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
581: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
582: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
583: (int)state->ruid, (int)state->euid, (int)state->suid);
584: if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_uid)) {
585: snprintf(errbuf, sizeof(errbuf),
586: "PERM_FULL_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
587: user_uid);
588: goto bad;
589: }
590: break;
591:
592: case PERM_RUNAS:
593: state->rgid = ostate->rgid;
594: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
595: state->sgid = ostate->sgid;
596: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
597: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
598: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
599: (int)state->rgid, (int)state->egid, (int)state->sgid);
600: if (GID_CHANGED && setgidx(ID_EFFECTIVE, state->egid)) {
601: errstr = N_("unable to change to runas gid");
602: goto bad;
603: }
604: state->grlist = runas_setgroups();
605: state->ruid = ostate->ruid;
606: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
607: state->suid = ostate->suid;
608: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
609: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
610: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
611: (int)state->ruid, (int)state->euid, (int)state->suid);
612: if (UID_CHANGED && setuidx(ID_EFFECTIVE, state->euid)) {
613: errstr = N_("unable to change to runas uid");
614: goto bad;
615: }
616: break;
617:
618: case PERM_SUDOERS:
619: state->grlist = ostate->grlist;
620: sudo_grlist_addref(state->grlist);
621:
622: /* assume euid == ROOT_UID, ruid == user */
623: state->rgid = ostate->rgid;
624: state->egid = sudoers_gid;
625: state->sgid = ostate->sgid;
626: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
627: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
628: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
629: (int)state->rgid, (int)state->egid, (int)state->sgid);
630: if (GID_CHANGED && setgidx(ID_EFFECTIVE, sudoers_gid)) {
631: errstr = N_("unable to change to sudoers gid");
632: goto bad;
633: }
634:
635: state->ruid = ROOT_UID;
636: /*
637: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
638: * we use a non-zero uid in order to avoid NFS lossage.
639: * Using uid 1 is a bit bogus but should work on all OS's.
640: */
641: if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
642: state->euid = 1;
643: else
644: state->euid = sudoers_uid;
645: state->suid = ROOT_UID;
646: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
647: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
648: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
649: (int)state->ruid, (int)state->euid, (int)state->suid);
650: if (UID_CHANGED) {
651: if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
652: if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
653: snprintf(errbuf, sizeof(errbuf),
654: "PERM_SUDOERS: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
655: ROOT_UID);
656: goto bad;
657: }
658: }
659: if (setuidx(ID_EFFECTIVE, state->euid)) {
660: snprintf(errbuf, sizeof(errbuf),
661: "PERM_SUDOERS: setuidx(ID_EFFECTIVE, %d)", sudoers_uid);
662: goto bad;
663: }
664: }
665: break;
666:
667: case PERM_TIMESTAMP:
668: state->grlist = ostate->grlist;
669: sudo_grlist_addref(state->grlist);
670: state->rgid = ostate->rgid;
671: state->egid = ostate->egid;
672: state->sgid = ostate->sgid;
673: state->ruid = ROOT_UID;
674: state->euid = timestamp_uid;
675: state->suid = ROOT_UID;
676: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
677: "[%d, %d, %d] -> [%d, %d, %d]", __func__,
678: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
679: (int)state->ruid, (int)state->euid, (int)state->suid);
680: if (UID_CHANGED) {
681: if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
682: if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
683: snprintf(errbuf, sizeof(errbuf),
684: "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
685: ROOT_UID);
686: goto bad;
687: }
688: }
689: if (setuidx(ID_EFFECTIVE, timestamp_uid)) {
690: snprintf(errbuf, sizeof(errbuf),
691: "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE, %d)", timestamp_uid);
692: goto bad;
693: }
694: }
695: break;
696: }
697:
698: perm_stack_depth++;
699: debug_return_bool(1);
700: bad:
701: if (errno == EAGAIN)
702: warningx(U_("%s: %s"), U_(errstr), U_("too many processes"));
703: else
704: warning("%s", U_(errstr));
705: if (noexit)
706: debug_return_bool(0);
707: exit(1);
708: }
709:
710: void
711: restore_perms(void)
712: {
713: struct perm_state *state, *ostate;
714: debug_decl(restore_perms, SUDO_DEBUG_PERMS)
715:
716: if (perm_stack_depth < 2)
717: debug_return;
718:
719: state = &perm_stack[perm_stack_depth - 1];
720: ostate = &perm_stack[perm_stack_depth - 2];
721: perm_stack_depth--;
722:
723: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
724: __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
725: (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
726: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
727: __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
728: (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
729:
730: if (OID(ruid) != -1 || OID(euid) != -1 || OID(suid) != -1) {
731: if (OID(euid) == ROOT_UID) {
732: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setuidx(ID_EFFECTIVE, %d)",
733: __func__, ROOT_UID);
734: if (setuidx(ID_EFFECTIVE, ROOT_UID)) {
735: warning("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
736: (int)state->ruid, (int)state->euid, (int)state->suid,
737: -1, ROOT_UID, -1);
738: goto bad;
739: }
740: }
741: if (OID(ruid) == OID(euid) && OID(euid) == OID(suid)) {
742: sudo_debug_printf(SUDO_DEBUG_INFO,
743: "%s: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
744: __func__, OID(ruid));
745: if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(ruid))) {
746: warning("setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
747: (int)state->ruid, (int)state->euid, (int)state->suid,
748: (int)OID(ruid), (int)OID(euid), (int)OID(suid));
749: goto bad;
750: }
751: } else if (OID(ruid) == -1 && OID(suid) == -1) {
752: /* May have already changed euid to ROOT_UID above. */
753: if (OID(euid) != ROOT_UID) {
754: sudo_debug_printf(SUDO_DEBUG_INFO,
755: "%s: setuidx(ID_EFFECTIVE, %d)", __func__, OID(euid));
756: if (setuidx(ID_EFFECTIVE, OID(euid))) {
757: warning("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
758: (int)state->ruid, (int)state->euid, (int)state->suid,
759: (int)OID(ruid), (int)OID(euid), (int)OID(suid));
760: goto bad;
761: }
762: }
763: } else if (OID(suid) == -1) {
764: /* Cannot set the real uid alone. */
765: sudo_debug_printf(SUDO_DEBUG_INFO,
766: "%s: setuidx(ID_REAL|ID_EFFECTIVE, %d)", __func__, OID(ruid));
767: if (setuidx(ID_REAL|ID_EFFECTIVE, OID(ruid))) {
768: warning("setuidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
769: (int)state->ruid, (int)state->euid, (int)state->suid,
770: (int)OID(ruid), (int)OID(euid), (int)OID(suid));
771: goto bad;
772: }
773: /* Restore the effective euid if it doesn't match the ruid. */
774: if (OID(euid) != OID(ruid)) {
775: sudo_debug_printf(SUDO_DEBUG_INFO,
776: "%s: setuidx(ID_EFFECTIVE, %d)", __func__, ostate->euid);
777: if (setuidx(ID_EFFECTIVE, ostate->euid)) {
778: warning("setuidx(ID_EFFECTIVE, %d)", ostate->euid);
779: goto bad;
780: }
781: }
782: }
783: }
784: if (OID(rgid) != -1 || OID(egid) != -1 || OID(sgid) != -1) {
785: if (OID(rgid) == OID(egid) && OID(egid) == OID(sgid)) {
786: sudo_debug_printf(SUDO_DEBUG_INFO,
787: "%s: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
788: __func__, OID(rgid));
789: if (setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(rgid))) {
790: warning("setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
791: (int)state->rgid, (int)state->egid, (int)state->sgid,
792: (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
793: goto bad;
794: }
795: } else if (OID(rgid) == -1 && OID(sgid) == -1) {
796: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setgidx(ID_EFFECTIVE, %d)",
797: __func__, OID(egid));
798: if (setgidx(ID_EFFECTIVE, OID(egid))) {
799: warning("setgidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
800: (int)state->rgid, (int)state->egid, (int)state->sgid,
801: (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
802: goto bad;
803: }
804: } else if (OID(sgid) == -1) {
805: sudo_debug_printf(SUDO_DEBUG_INFO,
806: "%s: setgidx(ID_EFFECTIVE|ID_REAL, %d)", __func__, OID(rgid));
807: if (setgidx(ID_REAL|ID_EFFECTIVE, OID(rgid))) {
808: warning("setgidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
809: (int)state->rgid, (int)state->egid, (int)state->sgid,
810: (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
811: goto bad;
812: }
813: }
814: }
815: if (state->grlist != ostate->grlist) {
816: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
817: warning("setgroups()");
818: goto bad;
819: }
820: }
821: sudo_grlist_delref(state->grlist);
822: debug_return;
823:
824: bad:
825: exit(1);
826: }
827:
828: #elif defined(HAVE_SETREUID)
829:
830: #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid)
831: #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
832:
833: /*
834: * Set real and effective and saved uids and gids based on perm.
835: * We always retain a saved uid of 0 unless we are headed for an exec().
836: * We only flip the effective gid since it only changes for PERM_SUDOERS.
837: * This version of set_perms() works fine with the "stay_setuid" option.
838: */
839: int
840: set_perms(int perm)
841: {
842: struct perm_state *state, *ostate = NULL;
843: char errbuf[1024];
844: const char *errstr = errbuf;
845: int noexit;
846: debug_decl(set_perms, SUDO_DEBUG_PERMS)
847:
848: noexit = ISSET(perm, PERM_NOEXIT);
849: CLR(perm, PERM_MASK);
850:
851: if (perm_stack_depth == PERM_STACK_MAX) {
852: errstr = N_("perm stack overflow");
853: errno = EINVAL;
854: goto bad;
855: }
856:
857: state = &perm_stack[perm_stack_depth];
858: if (perm != PERM_INITIAL) {
859: if (perm_stack_depth == 0) {
860: errstr = N_("perm stack underflow");
861: errno = EINVAL;
862: goto bad;
863: }
864: ostate = &perm_stack[perm_stack_depth - 1];
865: }
866:
867: switch (perm) {
868: case PERM_INITIAL:
869: /* Stash initial state */
870: state->ruid = getuid();
871: state->euid = geteuid();
872: state->rgid = getgid();
873: state->egid = getegid();
874: state->grlist = user_group_list;
875: sudo_grlist_addref(state->grlist);
876: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
877: "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
878: (int)state->ruid, (int)state->euid,
879: (int)state->rgid, (int)state->egid);
880: break;
881:
882: case PERM_ROOT:
883: state->ruid = ROOT_UID;
884: state->euid = ROOT_UID;
885: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
886: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
887: (int)ostate->euid, (int)state->ruid, (int)state->euid);
888: /*
889: * setreuid(0, 0) may fail on some systems if euid is not already 0.
890: */
891: if (ostate->euid != ROOT_UID) {
892: if (setreuid(-1, ROOT_UID)) {
893: snprintf(errbuf, sizeof(errbuf),
894: "PERM_ROOT: setreuid(-1, %d)", ROOT_UID);
895: goto bad;
896: }
897: }
898: if (ostate->ruid != ROOT_UID) {
899: if (setreuid(ROOT_UID, -1)) {
900: snprintf(errbuf, sizeof(errbuf),
901: "PERM_ROOT: setreuid(%d, -1)", ROOT_UID);
902: goto bad;
903: }
904: }
905: state->rgid = ostate->rgid;
906: state->egid = ROOT_GID;
907: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
908: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
909: (int)ostate->egid, (int)state->rgid, (int)state->egid);
910: if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
911: snprintf(errbuf, sizeof(errbuf),
912: "PERM_ROOT: setregid(%d, %d)", ID(rgid), ID(egid));
913: goto bad;
914: }
915: state->grlist = ostate->grlist;
916: sudo_grlist_addref(state->grlist);
917: break;
918:
919: case PERM_USER:
920: state->rgid = ostate->rgid;
921: state->egid = user_gid;
922: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
923: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
924: (int)ostate->egid, (int)state->rgid, (int)state->egid);
925: if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
926: snprintf(errbuf, sizeof(errbuf),
927: "PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid));
928: goto bad;
929: }
930: state->grlist = user_group_list;
931: sudo_grlist_addref(state->grlist);
932: if (state->grlist != ostate->grlist) {
933: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
934: errstr = "PERM_USER: setgroups";
935: goto bad;
936: }
937: }
938: state->ruid = ROOT_UID;
939: state->euid = user_uid;
940: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
941: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
942: (int)ostate->euid, (int)state->ruid, (int)state->euid);
943: if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
944: snprintf(errbuf, sizeof(errbuf),
945: "PERM_USER: setreuid(%d, %d)", ID(ruid), ID(euid));
946: goto bad;
947: }
948: break;
949:
950: case PERM_FULL_USER:
951: /* headed for exec() */
952: state->rgid = user_gid;
953: state->egid = user_gid;
954: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
955: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
956: (int)ostate->egid, (int)state->rgid, (int)state->egid);
957: if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
958: snprintf(errbuf, sizeof(errbuf),
959: "PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid));
960: goto bad;
961: }
962: state->grlist = user_group_list;
963: sudo_grlist_addref(state->grlist);
964: if (state->grlist != ostate->grlist) {
965: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
966: errstr = "PERM_FULL_USER: setgroups";
967: goto bad;
968: }
969: }
970: state->ruid = user_uid;
971: state->euid = user_uid;
972: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
973: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
974: (int)ostate->euid, (int)state->ruid, (int)state->euid);
975: if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
976: snprintf(errbuf, sizeof(errbuf),
977: "PERM_FULL_USER: setreuid(%d, %d)", ID(ruid), ID(euid));
978: goto bad;
979: }
980: break;
981:
982: case PERM_RUNAS:
983: state->rgid = ostate->rgid;
984: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
985: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
986: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
987: (int)ostate->egid, (int)state->rgid, (int)state->egid);
988: if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
989: errstr = N_("unable to change to runas gid");
990: goto bad;
991: }
992: state->grlist = runas_setgroups();
993: state->ruid = ROOT_UID;
994: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
995: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
996: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
997: (int)ostate->euid, (int)state->ruid, (int)state->euid);
998: if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
999: errstr = N_("unable to change to runas uid");
1000: goto bad;
1001: }
1002: break;
1003:
1004: case PERM_SUDOERS:
1005: state->grlist = ostate->grlist;
1006: sudo_grlist_addref(state->grlist);
1007:
1008: /* assume euid == ROOT_UID, ruid == user */
1009: state->rgid = ostate->rgid;
1010: state->egid = sudoers_gid;
1011: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
1012: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1013: (int)ostate->egid, (int)state->rgid, (int)state->egid);
1014: if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
1015: errstr = N_("unable to change to sudoers gid");
1016: goto bad;
1017: }
1018:
1019: state->ruid = ROOT_UID;
1020: /*
1021: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
1022: * we use a non-zero uid in order to avoid NFS lossage.
1023: * Using uid 1 is a bit bogus but should work on all OS's.
1024: */
1025: if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
1026: state->euid = 1;
1027: else
1028: state->euid = sudoers_uid;
1029: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
1030: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1031: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1032: if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
1033: snprintf(errbuf, sizeof(errbuf),
1034: "PERM_SUDOERS: setreuid(%d, %d)", ID(ruid), ID(euid));
1035: goto bad;
1036: }
1037: break;
1038:
1039: case PERM_TIMESTAMP:
1040: state->grlist = ostate->grlist;
1041: sudo_grlist_addref(state->grlist);
1042: state->rgid = ostate->rgid;
1043: state->egid = ostate->egid;
1044: state->ruid = ROOT_UID;
1045: state->euid = timestamp_uid;
1046: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
1047: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1048: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1049: if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
1050: snprintf(errbuf, sizeof(errbuf),
1051: "PERM_TIMESTAMP: setreuid(%d, %d)", ID(ruid), ID(euid));
1052: goto bad;
1053: }
1054: break;
1055: }
1056:
1057: perm_stack_depth++;
1058: debug_return_bool(1);
1059: bad:
1060: if (errno == EAGAIN)
1061: warningx(U_("%s: %s"), U_(errstr), U_("too many processes"));
1062: else
1063: warning("%s", U_(errstr));
1064: if (noexit)
1065: debug_return_bool(0);
1066: exit(1);
1067: }
1068:
1069: void
1070: restore_perms(void)
1071: {
1072: struct perm_state *state, *ostate;
1073: debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1074:
1075: if (perm_stack_depth < 2)
1076: debug_return;
1077:
1078: state = &perm_stack[perm_stack_depth - 1];
1079: ostate = &perm_stack[perm_stack_depth - 2];
1080: perm_stack_depth--;
1081:
1082: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
1083: __func__, (int)state->ruid, (int)state->euid,
1084: (int)ostate->ruid, (int)ostate->euid);
1085: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
1086: __func__, (int)state->rgid, (int)state->egid,
1087: (int)ostate->rgid, (int)ostate->egid);
1088:
1089: /*
1090: * When changing euid to ROOT_UID, setreuid() may fail even if
1091: * the ruid is ROOT_UID so call setuid() first.
1092: */
1093: if (OID(euid) == ROOT_UID) {
1094: /* setuid() may not set the saved ID unless the euid is ROOT_UID */
1095: if (ID(euid) != ROOT_UID)
1096: ignore_result(setreuid(-1, ROOT_UID));
1097: if (setuid(ROOT_UID)) {
1098: warning("setuid() [%d, %d] -> %d)", (int)state->ruid,
1099: (int)state->euid, ROOT_UID);
1100: goto bad;
1101: }
1102: }
1103: if (setreuid(OID(ruid), OID(euid))) {
1104: warning("setreuid() [%d, %d] -> [%d, %d]", (int)state->ruid,
1105: (int)state->euid, (int)OID(ruid), (int)OID(euid));
1106: goto bad;
1107: }
1108: if (setregid(OID(rgid), OID(egid))) {
1109: warning("setregid() [%d, %d] -> [%d, %d]", (int)state->rgid,
1110: (int)state->egid, (int)OID(rgid), (int)OID(egid));
1111: goto bad;
1112: }
1113: if (state->grlist != ostate->grlist) {
1114: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1115: warning("setgroups()");
1116: goto bad;
1117: }
1118: }
1119: sudo_grlist_delref(state->grlist);
1120: debug_return;
1121:
1122: bad:
1123: exit(1);
1124: }
1125:
1126: #elif defined(HAVE_SETEUID)
1127:
1128: #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
1129:
1130: /*
1131: * Set real and effective uids and gids based on perm.
1132: * We always retain a real or effective uid of ROOT_UID unless
1133: * we are headed for an exec().
1134: * This version of set_perms() works fine with the "stay_setuid" option.
1135: */
1136: int
1137: set_perms(int perm)
1138: {
1139: struct perm_state *state, *ostate = NULL;
1140: char errbuf[1024];
1141: const char *errstr = errbuf;
1142: int noexit;
1143: debug_decl(set_perms, SUDO_DEBUG_PERMS)
1144:
1145: noexit = ISSET(perm, PERM_NOEXIT);
1146: CLR(perm, PERM_MASK);
1147:
1148: if (perm_stack_depth == PERM_STACK_MAX) {
1149: errstr = N_("perm stack overflow");
1150: errno = EINVAL;
1151: goto bad;
1152: }
1153:
1154: state = &perm_stack[perm_stack_depth];
1155: if (perm != PERM_INITIAL) {
1156: if (perm_stack_depth == 0) {
1157: errstr = N_("perm stack underflow");
1158: errno = EINVAL;
1159: goto bad;
1160: }
1161: ostate = &perm_stack[perm_stack_depth - 1];
1162: }
1163:
1164: /*
1165: * Since we only have setuid() and seteuid() and semantics
1166: * for these calls differ on various systems, we set
1167: * real and effective uids to ROOT_UID initially to be safe.
1168: */
1169: if (perm != PERM_INITIAL) {
1170: if (ostate->euid != ROOT_UID && seteuid(ROOT_UID)) {
1171: snprintf(errbuf, sizeof(errbuf), "set_perms: seteuid(%d)", ROOT_UID);
1172: goto bad;
1173: }
1174: if (ostate->ruid != ROOT_UID && setuid(ROOT_UID)) {
1175: snprintf(errbuf, sizeof(errbuf), "set_perms: setuid(%d)", ROOT_UID);
1176: goto bad;
1177: }
1178: }
1179:
1180: switch (perm) {
1181: case PERM_INITIAL:
1182: /* Stash initial state */
1183: state->ruid = getuid();
1184: state->euid = geteuid();
1185: state->rgid = getgid();
1186: state->egid = getegid();
1187: state->grlist = user_group_list;
1188: sudo_grlist_addref(state->grlist);
1189: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
1190: "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
1191: (int)state->ruid, (int)state->euid,
1192: (int)state->rgid, (int)state->egid);
1193: break;
1194:
1195: case PERM_ROOT:
1196: /* We already set ruid/euid above. */
1197: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
1198: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1199: (int)ostate->euid, ROOT_UID, ROOT_UID);
1200: state->ruid = ROOT_UID;
1201: state->euid = ROOT_UID;
1202: state->rgid = ostate->rgid;
1203: state->egid = ROOT_GID;
1204: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
1205: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1206: (int)ostate->egid, ROOT_GID, ROOT_GID);
1207: if (GID_CHANGED && setegid(ROOT_GID)) {
1208: errstr = N_("unable to change to root gid");
1209: goto bad;
1210: }
1211: state->grlist = ostate->grlist;
1212: sudo_grlist_addref(state->grlist);
1213: break;
1214:
1215: case PERM_USER:
1216: state->egid = user_gid;
1217: state->rgid = ostate->rgid;
1218: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
1219: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1220: (int)ostate->egid, (int)state->rgid, (int)state->egid);
1221: if (GID_CHANGED && setegid(user_gid)) {
1222: snprintf(errbuf, sizeof(errbuf),
1223: "PERM_USER: setegid(%d)", user_gid);
1224: goto bad;
1225: }
1226: state->grlist = user_group_list;
1227: sudo_grlist_addref(state->grlist);
1228: if (state->grlist != ostate->grlist) {
1229: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1230: errstr = "PERM_USER: setgroups";
1231: goto bad;
1232: }
1233: }
1234: state->ruid = ROOT_UID;
1235: state->euid = user_uid;
1236: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
1237: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1238: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1239: if (seteuid(user_uid)) {
1240: snprintf(errbuf, sizeof(errbuf),
1241: "PERM_USER: seteuid(%d)", user_uid);
1242: goto bad;
1243: }
1244: break;
1245:
1246: case PERM_FULL_USER:
1247: /* headed for exec() */
1248: state->rgid = user_gid;
1249: state->egid = user_gid;
1250: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
1251: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1252: (int)ostate->egid, (int)state->rgid, (int)state->egid);
1253: if (GID_CHANGED && setgid(user_gid)) {
1254: snprintf(errbuf, sizeof(errbuf),
1255: "PERM_FULL_USER: setgid(%d)", user_gid);
1256: goto bad;
1257: }
1258: state->grlist = user_group_list;
1259: sudo_grlist_addref(state->grlist);
1260: if (state->grlist != ostate->grlist) {
1261: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1262: errstr = "PERM_FULL_USER: setgroups";
1263: goto bad;
1264: }
1265: }
1266: state->ruid = user_uid;
1267: state->euid = user_uid;
1268: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
1269: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1270: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1271: if (setuid(user_uid)) {
1272: snprintf(errbuf, sizeof(errbuf),
1273: "PERM_FULL_USER: setuid(%d)", user_uid);
1274: goto bad;
1275: }
1276: break;
1277:
1278: case PERM_RUNAS:
1279: state->rgid = ostate->rgid;
1280: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
1281: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
1282: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1283: (int)ostate->egid, (int)state->rgid, (int)state->egid);
1284: if (GID_CHANGED && setegid(state->egid)) {
1285: errstr = N_("unable to change to runas gid");
1286: goto bad;
1287: }
1288: state->grlist = runas_setgroups();
1289: state->ruid = ostate->ruid;
1290: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
1291: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
1292: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1293: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1294: if (seteuid(state->euid)) {
1295: errstr = N_("unable to change to runas uid");
1296: goto bad;
1297: }
1298: break;
1299:
1300: case PERM_SUDOERS:
1301: state->grlist = ostate->grlist;
1302: sudo_grlist_addref(state->grlist);
1303:
1304: /* assume euid == ROOT_UID, ruid == user */
1305: state->rgid = ostate->rgid;
1306: state->egid = sudoers_gid;
1307: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
1308: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1309: (int)ostate->egid, (int)state->rgid, (int)state->egid);
1310: if (GID_CHANGED && setegid(sudoers_gid)) {
1311: errstr = N_("unable to change to sudoers gid");
1312: goto bad;
1313: }
1314:
1315: state->ruid = ROOT_UID;
1316: /*
1317: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
1318: * we use a non-zero uid in order to avoid NFS lossage.
1319: * Using uid 1 is a bit bogus but should work on all OS's.
1320: */
1321: if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
1322: state->euid = 1;
1323: else
1324: state->euid = sudoers_uid;
1325: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
1326: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1327: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1328: if (seteuid(state->euid)) {
1329: snprintf(errbuf, sizeof(errbuf),
1330: "PERM_SUDOERS: seteuid(%d)", state->euid);
1331: goto bad;
1332: }
1333: break;
1334:
1335: case PERM_TIMESTAMP:
1336: state->grlist = ostate->grlist;
1337: sudo_grlist_addref(state->grlist);
1338: state->rgid = ostate->rgid;
1339: state->egid = ostate->egid;
1340: state->ruid = ROOT_UID;
1341: state->euid = timestamp_uid;
1342: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
1343: "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1344: (int)ostate->euid, (int)state->ruid, (int)state->euid);
1345: if (seteuid(timestamp_uid)) {
1346: snprintf(errbuf, sizeof(errbuf),
1347: "PERM_TIMESTAMP: seteuid(%d)", timestamp_uid);
1348: goto bad;
1349: }
1350: break;
1351: }
1352:
1353: perm_stack_depth++;
1354: debug_return_bool(1);
1355: bad:
1356: if (errno == EAGAIN)
1357: warningx(U_("%s: %s"), U_(errstr), U_("too many processes"));
1358: else
1359: warning("%s", U_(errstr));
1360: if (noexit)
1361: debug_return_bool(0);
1362: exit(1);
1363: }
1364:
1365: void
1366: restore_perms(void)
1367: {
1368: struct perm_state *state, *ostate;
1369: debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1370:
1371: if (perm_stack_depth < 2)
1372: debug_return;
1373:
1374: state = &perm_stack[perm_stack_depth - 1];
1375: ostate = &perm_stack[perm_stack_depth - 2];
1376: perm_stack_depth--;
1377:
1378: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
1379: __func__, (int)state->ruid, (int)state->euid,
1380: (int)ostate->ruid, (int)ostate->euid);
1381: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
1382: __func__, (int)state->rgid, (int)state->egid,
1383: (int)ostate->rgid, (int)ostate->egid);
1384:
1385: /*
1386: * Since we only have setuid() and seteuid() and semantics
1387: * for these calls differ on various systems, we set
1388: * real and effective uids to ROOT_UID initially to be safe.
1389: */
1390: if (seteuid(ROOT_UID)) {
1391: warningx("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID);
1392: goto bad;
1393: }
1394: if (setuid(ROOT_UID)) {
1395: warningx("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID,
1396: ROOT_UID, ROOT_UID);
1397: goto bad;
1398: }
1399:
1400: if (OID(egid) != -1 && setegid(ostate->egid)) {
1401: warning("setegid(%d)", (int)ostate->egid);
1402: goto bad;
1403: }
1404: if (state->grlist != ostate->grlist) {
1405: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1406: warning("setgroups()");
1407: goto bad;
1408: }
1409: }
1410: if (OID(euid) != -1 && seteuid(ostate->euid)) {
1411: warning("seteuid(%d)", ostate->euid);
1412: goto bad;
1413: }
1414: sudo_grlist_delref(state->grlist);
1415: debug_return;
1416:
1417: bad:
1418: exit(1);
1419: }
1420:
1421: #else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
1422:
1423: /*
1424: * Set uids and gids based on perm via setuid() and setgid().
1425: * NOTE: does not support the "stay_setuid" or timestampowner options.
1426: * Also, sudoers_uid and sudoers_gid are not used.
1427: */
1428: int
1429: set_perms(int perm)
1430: {
1431: struct perm_state *state, *ostate = NULL;
1432: char errbuf[1024];
1433: const char *errstr = errbuf;
1434: int noexit;
1435: debug_decl(set_perms, SUDO_DEBUG_PERMS)
1436:
1437: noexit = ISSET(perm, PERM_NOEXIT);
1438: CLR(perm, PERM_MASK);
1439:
1440: if (perm_stack_depth == PERM_STACK_MAX) {
1441: errstr = N_("perm stack overflow");
1442: errno = EINVAL;
1443: goto bad;
1444: }
1445:
1446: state = &perm_stack[perm_stack_depth];
1447: if (perm != PERM_INITIAL) {
1448: if (perm_stack_depth == 0) {
1449: errstr = N_("perm stack underflow");
1450: errno = EINVAL;
1451: goto bad;
1452: }
1453: ostate = &perm_stack[perm_stack_depth - 1];
1454: }
1455:
1456: switch (perm) {
1457: case PERM_INITIAL:
1458: /* Stash initial state */
1459: state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid();
1460: state->rgid = getgid();
1461: state->grlist = user_group_list;
1462: sudo_grlist_addref(state->grlist);
1463: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
1464: "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid);
1465: break;
1466:
1467: case PERM_ROOT:
1468: state->ruid = ROOT_UID;
1469: state->rgid = ROOT_GID;
1470: state->grlist = ostate->grlist;
1471: sudo_grlist_addref(state->grlist);
1472: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
1473: "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
1474: if (setuid(ROOT_UID)) {
1475: snprintf(errbuf, sizeof(errbuf), "PERM_ROOT: setuid(%d)", ROOT_UID);
1476: goto bad;
1477: }
1478: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
1479: "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
1480: if (setgid(ROOT_GID)) {
1481: errstr = N_("unable to change to root gid");
1482: goto bad;
1483: }
1484: break;
1485:
1486: case PERM_FULL_USER:
1487: state->rgid = user_gid;
1488: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
1489: "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
1490: (void) setgid(user_gid);
1491: state->grlist = user_group_list;
1492: sudo_grlist_addref(state->grlist);
1493: if (state->grlist != ostate->grlist) {
1494: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1495: errstr = "PERM_FULL_USER: setgroups";
1496: goto bad;
1497: }
1498: }
1499: state->ruid = user_uid;
1500: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
1501: "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
1502: if (setuid(user_uid)) {
1503: snprintf(errbuf, sizeof(errbuf),
1504: "PERM_FULL_USER: setuid(%d)", user_uid);
1505: goto bad;
1506: }
1507: break;
1508:
1509: case PERM_USER:
1510: case PERM_SUDOERS:
1511: case PERM_RUNAS:
1512: case PERM_TIMESTAMP:
1513: /* Unsupported since we can't set euid. */
1514: state->ruid = ostate->ruid;
1515: state->rgid = ostate->rgid;
1516: state->grlist = ostate->grlist;
1517: sudo_grlist_addref(state->grlist);
1518: break;
1519: }
1520:
1521: perm_stack_depth++;
1522: debug_return_bool(1);
1523: bad:
1524: if (errno == EAGAIN)
1525: warningx(U_("%s: %s"), U_(errstr), U_("too many processes"));
1526: else
1527: warning("%s", U_(errstr));
1528: if (noexit)
1529: debug_return_bool(0);
1530: exit(1);
1531: }
1532:
1533: void
1534: restore_perms(void)
1535: {
1536: struct perm_state *state, *ostate;
1537: debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1538:
1539: if (perm_stack_depth < 2)
1540: debug_return;
1541:
1542: state = &perm_stack[perm_stack_depth - 1];
1543: ostate = &perm_stack[perm_stack_depth - 2];
1544: perm_stack_depth--;
1545:
1546: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d] -> [%d]",
1547: __func__, (int)state->ruid, (int)ostate->ruid);
1548: sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d] -> [%d]",
1549: __func__, (int)state->rgid, (int)ostate->rgid);
1550:
1551: if (OID(rgid) != -1 && setgid(ostate->rgid)) {
1552: warning("setgid(%d)", (int)ostate->rgid);
1553: goto bad;
1554: }
1555: if (state->grlist != ostate->grlist) {
1556: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1557: warning("setgroups()");
1558: goto bad;
1559: }
1560: }
1561: sudo_grlist_delref(state->grlist);
1562: if (OID(ruid) != -1 && setuid(ostate->ruid)) {
1563: warning("setuid(%d)", (int)ostate->ruid);
1564: goto bad;
1565: }
1566: debug_return;
1567:
1568: bad:
1569: exit(1);
1570: }
1571: #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
1572:
1573: #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
1574: static struct group_list *
1575: runas_setgroups(void)
1576: {
1577: struct passwd *pw;
1578: struct group_list *grlist;
1579: debug_decl(runas_setgroups, SUDO_DEBUG_PERMS)
1580:
1581: if (def_preserve_groups) {
1582: sudo_grlist_addref(user_group_list);
1583: debug_return_ptr(user_group_list);
1584: }
1585:
1586: pw = runas_pw ? runas_pw : sudo_user.pw;
1587: #ifdef HAVE_SETAUTHDB
1588: aix_setauthdb(pw->pw_name);
1589: #endif
1590: grlist = sudo_get_grlist(pw);
1591: #ifdef HAVE_SETAUTHDB
1592: aix_restoreauthdb();
1593: #endif
1594: if (sudo_setgroups(grlist->ngids, grlist->gids) < 0)
1595: log_fatal(USE_ERRNO|MSG_ONLY, N_("unable to set runas group vector"));
1596: debug_return_ptr(grlist);
1597: }
1598: #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>