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