예제 #1
0
priv_set_t *priv_str_to_set (const char *buf, const char *sep,
      const char **endptr)
{
  /* Take a copy of the string since strtok_r will modify it.  */
  char *str = strdup (buf);
  if (!str)
    return NULL;

  priv_set_t *set = priv_allocset ();
  if (!set)
    {
      free (str);
      return NULL;
    }
  priv_emptyset (set);
  const priv_data_t *data = __priv_parse_data_cached ();
  if (!data)
    return NULL;
  priv_set_t *basic = data->pd_basicprivs;

  char *saveptr;
  char *priv = strtok_r (str, sep, &saveptr);
  if (!priv)
    return set;
  do
    {
      if (strcmp (priv, "basic") == 0 && basic)
          priv_union (basic, set);
      else if (strcmp (priv, "all") == 0)
          priv_fillset (set);
      else if (strcmp (priv, "none") == 0)
          priv_emptyset (set);
      else if (strcmp (priv, "zone") == 0)
        {
          priv_set_t *zone = priv_allocset ();
          if (!zone)
            goto inval;
          if (zone_getattr (getzoneid (), ZONE_ATTR_PRIVSET,
                zone, __PRIVSETSIZE) == 0)
            priv_union (zone, set);
          priv_freeset (zone);
        }
      else
        {
          int negate = *str == '-' || *str == '!';
          if (negate)
            str++;

          int res;
          if (negate)
            res = priv_delset (set, str);
          else
            res = priv_addset (set, str);
          if (res == -1)
            goto inval;
        }
    }
  while ((priv = strtok_r (NULL, sep, &saveptr))) ;

  free (str);
  return set;

inval:

   priv_freeset (set);
   free (str);
   __set_errno (EINVAL);
  return NULL;
}
예제 #2
0
/* Specify what privileges an suid root binary needs.  */
int __init_suid_priv (int flags, ...)
{
  int res = 0;
  priv_set_t *permit = NULL, *inherit = NULL, *scratch = NULL;

  /* Check flags.  */
  if (flags != PU_LIMITPRIVS && flags != PU_CLEARLIMITSET)
    return -1;

  /* We can only initialize once.  */
  if (__suidset)
    return -1;

  /* Do nothing if we are running as root but not setuid root.  */
  uid_t uid = getuid ();
  uid_t euid = geteuid ();
  if (uid == 0 && euid == 0)
    return 0;

  /* Allocate a scratch set.  */
  scratch = priv_allocset ();
  if (!scratch)
    goto error;

  /* Get the basic set.  */
  const priv_data_t *pd = __priv_parse_data_cached ();
  if (!pd)
    goto error;
  priv_set_t *basic = pd->pd_basicprivs;

  /* Get the inherited set.  */
  inherit = priv_allocset ();
  if (!inherit)
    goto error;
  if (getppriv (PRIV_INHERITABLE, inherit) != 0)
    goto error;

  /* Get the permitted set.  */
  permit = priv_allocset ();
  if (!permit)
    goto error;
  if (getppriv (PRIV_PERMITTED, permit) != 0)
    goto error;

  /* Get passed privileges.  */
  __suidset = priv_allocset ();
  if (!__suidset)
    goto error;
  priv_emptyset (__suidset);
  va_list ap;
  va_start (ap, flags);
  const char *priv;
  while ((priv = va_arg (ap, const char *)))
    if (priv_addset (__suidset, priv) != 0)
      goto error;

  /* Make sure that the passed privileges are a subset of the current
     permitted privileges.  */
  if (priv_issubset (__suidset, permit) != _B_TRUE)
    goto error;

  /* Set the effective privileges to the inherited ones.  */
  if (setppriv (PRIV_SET, PRIV_EFFECTIVE, inherit) != 0)
    goto error;

  /* Set the permitted privileges to those currently permitted privileges in
     set of the ones passed in, the inherited ones, and the basic set.  */
  priv_copyset (__suidset, scratch);
  priv_union (inherit, scratch);
  if (basic)
    priv_union (basic, scratch);
  priv_intersect (permit, scratch);
  if (setppriv (PRIV_SET, PRIV_PERMITTED, scratch) != 0)
    goto error;

  /* Check if we need to set the limit set.  */
  if (flags & PU_CLEARLIMITSET)
    {
      priv_emptyset (scratch);
      if (setppriv (PRIV_SET, PRIV_LIMIT, scratch) != 0)
        goto error;
    }
  else if (flags & PU_LIMITPRIVS)
    {
      if (setppriv (PRIV_SET, PRIV_LIMIT, scratch) != 0)
        goto error;
    }

  /* Change the uid to the caller's uid if we're setuid root.  */
  if (euid == 0 && setreuid (uid, uid) != 0)
    goto error;

  goto out;

error:
  res = -1;
  if (__suidset)
    {
      priv_freeset (__suidset);
      __suidset = NULL;
    }
  if (euid == 0)
    setreuid (uid, uid);

out:
  priv_freeset (permit);
  priv_freeset (inherit);
  priv_freeset (scratch);

  return res;
}