#include "memory.h"
#ifdef HAVE_CAPABILITIES
+
+DEFINE_MTYPE_STATIC(LIB, PRIVS, "Privilege information")
+
/* sort out some generic internal types for:
*
* privilege values (cap_value_t, priv_t) -> pvalue_t
exit(1);
}
- if ( !zprivs_state.syscaps_p )
- {
- fprintf (stderr, "privs_init: capabilities enabled, "
- "but no capabilities supplied\n");
- }
-
/* we have caps, we have no need to ever change back the original user */
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{
exit (1);
}
}
+
+ if ( !zprivs_state.syscaps_p )
+ return;
if ( !(zprivs_state.caps = cap_init()) )
{
current_caps = cap_get_proc();
if (current_caps)
+ {
current_caps_text = cap_to_text(current_caps, NULL);
+ cap_free(current_caps);
+ }
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 : "???");
+ if (current_caps_text)
+ cap_free(current_caps_text);
+ if (wanted_caps_text)
+ cap_free(wanted_caps_text);
exit (1);
}
/* we have caps, we have no need to ever change back the original user
* change real, effective and saved to the specified user.
*/
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{
int
zprivs_change_uid (zebra_privs_ops_t op)
{
-
+ if (zprivs_state.zsuid == zprivs_state.zuid)
+ return 0;
if (op == ZPRIVS_RAISE)
return seteuid (zprivs_state.zsuid);
else if (op == ZPRIVS_LOWER)
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
zprivs_init(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)
{
exit (1);
}
+ if (zprivs->vty_group)
+ {
+ /* in a "NULL" setup, this is allowed to fail too, but still try. */
+ if ((grentry = getgrnam (zprivs->vty_group)))
+ zprivs_state.vtygrp = grentry->gr_gid;
+ else
+ zprivs_state.vtygrp = (gid_t)-1;
+ }
+
/* NULL privs */
if (! (zprivs->user || zprivs->group
|| zprivs->cap_num_p || zprivs->cap_num_i) )
if (zprivs->user)
{
- if ( (pwentry = getpwnam (zprivs->user)) )
- {
- zprivs_state.zuid = pwentry->pw_uid;
- }
- else
+ if ( (pwentry = getpwnam (zprivs->user)) == NULL )
{
/* cant use log.h here as it depends on vty */
fprintf (stderr, "privs_init: could not lookup user %s\n",
zprivs->user);
exit (1);
}
+
+ zprivs_state.zuid = pwentry->pw_uid;
+ zprivs_state.zgid = pwentry->pw_gid;
}
grentry = NULL;
- if (zprivs->vty_group)
- /* Add the vty_group to the supplementary groups so it can be chowned to */
+ if (zprivs->group)
{
- if ( (grentry = getgrnam (zprivs->vty_group)) )
+ if ( (grentry = getgrnam (zprivs->group)) == NULL )
{
- zprivs_state.vtygrp = grentry->gr_gid;
- if ( setgroups (1, &zprivs_state.vtygrp) )
- {
- fprintf (stderr, "privs_init: could not setgroups, %s\n",
- safe_strerror (errno) );
- exit (1);
- }
+ fprintf (stderr, "privs_init: could not lookup group %s\n",
+ zprivs->group);
+ exit (1);
}
- else
+
+ zprivs_state.zgid = grentry->gr_gid;
+ }
+
+ if (zprivs->user)
+ {
+ ngroups = sizeof(groups);
+ if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 )
{
- fprintf (stderr, "privs_init: could not lookup vty group %s\n",
- zprivs->vty_group);
+ /* 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->group)
+
+ if (zprivs->vty_group)
+ /* Add the vty_group to the supplementary groups so it can be chowned to */
{
- if ( (grentry = getgrnam (zprivs->group)) )
+ if (zprivs_state.vtygrp == (gid_t)-1)
{
- zprivs_state.zgid = grentry->gr_gid;
+ fprintf (stderr, "privs_init: could not lookup vty group %s\n",
+ zprivs->vty_group);
+ exit (1);
}
- else
+
+ for ( i = 0; i < ngroups; i++ )
+ if ( groups[i] == zprivs_state.vtygrp )
+ {
+ found++;
+ break;
+ }
+
+ if (!found)
{
- fprintf (stderr, "privs_init: could not lookup group %s\n",
- zprivs->group);
+ fprintf (stderr, "privs_init: user(%s) is not part of vty group specified(%s)\n",
+ zprivs->user, zprivs->vty_group);
exit (1);
}
+ if ( i >= ngroups && ngroups < (int) ZEBRA_NUM_OF(groups) )
+ {
+ groups[i] = zprivs_state.vtygrp;
+ }
+ }
+
+ /* add groups only if we changed uid - otherwise skip */
+ if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid))
+ {
+ if ( setgroups (ngroups, groups) )
+ {
+ fprintf (stderr, "privs_init: could not setgroups, %s\n",
+ safe_strerror (errno) );
+ exit (1);
+ }
+ }
+
+ /* change gid only if we changed uid - otherwise skip */
+ if ((zprivs_state.zgid) && (zprivs_state.zsuid != zprivs_state.zuid))
+ {
/* change group now, forever. uid we do later */
if ( setregid (zprivs_state.zgid, zprivs_state.zgid) )
{
* This is not worth that much security wise, but all we can do.
*/
zprivs_state.zsuid = geteuid();
- if ( zprivs_state.zuid )
+ /* only change uid if we don't have the correct one */
+ if (( zprivs_state.zuid ) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (-1, zprivs_state.zuid) )
{
#ifdef HAVE_CAPABILITIES
zprivs_caps_terminate();
#else /* !HAVE_CAPABILITIES */
- if (zprivs_state.zuid)
+ /* only change uid if we don't have the correct one */
+ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid))
{
if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
{