Annotation of embedaddon/quagga/lib/privs.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Zebra privileges.
3: *
4: * Copyright (C) 2003 Paul Jakma.
5: * Copyright (C) 2005 Sun Microsystems, Inc.
6: *
7: * This file is part of GNU Zebra.
8: *
9: * GNU Zebra is free software; you can redistribute it and/or modify it
10: * under the terms of the GNU General Public License as published by the
11: * Free Software Foundation; either version 2, or (at your option) any
12: * later version.
13: *
14: * GNU Zebra is distributed in the hope that it will be useful, but
15: * WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17: * General Public License for more details.
18: *
19: * You should have received a copy of the GNU General Public License
20: * along with GNU Zebra; see the file COPYING. If not, write to the Free
21: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22: * 02111-1307, USA.
23: */
24: #include <zebra.h>
25: #include "log.h"
26: #include "privs.h"
27: #include "memory.h"
28:
29: #ifdef HAVE_CAPABILITIES
30: /* sort out some generic internal types for:
31: *
32: * privilege values (cap_value_t, priv_t) -> pvalue_t
33: * privilege set (..., priv_set_t) -> pset_t
34: * privilege working storage (cap_t, ...) -> pstorage_t
35: *
36: * values we think of as numeric (they're ints really, but we dont know)
37: * sets are mostly opaque, to hold a set of privileges, related in some way.
38: * storage binds together a set of sets we're interested in.
39: * (in reality: cap_value_t and priv_t are ints)
40: */
41: #ifdef HAVE_LCAPS
42: /* Linux doesn't have a 'set' type: a set of related privileges */
43: struct _pset {
44: int num;
45: cap_value_t *caps;
46: };
47: typedef cap_value_t pvalue_t;
48: typedef struct _pset pset_t;
49: typedef cap_t pstorage_t;
50:
51: #elif defined (HAVE_SOLARIS_CAPABILITIES)
52: typedef priv_t pvalue_t;
53: typedef priv_set_t pset_t;
54: typedef priv_set_t *pstorage_t;
55: #else /* neither LCAPS nor SOLARIS_CAPABILITIES */
56: #error "HAVE_CAPABILITIES defined, but neither LCAPS nor Solaris Capabilties!"
57: #endif /* HAVE_LCAPS */
58: #endif /* HAVE_CAPABILITIES */
59:
60: /* the default NULL state we report is RAISED, but could be LOWERED if
61: * zprivs_terminate is called and the NULL handler is installed.
62: */
63: static zebra_privs_current_t zprivs_null_state = ZPRIVS_RAISED;
64:
65: /* internal privileges state */
66: static struct _zprivs_t
67: {
68: #ifdef HAVE_CAPABILITIES
69: pstorage_t caps; /* working storage */
70: pset_t *syscaps_p; /* system-type requested permitted caps */
71: pset_t *syscaps_i; /* system-type requested inheritable caps */
72: #endif /* HAVE_CAPABILITIES */
73: uid_t zuid, /* uid to run as */
74: zsuid; /* saved uid */
75: gid_t zgid; /* gid to run as */
76: gid_t vtygrp; /* gid for vty sockets */
77: } zprivs_state;
78:
79: /* externally exported but not directly accessed functions */
80: #ifdef HAVE_CAPABILITIES
81: int zprivs_change_caps (zebra_privs_ops_t);
82: zebra_privs_current_t zprivs_state_caps (void);
83: #endif /* HAVE_CAPABILITIES */
84: int zprivs_change_uid (zebra_privs_ops_t);
85: zebra_privs_current_t zprivs_state_uid (void);
86: int zprivs_change_null (zebra_privs_ops_t);
87: zebra_privs_current_t zprivs_state_null (void);
88:
89: #ifdef HAVE_CAPABILITIES
90: /* internal capability API */
91: static pset_t *zcaps2sys (zebra_capabilities_t *, int);
92: static void zprivs_caps_init (struct zebra_privs_t *);
93: static void zprivs_caps_terminate (void);
94:
95: /* Map of Quagga abstract capabilities to system capabilities */
96: static struct
97: {
98: int num;
99: pvalue_t *system_caps;
100: } cap_map [ZCAP_MAX] =
101: {
102: #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */
103: [ZCAP_SETID] = { 2, (pvalue_t []) { CAP_SETGID,
104: CAP_SETUID }, },
105: [ZCAP_BIND] = { 2, (pvalue_t []) { CAP_NET_BIND_SERVICE,
106: CAP_NET_BROADCAST }, },
107: [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { CAP_NET_ADMIN }, },
108: [ZCAP_NET_RAW] = { 1, (pvalue_t []) { CAP_NET_RAW }, },
109: [ZCAP_CHROOT] = { 1, (pvalue_t []) { CAP_SYS_CHROOT, }, },
110: [ZCAP_NICE] = { 1, (pvalue_t []) { CAP_SYS_NICE }, },
111: [ZCAP_PTRACE] = { 1, (pvalue_t []) { CAP_SYS_PTRACE }, },
112: [ZCAP_DAC_OVERRIDE] = { 1, (pvalue_t []) { CAP_DAC_OVERRIDE }, },
113: [ZCAP_READ_SEARCH] = { 1, (pvalue_t []) { CAP_DAC_READ_SEARCH }, },
114: [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { CAP_SYS_ADMIN }, },
115: [ZCAP_FOWNER] = { 1, (pvalue_t []) { CAP_FOWNER }, },
116: #elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */
117: /* Quagga -> Solaris privilege mappings */
118: [ZCAP_SETID] = { 1, (pvalue_t []) { PRIV_PROC_SETID }, },
119: [ZCAP_BIND] = { 1, (pvalue_t []) { PRIV_NET_PRIVADDR }, },
120: /* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */
121: #ifdef PRIV_SYS_IP_CONFIG
122: [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_IP_CONFIG }, },
123: #else
124: [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_NET_CONFIG }, },
125: #endif
126: [ZCAP_NET_RAW] = { 2, (pvalue_t []) { PRIV_NET_RAWACCESS,
127: PRIV_NET_ICMPACCESS }, },
128: [ZCAP_CHROOT] = { 1, (pvalue_t []) { PRIV_PROC_CHROOT }, },
129: [ZCAP_NICE] = { 1, (pvalue_t []) { PRIV_PROC_PRIOCNTL }, },
130: [ZCAP_PTRACE] = { 1, (pvalue_t []) { PRIV_PROC_SESSION }, },
131: [ZCAP_DAC_OVERRIDE] = { 2, (pvalue_t []) { PRIV_FILE_DAC_EXECUTE,
132: PRIV_FILE_DAC_READ,
133: PRIV_FILE_DAC_SEARCH,
134: PRIV_FILE_DAC_WRITE,
135: PRIV_FILE_DAC_SEARCH }, },
136: [ZCAP_READ_SEARCH] = { 2, (pvalue_t []) { PRIV_FILE_DAC_SEARCH,
137: PRIV_FILE_DAC_READ }, },
138: [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_ADMIN }, },
139: [ZCAP_FOWNER] = { 1, (pvalue_t []) { PRIV_FILE_OWNER }, },
140: #endif /* HAVE_SOLARIS_CAPABILITIES */
141: };
142:
143: #ifdef HAVE_LCAPS
144: /* Linux forms of capabilities methods */
145: /* convert zebras privileges to system capabilities */
146: static pset_t *
147: zcaps2sys (zebra_capabilities_t *zcaps, int num)
148: {
149: pset_t *syscaps;
150: int i, j = 0, count = 0;
151:
152: if (!num)
153: return NULL;
154:
155: /* first count up how many system caps we have */
156: for (i= 0; i < num; i++)
157: count += cap_map[zcaps[i]].num;
158:
159: if ( (syscaps = XCALLOC (MTYPE_PRIVS, (sizeof(pset_t) * num))) == NULL)
160: {
161: fprintf (stderr, "%s: could not allocate syscaps!", __func__);
162: return NULL;
163: }
164:
165: syscaps->caps = XCALLOC (MTYPE_PRIVS, (sizeof (pvalue_t) * count));
166:
167: if (!syscaps->caps)
168: {
169: fprintf (stderr, "%s: could not XCALLOC caps!", __func__);
170: return NULL;
171: }
172:
173: /* copy the capabilities over */
174: count = 0;
175: for (i=0; i < num; i++)
176: for (j = 0; j < cap_map[zcaps[i]].num; j++)
177: syscaps->caps[count++] = cap_map[zcaps[i]].system_caps[j];
178:
179: /* iterations above should be exact same as previous count, obviously.. */
180: syscaps->num = count;
181:
182: return syscaps;
183: }
184:
185: /* set or clear the effective capabilities to/from permitted */
186: int
187: zprivs_change_caps (zebra_privs_ops_t op)
188: {
189: cap_flag_value_t cflag;
190:
191: /* should be no possibility of being called without valid caps */
192: assert (zprivs_state.syscaps_p && zprivs_state.caps);
193: if (! (zprivs_state.syscaps_p && zprivs_state.caps))
194: exit (1);
195:
196: if (op == ZPRIVS_RAISE)
197: cflag = CAP_SET;
198: else if (op == ZPRIVS_LOWER)
199: cflag = CAP_CLEAR;
200: else
201: return -1;
202:
203: if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE,
204: zprivs_state.syscaps_p->num,
205: zprivs_state.syscaps_p->caps,
206: cflag))
207: return cap_set_proc (zprivs_state.caps);
208: return -1;
209: }
210:
211: zebra_privs_current_t
212: zprivs_state_caps (void)
213: {
214: int i;
215: cap_flag_value_t val;
216:
217: /* should be no possibility of being called without valid caps */
218: assert (zprivs_state.syscaps_p && zprivs_state.caps);
219: if (! (zprivs_state.syscaps_p && zprivs_state.caps))
220: exit (1);
221:
222: for (i=0; i < zprivs_state.syscaps_p->num; i++)
223: {
224: if ( cap_get_flag (zprivs_state.caps, zprivs_state.syscaps_p->caps[i],
225: CAP_EFFECTIVE, &val) )
226: {
227: zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
228: safe_strerror (errno) );
229: return ZPRIVS_UNKNOWN;
230: }
231: if (val == CAP_SET)
232: return ZPRIVS_RAISED;
233: }
234: return ZPRIVS_LOWERED;
235: }
236:
237: static void
238: zprivs_caps_init (struct zebra_privs_t *zprivs)
239: {
240: zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
241: zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
242:
243: /* Tell kernel we want caps maintained across uid changes */
244: if ( prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1 )
245: {
246: fprintf (stderr, "privs_init: could not set PR_SET_KEEPCAPS, %s\n",
247: safe_strerror (errno) );
248: exit(1);
249: }
250:
251: if ( !zprivs_state.syscaps_p )
252: {
253: fprintf (stderr, "privs_init: capabilities enabled, "
254: "but no capabilities supplied\n");
255: }
256:
257: /* we have caps, we have no need to ever change back the original user */
258: if (zprivs_state.zuid)
259: {
260: if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
261: {
262: fprintf (stderr, "zprivs_init (cap): could not setreuid, %s\n",
263: safe_strerror (errno));
264: exit (1);
265: }
266: }
267:
268: if ( !(zprivs_state.caps = cap_init()) )
269: {
270: fprintf (stderr, "privs_init: failed to cap_init, %s\n",
271: safe_strerror (errno));
272: exit (1);
273: }
274:
275: if ( cap_clear (zprivs_state.caps) )
276: {
277: fprintf (stderr, "privs_init: failed to cap_clear, %s\n",
278: safe_strerror (errno));
279: exit (1);
280: }
281:
282: /* set permitted caps */
283: cap_set_flag(zprivs_state.caps, CAP_PERMITTED,
284: zprivs_state.syscaps_p->num,
285: zprivs_state.syscaps_p->caps,
286: CAP_SET);
287:
288: /* set inheritable caps, if any */
289: if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
290: {
291: cap_set_flag(zprivs_state.caps, CAP_INHERITABLE,
292: zprivs_state.syscaps_i->num,
293: zprivs_state.syscaps_i->caps,
294: CAP_SET);
295: }
296:
297: /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as
298: * and when, and only when, they are needed.
299: */
300: if ( cap_set_proc (zprivs_state.caps) )
301: {
302: fprintf (stderr, "privs_init: initial cap_set_proc failed\n");
303: exit (1);
304: }
305:
306: /* set methods for the caller to use */
307: zprivs->change = zprivs_change_caps;
308: zprivs->current_state = zprivs_state_caps;
309: }
310:
311: static void
312: zprivs_caps_terminate (void)
313: {
314: /* clear all capabilities */
315: if (zprivs_state.caps)
316: cap_clear (zprivs_state.caps);
317:
318: /* and boom, capabilities are gone forever */
319: if ( cap_set_proc (zprivs_state.caps) )
320: {
321: fprintf (stderr, "privs_terminate: cap_set_proc failed, %s",
322: safe_strerror (errno) );
323: exit (1);
324: }
325:
326: /* free up private state */
327: if (zprivs_state.syscaps_p->num)
328: {
329: XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p->caps);
330: XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p);
331: }
332:
333: if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num)
334: {
335: XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i->caps);
336: XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i);
337: }
338:
339: cap_free (zprivs_state.caps);
340: }
341: #elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */
342:
343: /* Solaris specific capability/privilege methods
344: *
345: * Resources:
346: * - the 'privileges' man page
347: * - http://cvs.opensolaris.org
348: * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1
349: */
350:
351: /* convert zebras privileges to system capabilities */
352: static pset_t *
353: zcaps2sys (zebra_capabilities_t *zcaps, int num)
354: {
355: pset_t *syscaps;
356: int i, j = 0;
357:
358: if ((syscaps = priv_allocset()) == NULL)
359: {
360: fprintf (stderr, "%s: could not allocate syscaps!\n", __func__);
361: exit (1);
362: }
363:
364: priv_emptyset (syscaps);
365:
366: for (i=0; i < num; i++)
367: for (j = 0; j < cap_map[zcaps[i]].num; j++)
368: priv_addset (syscaps, cap_map[zcaps[i]].system_caps[j]);
369:
370: return syscaps;
371: }
372:
373: /* callback exported to users to RAISE and LOWER effective privileges
374: * from nothing to the given permitted set and back down
375: */
376: int
377: zprivs_change_caps (zebra_privs_ops_t op)
378: {
379:
380: /* should be no possibility of being called without valid caps */
381: assert (zprivs_state.syscaps_p);
382: if (!zprivs_state.syscaps_p)
383: {
384: fprintf (stderr, "%s: Eek, missing caps!", __func__);
385: exit (1);
386: }
387:
388: /* to raise: copy original permitted into our working effective set
389: * to lower: just clear the working effective set
390: */
391: if (op == ZPRIVS_RAISE)
392: priv_copyset (zprivs_state.syscaps_p, zprivs_state.caps);
393: else if (op == ZPRIVS_LOWER)
394: priv_emptyset (zprivs_state.caps);
395: else
396: return -1;
397:
398: if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0)
399: return -1;
400:
401: return 0;
402: }
403:
404: /* Retrieve current privilege state, is it RAISED or LOWERED? */
405: zebra_privs_current_t
406: zprivs_state_caps (void)
407: {
408: zebra_privs_current_t result;
409: pset_t *effective;
410:
411: if ( (effective = priv_allocset()) == NULL)
412: {
413: fprintf (stderr, "%s: failed to get priv_allocset! %s\n", __func__,
414: safe_strerror (errno));
415: return ZPRIVS_UNKNOWN;
416: }
417:
418: if (getppriv (PRIV_EFFECTIVE, effective))
419: {
420: fprintf (stderr, "%s: failed to get state! %s\n", __func__,
421: safe_strerror (errno));
422: result = ZPRIVS_UNKNOWN;
423: }
424: else
425: {
426: if (priv_isemptyset (effective) == B_TRUE)
427: result = ZPRIVS_LOWERED;
428: else
429: result = ZPRIVS_RAISED;
430: }
431:
432: if (effective)
433: priv_freeset (effective);
434:
435: return result;
436: }
437:
438: static void
439: zprivs_caps_init (struct zebra_privs_t *zprivs)
440: {
441: pset_t *basic;
442: pset_t *empty;
443:
444: /* the specified sets */
445: zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
446: zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i);
447:
448: /* nonsensical to have gotten here but not have capabilities */
449: if (!zprivs_state.syscaps_p)
450: {
451: fprintf (stderr, "%s: capabilities enabled, "
452: "but no valid capabilities supplied\n",
453: __func__);
454: }
455:
456: /* We retain the basic set in our permitted set, as Linux has no
457: * equivalent. The basic set on Linux hence is implicit, always
458: * there.
459: */
460: if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL)
461: {
462: fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
463: exit (1);
464: }
465:
466: /* Add the basic set to the permitted set */
467: priv_union (basic, zprivs_state.syscaps_p);
468: priv_freeset (basic);
469:
470: /* we need an empty set for 'effective', potentially for inheritable too */
471: if ( (empty = priv_allocset()) == NULL)
472: {
473: fprintf (stderr, "%s: couldn't get empty set!\n", __func__);
474: exit (1);
475: }
476: priv_emptyset (empty);
477:
478: /* Hey kernel, we know about privileges!
479: * this isn't strictly required, use of setppriv should have same effect
480: */
481: if (setpflags (PRIV_AWARE, 1))
482: {
483: fprintf (stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__,
484: safe_strerror (errno) );
485: exit (1);
486: }
487:
488: /* need either valid or empty sets for both p and i.. */
489: assert (zprivs_state.syscaps_i && zprivs_state.syscaps_p);
490:
491: /* we have caps, we have no need to ever change back the original user
492: * change real, effective and saved to the specified user.
493: */
494: if (zprivs_state.zuid)
495: {
496: if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
497: {
498: fprintf (stderr, "%s: could not setreuid, %s\n",
499: __func__, safe_strerror (errno));
500: exit (1);
501: }
502: }
503:
504: /* set the permitted set */
505: if (setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p))
506: {
507: fprintf (stderr, "%s: error setting permitted set!, %s\n", __func__,
508: safe_strerror (errno) );
509: exit (1);
510: }
511:
512: /* set the inheritable set */
513: if (setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i))
514: {
515: fprintf (stderr, "%s: error setting inheritable set!, %s\n", __func__,
516: safe_strerror (errno) );
517: exit (1);
518: }
519:
520: /* now clear the effective set and we're ready to go */
521: if (setppriv (PRIV_SET, PRIV_EFFECTIVE, empty))
522: {
523: fprintf (stderr, "%s: error setting effective set!, %s\n", __func__,
524: safe_strerror (errno) );
525: exit (1);
526: }
527:
528: /* we'll use this as our working-storage privset */
529: zprivs_state.caps = empty;
530:
531: /* set methods for the caller to use */
532: zprivs->change = zprivs_change_caps;
533: zprivs->current_state = zprivs_state_caps;
534: }
535:
536: static void
537: zprivs_caps_terminate (void)
538: {
539: assert (zprivs_state.caps);
540:
541: /* clear all capabilities */
542: priv_emptyset (zprivs_state.caps);
543: setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps);
544: setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps);
545: setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps);
546:
547: /* free up private state */
548: if (zprivs_state.syscaps_p)
549: priv_freeset (zprivs_state.syscaps_p);
550: if (zprivs_state.syscaps_i)
551: priv_freeset (zprivs_state.syscaps_i);
552:
553: priv_freeset (zprivs_state.caps);
554: }
555: #else /* !HAVE_LCAPS && ! HAVE_SOLARIS_CAPABILITIES */
556: #error "Neither Solaris nor Linux capabilities, dazed and confused..."
557: #endif /* HAVE_LCAPS */
558: #endif /* HAVE_CAPABILITIES */
559:
560: int
561: zprivs_change_uid (zebra_privs_ops_t op)
562: {
563:
564: if (op == ZPRIVS_RAISE)
565: return seteuid (zprivs_state.zsuid);
566: else if (op == ZPRIVS_LOWER)
567: return seteuid (zprivs_state.zuid);
568: else
569: return -1;
570: }
571:
572: zebra_privs_current_t
573: zprivs_state_uid (void)
574: {
575: return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED);
576: }
577:
578: int
579: zprivs_change_null (zebra_privs_ops_t op)
580: {
581: return 0;
582: }
583:
584: zebra_privs_current_t
585: zprivs_state_null (void)
586: {
587: return zprivs_null_state;
588: }
589:
590: void
591: zprivs_init(struct zebra_privs_t *zprivs)
592: {
593: struct passwd *pwentry = NULL;
594: struct group *grentry = NULL;
595:
596: if (!zprivs)
597: {
598: fprintf (stderr, "zprivs_init: called with NULL arg!\n");
599: exit (1);
600: }
601:
602: /* NULL privs */
603: if (! (zprivs->user || zprivs->group
604: || zprivs->cap_num_p || zprivs->cap_num_i) )
605: {
606: zprivs->change = zprivs_change_null;
607: zprivs->current_state = zprivs_state_null;
608: return;
609: }
610:
611: if (zprivs->user)
612: {
613: if ( (pwentry = getpwnam (zprivs->user)) )
614: {
615: zprivs_state.zuid = pwentry->pw_uid;
616: }
617: else
618: {
619: /* cant use log.h here as it depends on vty */
620: fprintf (stderr, "privs_init: could not lookup user %s\n",
621: zprivs->user);
622: exit (1);
623: }
624: }
625:
626: grentry = NULL;
627:
628: if (zprivs->vty_group)
629: /* Add the vty_group to the supplementary groups so it can be chowned to */
630: {
631: if ( (grentry = getgrnam (zprivs->vty_group)) )
632: {
633: zprivs_state.vtygrp = grentry->gr_gid;
634: if ( setgroups (1, &zprivs_state.vtygrp) )
635: {
636: fprintf (stderr, "privs_init: could not setgroups, %s\n",
637: safe_strerror (errno) );
638: exit (1);
639: }
640: }
641: else
642: {
643: fprintf (stderr, "privs_init: could not lookup vty group %s\n",
644: zprivs->vty_group);
645: exit (1);
646: }
647: }
648:
649: if (zprivs->group)
650: {
651: if ( (grentry = getgrnam (zprivs->group)) )
652: {
653: zprivs_state.zgid = grentry->gr_gid;
654: }
655: else
656: {
657: fprintf (stderr, "privs_init: could not lookup group %s\n",
658: zprivs->group);
659: exit (1);
660: }
661: /* change group now, forever. uid we do later */
662: if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
663: {
664: fprintf (stderr, "zprivs_init: could not setregid, %s\n",
665: safe_strerror (errno) );
666: exit (1);
667: }
668: }
669:
670: #ifdef HAVE_CAPABILITIES
671: zprivs_caps_init (zprivs);
672: #else /* !HAVE_CAPABILITIES */
673: /* we dont have caps. we'll need to maintain rid and saved uid
674: * and change euid back to saved uid (who we presume has all neccessary
675: * privileges) whenever we are asked to raise our privileges.
676: *
677: * This is not worth that much security wise, but all we can do.
678: */
679: zprivs_state.zsuid = geteuid();
680: if ( zprivs_state.zuid )
681: {
682: if ( setreuid (-1, zprivs_state.zuid) )
683: {
684: fprintf (stderr, "privs_init (uid): could not setreuid, %s\n",
685: safe_strerror (errno));
686: exit (1);
687: }
688: }
689:
690: zprivs->change = zprivs_change_uid;
691: zprivs->current_state = zprivs_state_uid;
692: #endif /* HAVE_CAPABILITIES */
693: }
694:
695: void
696: zprivs_terminate (struct zebra_privs_t *zprivs)
697: {
698: if (!zprivs)
699: {
700: fprintf (stderr, "%s: no privs struct given, terminating", __func__);
701: exit (0);
702: }
703:
704: #ifdef HAVE_CAPABILITIES
705: zprivs_caps_terminate();
706: #else /* !HAVE_CAPABILITIES */
707: if (zprivs_state.zuid)
708: {
709: if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
710: {
711: fprintf (stderr, "privs_terminate: could not setreuid, %s",
712: safe_strerror (errno) );
713: exit (1);
714: }
715: }
716: #endif /* HAVE_LCAPS */
717:
718: zprivs->change = zprivs_change_null;
719: zprivs->current_state = zprivs_state_null;
720: zprivs_null_state = ZPRIVS_LOWERED;
721: return;
722: }
723:
724: void
725: zprivs_get_ids(struct zprivs_ids_t *ids)
726: {
727:
728: ids->uid_priv = getuid();
729: (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
730: : (ids->uid_normal = -1);
731: (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
732: : (ids->gid_normal = -1);
733: (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
734: : (ids->gid_vty = -1);
735:
736: return;
737: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>