diff options
| -rw-r--r-- | lib/privs.c | 107 | ||||
| -rw-r--r-- | lib/privs.h | 14 | ||||
| -rw-r--r-- | lib/zebra.h | 9 | 
3 files changed, 86 insertions, 44 deletions
| diff --git a/lib/privs.c b/lib/privs.c index 35e5a76b..f3a15cea 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -25,7 +25,6 @@  #include "log.h"  #include "privs.h"  #include "memory.h" -         /* internal privileges state */  static struct _zprivs_t @@ -40,6 +39,7 @@ static struct _zprivs_t    uid_t zuid,                 /* uid to run as            */          zsuid;                /* saved uid                */    gid_t zgid;                 /* gid to run as            */ +  gid_t vtygrp;               /* gid for vty sockets      */  } zprivs_state;  /* externally exported but not directly accessed functions */ @@ -69,11 +69,9 @@ cap_map [ZCAP_MAX] =    [ZCAP_DAC_OVERRIDE] = CAP_DAC_OVERRIDE,    [ZCAP_READ_SEARCH] = CAP_DAC_READ_SEARCH,    [ZCAP_SYS_ADMIN] = CAP_SYS_ADMIN, -  [ZCAP_FOWNER] = ZCAP_FOWNER +  [ZCAP_FOWNER] = CAP_FOWNER  }; -static cap_value_t cap_setuid_value [] = { CAP_SETUID }; -  /* convert zebras privileges to system capabilities */  static cap_value_t *  zcaps2sys (zebra_capabilities_t *zcaps, int num) @@ -176,6 +174,12 @@ zprivs_init(struct zebra_privs_t *zprivs)    struct passwd *pwentry = NULL;    struct group *grentry = NULL; +  if (!zprivs) +    { +      zlog_err ("zprivs_init: called with NULL arg!"); +      exit (1); +    } +    /* NULL privs */    if (! (zprivs->user || zprivs->group            || zprivs->cap_num_p || zprivs->cap_num_i) ) @@ -188,7 +192,31 @@ zprivs_init(struct zebra_privs_t *zprivs)    if (zprivs->user)      {        if ( (pwentry = getpwnam (zprivs->user)) ) -        zprivs_state.zuid = pwentry->pw_uid; +        { +          zprivs_state.zuid = pwentry->pw_uid; +        } +      else +        { +          zlog_err ("privs_init: could not lookup supplied user"); +          exit (1); +        } +    } + +  grentry = NULL; + +  if (zprivs->vty_group) +    /* Add the vty_group to the supplementary groups so it can be chowned to */ +    { +      if ( (grentry = getgrnam (zprivs->vty_group)) ) +        { +          zprivs_state.vtygrp = grentry->gr_gid; +          if ( setgroups (1, &zprivs_state.vtygrp) ) +            { +              zlog_err ("privs_init: could not setgroups, %s", +                         strerror (errno) ); +              exit (1); +            }        +        }        else          {            zlog_err ("privs_init: could not lookup supplied user"); @@ -198,18 +226,20 @@ zprivs_init(struct zebra_privs_t *zprivs)    if (zprivs->group)      { -      if ( (grentry = getgrnam (zprivs->user)) ) -        zprivs_state.zgid = grentry->gr_gid; +      if ( (grentry = getgrnam (zprivs->group)) ) +        { +          zprivs_state.zgid = grentry->gr_gid; +        }        else          {            zlog_err ("privs_init: could not lookup supplied user");            exit (1);          } -              /* change group now, forever. uid we do later */        if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )          { -          zlog_err ("privs_init: could not setregid"); +          zlog_err ("zprivs_init: could not setregid, %s", +                    strerror (errno) );            exit (1);          }      } @@ -238,6 +268,17 @@ zprivs_init(struct zebra_privs_t *zprivs)        zlog_err ("privs_init: failed to cap_init, %s", strerror (errno) );        exit (1);      } + +  /* we have caps, we have no need to ever change back the original user */ +  if (zprivs_state.zuid) +    { +      if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) ) +        { +          zlog_err ("zprivs_init (cap): could not setreuid, %s",  +                     strerror (errno) ); +          exit (1); +        } +    }    if ( cap_clear (zprivs_state.caps) )      { @@ -251,12 +292,6 @@ zprivs_init(struct zebra_privs_t *zprivs)    cap_set_flag(zprivs_state.caps, CAP_EFFECTIVE,                  zprivs_state.sys_num_p, zprivs_state.syscaps_p, CAP_SET); -  /* still need CAP_SETUID for the moment */ -  cap_set_flag(zprivs_state.caps, CAP_PERMITTED, -               1, cap_setuid_value, CAP_SET); -  cap_set_flag(zprivs_state.caps, CAP_EFFECTIVE, -  				1, cap_setuid_value, CAP_SET); -    /* set inheritable caps, if any */    if (zprivs_state.sys_num_i)      { @@ -264,8 +299,8 @@ zprivs_init(struct zebra_privs_t *zprivs)                     zprivs_state.sys_num_i, zprivs_state.syscaps_i, CAP_SET);      } -  /* apply caps. CAP_EFFECTIVE is clear bar cap_setuid_value.  -   * we'll raise the caps as and when, and only when, they are needed. +  /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as  +   * and when, and only when, they are needed.     */    if ( cap_set_proc (zprivs_state.caps) )       { @@ -273,28 +308,7 @@ zprivs_init(struct zebra_privs_t *zprivs)        exit (1);      } -  /* we have caps, we have no need to ever change back the original user */ -  if (zprivs_state.zuid) -    { -      if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) ) -        { -          zlog_err ("privs_init (cap): could not setreuid, %s", strerror (errno) ); -          exit (1); -        } -    } - -  /* No more need for cap_setuid_value */ -  cap_set_flag(zprivs_state.caps, CAP_PERMITTED, -               1, cap_setuid_value, CAP_CLEAR); -  cap_set_flag(zprivs_state.caps, CAP_EFFECTIVE, -  				1, cap_setuid_value, CAP_CLEAR); -  if ( cap_set_proc (zprivs_state.caps) )  -    { -      zlog_err ("privs_init: cap_set_proc failed to clear cap_setuid, %s", -                strerror (errno) ); -      exit (1); -    } - +  /* set methods for the caller to use */    zprivs->change = zprivs_change_caps;    zprivs->current_state = zprivs_state_caps; @@ -354,3 +368,18 @@ zprivs_terminate (void)  #endif /* HAVE_LCAPS */    return;  } + +void +zprivs_get_ids(struct zprivs_ids_t *ids) +{ + +   ids->uid_priv = getuid(); +   (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid) +                     : (ids->uid_normal = -1); +   (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid) +                     : (ids->gid_normal = -1); +   (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp) +                       : (ids->gid_vty = -1); +    +   return; +} diff --git a/lib/privs.h b/lib/privs.h index 3cdd20da..65c9f358 100644 --- a/lib/privs.h +++ b/lib/privs.h @@ -63,7 +63,7 @@ struct zebra_privs_t    int cap_num_i;                        char *user;                         /* user and group to run as */    char *group; - +  char *vty_group;                    /* group to chown vty socket to */    /* methods */    int       (*change) (zebra_privs_ops_t);    /* change privileges, 0 on success */ @@ -71,9 +71,21 @@ struct zebra_privs_t      (*current_state) (void);          /* current privilege state */  }; +struct zprivs_ids_t +{ +  /* -1 is undefined */ +  uid_t uid_priv;                     /* privileged uid */ +  uid_t uid_normal;                   /* normal uid */ +  gid_t gid_priv;                     /* privileged uid */ +  gid_t gid_normal;                   /* normal uid */ +  gid_t gid_vty;                      /* vty gid */ +}; +    /* initialise zebra privileges */  void zprivs_init (struct zebra_privs_t *zprivs);    /* drop all and terminate privileges */   void zprivs_terminate (void); +  /* query for runtime uid's and gid's, eg vty needs this */ +void zprivs_get_ids(struct zprivs_ids_t *);  #endif /* _ZEBRA_PRIVS_H */ diff --git a/lib/zebra.h b/lib/zebra.h index 15608dbc..3d71ad8d 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -72,10 +72,6 @@ typedef int socklen_t;  #ifdef HAVE_RUSAGE  #include <sys/resource.h>  #endif /* HAVE_RUSAGE */ -#ifdef HAVE_LCAPS -#include <sys/capability.h> -#include <sys/prctl.h> -#endif /* HAVE_LCAPS */  /* machine dependent includes */  #ifdef SUNOS_5 @@ -96,6 +92,11 @@ typedef int socklen_t;  #include <stdarg.h>  #include <assert.h> +#ifdef HAVE_LCAPS +#include <sys/capability.h> +#include <sys/prctl.h> +#endif /* HAVE_LCAPS */ +  /* network include group */  #include <sys/socket.h> | 
