Blame nslcd/group.c

Packit 6bd9ab
/*
Packit 6bd9ab
   group.c - group entry lookup routines
Packit 6bd9ab
   Parts of this file were part of the nss_ldap library (as ldap-grp.c)
Packit 6bd9ab
   which has been forked into the nss-pam-ldapd library.
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 1997-2006 Luke Howard
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2015 Arthur de Jong
Packit 6bd9ab
   Copyright (C) 2013 Steve Hill
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#include "config.h"
Packit 6bd9ab
Packit 6bd9ab
#include <stdio.h>
Packit 6bd9ab
#include <stdlib.h>
Packit 6bd9ab
#include <string.h>
Packit 6bd9ab
/* for gid_t */
Packit 6bd9ab
#include <grp.h>
Packit 6bd9ab
Packit 6bd9ab
#include "common/set.h"
Packit 6bd9ab
#include "common.h"
Packit 6bd9ab
#include "log.h"
Packit 6bd9ab
#include "myldap.h"
Packit 6bd9ab
#include "cfg.h"
Packit 6bd9ab
#include "attmap.h"
Packit 6bd9ab
#include "compat/strndup.h"
Packit 6bd9ab
Packit 6bd9ab
/* ( nisSchema.2.2 NAME 'posixGroup' SUP top STRUCTURAL
Packit 6bd9ab
 *   DESC 'Abstraction of a group of accounts'
Packit 6bd9ab
 *   MUST ( cn $ gidNumber )
Packit 6bd9ab
 *   MAY ( userPassword $ memberUid $ description ) )
Packit 6bd9ab
 *
Packit 6bd9ab
 * apart from the above a member attribute is also supported that
Packit 6bd9ab
 * may contains a DN of a user
Packit 6bd9ab
 *
Packit 6bd9ab
 * nested groups (groups that are member of a group) are currently
Packit 6bd9ab
 * not supported
Packit 6bd9ab
 */
Packit 6bd9ab
Packit 6bd9ab
/* the search base for searches */
Packit 6bd9ab
const char *group_bases[NSS_LDAP_CONFIG_MAX_BASES] = { NULL };
Packit 6bd9ab
Packit 6bd9ab
/* the search scope for searches */
Packit 6bd9ab
int group_scope = LDAP_SCOPE_DEFAULT;
Packit 6bd9ab
Packit 6bd9ab
/* the basic search filter for searches */
Packit 6bd9ab
const char *group_filter = "(objectClass=posixGroup)";
Packit 6bd9ab
Packit 6bd9ab
/* the attributes to request with searches */
Packit 6bd9ab
const char *attmap_group_cn           = "cn";
Packit 6bd9ab
const char *attmap_group_userPassword = "\"*\"";
Packit 6bd9ab
const char *attmap_group_gidNumber    = "gidNumber";
Packit 6bd9ab
const char *attmap_group_memberUid    = "memberUid";
Packit 6bd9ab
const char *attmap_group_member       = "member";
Packit 6bd9ab
Packit 6bd9ab
/* special property for objectSid-based searches
Packit 6bd9ab
   (these are already LDAP-escaped strings) */
Packit 6bd9ab
static char *gidSid = NULL;
Packit 6bd9ab
Packit 6bd9ab
/* BUILTIN SID definitions */
Packit 6bd9ab
static char *builtinSid = NULL;
Packit 6bd9ab
const gid_t min_builtin_rid = 544;
Packit 6bd9ab
const gid_t max_builtin_rid = 552;
Packit 6bd9ab
Packit 6bd9ab
/* default values for attributes */
Packit 6bd9ab
static const char *default_group_userPassword = "*"; /* unmatchable */
Packit 6bd9ab
Packit 6bd9ab
/* the attribute list to request with searches */
Packit 6bd9ab
static const char **group_attrs = NULL;
Packit 6bd9ab
Packit 6bd9ab
/* the attribute list for bymember searches (without member attributes) */
Packit 6bd9ab
static const char **group_bymember_attrs = NULL;
Packit 6bd9ab
Packit 6bd9ab
/* create a search filter for searching a group entry
Packit 6bd9ab
   by name, return -1 on errors */
Packit 6bd9ab
static int mkfilter_group_byname(const char *name,
Packit 6bd9ab
                                 char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  char safename[BUFLEN_SAFENAME];
Packit 6bd9ab
  /* escape attribute */
Packit 6bd9ab
  if (myldap_escape(name, safename, sizeof(safename)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "mkfilter_group_byname(): safename buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* build filter */
Packit 6bd9ab
  return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
Packit 6bd9ab
                    group_filter, attmap_group_cn, safename);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* create a search filter for searching a group entry
Packit 6bd9ab
   by gid, return -1 on errors */
Packit 6bd9ab
static int mkfilter_group_bygid(gid_t gid, char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  gid -= nslcd_cfg->nss_gid_offset;
Packit 6bd9ab
  /* if searching for a Windows domain SID */
Packit 6bd9ab
  if (gidSid != NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* the given gid is a BUILTIN gid, the SID prefix is not the domain SID */
Packit 6bd9ab
    if ((gid >= min_builtin_rid) && (gid <= max_builtin_rid))
Packit 6bd9ab
      return mysnprintf(buffer, buflen, "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))",
Packit 6bd9ab
                        group_filter, attmap_group_gidNumber, builtinSid,
Packit 6bd9ab
                        (int)(gid & 0xff), (int)((gid >> 8) & 0xff),
Packit 6bd9ab
                        (int)((gid >> 16) & 0xff), (int)((gid >> 24) & 0xff));
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))",
Packit 6bd9ab
                      group_filter, attmap_group_gidNumber, gidSid,
Packit 6bd9ab
                      (int)(gid & 0xff), (int)((gid >> 8) & 0xff),
Packit 6bd9ab
                      (int)((gid >> 16) & 0xff), (int)((gid >> 24) & 0xff));
Packit 6bd9ab
  }
Packit 6bd9ab
  else
Packit 6bd9ab
  {
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%lu))",
Packit 6bd9ab
                      group_filter, attmap_group_gidNumber, (unsigned long int)gid);
Packit 6bd9ab
  }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* create a search filter for searching a group entry
Packit 6bd9ab
   by member uid, return -1 on errors */
Packit 6bd9ab
static int mkfilter_group_bymember(MYLDAP_SESSION *session,
Packit 6bd9ab
                                   const char *uid,
Packit 6bd9ab
                                   char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  char dn[BUFLEN_DN];
Packit 6bd9ab
  char safeuid[BUFLEN_SAFENAME];
Packit 6bd9ab
  char safedn[BUFLEN_SAFEDN];
Packit 6bd9ab
  /* escape attribute */
Packit 6bd9ab
  if (myldap_escape(uid, safeuid, sizeof(safeuid)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "mkfilter_group_bymember(): safeuid buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* try to translate uid to DN */
Packit 6bd9ab
  if ((strcasecmp(attmap_group_member, "\"\"") == 0) ||
Packit 6bd9ab
      (uid2dn(session, uid, dn, sizeof(dn)) == NULL))
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
Packit 6bd9ab
                      group_filter, attmap_group_memberUid, safeuid);
Packit 6bd9ab
  /* escape DN */
Packit 6bd9ab
  if (myldap_escape(dn, safedn, sizeof(safedn)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "mkfilter_group_bymember(): safedn buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* also lookup using user DN */
Packit 6bd9ab
  return mysnprintf(buffer, buflen, "(&%s(|(%s=%s)(%s=%s)))",
Packit 6bd9ab
                    group_filter,
Packit 6bd9ab
                    attmap_group_memberUid, safeuid,
Packit 6bd9ab
                    attmap_group_member, safedn);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static int mkfilter_group_bymemberdn(const char *dn,
Packit 6bd9ab
                                     char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  char safedn[BUFLEN_SAFEDN];
Packit 6bd9ab
  /* escape DN */
Packit 6bd9ab
  if (myldap_escape(dn, safedn, sizeof(safedn)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "mkfilter_group_bymemberdn(): safedn buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  return mysnprintf(buffer, buflen,
Packit 6bd9ab
                    "(&%s(%s=%s))",
Packit 6bd9ab
                    group_filter,
Packit 6bd9ab
                    attmap_group_member, safedn);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
void group_init(void)
Packit 6bd9ab
{
Packit 6bd9ab
  int i;
Packit 6bd9ab
  SET *set;
Packit 6bd9ab
  /* set up search bases */
Packit 6bd9ab
  if (group_bases[0] == NULL)
Packit 6bd9ab
    for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
Packit 6bd9ab
      group_bases[i] = nslcd_cfg->bases[i];
Packit 6bd9ab
  /* set up scope */
Packit 6bd9ab
  if (group_scope == LDAP_SCOPE_DEFAULT)
Packit 6bd9ab
    group_scope = nslcd_cfg->scope;
Packit 6bd9ab
  /* special case when gidNumber references objectSid */
Packit 6bd9ab
  if (strncasecmp(attmap_group_gidNumber, "objectSid:", 10) == 0)
Packit 6bd9ab
  {
Packit 6bd9ab
    gidSid = sid2search(attmap_group_gidNumber + 10);
Packit 6bd9ab
    builtinSid = sid2search("S-1-5-32");
Packit 6bd9ab
    attmap_group_gidNumber = strndup(attmap_group_gidNumber, 9);
Packit 6bd9ab
  }
Packit 6bd9ab
  /* set up attribute list */
Packit 6bd9ab
  set = set_new();
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_cn);
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_userPassword);
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_gidNumber);
Packit 6bd9ab
  if (!nslcd_cfg->nss_getgrent_skipmembers)
Packit 6bd9ab
  {
Packit 6bd9ab
    attmap_add_attributes(set, attmap_group_memberUid);
Packit 6bd9ab
    attmap_add_attributes(set, attmap_group_member);
Packit 6bd9ab
  }
Packit 6bd9ab
  group_attrs = set_tolist(set);
Packit 6bd9ab
  if (group_attrs == NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_CRIT, "malloc() failed to allocate memory");
Packit 6bd9ab
    exit(EXIT_FAILURE);
Packit 6bd9ab
  }
Packit 6bd9ab
  set_free(set);
Packit 6bd9ab
  /* set up bymember attribute list */
Packit 6bd9ab
  set = set_new();
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_cn);
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_userPassword);
Packit 6bd9ab
  attmap_add_attributes(set, attmap_group_gidNumber);
Packit 6bd9ab
  group_bymember_attrs = set_tolist(set);
Packit 6bd9ab
  if (group_bymember_attrs == NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_CRIT, "malloc() failed to allocate memory");
Packit 6bd9ab
    exit(EXIT_FAILURE);
Packit 6bd9ab
  }
Packit 6bd9ab
  set_free(set);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static int do_write_group(TFILE *fp, MYLDAP_ENTRY *entry,
Packit 6bd9ab
                          const char **names, gid_t gids[], int numgids,
Packit 6bd9ab
                          const char *passwd, const char **members,
Packit 6bd9ab
                          const char *reqname)
Packit 6bd9ab
{
Packit 6bd9ab
  int32_t tmpint32, tmp2int32, tmp3int32;
Packit 6bd9ab
  int i, j;
Packit 6bd9ab
  /* write entries for all names and gids */
Packit 6bd9ab
  for (i = 0; names[i] != NULL; i++)
Packit 6bd9ab
  {
Packit 6bd9ab
    if (!isvalidname(names[i]))
Packit 6bd9ab
    {
Packit 6bd9ab
      log_log(LOG_WARNING, "%s: %s: denied by validnames option",
Packit 6bd9ab
              myldap_get_dn(entry), attmap_group_cn);
Packit 6bd9ab
    }
Packit 6bd9ab
    else if ((reqname == NULL) || (STR_CMP(reqname, names[i]) == 0))
Packit 6bd9ab
    {
Packit 6bd9ab
      for (j = 0; j < numgids; j++)
Packit 6bd9ab
      {
Packit 6bd9ab
        WRITE_INT32(fp, NSLCD_RESULT_BEGIN);
Packit 6bd9ab
        WRITE_STRING(fp, names[i]);
Packit 6bd9ab
        WRITE_STRING(fp, passwd);
Packit 6bd9ab
        WRITE_INT32(fp, gids[j]);
Packit 6bd9ab
        WRITE_STRINGLIST(fp, members);
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  return 0;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static void getmembers(MYLDAP_ENTRY *entry, MYLDAP_SESSION *session,
Packit 6bd9ab
                       SET *members, SET *seen, SET *subgroups)
Packit 6bd9ab
{
Packit 6bd9ab
  char buf[BUFLEN_NAME];
Packit 6bd9ab
  int i;
Packit 6bd9ab
  const char **values;
Packit 6bd9ab
  const char ***derefs;
Packit 6bd9ab
  /* add the memberUid values */
Packit 6bd9ab
  values = myldap_get_values(entry, attmap_group_memberUid);
Packit 6bd9ab
  if (values != NULL)
Packit 6bd9ab
    for (i = 0; values[i] != NULL; i++)
Packit 6bd9ab
    {
Packit 6bd9ab
      /* only add valid usernames */
Packit 6bd9ab
      if (isvalidname(values[i]))
Packit 6bd9ab
        set_add(members, values[i]);
Packit 6bd9ab
    }
Packit 6bd9ab
  /* skip rest if attmap_group_member is blank */
Packit 6bd9ab
  if (strcasecmp(attmap_group_member, "\"\"") == 0)
Packit 6bd9ab
    return;
Packit 6bd9ab
  /* add deref'd entries if we have them*/
Packit 6bd9ab
  derefs = myldap_get_deref_values(entry, attmap_group_member, attmap_passwd_uid);
Packit 6bd9ab
  if (derefs != NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* add deref'd uid attributes */
Packit 6bd9ab
    for (i = 0; derefs[0][i] != NULL; i++)
Packit 6bd9ab
      set_add(members, derefs[0][i]);
Packit 6bd9ab
    /* add non-deref'd attribute values as subgroups */
Packit 6bd9ab
    for (i = 0; derefs[1][i] != NULL; i++)
Packit 6bd9ab
    {
Packit 6bd9ab
      if ((seen == NULL) || (!set_contains(seen, derefs[1][i])))
Packit 6bd9ab
      {
Packit 6bd9ab
        if (seen != NULL)
Packit 6bd9ab
          set_add(seen, derefs[1][i]);
Packit 6bd9ab
        if (subgroups != NULL)
Packit 6bd9ab
          set_add(subgroups, derefs[1][i]);
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
    return; /* no need to parse the member attribute ourselves */
Packit 6bd9ab
  }
Packit 6bd9ab
  /* add the member values */
Packit 6bd9ab
  values = myldap_get_values(entry, attmap_group_member);
Packit 6bd9ab
  if (values != NULL)
Packit 6bd9ab
    for (i = 0; values[i] != NULL; i++)
Packit 6bd9ab
    {
Packit 6bd9ab
      if ((seen == NULL) || (!set_contains(seen, values[i])))
Packit 6bd9ab
      {
Packit 6bd9ab
        if (seen != NULL)
Packit 6bd9ab
          set_add(seen, values[i]);
Packit 6bd9ab
        /* transform the DN into a uid (dn2uid() already checks validity) */
Packit 6bd9ab
        if (dn2uid(session, values[i], buf, sizeof(buf)) != NULL)
Packit 6bd9ab
          set_add(members, buf);
Packit 6bd9ab
        /* wasn't a UID - try handling it as a nested group */
Packit 6bd9ab
        else if (subgroups != NULL)
Packit 6bd9ab
          set_add(subgroups, values[i]);
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
/* the maximum number of gidNumber attributes per entry */
Packit 6bd9ab
#define MAXGIDS_PER_ENTRY 5
Packit 6bd9ab
Packit 6bd9ab
static int write_group(TFILE *fp, MYLDAP_ENTRY *entry, const char *reqname,
Packit 6bd9ab
                       const gid_t *reqgid, int wantmembers,
Packit 6bd9ab
                       MYLDAP_SESSION *session)
Packit 6bd9ab
{
Packit 6bd9ab
  const char **names, **gidvalues;
Packit 6bd9ab
  const char *passwd;
Packit 6bd9ab
  const char **members = NULL;
Packit 6bd9ab
  SET *set, *seen=NULL, *subgroups=NULL;
Packit 6bd9ab
  gid_t gids[MAXGIDS_PER_ENTRY];
Packit 6bd9ab
  int numgids;
Packit 6bd9ab
  char *tmp;
Packit 6bd9ab
  char passbuffer[BUFLEN_PASSWORDHASH];
Packit 6bd9ab
  MYLDAP_SEARCH *search;
Packit 6bd9ab
  MYLDAP_ENTRY *entry2;
Packit 6bd9ab
  int rc;
Packit 6bd9ab
  /* get group name (cn) */
Packit 6bd9ab
  names = myldap_get_values(entry, attmap_group_cn);
Packit 6bd9ab
  if ((names == NULL) || (names[0] == NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: missing",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_group_cn);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* get the group id(s) */
Packit 6bd9ab
  if (reqgid != NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    gids[0] = *reqgid;
Packit 6bd9ab
    numgids = 1;
Packit 6bd9ab
  }
Packit 6bd9ab
  else
Packit 6bd9ab
  {
Packit 6bd9ab
    gidvalues = myldap_get_values_len(entry, attmap_group_gidNumber);
Packit 6bd9ab
    if ((gidvalues == NULL) || (gidvalues[0] == NULL))
Packit 6bd9ab
    {
Packit 6bd9ab
      log_log(LOG_WARNING, "%s: %s: missing",
Packit 6bd9ab
              myldap_get_dn(entry), attmap_group_gidNumber);
Packit 6bd9ab
      return 0;
Packit 6bd9ab
    }
Packit 6bd9ab
    for (numgids = 0; (numgids < MAXGIDS_PER_ENTRY) && (gidvalues[numgids] != NULL); numgids++)
Packit 6bd9ab
    {
Packit 6bd9ab
      if (gidSid != NULL)
Packit 6bd9ab
        gids[numgids] = (gid_t)binsid2id(gidvalues[numgids]);
Packit 6bd9ab
      else
Packit 6bd9ab
      {
Packit 6bd9ab
        errno = 0;
Packit 6bd9ab
        gids[numgids] = strtogid(gidvalues[numgids], &tmp, 10);
Packit 6bd9ab
        if ((*(gidvalues[numgids]) == '\0') || (*tmp != '\0'))
Packit 6bd9ab
        {
Packit 6bd9ab
          log_log(LOG_WARNING, "%s: %s: non-numeric",
Packit 6bd9ab
                  myldap_get_dn(entry), attmap_group_gidNumber);
Packit 6bd9ab
          return 0;
Packit 6bd9ab
        }
Packit 6bd9ab
        else if ((errno != 0) || (strchr(gidvalues[numgids], '-') != NULL))
Packit 6bd9ab
        {
Packit 6bd9ab
          log_log(LOG_WARNING, "%s: %s: out of range",
Packit 6bd9ab
                  myldap_get_dn(entry), attmap_group_gidNumber);
Packit 6bd9ab
          return 0;
Packit 6bd9ab
        }
Packit 6bd9ab
      }
Packit 6bd9ab
      gids[numgids] += nslcd_cfg->nss_gid_offset;
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  /* get group passwd (userPassword) (use only first entry) */
Packit 6bd9ab
  passwd = get_userpassword(entry, attmap_group_userPassword,
Packit 6bd9ab
                            passbuffer, sizeof(passbuffer));
Packit 6bd9ab
  if (passwd == NULL)
Packit 6bd9ab
    passwd = default_group_userPassword;
Packit 6bd9ab
  /* get group members (memberUid&member) */
Packit 6bd9ab
  if (wantmembers)
Packit 6bd9ab
  {
Packit 6bd9ab
    set = set_new();
Packit 6bd9ab
    if (set != NULL)
Packit 6bd9ab
    {
Packit 6bd9ab
      if (nslcd_cfg->nss_nested_groups)
Packit 6bd9ab
      {
Packit 6bd9ab
        seen = set_new();
Packit 6bd9ab
        subgroups = set_new();
Packit 6bd9ab
      }
Packit 6bd9ab
      /* collect the members from this group */
Packit 6bd9ab
      getmembers(entry, session, set, seen, subgroups);
Packit 6bd9ab
      /* add the members of any nested groups */
Packit 6bd9ab
      if (subgroups != NULL)
Packit 6bd9ab
      {
Packit 6bd9ab
        while ((tmp = set_pop(subgroups)) != NULL)
Packit 6bd9ab
        {
Packit 6bd9ab
          search = myldap_search(session, tmp, LDAP_SCOPE_BASE, group_filter, group_attrs, NULL);
Packit 6bd9ab
          if (search != NULL)
Packit 6bd9ab
            while ((entry2 = myldap_get_entry(search, NULL)) != NULL)
Packit 6bd9ab
              getmembers(entry2, session, set, seen, subgroups);
Packit 6bd9ab
          free(tmp);
Packit 6bd9ab
        }
Packit 6bd9ab
      }
Packit 6bd9ab
      members = set_tolist(set);
Packit 6bd9ab
      set_free(set);
Packit 6bd9ab
      if (seen != NULL)
Packit 6bd9ab
        set_free(seen);
Packit 6bd9ab
      if (subgroups != NULL)
Packit 6bd9ab
        set_free(subgroups);
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  /* write entries (split to a separate function so we can ensure the call
Packit 6bd9ab
     to free() below in case a write fails) */
Packit 6bd9ab
  rc = do_write_group(fp, entry, names, gids, numgids, passwd, members,
Packit 6bd9ab
                      reqname);
Packit 6bd9ab
  /* free and return */
Packit 6bd9ab
  if (members != NULL)
Packit 6bd9ab
    free(members);
Packit 6bd9ab
  return rc;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  group, byname, NSLCD_ACTION_GROUP_BYNAME,
Packit 6bd9ab
  char name[BUFLEN_NAME];
Packit 6bd9ab
  char filter[BUFLEN_FILTER];
Packit 6bd9ab
  READ_STRING(fp, name);
Packit 6bd9ab
  log_setrequest("group=\"%s\"", name);
Packit 6bd9ab
  if (!isvalidname(name))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "request denied by validnames option");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  },
Packit 6bd9ab
  mkfilter_group_byname(name, filter, sizeof(filter)),
Packit 6bd9ab
  write_group(fp, entry, name, NULL, 1, session)
Packit 6bd9ab
)
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  group, bygid, NSLCD_ACTION_GROUP_BYGID,
Packit 6bd9ab
  gid_t gid;
Packit 6bd9ab
  char filter[BUFLEN_FILTER];
Packit 6bd9ab
  READ_INT32(fp, gid);
Packit 6bd9ab
  log_setrequest("group=%lu", (unsigned long int)gid);,
Packit 6bd9ab
  mkfilter_group_bygid(gid, filter, sizeof(filter)),
Packit 6bd9ab
  write_group(fp, entry, NULL, &gid, 1, session)
Packit 6bd9ab
)
Packit 6bd9ab
Packit 6bd9ab
int nslcd_group_bymember(TFILE *fp, MYLDAP_SESSION *session)
Packit 6bd9ab
{
Packit 6bd9ab
  /* define common variables */
Packit 6bd9ab
  int32_t tmpint32;
Packit 6bd9ab
  MYLDAP_SEARCH *search;
Packit 6bd9ab
  MYLDAP_ENTRY *entry;
Packit 6bd9ab
  const char *dn;
Packit 6bd9ab
  const char *base;
Packit 6bd9ab
  int rc, i;
Packit 6bd9ab
  char name[BUFLEN_NAME];
Packit 6bd9ab
  char filter[BUFLEN_FILTER];
Packit 6bd9ab
  SET *seen=NULL, *tocheck=NULL;
Packit 6bd9ab
  /* read request parameters */
Packit 6bd9ab
  READ_STRING(fp, name);
Packit 6bd9ab
  log_setrequest("group/member=\"%s\"", name);
Packit 6bd9ab
  /* validate request */
Packit 6bd9ab
  if (!isvalidname(name))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "request denied by validnames option");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  if ((nslcd_cfg->nss_initgroups_ignoreusers != NULL) &&
Packit 6bd9ab
      set_contains(nslcd_cfg->nss_initgroups_ignoreusers, name))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_DEBUG, "ignored group member");
Packit 6bd9ab
    /* just end the request, returning no results */
Packit 6bd9ab
    WRITE_INT32(fp, NSLCD_VERSION);
Packit 6bd9ab
    WRITE_INT32(fp, NSLCD_ACTION_GROUP_BYMEMBER);
Packit 6bd9ab
    WRITE_INT32(fp, NSLCD_RESULT_END);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* write the response header */
Packit 6bd9ab
  WRITE_INT32(fp, NSLCD_VERSION);
Packit 6bd9ab
  WRITE_INT32(fp, NSLCD_ACTION_GROUP_BYMEMBER);
Packit 6bd9ab
  /* prepare the search filter */
Packit 6bd9ab
  if (mkfilter_group_bymember(session, name, filter, sizeof(filter)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "nslcd_group_bymember(): filter buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  if ((nslcd_cfg->nss_nested_groups) && (strcasecmp(attmap_group_member, "\"\"") != 0))
Packit 6bd9ab
  {
Packit 6bd9ab
    seen = set_new();
Packit 6bd9ab
    tocheck = set_new();
Packit 6bd9ab
    if ((seen != NULL) && (tocheck == NULL))
Packit 6bd9ab
    {
Packit 6bd9ab
      set_free(seen);
Packit 6bd9ab
      seen = NULL;
Packit 6bd9ab
    }
Packit 6bd9ab
    else if ((tocheck != NULL) && (seen == NULL))
Packit 6bd9ab
    {
Packit 6bd9ab
      set_free(tocheck);
Packit 6bd9ab
      tocheck = NULL;
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  /* perform a search for each search base */
Packit 6bd9ab
  for (i = 0; (base = group_bases[i]) != NULL; i++)
Packit 6bd9ab
  {
Packit 6bd9ab
    /* do the LDAP search */
Packit 6bd9ab
    search = myldap_search(session, base, group_scope, filter,
Packit 6bd9ab
                           group_bymember_attrs, NULL);
Packit 6bd9ab
    if (search == NULL)
Packit 6bd9ab
    {
Packit 6bd9ab
      if (seen != NULL)
Packit 6bd9ab
      {
Packit 6bd9ab
        set_free(seen);
Packit 6bd9ab
        set_free(tocheck);
Packit 6bd9ab
      }
Packit 6bd9ab
      return -1;
Packit 6bd9ab
    }
Packit 6bd9ab
    /* go over results */
Packit 6bd9ab
    while ((entry = myldap_get_entry(search, &rc)) != NULL)
Packit 6bd9ab
    {
Packit 6bd9ab
      if ((seen == NULL) || (!set_contains(seen, dn = myldap_get_dn(entry))))
Packit 6bd9ab
      {
Packit 6bd9ab
        if (seen != NULL)
Packit 6bd9ab
        {
Packit 6bd9ab
          set_add(seen, dn);
Packit 6bd9ab
          set_add(tocheck, dn);
Packit 6bd9ab
        }
Packit 6bd9ab
        if (write_group(fp, entry, NULL, NULL, 0, session))
Packit 6bd9ab
        {
Packit 6bd9ab
          if (seen != NULL)
Packit 6bd9ab
          {
Packit 6bd9ab
            set_free(seen);
Packit 6bd9ab
            set_free(tocheck);
Packit 6bd9ab
          }
Packit 6bd9ab
          return -1;
Packit 6bd9ab
        }
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
  }
Packit 6bd9ab
  /* write possible parent groups */
Packit 6bd9ab
  if (tocheck != NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    while ((dn = set_pop(tocheck)) != NULL)
Packit 6bd9ab
    {
Packit 6bd9ab
      /* make filter for finding groups with our group as member */
Packit 6bd9ab
      if (mkfilter_group_bymemberdn(dn, filter, sizeof(filter)))
Packit 6bd9ab
      {
Packit 6bd9ab
        log_log(LOG_WARNING, "nslcd_group_bymember(): filter buffer too small");
Packit 6bd9ab
        free((void *)dn);
Packit 6bd9ab
        set_free(seen);
Packit 6bd9ab
        set_free(tocheck);
Packit 6bd9ab
        return -1;
Packit 6bd9ab
      }
Packit 6bd9ab
      free((void *)dn);
Packit 6bd9ab
      /* do the LDAP searches */
Packit 6bd9ab
      for (i = 0; (base = group_bases[i]) != NULL; i++)
Packit 6bd9ab
      {
Packit 6bd9ab
        search = myldap_search(session, base, group_scope, filter, group_bymember_attrs, NULL);
Packit 6bd9ab
        if (search != NULL)
Packit 6bd9ab
        {
Packit 6bd9ab
          while ((entry = myldap_get_entry(search, NULL)) != NULL)
Packit 6bd9ab
          {
Packit 6bd9ab
            dn = myldap_get_dn(entry);
Packit 6bd9ab
            if (!set_contains(seen, dn))
Packit 6bd9ab
            {
Packit 6bd9ab
              set_add(seen, dn);
Packit 6bd9ab
              set_add(tocheck, dn);
Packit 6bd9ab
              if (write_group(fp, entry, NULL, NULL, 0, session))
Packit 6bd9ab
              {
Packit 6bd9ab
                set_free(seen);
Packit 6bd9ab
                set_free(tocheck);
Packit 6bd9ab
                return -1;
Packit 6bd9ab
              }
Packit 6bd9ab
            }
Packit 6bd9ab
          }
Packit 6bd9ab
        }
Packit 6bd9ab
      }
Packit 6bd9ab
    }
Packit 6bd9ab
    set_free(seen);
Packit 6bd9ab
    set_free(tocheck);
Packit 6bd9ab
  }
Packit 6bd9ab
  /* write the final result code */
Packit 6bd9ab
  if (rc == LDAP_SUCCESS)
Packit 6bd9ab
  {
Packit 6bd9ab
    WRITE_INT32(fp, NSLCD_RESULT_END);
Packit 6bd9ab
  }
Packit 6bd9ab
  return 0;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  group, all, NSLCD_ACTION_GROUP_ALL,
Packit 6bd9ab
  const char *filter;
Packit 6bd9ab
  log_setrequest("group(all)");,
Packit 6bd9ab
  (filter = group_filter, 0),
Packit 6bd9ab
  write_group(fp, entry, NULL, NULL, 1, session)
Packit 6bd9ab
)