Annotation of embedaddon/quagga/lib/privs.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>