#include "log.h"
#include "privs.h"
#include "memory.h"
+#include "lib_errors.h"
#ifdef HAVE_CAPABILITIES
pvalue_t *system_caps;
} cap_map[ZCAP_MAX] = {
#ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */
- [ZCAP_SETID] =
- {
- 2,
- (pvalue_t[]){CAP_SETGID, CAP_SETUID},
- },
- [ZCAP_BIND] =
- {
- 1,
- (pvalue_t[]){CAP_NET_BIND_SERVICE},
- },
- [ZCAP_NET_ADMIN] =
- {
- 1,
- (pvalue_t[]){CAP_NET_ADMIN},
- },
- [ZCAP_NET_RAW] =
- {
- 1,
- (pvalue_t[]){CAP_NET_RAW},
- },
- [ZCAP_CHROOT] =
- {
- 1,
- (pvalue_t[]){
- CAP_SYS_CHROOT,
+ [ZCAP_SETID] =
+ {
+ 2, (pvalue_t[]){CAP_SETGID, CAP_SETUID},
+ },
+ [ZCAP_BIND] =
+ {
+ 1, (pvalue_t[]){CAP_NET_BIND_SERVICE},
+ },
+ [ZCAP_NET_ADMIN] =
+ {
+ 1, (pvalue_t[]){CAP_NET_ADMIN},
+ },
+ [ZCAP_NET_RAW] =
+ {
+ 1, (pvalue_t[]){CAP_NET_RAW},
+ },
+ [ZCAP_CHROOT] =
+ {
+ 1,
+ (pvalue_t[]){
+ CAP_SYS_CHROOT,
+ },
+ },
+ [ZCAP_NICE] =
+ {
+ 1, (pvalue_t[]){CAP_SYS_NICE},
+ },
+ [ZCAP_PTRACE] =
+ {
+ 1, (pvalue_t[]){CAP_SYS_PTRACE},
+ },
+ [ZCAP_DAC_OVERRIDE] =
+ {
+ 1, (pvalue_t[]){CAP_DAC_OVERRIDE},
+ },
+ [ZCAP_READ_SEARCH] =
+ {
+ 1, (pvalue_t[]){CAP_DAC_READ_SEARCH},
+ },
+ [ZCAP_SYS_ADMIN] =
+ {
+ 1, (pvalue_t[]){CAP_SYS_ADMIN},
+ },
+ [ZCAP_FOWNER] =
+ {
+ 1, (pvalue_t[]){CAP_FOWNER},
},
- },
- [ZCAP_NICE] =
- {
- 1,
- (pvalue_t[]){CAP_SYS_NICE},
- },
- [ZCAP_PTRACE] =
- {
- 1,
- (pvalue_t[]){CAP_SYS_PTRACE},
- },
- [ZCAP_DAC_OVERRIDE] =
- {
- 1,
- (pvalue_t[]){CAP_DAC_OVERRIDE},
- },
- [ZCAP_READ_SEARCH] =
- {
- 1,
- (pvalue_t[]){CAP_DAC_READ_SEARCH},
- },
- [ZCAP_SYS_ADMIN] =
- {
- 1,
- (pvalue_t[]){CAP_SYS_ADMIN},
- },
- [ZCAP_FOWNER] =
- {
- 1,
- (pvalue_t[]){CAP_FOWNER},
- },
#elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */
- /* Quagga -> Solaris privilege mappings */
- [ZCAP_SETID] =
- {
- 1,
- (pvalue_t[]){PRIV_PROC_SETID},
- },
- [ZCAP_BIND] =
- {
- 1,
- (pvalue_t[]){PRIV_NET_PRIVADDR},
- },
+ /* Quagga -> Solaris privilege mappings */
+ [ZCAP_SETID] =
+ {
+ 1, (pvalue_t[]){PRIV_PROC_SETID},
+ },
+ [ZCAP_BIND] =
+ {
+ 1, (pvalue_t[]){PRIV_NET_PRIVADDR},
+ },
/* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */
#ifdef PRIV_SYS_IP_CONFIG
- [ZCAP_NET_ADMIN] =
- {
- 1,
- (pvalue_t[]){PRIV_SYS_IP_CONFIG},
- },
+ [ZCAP_NET_ADMIN] =
+ {
+ 1, (pvalue_t[]){PRIV_SYS_IP_CONFIG},
+ },
#else
- [ZCAP_NET_ADMIN] =
- {
- 1,
- (pvalue_t[]){PRIV_SYS_NET_CONFIG},
- },
+ [ZCAP_NET_ADMIN] =
+ {
+ 1, (pvalue_t[]){PRIV_SYS_NET_CONFIG},
+ },
#endif
- [ZCAP_NET_RAW] =
- {
- 2,
- (pvalue_t[]){PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS},
- },
- [ZCAP_CHROOT] =
- {
- 1,
- (pvalue_t[]){PRIV_PROC_CHROOT},
- },
- [ZCAP_NICE] =
- {
- 1,
- (pvalue_t[]){PRIV_PROC_PRIOCNTL},
- },
- [ZCAP_PTRACE] =
- {
- 1,
- (pvalue_t[]){PRIV_PROC_SESSION},
- },
- [ZCAP_DAC_OVERRIDE] =
- {
- 5,
- (pvalue_t[]){PRIV_FILE_DAC_EXECUTE, PRIV_FILE_DAC_READ,
- PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_WRITE,
- PRIV_FILE_DAC_SEARCH},
- },
- [ZCAP_READ_SEARCH] =
- {
- 2,
- (pvalue_t[]){PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_READ},
- },
- [ZCAP_SYS_ADMIN] =
- {
- 1,
- (pvalue_t[]){PRIV_SYS_ADMIN},
- },
- [ZCAP_FOWNER] =
- {
- 1,
- (pvalue_t[]){PRIV_FILE_OWNER},
- },
+ [ZCAP_NET_RAW] =
+ {
+ 2, (pvalue_t[]){PRIV_NET_RAWACCESS,
+ PRIV_NET_ICMPACCESS},
+ },
+ [ZCAP_CHROOT] =
+ {
+ 1, (pvalue_t[]){PRIV_PROC_CHROOT},
+ },
+ [ZCAP_NICE] =
+ {
+ 1, (pvalue_t[]){PRIV_PROC_PRIOCNTL},
+ },
+ [ZCAP_PTRACE] =
+ {
+ 1, (pvalue_t[]){PRIV_PROC_SESSION},
+ },
+ [ZCAP_DAC_OVERRIDE] =
+ {
+ 5, (pvalue_t[]){PRIV_FILE_DAC_EXECUTE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ PRIV_FILE_DAC_SEARCH},
+ },
+ [ZCAP_READ_SEARCH] =
+ {
+ 2, (pvalue_t[]){PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_READ},
+ },
+ [ZCAP_SYS_ADMIN] =
+ {
+ 1, (pvalue_t[]){PRIV_SYS_ADMIN},
+ },
+ [ZCAP_FOWNER] =
+ {
+ 1, (pvalue_t[]){PRIV_FILE_OWNER},
+ },
#endif /* HAVE_SOLARIS_CAPABILITIES */
};
if (cap_get_flag(zprivs_state.caps,
zprivs_state.syscaps_p->caps[i], CAP_EFFECTIVE,
&val)) {
- zlog_warn(
+ flog_err(
+ EC_LIB_SYSTEM_CALL,
"zprivs_state_caps: could not cap_get_flag, %s",
safe_strerror(errno));
return ZPRIVS_UNKNOWN;
}
#endif /* HAVE_GETGROUPLIST */
-void zprivs_init(struct zebra_privs_t *zprivs)
+struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
+ const char *funcname)
+{
+ int save_errno = errno;
+
+ if (!privs)
+ return NULL;
+
+ errno = 0;
+ if (privs->change(ZPRIVS_RAISE)) {
+ zlog_err("%s: Failed to raise privileges (%s)",
+ funcname, safe_strerror(errno));
+ }
+ errno = save_errno;
+ privs->raised_in_funcname = funcname;
+ return privs;
+}
+
+void _zprivs_lower(struct zebra_privs_t **privs)
+{
+ int save_errno = errno;
+
+ if (!*privs)
+ return;
+
+ errno = 0;
+ if ((*privs)->change(ZPRIVS_LOWER)) {
+ zlog_err("%s: Failed to lower privileges (%s)",
+ (*privs)->raised_in_funcname, safe_strerror(errno));
+ }
+ errno = save_errno;
+ (*privs)->raised_in_funcname = NULL;
+ *privs = NULL;
+}
+
+void zprivs_preinit(struct zebra_privs_t *zprivs)
{
struct passwd *pwentry = NULL;
struct group *grentry = NULL;
- gid_t groups[NGROUPS_MAX];
- int i, ngroups = 0;
- int found = 0;
if (!zprivs) {
fprintf(stderr, "zprivs_init: called with NULL arg!\n");
zprivs_state.zgid = grentry->gr_gid;
}
+}
+
+void zprivs_init(struct zebra_privs_t *zprivs)
+{
+ gid_t groups[NGROUPS_MAX];
+ int i, ngroups = 0;
+ int found = 0;
+
+ /* NULL privs */
+ if (!(zprivs->user || zprivs->group || zprivs->cap_num_p
+ || zprivs->cap_num_i))
+ return;
if (zprivs->user) {
ngroups = sizeof(groups);
if (zprivs->vty_group)
/* Add the vty_group to the supplementary groups so it can be chowned to
- */
+ */
{
if (zprivs_state.vtygrp == (gid_t)-1) {
fprintf(stderr,
#ifdef HAVE_CAPABILITIES
zprivs_caps_init(zprivs);
+
+ /*
+ * If we have initialized the system with no requested
+ * capabilities, change will not have been set
+ * to anything by zprivs_caps_init, As such
+ * we should make sure that when we attempt
+ * to raize privileges that we actually have
+ * a do nothing function to call instead of a
+ * crash :).
+ */
+ if (!zprivs->change)
+ zprivs->change = zprivs_change_null;
+
#else /* !HAVE_CAPABILITIES */
/* we dont have caps. we'll need to maintain rid and saved uid
* and change euid back to saved uid (who we presume has all neccessary
}
#ifdef HAVE_CAPABILITIES
- zprivs_caps_terminate();
+ if (zprivs->user || zprivs->group || zprivs->cap_num_p
+ || zprivs->cap_num_i)
+ zprivs_caps_terminate();
#else /* !HAVE_CAPABILITIES */
/* only change uid if we don't have the correct one */
if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) {