Annotation of embedaddon/quagga/lib/privs.c, revision 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>