summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-07-21 21:58:02 -0600
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-07-21 21:58:02 -0600
commitc7181f7eab2fd36084f51f36e49f2d663953ce86 (patch)
tree74982ef0623680de7d98d5eaf240dae89f90e13c
parent6fc3d82aae15d5e80e70dbb3adda1c39ef3b62f7 (diff)
these changes were sitting here, I don't know how longHEADmaster
-rw-r--r--Makefile.am2
-rw-r--r--README60
-rw-r--r--nslcd/Makefile.am2
-rw-r--r--nslcd/db_group.c612
4 files changed, 675 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index a395f81..dee710d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ uninstall-local: uninstall-nslcd_conf
# install a default configuration file if it is not already there
install-nslcd_conf:
+ @$(NORMAL_INSTALL)
@if [ -f $(DESTDIR)$(NSLCD_CONF_PATH) ]; then \
echo "$(DESTDIR)$(NSLCD_CONF_PATH) already exists, install will not overwrite"; \
else \
@@ -48,6 +49,7 @@ install-nslcd_conf:
$(INSTALL) -m 600 $(srcdir)/nslcd.conf $(DESTDIR)$(NSLCD_CONF_PATH); \
fi
uninstall-nslcd_conf:
+ @$(NORMAL_UNINSTALL)
-rm -f $(DESTDIR)$(NSLCD_CONF_PATH)
# target for generating the ChangeLog file
diff --git a/README b/README
index 1395d95..a8d4cd2 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+-*- fill-column: 80 -*-
+
nss-pam-ldapd - NSS and PAM libraries for name lookups and authentication
using LDAP
@@ -34,6 +36,64 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
+PAM OPTIONS
+===========
+
+Options affecting libpam:pam_get_authtok(3):
+pam_sm_authenticate
+pam_sm_chauthtok
+
+
+use_first_pass
+
+ The argument use_first_pass forces the module to use a previous stacked
+ modules password and will never prompt the user - if no password is
+ available or the password is not appropriate, the user will be denied
+ access.
+
+try_first_pass
+
+ Before prompting the user for their password, the module first tries the
+ previous stacked module's password in case that satisfies this module as
+ well.
+
+use_authtok
+
+ When password changing enforce the module to use the new password provided
+ by a previously stacked password module (this is used in the example of the
+ stacking of the pam_cracklib module documented below).
+
+Options (only?) affecting pam_ldap.so itself:
+
+nullok
+
+ The default action of this module is to not permit the user access to a
+ service if their official password is blank. The nullok argument overrides
+ this default.
+
+no_warn
+
+ Do not print messages with pam_error(3).
+
+ignore_unknown_user
+
+ Return PAM_IGNORE instead of PAM_USER_UNKNOWN in the event of an unknown
+ user.
+
+ignore_authoinfo_unavail
+
+ Return PAM_IGNORE instead of PAM_AUTHINFO_UNAVAIL.
+
+debug
+
+ Turns on debugging via syslog(3).
+
+minimum_uid=<UID>
+
+ By default, this module works for all user ID numbers. The minimum_uid=
+ option sets a minumum UID to answer for. Requests for a UID lower than
+ minimum_uid= will result PAM_UNKNOWN_USER being returned (or PAM_IGNORE if
+ ignore_uknown_user is set).
INTRODUCTION
============
diff --git a/nslcd/Makefile.am b/nslcd/Makefile.am
index a6fc7f8..86bdbda 100644
--- a/nslcd/Makefile.am
+++ b/nslcd/Makefile.am
@@ -31,7 +31,7 @@ nslcd_SOURCES = nslcd.c ../nslcd.h ../common/nslcd-prot.h \
dispatch.c dispatch.h \
cfg.c cfg.h \
nsswitch.c invalidator.c \
- db_config.c db_pam.c db_passwd.c db_shadow.c \
+ db_config.c db_pam.c db_passwd.c db_shadow.c db_group.c \
hackers.c hackers_watch.c hackers_parse.c \
hackers.h hackers_watch.h hackers_parse.h
nslcd_LDADD = ../common/libtio.a ../common/libdict.a \
diff --git a/nslcd/db_group.c b/nslcd/db_group.c
new file mode 100644
index 0000000..6741b48
--- /dev/null
+++ b/nslcd/db_group.c
@@ -0,0 +1,612 @@
+/*
+ group.c - group entry lookup routines
+ Parts of this file were part of the nss_ldap library (as ldap-grp.c)
+ which has been forked into the nss-pam-ldapd library.
+
+ Copyright (C) 1997-2006 Luke Howard
+ Copyright (C) 2006 West Consulting
+ Copyright (C) 2006-2014 Arthur de Jong
+ Copyright (C) 2013 Steve Hill
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* for gid_t */
+#include <grp.h>
+
+#include "common/set.h"
+#include "common.h"
+#include "log.h"
+#include "cfg.h"
+#include "compat/strndup.h"
+
+/* ( nisSchema.2.2 NAME 'posixGroup' SUP top STRUCTURAL
+ * DESC 'Abstraction of a group of accounts'
+ * MUST ( cn $ gidNumber )
+ * MAY ( userPassword $ memberUid $ description ) )
+ *
+ * apart from the above a member attribute is also supported that
+ * may contains a DN of a user
+ *
+ * nested groups (groups that are member of a group) are currently
+ * not supported
+ */
+
+/* the search base for searches */
+const char *group_bases[NSS_LDAP_CONFIG_MAX_BASES] = { NULL };
+
+/* the search scope for searches */
+int group_scope = LDAP_SCOPE_DEFAULT;
+
+/* the basic search filter for searches */
+const char *group_filter = "(objectClass=posixGroup)";
+
+/* the attributes to request with searches */
+const char *attmap_group_cn = "cn";
+const char *attmap_group_userPassword = "\"*\"";
+const char *attmap_group_gidNumber = "gidNumber";
+const char *attmap_group_memberUid = "memberUid";
+const char *attmap_group_member = "member";
+
+/* special property for objectSid-based searches
+ (these are already LDAP-escaped strings) */
+static char *gidSid = NULL;
+
+/* BUILTIN SID definitions */
+static char *builtinSid = NULL;
+const gid_t min_builtin_rid = 544;
+const gid_t max_builtin_rid = 552;
+
+/* default values for attributes */
+static const char *default_group_userPassword = "*"; /* unmatchable */
+
+/* the attribute list to request with searches */
+static const char **group_attrs = NULL;
+
+/* the attribute list for bymember searches (without member attributes) */
+static const char **group_bymember_attrs = NULL;
+
+/* create a search filter for searching a group entry
+ by name, return -1 on errors */
+static int mkfilter_group_byname(const char *name,
+ char *buffer, size_t buflen)
+{
+ char safename[BUFLEN_SAFENAME];
+ /* escape attribute */
+ if (myldap_escape(name, safename, sizeof(safename)))
+ {
+ log_log(LOG_ERR, "mkfilter_group_byname(): safename buffer too small");
+ return -1;
+ }
+ /* build filter */
+ return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
+ group_filter, attmap_group_cn, safename);
+}
+
+/* create a search filter for searching a group entry
+ by gid, return -1 on errors */
+static int mkfilter_group_bygid(gid_t gid, char *buffer, size_t buflen)
+{
+ /* if searching for a Windows domain SID */
+ if (gidSid != NULL)
+ {
+ /* the given gid is a BUILTIN gid, the SID prefix is not the domain SID */
+ if ((gid >= min_builtin_rid) && (gid <= max_builtin_rid))
+ return mysnprintf(buffer, buflen, "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))",
+ group_filter, attmap_group_gidNumber, builtinSid,
+ (int)(gid & 0xff), (int)((gid >> 8) & 0xff),
+ (int)((gid >> 16) & 0xff), (int)((gid >> 24) & 0xff));
+ return mysnprintf(buffer, buflen, "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))",
+ group_filter, attmap_group_gidNumber, gidSid,
+ (int)(gid & 0xff), (int)((gid >> 8) & 0xff),
+ (int)((gid >> 16) & 0xff), (int)((gid >> 24) & 0xff));
+ }
+ else
+ {
+ return mysnprintf(buffer, buflen, "(&%s(%s=%lu))",
+ group_filter, attmap_group_gidNumber, (unsigned long int)gid);
+ }
+}
+
+/* create a search filter for searching a group entry
+ by member uid, return -1 on errors */
+static int mkfilter_group_bymember(MYLDAP_SESSION *session,
+ const char *uid,
+ char *buffer, size_t buflen)
+{
+ char dn[BUFLEN_DN];
+ char safeuid[BUFLEN_SAFENAME];
+ char safedn[BUFLEN_SAFEDN];
+ /* escape attribute */
+ if (myldap_escape(uid, safeuid, sizeof(safeuid)))
+ {
+ log_log(LOG_ERR, "mkfilter_group_bymember(): safeuid buffer too small");
+ return -1;
+ }
+ /* try to translate uid to DN */
+ if ((strcasecmp(attmap_group_member, "\"\"") == 0) ||
+ (uid2dn(session, uid, dn, sizeof(dn)) == NULL))
+ return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
+ group_filter, attmap_group_memberUid, safeuid);
+ /* escape DN */
+ if (myldap_escape(dn, safedn, sizeof(safedn)))
+ {
+ log_log(LOG_ERR, "mkfilter_group_bymember(): safedn buffer too small");
+ return -1;
+ }
+ /* also lookup using user DN */
+ return mysnprintf(buffer, buflen, "(&%s(|(%s=%s)(%s=%s)))",
+ group_filter,
+ attmap_group_memberUid, safeuid,
+ attmap_group_member, safedn);
+}
+
+static int mkfilter_group_bymemberdn(const char *dn,
+ char *buffer, size_t buflen)
+{
+ char safedn[BUFLEN_SAFEDN];
+ /* escape DN */
+ if (myldap_escape(dn, safedn, sizeof(safedn)))
+ {
+ log_log(LOG_ERR, "mkfilter_group_bymemberdn(): safedn buffer too small");
+ return -1;
+ }
+ return mysnprintf(buffer, buflen,
+ "(&%s(%s=%s))",
+ group_filter,
+ attmap_group_member, safedn);
+}
+
+void group_init(void)
+{
+ int i;
+ SET *set;
+ /* set up search bases */
+ if (group_bases[0] == NULL)
+ for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
+ group_bases[i] = nslcd_cfg->bases[i];
+ /* set up scope */
+ if (group_scope == LDAP_SCOPE_DEFAULT)
+ group_scope = nslcd_cfg->scope;
+ /* special case when gidNumber references objectSid */
+ if (strncasecmp(attmap_group_gidNumber, "objectSid:", 10) == 0)
+ {
+ gidSid = sid2search(attmap_group_gidNumber + 10);
+ builtinSid = sid2search("S-1-5-32");
+ attmap_group_gidNumber = strndup(attmap_group_gidNumber, 9);
+ }
+ /* set up attribute list */
+ set = set_new();
+ attmap_add_attributes(set, attmap_group_cn);
+ attmap_add_attributes(set, attmap_group_userPassword);
+ attmap_add_attributes(set, attmap_group_memberUid);
+ attmap_add_attributes(set, attmap_group_gidNumber);
+ attmap_add_attributes(set, attmap_group_member);
+ group_attrs = set_tolist(set);
+ if (group_attrs == NULL)
+ {
+ log_log(LOG_CRIT, "malloc() failed to allocate memory");
+ exit(EXIT_FAILURE);
+ }
+ set_free(set);
+ /* set up bymember attribute list */
+ set = set_new();
+ attmap_add_attributes(set, attmap_group_cn);
+ attmap_add_attributes(set, attmap_group_userPassword);
+ attmap_add_attributes(set, attmap_group_gidNumber);
+ group_bymember_attrs = set_tolist(set);
+ if (group_bymember_attrs == NULL)
+ {
+ log_log(LOG_CRIT, "malloc() failed to allocate memory");
+ exit(EXIT_FAILURE);
+ }
+ set_free(set);
+}
+
+static int do_write_group(TFILE *fp, MYLDAP_ENTRY *entry,
+ const char **names, gid_t gids[], int numgids,
+ const char *passwd, const char **members,
+ const char *reqname)
+{
+ int32_t tmpint32, tmp2int32, tmp3int32;
+ int i, j;
+ /* write entries for all names and gids */
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (!isvalidname(names[i]))
+ {
+ log_log(LOG_WARNING, "%s: %s: denied by validnames option",
+ myldap_get_dn(entry), attmap_group_cn);
+ }
+ else if ((reqname == NULL) || (STR_CMP(reqname, names[i]) == 0))
+ {
+ for (j = 0; j < numgids; j++)
+ {
+ WRITE_INT32(fp, NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp, names[i]);
+ WRITE_STRING(fp, passwd);
+ WRITE_INT32(fp, gids[j]);
+ WRITE_STRINGLIST(fp, members);
+ }
+ }
+ }
+ return 0;
+}
+
+static void getmembers(MYLDAP_ENTRY *entry, MYLDAP_SESSION *session,
+ SET *members, SET *seen, SET *subgroups)
+{
+ char buf[BUFLEN_NAME];
+ int i;
+ const char **values;
+ const char ***derefs;
+ /* add the memberUid values */
+ values = myldap_get_values(entry, attmap_group_memberUid);
+ if (values != NULL)
+ for (i = 0; values[i] != NULL; i++)
+ {
+ /* only add valid usernames */
+ if (isvalidname(values[i]))
+ set_add(members, values[i]);
+ }
+ /* skip rest if attmap_group_member is blank */
+ if (strcasecmp(attmap_group_member, "\"\"") == 0)
+ return;
+ /* add deref'd entries if we have them*/
+ derefs = myldap_get_deref_values(entry, attmap_group_member, attmap_passwd_uid);
+ if (derefs != NULL)
+ {
+ /* add deref'd uid attributes */
+ for (i = 0; derefs[0][i] != NULL; i++)
+ set_add(members, derefs[0][i]);
+ /* add non-deref'd attribute values as subgroups */
+ for (i = 0; derefs[1][i] != NULL; i++)
+ {
+ if ((seen == NULL) || (!set_contains(seen, derefs[1][i])))
+ {
+ if (seen != NULL)
+ set_add(seen, derefs[1][i]);
+ if (subgroups != NULL)
+ set_add(subgroups, derefs[1][i]);
+ }
+ }
+ return; /* no need to parse the member attribute ourselves */
+ }
+ /* add the member values */
+ values = myldap_get_values(entry, attmap_group_member);
+ if (values != NULL)
+ for (i = 0; values[i] != NULL; i++)
+ {
+ if ((seen == NULL) || (!set_contains(seen, values[i])))
+ {
+ if (seen != NULL)
+ set_add(seen, values[i]);
+ /* transform the DN into a uid (dn2uid() already checks validity) */
+ if (dn2uid(session, values[i], buf, sizeof(buf)) != NULL)
+ set_add(members, buf);
+ /* wasn't a UID - try handling it as a nested group */
+ else if (subgroups != NULL)
+ set_add(subgroups, values[i]);
+ }
+ }
+}
+
+/* the maximum number of gidNumber attributes per entry */
+#define MAXGIDS_PER_ENTRY 5
+
+static int write_group(TFILE *fp, MYLDAP_ENTRY *entry, const char *reqname,
+ const gid_t *reqgid, int wantmembers,
+ MYLDAP_SESSION *session)
+{
+ const char **names, **gidvalues;
+ const char *passwd;
+ const char **members = NULL;
+ SET *set, *seen=NULL, *subgroups=NULL;
+ gid_t gids[MAXGIDS_PER_ENTRY];
+ int numgids;
+ char *tmp;
+ char passbuffer[BUFLEN_PASSWORDHASH];
+ MYLDAP_SEARCH *search;
+ MYLDAP_ENTRY *entry2;
+ int rc;
+ /* get group name (cn) */
+ names = myldap_get_values(entry, attmap_group_cn);
+ if ((names == NULL) || (names[0] == NULL))
+ {
+ log_log(LOG_WARNING, "%s: %s: missing",
+ myldap_get_dn(entry), attmap_group_cn);
+ return 0;
+ }
+ /* get the group id(s) */
+ if (reqgid != NULL)
+ {
+ gids[0] = *reqgid;
+ numgids = 1;
+ }
+ else
+ {
+ gidvalues = myldap_get_values_len(entry, attmap_group_gidNumber);
+ if ((gidvalues == NULL) || (gidvalues[0] == NULL))
+ {
+ log_log(LOG_WARNING, "%s: %s: missing",
+ myldap_get_dn(entry), attmap_group_gidNumber);
+ return 0;
+ }
+ for (numgids = 0; (numgids < MAXGIDS_PER_ENTRY) && (gidvalues[numgids] != NULL); numgids++)
+ {
+ if (gidSid != NULL)
+ gids[numgids] = (gid_t)binsid2id(gidvalues[numgids]);
+ else
+ {
+ errno = 0;
+ gids[numgids] = strtogid(gidvalues[numgids], &tmp, 10);
+ if ((*(gidvalues[numgids]) == '\0') || (*tmp != '\0'))
+ {
+ log_log(LOG_WARNING, "%s: %s: non-numeric",
+ myldap_get_dn(entry), attmap_group_gidNumber);
+ return 0;
+ }
+ else if ((errno != 0) || (strchr(gidvalues[numgids], '-') != NULL))
+ {
+ log_log(LOG_WARNING, "%s: %s: out of range",
+ myldap_get_dn(entry), attmap_group_gidNumber);
+ return 0;
+ }
+ }
+ }
+ }
+ /* get group passwd (userPassword) (use only first entry) */
+ passwd = get_userpassword(entry, attmap_group_userPassword,
+ passbuffer, sizeof(passbuffer));
+ if (passwd == NULL)
+ passwd = default_group_userPassword;
+ /* get group members (memberUid&member) */
+ if (wantmembers)
+ {
+ set = set_new();
+ if (set != NULL)
+ {
+ if (nslcd_cfg->nss_nested_groups)
+ {
+ seen = set_new();
+ subgroups = set_new();
+ }
+ /* collect the members from this group */
+ getmembers(entry, session, set, seen, subgroups);
+ /* add the members of any nested groups */
+ if (subgroups != NULL)
+ {
+ while ((tmp = set_pop(subgroups)) != NULL)
+ {
+ search = myldap_search(session, tmp, LDAP_SCOPE_BASE, group_filter, group_attrs, NULL);
+ if (search != NULL)
+ while ((entry2 = myldap_get_entry(search, NULL)) != NULL)
+ getmembers(entry2, session, set, seen, subgroups);
+ free(tmp);
+ }
+ }
+ members = set_tolist(set);
+ set_free(set);
+ if (seen != NULL)
+ set_free(seen);
+ if (subgroups != NULL)
+ set_free(subgroups);
+ }
+ }
+ /* write entries (split to a separate function so we can ensure the call
+ to free() below in case a write fails) */
+ rc = do_write_group(fp, entry, names, gids, numgids, passwd, members,
+ reqname);
+ /* free and return */
+ if (members != NULL)
+ free(members);
+ return rc;
+}
+
+NSLCD_HANDLE(GROUP, BYNAME
+ ,/* decls */
+ char name[BUFLEN_NAME];
+ char filter[BUFLEN_FILTER];
+ ,/* read */
+ READ_STRING(fp, name);
+ log_setrequest("group=\"%s\"", name);
+ ,/* check */
+ if (!isvalidname(name))
+ {
+ log_log(LOG_WARNING, "request denied by validnames option");
+ return -1;
+ },
+ ,/* search */
+ mkfilter_group_byname(name, filter, sizeof(filter));
+ ,/* write */
+ write_group(fp, entry, name, NULL, 1, session);
+ ,/* cleanup */
+)
+
+NSLCD_HANDLE(GROUP, BYGID
+ ,/* decls */
+ gid_t gid;
+ char filter[BUFLEN_FILTER];
+ ,/* read */
+ READ_INT32(fp, gid);
+ log_setrequest("group=%lu", (unsigned long int)gid);
+ ,/* check */
+ ,/* search */
+ mkfilter_group_bygid(gid, filter, sizeof(filter));
+ ,/* write */
+ write_group(fp, entry, NULL, &gid, 1, session);
+ ,/* cleanup */
+)
+
+int nslcd_group_bymember(TFILE *fp, MYLDAP_SESSION *session)
+{
+ /* define common variables */
+ int32_t tmpint32;
+ MYLDAP_SEARCH *search;
+ MYLDAP_ENTRY *entry;
+ const char *dn;
+ const char *base;
+ int rc, i;
+ char name[BUFLEN_NAME];
+ char filter[BUFLEN_FILTER];
+ SET *seen=NULL, *tocheck=NULL;
+ /* read request parameters */
+ READ_STRING(fp, name);
+ log_setrequest("group/member=\"%s\"", name);
+ /* validate request */
+ if (!isvalidname(name))
+ {
+ log_log(LOG_WARNING, "request denied by validnames option");
+ return -1;
+ }
+ if ((nslcd_cfg->nss_initgroups_ignoreusers != NULL) &&
+ set_contains(nslcd_cfg->nss_initgroups_ignoreusers, name))
+ {
+ log_log(LOG_DEBUG, "ignored group member");
+ /* just end the request, returning no results */
+ WRITE_INT32(fp, NSLCD_VERSION);
+ WRITE_INT32(fp, NSLCD_ACTION_GROUP_BYMEMBER);
+ WRITE_INT32(fp, NSLCD_RESULT_END);
+ return 0;
+ }
+ /* write the response header */
+ WRITE_INT32(fp, NSLCD_VERSION);
+ WRITE_INT32(fp, NSLCD_ACTION_GROUP_BYMEMBER);
+ /* prepare the search filter */
+ if (mkfilter_group_bymember(session, name, filter, sizeof(filter)))
+ {
+ log_log(LOG_WARNING, "nslcd_group_bymember(): filter buffer too small");
+ return -1;
+ }
+ if ((nslcd_cfg->nss_nested_groups) && (strcasecmp(attmap_group_member, "\"\"") != 0))
+ {
+ seen = set_new();
+ tocheck = set_new();
+ if ((seen != NULL) && (tocheck == NULL))
+ {
+ set_free(seen);
+ seen = NULL;
+ }
+ else if ((tocheck != NULL) && (seen == NULL))
+ {
+ set_free(tocheck);
+ tocheck = NULL;
+ }
+ }
+ /* perform a search for each search base */
+ for (i = 0; (base = group_bases[i]) != NULL; i++)
+ {
+ /* do the LDAP search */
+ search = myldap_search(session, base, group_scope, filter,
+ group_bymember_attrs, NULL);
+ if (search == NULL)
+ {
+ if (seen != NULL)
+ {
+ set_free(seen);
+ set_free(tocheck);
+ }
+ return -1;
+ }
+ /* go over results */
+ while ((entry = myldap_get_entry(search, &rc)) != NULL)
+ {
+ if ((seen == NULL) || (!set_contains(seen, dn = myldap_get_dn(entry))))
+ {
+ if (seen != NULL)
+ {
+ set_add(seen, dn);
+ set_add(tocheck, dn);
+ }
+ if (write_group(fp, entry, NULL, NULL, 0, session))
+ {
+ if (seen != NULL)
+ {
+ set_free(seen);
+ set_free(tocheck);
+ }
+ return -1;
+ }
+ }
+ }
+ }
+ /* write possible parent groups */
+ if (tocheck != NULL)
+ {
+ while ((dn = set_pop(tocheck)) != NULL)
+ {
+ /* make filter for finding groups with our group as member */
+ if (mkfilter_group_bymemberdn(dn, filter, sizeof(filter)))
+ {
+ log_log(LOG_WARNING, "nslcd_group_bymember(): filter buffer too small");
+ free((void *)dn);
+ set_free(seen);
+ set_free(tocheck);
+ return -1;
+ }
+ free((void *)dn);
+ /* do the LDAP searches */
+ for (i = 0; (base = group_bases[i]) != NULL; i++)
+ {
+ search = myldap_search(session, base, group_scope, filter, group_bymember_attrs, NULL);
+ if (search != NULL)
+ {
+ while ((entry = myldap_get_entry(search, NULL)) != NULL)
+ {
+ dn = myldap_get_dn(entry);
+ if (!set_contains(seen, dn))
+ {
+ set_add(seen, dn);
+ set_add(tocheck, dn);
+ if (write_group(fp, entry, NULL, NULL, 0, session))
+ {
+ set_free(seen);
+ set_free(tocheck);
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+ set_free(seen);
+ set_free(tocheck);
+ }
+ /* write the final result code */
+ if (rc == LDAP_SUCCESS)
+ {
+ WRITE_INT32(fp, NSLCD_RESULT_END);
+ }
+ return 0;
+}
+
+NSLCD_HANDLE(GROUP, ALL
+ ,/* decls */
+ const char *filter;
+ ,/* read */
+ log_setrequest("group(all)");
+ ,/* check */
+ ,/* search */
+ (filter = group_filter, 0),
+ ,/* write */
+ return write_group(fp, entry, NULL, NULL, 1, session);
+ ,/* cleanup */
+)