Diff for /embedaddon/quagga/lib/privs.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 17:26:12 version 1.1.1.2, 2016/11/02 10:09:11
Line 2 Line 2
  * Zebra privileges.   * Zebra privileges.
  *   *
  * Copyright (C) 2003 Paul Jakma.   * Copyright (C) 2003 Paul Jakma.
 * Copyright (C) 2005 Sun Microsystems, Inc. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  *   *
  * This file is part of GNU Zebra.   * This file is part of GNU Zebra.
  *   *
Line 47  struct _pset { Line 47  struct _pset {
 typedef cap_value_t pvalue_t;  typedef cap_value_t pvalue_t;
 typedef struct _pset pset_t;  typedef struct _pset pset_t;
 typedef cap_t pstorage_t;  typedef cap_t pstorage_t;
 #elif defined (HAVE_SOLARIS_CAPABILITIES)  #elif defined (HAVE_SOLARIS_CAPABILITIES)
 typedef priv_t pvalue_t;  typedef priv_t pvalue_t;
 typedef priv_set_t pset_t;  typedef priv_set_t pset_t;
Line 56  typedef priv_set_t *pstorage_t; Line 56  typedef priv_set_t *pstorage_t;
 #error "HAVE_CAPABILITIES defined, but neither LCAPS nor Solaris Capabilties!"  #error "HAVE_CAPABILITIES defined, but neither LCAPS nor Solaris Capabilties!"
 #endif /* HAVE_LCAPS */  #endif /* HAVE_LCAPS */
 #endif /* HAVE_CAPABILITIES */  #endif /* HAVE_CAPABILITIES */
 /* the default NULL state we report is RAISED, but could be LOWERED if  /* the default NULL state we report is RAISED, but could be LOWERED if
  * zprivs_terminate is called and the NULL handler is installed.   * zprivs_terminate is called and the NULL handler is installed.
  */   */
Line 102  static struct Line 102  static struct
 #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */  #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */
   [ZCAP_SETID] =        { 2, (pvalue_t []) { CAP_SETGID,    [ZCAP_SETID] =        { 2, (pvalue_t []) { CAP_SETGID,
                                              CAP_SETUID                 }, },                                               CAP_SETUID                 }, },
  [ZCAP_BIND] =         { 2, (pvalue_t []) { CAP_NET_BIND_SERVICE,  [ZCAP_BIND] =         { 2, (pvalue_t []) { CAP_NET_BIND_SERVICE       }, },
                                             CAP_NET_BROADCAST          }, }, 
   [ZCAP_NET_ADMIN] =    { 1, (pvalue_t []) { CAP_NET_ADMIN              }, },    [ZCAP_NET_ADMIN] =    { 1, (pvalue_t []) { CAP_NET_ADMIN              }, },
   [ZCAP_NET_RAW] =      { 1, (pvalue_t []) { CAP_NET_RAW                }, },    [ZCAP_NET_RAW] =      { 1, (pvalue_t []) { CAP_NET_RAW                }, },
   [ZCAP_CHROOT] =       { 1, (pvalue_t []) { CAP_SYS_CHROOT,            }, },    [ZCAP_CHROOT] =       { 1, (pvalue_t []) { CAP_SYS_CHROOT,            }, },
Line 139  static struct Line 138  static struct
   [ZCAP_FOWNER] =       { 1, (pvalue_t []) { PRIV_FILE_OWNER            }, },    [ZCAP_FOWNER] =       { 1, (pvalue_t []) { PRIV_FILE_OWNER            }, },
 #endif /* HAVE_SOLARIS_CAPABILITIES */  #endif /* HAVE_SOLARIS_CAPABILITIES */
 };  };
 #ifdef HAVE_LCAPS  #ifdef HAVE_LCAPS
 /* Linux forms of capabilities methods */  /* Linux forms of capabilities methods */
 /* convert zebras privileges to system capabilities */  /* convert zebras privileges to system capabilities */
Line 299  zprivs_caps_init (struct zebra_privs_t *zprivs) Line 298  zprivs_caps_init (struct zebra_privs_t *zprivs)
    */     */
   if ( cap_set_proc (zprivs_state.caps) )     if ( cap_set_proc (zprivs_state.caps) ) 
     {      {
      fprintf (stderr, "privs_init: initial cap_set_proc failed\n");      cap_t current_caps;
       char *current_caps_text = NULL;
       char *wanted_caps_text = NULL;
 
       fprintf(stderr, "privs_init: initial cap_set_proc failed: %s\n",
               safe_strerror(errno));
 
       current_caps = cap_get_proc();
       if (current_caps)
           current_caps_text = cap_to_text(current_caps, NULL);
 
       wanted_caps_text = cap_to_text(zprivs_state.caps, NULL);
       fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???");
       fprintf(stderr, "Have   caps: %s\n", current_caps_text ? current_caps_text : "???");
 
       exit (1);        exit (1);
     }      }
       
Line 339  zprivs_caps_terminate (void) Line 352  zprivs_caps_terminate (void)
   cap_free (zprivs_state.caps);    cap_free (zprivs_state.caps);
 }  }
 #elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */  #elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */
 /* Solaris specific capability/privilege methods   /* Solaris specific capability/privilege methods 
  *   *
  * Resources:   * Resources:
Line 348  zprivs_caps_terminate (void) Line 361  zprivs_caps_terminate (void)
  * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1   * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1
  */   */
   
   static pset_t *
   zprivs_caps_minimal ()
   {
     pset_t *minimal;
   
     if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL)
       {
         fprintf (stderr, "%s: couldn't get basic set!\n", __func__);
         exit (1);
       }
   
      /* create a minimal privilege set from the basic set */
     (void) priv_delset(minimal, PRIV_PROC_EXEC);
     (void) priv_delset(minimal, PRIV_PROC_INFO);
     (void) priv_delset(minimal, PRIV_PROC_SESSION);
     (void) priv_delset(minimal, PRIV_FILE_LINK_ANY);
   
     return  minimal;
   }
   
 /* convert zebras privileges to system capabilities */  /* convert zebras privileges to system capabilities */
 static pset_t *  static pset_t *
 zcaps2sys (zebra_capabilities_t *zcaps, int num)  zcaps2sys (zebra_capabilities_t *zcaps, int num)
Line 376  zcaps2sys (zebra_capabilities_t *zcaps, int num) Line 409  zcaps2sys (zebra_capabilities_t *zcaps, int num)
 int   int 
 zprivs_change_caps (zebra_privs_ops_t op)  zprivs_change_caps (zebra_privs_ops_t op)
 {  {
     pset_t *privset;
       
   /* should be no possibility of being called without valid caps */    /* should be no possibility of being called without valid caps */
   assert (zprivs_state.syscaps_p);    assert (zprivs_state.syscaps_p);
   if (!zprivs_state.syscaps_p)    if (!zprivs_state.syscaps_p)
     {      {
         fprintf (stderr, "%s: Eek, missing privileged caps!", __func__);
         exit (1);
       }
   
     assert (zprivs_state.caps);
     if (!zprivs_state.caps)
       {
       fprintf (stderr, "%s: Eek, missing caps!", __func__);        fprintf (stderr, "%s: Eek, missing caps!", __func__);
       exit (1);        exit (1);
     }      }
  
  /* to raise: copy original permitted into our working effective set  /* to raise: copy original permitted as our working effective set
   * to lower: just clear the working effective set   * to lower: copy regular effective set stored in zprivs_state.caps
    */     */
   if (op == ZPRIVS_RAISE)    if (op == ZPRIVS_RAISE)
    priv_copyset (zprivs_state.syscaps_p, zprivs_state.caps);    privset = zprivs_state.syscaps_p;
   else if (op == ZPRIVS_LOWER)    else if (op == ZPRIVS_LOWER)
    priv_emptyset (zprivs_state.caps);    privset = zprivs_state.caps;
   else    else
     return -1;      return -1;
       
  if (setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps) != 0)  if (setppriv (PRIV_SET, PRIV_EFFECTIVE, privset) != 0)
     return -1;      return -1;
       
   return 0;    return 0;
Line 423  zprivs_state_caps (void) Line 464  zprivs_state_caps (void)
     }      }
   else    else
     {      {
      if (priv_isemptyset (effective) == B_TRUE)      if (priv_isequalset (effective, zprivs_state.syscaps_p))
         result = ZPRIVS_RAISED;
       else if (priv_isequalset (effective, zprivs_state.caps))
         result = ZPRIVS_LOWERED;          result = ZPRIVS_LOWERED;
       else        else
        result = ZPRIVS_RAISED;        result = ZPRIVS_UNKNOWN;
     }      }
       
  if (effective)  priv_freeset (effective);
    priv_freeset (effective); 
   
   return result;    return result;
 }  }
   
Line 439  static void Line 480  static void
 zprivs_caps_init (struct zebra_privs_t *zprivs)  zprivs_caps_init (struct zebra_privs_t *zprivs)
 {  {
   pset_t *basic;    pset_t *basic;
  pset_t *empty;  pset_t *minimal;
       
   /* the specified sets */    /* the specified sets */
   zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);    zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p);
Line 467  zprivs_caps_init (struct zebra_privs_t *zprivs) Line 508  zprivs_caps_init (struct zebra_privs_t *zprivs)
   priv_union (basic, zprivs_state.syscaps_p);    priv_union (basic, zprivs_state.syscaps_p);
   priv_freeset (basic);    priv_freeset (basic);
       
   /* we need an empty set for 'effective', potentially for inheritable too */  
   if ( (empty = priv_allocset()) == NULL)  
     {  
       fprintf (stderr, "%s: couldn't get empty set!\n", __func__);  
       exit (1);  
     }  
   priv_emptyset (empty);  
     
   /* Hey kernel, we know about privileges!     /* Hey kernel, we know about privileges! 
    * this isn't strictly required, use of setppriv should have same effect     * this isn't strictly required, use of setppriv should have same effect
    */     */
Line 517  zprivs_caps_init (struct zebra_privs_t *zprivs) Line 550  zprivs_caps_init (struct zebra_privs_t *zprivs)
       exit (1);        exit (1);
     }      }
   
  /* now clear the effective set and we're ready to go */  /* we need a minimal basic set for 'effective', potentially for inheritable too */
  if (setppriv (PRIV_SET, PRIV_EFFECTIVE, empty))  minimal = zprivs_caps_minimal();
 
   /* now set the effective set with a subset of basic privileges */
   if (setppriv (PRIV_SET, PRIV_EFFECTIVE, minimal))
     {      {
       fprintf (stderr, "%s: error setting effective set!, %s\n", __func__,        fprintf (stderr, "%s: error setting effective set!, %s\n", __func__,
                safe_strerror (errno) );                 safe_strerror (errno) );
       exit (1);        exit (1);
     }      }
       
  /* we'll use this as our working-storage privset */  /* we'll use the minimal set as our working-storage privset */
  zprivs_state.caps = empty;  zprivs_state.caps = minimal;
       
   /* set methods for the caller to use */    /* set methods for the caller to use */
   zprivs->change = zprivs_change_caps;    zprivs->change = zprivs_change_caps;
Line 538  zprivs_caps_terminate (void) Line 574  zprivs_caps_terminate (void)
 {  {
   assert (zprivs_state.caps);    assert (zprivs_state.caps);
       
  /* clear all capabilities */  /* clear all capabilities by using working-storage privset */
  priv_emptyset (zprivs_state.caps); 
   setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps);    setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps);
   setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps);    setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps);
   setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps);    setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps);
Line 556  zprivs_caps_terminate (void) Line 591  zprivs_caps_terminate (void)
 #error "Neither Solaris nor Linux capabilities, dazed and confused..."  #error "Neither Solaris nor Linux capabilities, dazed and confused..."
 #endif /* HAVE_LCAPS */  #endif /* HAVE_LCAPS */
 #endif /* HAVE_CAPABILITIES */  #endif /* HAVE_CAPABILITIES */
 int  int
 zprivs_change_uid (zebra_privs_ops_t op)  zprivs_change_uid (zebra_privs_ops_t op)
 {  {
Line 587  zprivs_state_null (void) Line 622  zprivs_state_null (void)
   return zprivs_null_state;    return zprivs_null_state;
 }  }
   
   #ifndef HAVE_GETGROUPLIST
   /* Solaris 11 has no getgrouplist() */
   static int
   getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
   {
     struct group *grp;
     size_t usridx;
     int pos = 0, ret;
   
     if (pos < *ngroups)
       groups[pos] = group;
     pos++;
   
     setgrent();
     while ((grp = getgrent()))
       {
         if (grp->gr_gid == group)
           continue;
         for (usridx = 0; grp->gr_mem[usridx] != NULL; usridx++)
           if (!strcmp (grp->gr_mem[usridx], user))
             {
               if (pos < *ngroups)
                 groups[pos] = grp->gr_gid;
               pos++;
               break;
             }
       }
     endgrent();
   
     ret = (pos <= *ngroups) ? pos : -1;
     *ngroups = pos;
     return ret;
   }
   #endif /* HAVE_GETGROUPLIST */
   
 void  void
 zprivs_init(struct zebra_privs_t *zprivs)  zprivs_init(struct zebra_privs_t *zprivs)
 {  {
   struct passwd *pwentry = NULL;    struct passwd *pwentry = NULL;
   struct group *grentry = NULL;    struct group *grentry = NULL;
     gid_t groups[NGROUPS_MAX];
     int i, ngroups = 0;
   
   if (!zprivs)    if (!zprivs)
     {      {
Line 610  zprivs_init(struct zebra_privs_t *zprivs) Line 682  zprivs_init(struct zebra_privs_t *zprivs)
   
   if (zprivs->user)    if (zprivs->user)
     {      {
      if ( (pwentry = getpwnam (zprivs->user)) )      if ( (pwentry = getpwnam (zprivs->user)) == NULL )
         {          {
           zprivs_state.zuid = pwentry->pw_uid;  
         }  
       else  
         {  
           /* cant use log.h here as it depends on vty */            /* cant use log.h here as it depends on vty */
           fprintf (stderr, "privs_init: could not lookup user %s\n",            fprintf (stderr, "privs_init: could not lookup user %s\n",
                    zprivs->user);                     zprivs->user);
           exit (1);            exit (1);
         }          }
   
         zprivs_state.zuid = pwentry->pw_uid;
         zprivs_state.zgid = pwentry->pw_gid;
     }      }
   
   grentry = NULL;    grentry = NULL;
   
     if (zprivs->group)
       {
         if ( (grentry = getgrnam (zprivs->group)) == NULL )
           {
             fprintf (stderr, "privs_init: could not lookup group %s\n",
                      zprivs->group);
             exit (1);
           }
   
         zprivs_state.zgid = grentry->gr_gid;
       }
   
     if (zprivs->user)
       {
         ngroups = sizeof(groups);
         if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 )
           {
             /* cant use log.h here as it depends on vty */
             fprintf (stderr, "privs_init: could not getgrouplist for user %s\n",
                      zprivs->user);
             exit (1);
           }
       }
   
   if (zprivs->vty_group)    if (zprivs->vty_group)
     /* Add the vty_group to the supplementary groups so it can be chowned to */      /* Add the vty_group to the supplementary groups so it can be chowned to */
     {      {
       if ( (grentry = getgrnam (zprivs->vty_group)) )        if ( (grentry = getgrnam (zprivs->vty_group)) )
         {          {
           zprivs_state.vtygrp = grentry->gr_gid;            zprivs_state.vtygrp = grentry->gr_gid;
          if ( setgroups (1, &zprivs_state.vtygrp) )
           for ( i = 0; i < ngroups; i++ )
             if ( groups[i] == zprivs_state.vtygrp )
               break;
 
           if ( i >= ngroups && ngroups < (int) ZEBRA_NUM_OF(groups) )
             {              {
              fprintf (stderr, "privs_init: could not setgroups, %s\n",              groups[i] = zprivs_state.vtygrp;
                         safe_strerror (errno) );            }
              exit (1); 
            }        
         }          }
       else        else
         {          {
Line 645  zprivs_init(struct zebra_privs_t *zprivs) Line 743  zprivs_init(struct zebra_privs_t *zprivs)
           exit (1);            exit (1);
         }          }
     }      }
  
  if (zprivs->group)  if (ngroups)
     {      {
      if ( (grentry = getgrnam (zprivs->group)) )      if ( setgroups (ngroups, groups) )
         {          {
          zprivs_state.zgid = grentry->gr_gid;          fprintf (stderr, "privs_init: could not setgroups, %s\n",
        }                   safe_strerror (errno) );
      else 
        { 
          fprintf (stderr, "privs_init: could not lookup group %s\n", 
                   zprivs->group); 
           exit (1);            exit (1);
         }          }
       }
   
     if (zprivs_state.zgid)
       {
       /* change group now, forever. uid we do later */        /* change group now, forever. uid we do later */
       if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )        if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
         {          {

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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