Annotation of embedaddon/sudo/plugins/sudoers/set_perms.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1994-1996,1998-2011 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/param.h>
25: #include <sys/stat.h>
26: #include <stdio.h>
27: #ifdef STDC_HEADERS
28: # include <stdlib.h>
29: # include <stddef.h>
30: #else
31: # ifdef HAVE_STDLIB_H
32: # include <stdlib.h>
33: # endif
34: #endif /* STDC_HEADERS */
35: #ifdef HAVE_STRING_H
36: # include <string.h>
37: #endif /* HAVE_STRING_H */
38: #ifdef HAVE_STRINGS_H
39: # include <strings.h>
40: #endif /* HAVE_STRINGS_H */
41: #ifdef HAVE_UNISTD_H
42: # include <unistd.h>
43: #endif /* HAVE_UNISTD_H */
44: #include <pwd.h>
45: #include <errno.h>
46: #include <grp.h>
47:
48: #include "sudoers.h"
49:
50: /*
51: * Prototypes
52: */
53: static struct group_list *runas_setgroups(void);
54:
55: /*
56: * We keep track of the current permisstions and use a stack to restore
57: * the old permissions. A depth of 16 is overkill.
58: */
59: struct perm_state {
60: uid_t ruid;
61: uid_t euid;
62: #ifdef HAVE_SETRESUID
63: uid_t suid;
64: #endif
65: gid_t rgid;
66: gid_t egid;
67: #ifdef HAVE_SETRESUID
68: gid_t sgid;
69: #endif
70: struct group_list *grlist;
71: };
72:
73: #define PERM_STACK_MAX 16
74: static struct perm_state perm_stack[PERM_STACK_MAX];
75: static int perm_stack_depth = 0;
76:
77: #undef ID
78: #define ID(x) (state->x == ostate->x ? -1 : state->x)
79: #undef OID
80: #define OID(x) (ostate->x == state->x ? -1 : ostate->x)
81:
82: void
83: rewind_perms(void)
84: {
85: while (perm_stack_depth > 1)
86: restore_perms();
87: grlist_delref(perm_stack[0].grlist);
88: }
89:
90: #ifdef HAVE_SETRESUID
91:
92: /*
93: * Set real and effective and saved uids and gids based on perm.
94: * We always retain a saved uid of 0 unless we are headed for an exec().
95: * We only flip the effective gid since it only changes for PERM_SUDOERS.
96: * This version of set_perms() works fine with the "stay_setuid" option.
97: */
98: int
99: set_perms(int perm)
100: {
101: struct perm_state *state, *ostate = NULL;
102: const char *errstr;
103: int noexit;
104:
105: noexit = ISSET(perm, PERM_NOEXIT);
106: CLR(perm, PERM_MASK);
107:
108: if (perm_stack_depth == PERM_STACK_MAX) {
109: errstr = _("perm stack overflow");
110: errno = EINVAL;
111: goto bad;
112: }
113:
114: state = &perm_stack[perm_stack_depth];
115: if (perm != PERM_INITIAL) {
116: if (perm_stack_depth == 0) {
117: errstr = _("perm stack underflow");
118: errno = EINVAL;
119: goto bad;
120: }
121: ostate = &perm_stack[perm_stack_depth - 1];
122: if (memcmp(state, ostate, sizeof(*state)) == 0)
123: goto done;
124: }
125:
126: switch (perm) {
127: case PERM_INITIAL:
128: /* Stash initial state */
129: #ifdef HAVE_GETRESUID
130: if (getresuid(&state->ruid, &state->euid, &state->suid)) {
131: errstr = "getresuid";
132: goto bad;
133:
134: }
135: if (getresgid(&state->rgid, &state->egid, &state->sgid)) {
136: errstr = "getresgid";
137: goto bad;
138: }
139: #else
140: state->ruid = getuid();
141: state->euid = geteuid();
142: state->suid = state->euid; /* in case we are setuid */
143:
144: state->rgid = getgid();
145: state->egid = getegid();
146: state->sgid = state->egid; /* in case we are setgid */
147: #endif
148: state->grlist = user_group_list;
149: grlist_addref(state->grlist);
150: break;
151:
152: case PERM_ROOT:
153: state->ruid = ROOT_UID;
154: state->euid = ROOT_UID;
155: state->suid = ROOT_UID;
156: if (setresuid(ID(ruid), ID(euid), ID(suid))) {
157: errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)";
158: goto bad;
159: }
160: state->rgid = -1;
161: state->egid = -1;
162: state->sgid = -1;
163: state->grlist = ostate->grlist;
164: grlist_addref(state->grlist);
165: break;
166:
167: case PERM_USER:
168: state->rgid = -1;
169: state->egid = user_gid;
170: state->sgid = -1;
171: if (setresgid(-1, ID(egid), -1)) {
172: errstr = "setresgid(-1, user_gid, -1)";
173: goto bad;
174: }
175: state->grlist = user_group_list;
176: grlist_addref(state->grlist);
177: if (state->grlist != ostate->grlist) {
178: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
179: errstr = "setgroups()";
180: goto bad;
181: }
182: }
183: state->ruid = user_uid;
184: state->euid = user_uid;
185: state->suid = ROOT_UID;
186: if (setresuid(ID(ruid), ID(euid), ID(suid))) {
187: errstr = "setresuid(user_uid, user_uid, ROOT_UID)";
188: goto bad;
189: }
190: break;
191:
192: case PERM_FULL_USER:
193: /* headed for exec() */
194: state->rgid = user_gid;
195: state->egid = user_gid;
196: state->sgid = user_gid;
197: if (setresgid(ID(rgid), ID(egid), ID(sgid))) {
198: errstr = "setresgid(user_gid, user_gid, user_gid)";
199: goto bad;
200: }
201: state->grlist = user_group_list;
202: grlist_addref(state->grlist);
203: if (state->grlist != ostate->grlist) {
204: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
205: errstr = "setgroups()";
206: goto bad;
207: }
208: }
209: state->ruid = user_uid;
210: state->euid = user_uid;
211: state->suid = user_uid;
212: if (setresuid(ID(ruid), ID(euid), ID(suid))) {
213: errstr = "setresuid(user_uid, user_uid, user_uid)";
214: goto bad;
215: }
216: break;
217:
218: case PERM_RUNAS:
219: state->rgid = -1;
220: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
221: state->sgid = -1;
222: if (setresgid(-1, ID(egid), -1)) {
223: errstr = _("unable to change to runas gid");
224: goto bad;
225: }
226: state->grlist = runas_setgroups();
227: state->ruid = -1;
228: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
229: state->suid = -1;
230: if (setresuid(-1, ID(euid), -1)) {
231: errstr = _("unable to change to runas uid");
232: goto bad;
233: }
234: break;
235:
236: case PERM_SUDOERS:
237: state->grlist = ostate->grlist;
238: grlist_addref(state->grlist);
239:
240: /* assumes euid == ROOT_UID, ruid == user */
241: state->rgid = -1;
242: state->egid = sudoers_gid;
243: state->sgid = -1;
244: if (setresgid(-1, ID(egid), -1))
245: error(1, _("unable to change to sudoers gid"));
246:
247: state->ruid = ROOT_UID;
248: /*
249: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
250: * we use a non-zero uid in order to avoid NFS lossage.
251: * Using uid 1 is a bit bogus but should work on all OS's.
252: */
253: if (sudoers_uid == ROOT_UID && (sudoers_mode & 040))
254: state->euid = 1;
255: else
256: state->euid = sudoers_uid;
257: state->suid = ROOT_UID;
258: if (setresuid(ID(ruid), ID(euid), ID(suid))) {
259: errstr = "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)";
260: goto bad;
261: }
262: break;
263:
264: case PERM_TIMESTAMP:
265: state->grlist = ostate->grlist;
266: grlist_addref(state->grlist);
267: state->rgid = -1;
268: state->egid = -1;
269: state->sgid = -1;
270: state->ruid = ROOT_UID;
271: state->euid = timestamp_uid;
272: state->suid = ROOT_UID;
273: if (setresuid(ID(ruid), ID(euid), ID(suid))) {
274: errstr = "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)";
275: goto bad;
276: }
277: break;
278: }
279:
280: done:
281: perm_stack_depth++;
282: return 1;
283: bad:
284: /* XXX - better warnings inline */
285: warningx("%s: %s", errstr,
286: errno == EAGAIN ? _("too many processes") : strerror(errno));
287: if (noexit)
288: return 0;
289: exit(1);
290: }
291:
292: void
293: restore_perms(void)
294: {
295: struct perm_state *state, *ostate;
296:
297: if (perm_stack_depth < 2)
298: return;
299:
300: state = &perm_stack[perm_stack_depth - 1];
301: ostate = &perm_stack[perm_stack_depth - 2];
302: perm_stack_depth--;
303:
304: /* XXX - more cases here where euid != ruid */
305: if (OID(euid) == ROOT_UID && state->euid != ROOT_UID) {
306: if (setresuid(-1, ROOT_UID, -1)) {
307: warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
308: (int)state->ruid, (int)state->euid, (int)state->suid,
309: -1, ROOT_UID, -1);
310: goto bad;
311: }
312: }
313: if (setresuid(OID(ruid), OID(euid), OID(suid))) {
314: warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
315: (int)state->ruid, (int)state->euid, (int)state->suid,
316: (int)OID(ruid), (int)OID(euid), (int)OID(suid));
317: goto bad;
318: }
319: if (setresgid(OID(rgid), OID(egid), OID(sgid))) {
320: warning("setresgid() [%d, %d, %d] -> [%d, %d, %d]",
321: (int)state->rgid, (int)state->egid, (int)state->sgid,
322: (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
323: goto bad;
324: }
325: if (state->grlist != ostate->grlist) {
326: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
327: warning("setgroups()");
328: goto bad;
329: }
330: }
331: grlist_delref(state->grlist);
332: return;
333:
334: bad:
335: exit(1);
336: }
337:
338: #else
339: # ifdef HAVE_SETREUID
340:
341: /*
342: * Set real and effective uids and gids based on perm.
343: * We always retain a real or effective uid of ROOT_UID unless
344: * we are headed for an exec().
345: * This version of set_perms() works fine with the "stay_setuid" option.
346: */
347: int
348: set_perms(int perm)
349: {
350: struct perm_state *state, *ostate = NULL;
351: const char *errstr;
352: int noexit;
353:
354: noexit = ISSET(perm, PERM_NOEXIT);
355: CLR(perm, PERM_MASK);
356:
357: if (perm_stack_depth == PERM_STACK_MAX) {
358: errstr = _("perm stack overflow");
359: errno = EINVAL;
360: goto bad;
361: }
362:
363: state = &perm_stack[perm_stack_depth];
364: if (perm != PERM_INITIAL) {
365: if (perm_stack_depth == 0) {
366: errstr = _("perm stack underflow");
367: errno = EINVAL;
368: goto bad;
369: }
370: ostate = &perm_stack[perm_stack_depth - 1];
371: if (memcmp(state, ostate, sizeof(*state)) == 0)
372: goto done;
373: }
374:
375: switch (perm) {
376: case PERM_INITIAL:
377: /* Stash initial state */
378: state->ruid = getuid();
379: state->euid = geteuid();
380: state->rgid = getgid();
381: state->egid = getegid();
382: state->grlist = user_group_list;
383: grlist_addref(state->grlist);
384: break;
385:
386: case PERM_ROOT:
387: /*
388: * setreuid(0, 0) may fail on some systems
389: * when the euid is not already 0.
390: */
391: if (setreuid(-1, ROOT_UID)) {
392: errstr = "setreuid(-1, ROOT_UID)";
393: goto bad;
394: }
395: if (setuid(ROOT_UID)) {
396: errstr = "setuid(ROOT_UID)";
397: goto bad;
398: }
399: state->ruid = ROOT_UID;
400: state->euid = ROOT_UID;
401: state->rgid = -1;
402: state->egid = -1;
403: state->grlist = ostate->grlist;
404: grlist_addref(state->grlist);
405: break;
406:
407: case PERM_USER:
408: state->rgid = -1;
409: state->egid = user_gid;
410: if (setregid(-1, ID(egid))) {
411: errstr = "setregid(-1, user_gid)";
412: goto bad;
413: }
414: state->grlist = user_group_list;
415: grlist_addref(state->grlist);
416: if (state->grlist != ostate->grlist) {
417: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
418: errstr = "setgroups()";
419: goto bad;
420: }
421: }
422: state->ruid = ROOT_UID;
423: state->euid = user_uid;
424: if (setreuid(ID(ruid), ID(euid))) {
425: errstr = "setreuid(ROOT_UID, user_uid)";
426: goto bad;
427: }
428: break;
429:
430: case PERM_FULL_USER:
431: /* headed for exec() */
432: state->rgid = user_gid;
433: state->egid = user_gid;
434: if (setregid(ID(rgid), ID(egid))) {
435: errstr = "setregid(user_gid, user_gid)";
436: goto bad;
437: }
438: state->grlist = user_group_list;
439: grlist_addref(state->grlist);
440: if (state->grlist != ostate->grlist) {
441: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
442: errstr = "setgroups()";
443: goto bad;
444: }
445: }
446: state->ruid = user_uid;
447: state->euid = user_uid;
448: if (setreuid(ID(ruid), ID(euid))) {
449: errstr = "setreuid(user_uid, user_uid)";
450: goto bad;
451: }
452: break;
453:
454: case PERM_RUNAS:
455: state->rgid = -1;
456: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
457: if (setregid(ID(rgid), ID(egid))) {
458: errstr = _("unable to change to runas gid");
459: goto bad;
460: }
461: state->grlist = runas_setgroups();
462: state->ruid = ROOT_UID;
463: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
464: if (setreuid(ID(ruid), ID(euid))) {
465: errstr = _("unable to change to runas uid");
466: goto bad;
467: }
468: break;
469:
470: case PERM_SUDOERS:
471: state->grlist = ostate->grlist;
472: grlist_addref(state->grlist);
473:
474: /* assume euid == ROOT_UID, ruid == user */
475: state->rgid = -1;
476: state->egid = sudoers_gid;
477: if (setregid(-1, ID(egid)))
478: error(1, _("unable to change to sudoers gid"));
479:
480: state->ruid = ROOT_UID;
481: /*
482: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
483: * we use a non-zero uid in order to avoid NFS lossage.
484: * Using uid 1 is a bit bogus but should work on all OS's.
485: */
486: if (sudoers_uid == ROOT_UID && (sudoers_mode & 040))
487: state->euid = 1;
488: else
489: state->euid = sudoers_uid;
490: if (setreuid(ID(ruid), ID(euid))) {
491: errstr = "setreuid(ROOT_UID, SUDOERS_UID)";
492: goto bad;
493: }
494: break;
495:
496: case PERM_TIMESTAMP:
497: state->grlist = ostate->grlist;
498: grlist_addref(state->grlist);
499: state->rgid = -1;
500: state->egid = -1;
501: state->ruid = ROOT_UID;
502: state->euid = timestamp_uid;
503: if (setreuid(ID(ruid), ID(euid))) {
504: errstr = "setreuid(ROOT_UID, timestamp_uid)";
505: goto bad;
506: }
507: break;
508: }
509:
510: done:
511: perm_stack_depth++;
512: return 1;
513: bad:
514: /* XXX - better warnings inline */
515: warningx("%s: %s", errstr,
516: errno == EAGAIN ? _("too many processes") : strerror(errno));
517: if (noexit)
518: return 0;
519: exit(1);
520: }
521:
522: void
523: restore_perms(void)
524: {
525: struct perm_state *state, *ostate;
526:
527: if (perm_stack_depth < 2)
528: return;
529:
530: state = &perm_stack[perm_stack_depth - 1];
531: ostate = &perm_stack[perm_stack_depth - 2];
532: perm_stack_depth--;
533:
534: /*
535: * When changing euid to ROOT_UID, setreuid() may fail even if
536: * the ruid is ROOT_UID so call setuid() first.
537: */
538: if (OID(euid) == ROOT_UID) {
539: /* setuid() may not set the saved ID unless the euid is ROOT_UID */
540: if (ID(euid) != ROOT_UID)
541: (void)setreuid(-1, ROOT_UID);
542: if (setuid(ROOT_UID)) {
543: warning("setuid() [%d, %d] -> %d)", (int)state->ruid,
544: (int)state->euid, ROOT_UID);
545: goto bad;
546: }
547: }
548: if (setreuid(OID(ruid), OID(euid))) {
549: warning("setreuid() [%d, %d] -> [%d, %d]", (int)state->ruid,
550: (int)state->euid, (int)OID(ruid), (int)OID(euid));
551: goto bad;
552: }
553: if (setregid(OID(rgid), OID(egid))) {
554: warning("setregid() [%d, %d] -> [%d, %d]", (int)state->rgid,
555: (int)state->egid, (int)OID(rgid), (int)OID(egid));
556: goto bad;
557: }
558: if (state->grlist != ostate->grlist) {
559: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
560: warning("setgroups()");
561: goto bad;
562: }
563: }
564: grlist_delref(state->grlist);
565: return;
566:
567: bad:
568: exit(1);
569: }
570:
571: # else /* !HAVE_SETRESUID && !HAVE_SETREUID */
572: # ifdef HAVE_SETEUID
573:
574: /*
575: * Set real and effective uids and gids based on perm.
576: * We always retain a real or effective uid of ROOT_UID unless
577: * we are headed for an exec().
578: * This version of set_perms() works fine with the "stay_setuid" option.
579: */
580: int
581: set_perms(int perm)
582: {
583: struct perm_state *state, *ostate = NULL;
584: const char *errstr;
585: int noexit;
586:
587: noexit = ISSET(perm, PERM_NOEXIT);
588: CLR(perm, PERM_MASK);
589:
590: if (perm_stack_depth == PERM_STACK_MAX) {
591: errstr = _("perm stack overflow");
592: errno = EINVAL;
593: goto bad;
594: }
595:
596: state = &perm_stack[perm_stack_depth];
597: if (perm != PERM_INITIAL) {
598: if (perm_stack_depth == 0) {
599: errstr = _("perm stack underflow");
600: errno = EINVAL;
601: goto bad;
602: }
603: ostate = &perm_stack[perm_stack_depth - 1];
604: if (memcmp(state, ostate, sizeof(*state)) == 0)
605: goto done;
606: }
607:
608: /*
609: * Since we only have setuid() and seteuid() and semantics
610: * for these calls differ on various systems, we set
611: * real and effective uids to ROOT_UID initially to be safe.
612: */
613: if (perm != PERM_INITIAL) {
614: if (seteuid(ROOT_UID)) {
615: errstr = "seteuid(ROOT_UID)";
616: goto bad;
617: }
618: if (setuid(ROOT_UID)) {
619: errstr = "setuid(ROOT_UID)";
620: goto bad;
621: }
622: }
623:
624: switch (perm) {
625: case PERM_INITIAL:
626: /* Stash initial state */
627: state->ruid = getuid();
628: state->euid = geteuid();
629: state->rgid = getgid();
630: state->egid = getegid();
631: state->grlist = user_group_list;
632: grlist_addref(state->grlist);
633: break;
634:
635: case PERM_ROOT:
636: /* We already set ruid/euid above. */
637: state->ruid = ROOT_UID;
638: state->euid = ROOT_UID;
639: state->rgid = -1;
640: state->egid = -1;
641: state->grlist = ostate->grlist;
642: grlist_addref(state->grlist);
643: break;
644:
645: case PERM_USER:
646: state->egid = user_gid;
647: if (setegid(ID(egid))) {
648: errstr = "setegid(user_gid)";
649: goto bad;
650: }
651: state->grlist = user_group_list;
652: grlist_addref(state->grlist);
653: if (state->grlist != ostate->grlist) {
654: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
655: errstr = "setgroups()";
656: goto bad;
657: }
658: }
659: state->rgid = -1;
660: state->ruid = ROOT_UID;
661: state->euid = user_uid;
662: if (seteuid(ID(euid))) {
663: errstr = "seteuid(user_uid)";
664: goto bad;
665: }
666: break;
667:
668: case PERM_FULL_USER:
669: /* headed for exec() */
670: state->rgid = user_gid;
671: state->egid = user_gid;
672: if (setgid(user_gid)) {
673: errstr = "setgid(user_gid)";
674: goto bad;
675: }
676: state->grlist = user_group_list;
677: grlist_addref(state->grlist);
678: if (state->grlist != ostate->grlist) {
679: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
680: errstr = "setgroups()";
681: goto bad;
682: }
683: }
684: state->ruid = user_uid;
685: state->euid = user_uid;
686: if (setuid(user_uid)) {
687: errstr = "setuid(user_uid)";
688: goto bad;
689: }
690: break;
691:
692: case PERM_RUNAS:
693: state->rgid = -1;
694: state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
695: if (setegid(ID(egid))) {
696: errstr = _("unable to change to runas gid");
697: goto bad;
698: }
699: state->grlist = runas_setgroups();
700: state->ruid = -1;
701: state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
702: if (seteuid(ID(euid))) {
703: errstr = _("unable to change to runas uid");
704: goto bad;
705: }
706: break;
707:
708: case PERM_SUDOERS:
709: state->grlist = ostate->grlist;
710: grlist_addref(state->grlist);
711:
712: /* assume euid == ROOT_UID, ruid == user */
713: state->rgid = -1;
714: state->egid = sudoers_gid;
715: if (setegid(ID(egid)))
716: error(1, _("unable to change to sudoers gid"));
717:
718: state->ruid = ROOT_UID;
719: /*
720: * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
721: * we use a non-zero uid in order to avoid NFS lossage.
722: * Using uid 1 is a bit bogus but should work on all OS's.
723: */
724: if (sudoers_uid == ROOT_UID && (sudoers_mode & 040))
725: state->euid = 1;
726: else
727: state->euid = sudoers_uid;
728: if (seteuid(ID(euid))) {
729: errstr = "seteuid(SUDOERS_UID)";
730: goto bad;
731: }
732: break;
733:
734: case PERM_TIMESTAMP:
735: state->grlist = ostate->grlist;
736: grlist_addref(state->grlist);
737: state->rgid = -1;
738: state->egid = -1;
739: state->ruid = ROOT_UID;
740: state->euid = timestamp_uid;
741: if (seteuid(ID(euid))) {
742: errstr = "seteuid(timestamp_uid)";
743: goto bad;
744: }
745: break;
746: }
747:
748: done:
749: perm_stack_depth++;
750: return 1;
751: bad:
752: /* XXX - better warnings inline */
753: warningx("%s: %s", errstr,
754: errno == EAGAIN ? _("too many processes") : strerror(errno));
755: if (noexit)
756: return 0;
757: exit(1);
758: }
759:
760: void
761: restore_perms(void)
762: {
763: struct perm_state *state, *ostate;
764:
765: if (perm_stack_depth < 2)
766: return;
767:
768: state = &perm_stack[perm_stack_depth - 1];
769: ostate = &perm_stack[perm_stack_depth - 2];
770: perm_stack_depth--;
771:
772: /*
773: * Since we only have setuid() and seteuid() and semantics
774: * for these calls differ on various systems, we set
775: * real and effective uids to ROOT_UID initially to be safe.
776: */
777: if (seteuid(ROOT_UID)) {
778: errstr = "seteuid(ROOT_UID)";
779: goto bad;
780: }
781: if (setuid(ROOT_UID)) {
782: errstr = "setuid(ROOT_UID)";
783: goto bad;
784: }
785:
786: if (setegid(OID(egid))) {
787: warning("setegid(%d)", (int)OID(egid));
788: goto bad;
789: }
790: if (state->grlist != ostate->grlist) {
791: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
792: warning("setgroups()");
793: goto bad;
794: }
795: }
796: if (seteuid(OID(euid))) {
797: warning("seteuid(%d)", (int)OID(euid));
798: goto bad;
799: }
800: grlist_delref(state->grlist);
801: return;
802:
803: bad:
804: exit(1);
805: }
806:
807: # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
808:
809: /*
810: * Set uids and gids based on perm via setuid() and setgid().
811: * NOTE: does not support the "stay_setuid" or timestampowner options.
812: * Also, sudoers_uid and sudoers_gid are not used.
813: */
814: int
815: set_perms(int perm)
816: {
817: struct perm_state *state, *ostate = NULL;
818: const char *errstr;
819: int noexit;
820:
821: noexit = ISSET(perm, PERM_NOEXIT);
822: CLR(perm, PERM_MASK);
823:
824: if (perm_stack_depth == PERM_STACK_MAX) {
825: errstr = _("perm stack overflow");
826: errno = EINVAL;
827: goto bad;
828: }
829:
830: state = &perm_stack[perm_stack_depth];
831: if (perm != PERM_INITIAL) {
832: if (perm_stack_depth == 0) {
833: errstr = _("perm stack underflow");
834: errno = EINVAL;
835: goto bad;
836: }
837: ostate = &perm_stack[perm_stack_depth - 1];
838: if (memcmp(state, ostate, sizeof(*state)) == 0)
839: goto done;
840: }
841:
842: switch (perm) {
843: case PERM_INITIAL:
844: /* Stash initial state */
845: state->ruid = getuid();
846: state->rgid = getgid();
847: state->grlist = user_group_list;
848: grlist_addref(state->grlist);
849: break;
850:
851: case PERM_ROOT:
852: state->ruid = ROOT_UID;
853: state->rgid = -1;
854: state->grlist = ostate->grlist;
855: grlist_addref(state->grlist);
856: if (setuid(ROOT_UID)) {
857: errstr = "setuid(ROOT_UID)";
858: goto bad;
859: }
860: break;
861:
862: case PERM_FULL_USER:
863: state->rgid = user_gid;
864: (void) setgid(user_gid);
865: state->grlist = user_group_list;
866: grlist_addref(state->grlist);
867: if (state->grlist != ostate->grlist) {
868: if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
869: errstr = "setgroups()";
870: goto bad;
871: }
872: }
873: state->ruid = user_uid;
874: if (setuid(user_uid)) {
875: errstr = "setuid(user_uid)";
876: goto bad;
877: }
878: break;
879:
880: case PERM_USER:
881: case PERM_SUDOERS:
882: case PERM_RUNAS:
883: case PERM_TIMESTAMP:
884: /* Unsupported since we can't set euid. */
885: break;
886: }
887:
888: done:
889: perm_stack_depth++;
890: return 1;
891: bad:
892: /* XXX - better warnings inline */
893: warningx("%s: %s", errstr,
894: errno == EAGAIN ? _("too many processes") : strerror(errno));
895: if (noexit)
896: return 0;
897: exit(1);
898: }
899:
900: void
901: restore_perms(void)
902: {
903: struct perm_state *state, *ostate;
904:
905: if (perm_stack_depth < 2)
906: return;
907:
908: state = &perm_stack[perm_stack_depth - 1];
909: ostate = &perm_stack[perm_stack_depth - 2];
910: perm_stack_depth--;
911:
912: if (OID(rgid) != -1 && setgid(ostate->rgid)) {
913: warning("setgid(%d)", (int)ostate->rgid);
914: goto bad;
915: }
916: if (state->grlist != ostate->grlist) {
917: if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
918: warning("setgroups()");
919: goto bad;
920: }
921: }
922: grlist_delref(state->grlist);
923: if (OID(ruid) != -1 && setuid(ostate->ruid)) {
924: warning("setuid(%d)", (int)ostate->ruid);
925: goto bad;
926: }
927: return;
928:
929: bad:
930: exit(1);
931: }
932: # endif /* HAVE_SETEUID */
933: # endif /* HAVE_SETREUID */
934: #endif /* HAVE_SETRESUID */
935:
936: static struct group_list *
937: runas_setgroups(void)
938: {
939: struct passwd *pw;
940: struct group_list *grlist;
941:
942: if (def_preserve_groups) {
943: grlist_addref(user_group_list);
944: return user_group_list;
945: }
946:
947: pw = runas_pw ? runas_pw : sudo_user.pw;
948: #ifdef HAVE_SETAUTHDB
949: aix_setauthdb(pw->pw_name);
950: #endif
951: grlist = get_group_list(pw);
952: #ifdef HAVE_SETAUTHDB
953: aix_restoreauthdb();
954: #endif
955: if (sudo_setgroups(grlist->ngids, grlist->gids) < 0)
956: log_error(USE_ERRNO|MSG_ONLY, _("unable to set runas group vector"));
957: return grlist;
958: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>