File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / privs.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

    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>