Line data Source code
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 1070 : zprivs_change_uid (zebra_privs_ops_t op)
562 : {
563 :
564 1070 : if (op == ZPRIVS_RAISE)
565 535 : return seteuid (zprivs_state.zsuid);
566 535 : else if (op == ZPRIVS_LOWER)
567 535 : return seteuid (zprivs_state.zuid);
568 : else
569 0 : return -1;
570 : }
571 :
572 : zebra_privs_current_t
573 0 : zprivs_state_uid (void)
574 : {
575 0 : return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED);
576 : }
577 :
578 : int
579 0 : zprivs_change_null (zebra_privs_ops_t op)
580 : {
581 0 : return 0;
582 : }
583 :
584 : zebra_privs_current_t
585 0 : zprivs_state_null (void)
586 : {
587 0 : return zprivs_null_state;
588 : }
589 :
590 : void
591 45 : zprivs_init(struct zebra_privs_t *zprivs)
592 : {
593 45 : struct passwd *pwentry = NULL;
594 45 : struct group *grentry = NULL;
595 :
596 45 : if (!zprivs)
597 : {
598 0 : fprintf (stderr, "zprivs_init: called with NULL arg!\n");
599 0 : exit (1);
600 : }
601 :
602 : /* NULL privs */
603 45 : if (! (zprivs->user || zprivs->group
604 0 : || zprivs->cap_num_p || zprivs->cap_num_i) )
605 : {
606 0 : zprivs->change = zprivs_change_null;
607 0 : zprivs->current_state = zprivs_state_null;
608 0 : return;
609 : }
610 :
611 45 : if (zprivs->user)
612 : {
613 45 : if ( (pwentry = getpwnam (zprivs->user)) )
614 : {
615 45 : zprivs_state.zuid = pwentry->pw_uid;
616 : }
617 : else
618 : {
619 : /* cant use log.h here as it depends on vty */
620 0 : fprintf (stderr, "privs_init: could not lookup user %s\n",
621 : zprivs->user);
622 0 : exit (1);
623 : }
624 : }
625 :
626 45 : grentry = NULL;
627 :
628 45 : if (zprivs->vty_group)
629 : /* Add the vty_group to the supplementary groups so it can be chowned to */
630 : {
631 0 : if ( (grentry = getgrnam (zprivs->vty_group)) )
632 : {
633 0 : zprivs_state.vtygrp = grentry->gr_gid;
634 0 : if ( setgroups (1, &zprivs_state.vtygrp) )
635 : {
636 0 : fprintf (stderr, "privs_init: could not setgroups, %s\n",
637 0 : safe_strerror (errno) );
638 0 : exit (1);
639 : }
640 : }
641 : else
642 : {
643 0 : fprintf (stderr, "privs_init: could not lookup vty group %s\n",
644 : zprivs->vty_group);
645 0 : exit (1);
646 : }
647 : }
648 :
649 45 : if (zprivs->group)
650 : {
651 45 : if ( (grentry = getgrnam (zprivs->group)) )
652 : {
653 45 : zprivs_state.zgid = grentry->gr_gid;
654 : }
655 : else
656 : {
657 0 : fprintf (stderr, "privs_init: could not lookup group %s\n",
658 : zprivs->group);
659 0 : exit (1);
660 : }
661 : /* change group now, forever. uid we do later */
662 45 : if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
663 : {
664 0 : fprintf (stderr, "zprivs_init: could not setregid, %s\n",
665 0 : safe_strerror (errno) );
666 0 : 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 45 : zprivs_state.zsuid = geteuid();
680 45 : if ( zprivs_state.zuid )
681 : {
682 0 : if ( setreuid (-1, zprivs_state.zuid) )
683 : {
684 0 : fprintf (stderr, "privs_init (uid): could not setreuid, %s\n",
685 0 : safe_strerror (errno));
686 0 : exit (1);
687 : }
688 : }
689 :
690 45 : zprivs->change = zprivs_change_uid;
691 45 : zprivs->current_state = zprivs_state_uid;
692 : #endif /* HAVE_CAPABILITIES */
693 : }
694 :
695 : void
696 0 : zprivs_terminate (struct zebra_privs_t *zprivs)
697 : {
698 0 : if (!zprivs)
699 : {
700 0 : fprintf (stderr, "%s: no privs struct given, terminating", __func__);
701 0 : exit (0);
702 : }
703 :
704 : #ifdef HAVE_CAPABILITIES
705 : zprivs_caps_terminate();
706 : #else /* !HAVE_CAPABILITIES */
707 0 : if (zprivs_state.zuid)
708 : {
709 0 : if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
710 : {
711 0 : fprintf (stderr, "privs_terminate: could not setreuid, %s",
712 0 : safe_strerror (errno) );
713 0 : exit (1);
714 : }
715 : }
716 : #endif /* HAVE_LCAPS */
717 :
718 0 : zprivs->change = zprivs_change_null;
719 0 : zprivs->current_state = zprivs_state_null;
720 0 : zprivs_null_state = ZPRIVS_LOWERED;
721 0 : return;
722 : }
723 :
724 : void
725 45 : zprivs_get_ids(struct zprivs_ids_t *ids)
726 : {
727 :
728 45 : ids->uid_priv = getuid();
729 45 : (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid)
730 45 : : (ids->uid_normal = -1);
731 45 : (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid)
732 45 : : (ids->gid_normal = -1);
733 45 : (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp)
734 45 : : (ids->gid_vty = -1);
735 :
736 45 : return;
737 : }
|