LCOV - code coverage report
Current view: top level - lib - privs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 32 77 41.6 %
Date: 2015-11-19 Functions: 3 7 42.9 %

          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             : }

Generated by: LCOV version 1.10