summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-03-24 22:52:44 +0100
committerArthur de Jong <arthur@arthurdejong.org>2013-03-24 22:52:44 +0100
commit3daa68d35cf18c0dc80c8c24c7aa23c6273d06c4 (patch)
tree3b1e8c1596f292dbe67fb1cc903237de0466be66
parentedd119c3a0d532fc5f87ccf89585370cb2fa3fed (diff)
parent642064cc205cf484bd904d94141eba8740aa0a28 (diff)
Implement support for nested groups
-rw-r--r--AUTHORS1
-rw-r--r--README10
-rw-r--r--man/nslcd.conf.5.xml13
-rw-r--r--nslcd/cfg.c7
-rw-r--r--nslcd/cfg.h1
-rw-r--r--nslcd/group.c207
-rw-r--r--pynslcd/cfg.py3
-rw-r--r--pynslcd/common.py17
-rw-r--r--pynslcd/group.py55
-rw-r--r--tests/test.ldif272
-rwxr-xr-xtests/test_nsscmds.sh24
11 files changed, 556 insertions, 54 deletions
diff --git a/AUTHORS b/AUTHORS
index 1d9f989..1f88b1b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -120,3 +120,4 @@ Matthew L. Dailey <matthew.l.dailey@dartmouth.edu>
Chris Hiestand <chiestand@salk.edu>
Jon Severinsson <jon@severinsson.net>
Thorsten Glaser <t.glaser@tarent.de>
+Steve Hill <steve@opendium.com>
diff --git a/README b/README
index d997e68..ad906a5 100644
--- a/README
+++ b/README
@@ -15,7 +15,7 @@
Copyright (C) 1997-2006 Luke Howard
Copyright (C) 2006-2007 West Consulting
- Copyright (C) 2006-2012 Arthur de Jong
+ Copyright (C) 2006-2013 Arthur de Jong
Copyright (C) 2009 Howard Chu
Copyright (C) 2010 Symas Corporation
@@ -158,7 +158,6 @@ unsupported features
Since nss-pam-ldapd was forked from nss_ldap most of the features that came
with nss_ldap are available. The most important differences:
- the configuration file formats are not fully compatible
-- nested groups are currently unsupported
- rootbinddn/rootbindpw support is removed and is not likely to return
For the PAM module some functionality is missing. Comparing it to pam_ldap:
@@ -356,8 +355,11 @@ If the DN value already contains a uid value (e.g. uid=arthur, dc=example,
dc=com) the lookup is skipped and the value from the DN is used. A cache is
maintained that saves the DN to uid translations for 15 minutes.
-Currently, having nested groups by member values pointing to other groups,
-as well as the memberOf attribute in posixAccount entries are unsupported.
+The member attribute may also contain the DN of another group entry. These
+nested groups are parsed recursively depending on the nss_nested_groups
+option.
+
+Currently, the memberOf attribute in posixAccount entries is unsupported.
case sensitivity
----------------
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml
index 3dc044a..5bee5f4 100644
--- a/man/nslcd.conf.5.xml
+++ b/man/nslcd.conf.5.xml
@@ -720,6 +720,19 @@
</listitem>
</varlistentry>
+ <varlistentry id="nss_nested_groups"> <!-- since 0.9.0 -->
+ <term><option>nss_nested_groups</option> yes|no</term>
+ <listitem>
+ <para>
+ If this option is set, the <litera>member</litera> attribute of a
+ group may point to another group.
+ Members of nested groups are also returned in the higher level group
+ and parent groups are returned when finding groups for a specific user.
+ The default is not to perform extra searches for nested groups.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="validnames"> <!-- since 0.8.2 -->
<term><option>validnames</option> <replaceable>REGEX</replaceable></term>
<listitem>
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index c2b9674..056b6e2 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -1089,6 +1089,7 @@ static void cfg_defaults(struct ldap_config *cfg)
cfg->pagesize = 0;
cfg->nss_initgroups_ignoreusers = NULL;
cfg->nss_min_uid = 0;
+ cfg->nss_nested_groups = 0;
cfg->validnames_str = NULL;
handle_validnames(__FILE__, __LINE__, "",
"/^[a-z0-9._@$()]([a-z0-9._@$() \\~-]*[a-z0-9._@$()~-])?$/i",
@@ -1408,6 +1409,11 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
cfg->nss_min_uid = get_int(filename, lnr, keyword, &line);
get_eol(filename, lnr, keyword, &line);
}
+ else if (strcasecmp(keyword, "nss_nested_groups") == 0)
+ {
+ cfg->nss_nested_groups = get_boolean(filename, lnr, keyword, &line);
+ get_eol(filename, lnr, keyword, &line);
+ }
else if (strcasecmp(keyword, "validnames") == 0)
{
handle_validnames(filename, lnr, keyword, line, cfg);
@@ -1671,6 +1677,7 @@ static void cfg_dump(void)
log_log(LOG_DEBUG, "CFG: nss_initgroups_ignoreusers %s", buffer);
}
log_log(LOG_DEBUG, "CFG: nss_min_uid %d", nslcd_cfg->nss_min_uid);
+ log_log(LOG_DEBUG, "CFG: nss_nested_groups %s", print_boolean(nslcd_cfg->nss_nested_groups));
log_log(LOG_DEBUG, "CFG: validnames %s", nslcd_cfg->validnames_str);
log_log(LOG_DEBUG, "CFG: ignorecase %s", print_boolean(nslcd_cfg->ignorecase));
for (i = 0; i < NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES; i++)
diff --git a/nslcd/cfg.h b/nslcd/cfg.h
index 5acb1d0..7caaa02 100644
--- a/nslcd/cfg.h
+++ b/nslcd/cfg.h
@@ -119,6 +119,7 @@ struct ldap_config {
int pagesize; /* set to a greater than 0 to enable handling of paged results with the specified size */
SET *nss_initgroups_ignoreusers; /* the users for which no initgroups() searches should be done */
uid_t nss_min_uid; /* minimum uid for users retrieved from LDAP */
+ int nss_nested_groups; /* maximum group recursion depth */
regex_t validnames; /* the regular expression to determine valid names */
char *validnames_str; /* string version of validnames regexp */
int ignorecase; /* whether or not case should be ignored in lookups */
diff --git a/nslcd/group.c b/nslcd/group.c
index 868110c..175fceb 100644
--- a/nslcd/group.c
+++ b/nslcd/group.c
@@ -6,6 +6,7 @@
Copyright (C) 1997-2006 Luke Howard
Copyright (C) 2006 West Consulting
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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
@@ -135,6 +136,20 @@ static int mkfilter_group_bymember(MYLDAP_SESSION *session,
attmap_group_member, safedn);
}
+static int mkfilter_group_bymemberdn(MYLDAP_SESSION *session,
+ const char *dn,
+ char *buffer, size_t buflen)
+{
+ char safedn[300];
+ /* escape DN */
+ if (myldap_escape(dn, safedn, sizeof(safedn)))
+ return -1;
+ return mysnprintf(buffer, buflen,
+ "(&%s(%s=%s))",
+ group_filter,
+ attmap_group_member, safedn);
+}
+
void group_init(void)
{
int i;
@@ -198,16 +213,12 @@ static int do_write_group(TFILE *fp, MYLDAP_ENTRY *entry,
return 0;
}
-/* return the list of members */
-static const char **getmembers(MYLDAP_ENTRY *entry, MYLDAP_SESSION *session)
+static void getmembers(MYLDAP_ENTRY *entry, MYLDAP_SESSION *session,
+ SET *members, SET *seen, SET *subgroups)
{
char buf[256];
int i;
const char **values;
- SET *set;
- set = set_new();
- if (set == NULL)
- return NULL;
/* add the memberUid values */
values = myldap_get_values(entry, attmap_group_memberUid);
if (values != NULL)
@@ -215,21 +226,25 @@ static const char **getmembers(MYLDAP_ENTRY *entry, MYLDAP_SESSION *session)
{
/* only add valid usernames */
if (isvalidname(values[i]))
- set_add(set, values[i]);
+ set_add(members, values[i]);
}
/* add the member values */
values = myldap_get_values(entry, attmap_group_member);
if (values != NULL)
for (i = 0; values[i] != NULL; i++)
{
- /* transform the DN into a uid (dn2uid() already checks validity) */
- if (dn2uid(session, values[i], buf, sizeof(buf)) != NULL)
- set_add(set, buf);
+ 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]);
+ }
}
- /* return the members */
- values = set_tolist(set);
- set_free(set);
- return values;
}
/* the maximum number of gidNumber attributes per entry */
@@ -241,11 +256,14 @@ static int write_group(TFILE *fp, MYLDAP_ENTRY *entry, const char *reqname,
{
const char **names, **gidvalues;
const char *passwd;
- const char **members;
+ const char **members = NULL;
+ SET *set, *seen=NULL, *subgroups=NULL;
gid_t gids[MAXGIDS_PER_ENTRY];
int numgids;
char *tmp;
char passbuffer[64];
+ MYLDAP_SEARCH *search;
+ MYLDAP_ENTRY *entry2;
int rc;
/* get group name (cn) */
names = myldap_get_values(entry, attmap_group_cn);
@@ -300,9 +318,36 @@ static int write_group(TFILE *fp, MYLDAP_ENTRY *entry, const char *reqname,
passwd = default_group_userPassword;
/* get group memebers (memberUid&member) */
if (wantmembers)
- members = getmembers(entry, session);
- else
- members = NULL;
+ {
+ 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);
+ }
+ }
+ 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,
@@ -338,12 +383,22 @@ NSLCD_HANDLE(
write_group(fp, entry, NULL, &gid, 1, session)
)
-NSLCD_HANDLE(
- group, bymember, NSLCD_ACTION_GROUP_BYMEMBER,
+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[256];
char filter[4096];
+ 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");
@@ -358,10 +413,114 @@ NSLCD_HANDLE(
WRITE_INT32(fp, NSLCD_ACTION_GROUP_BYMEMBER);
WRITE_INT32(fp, NSLCD_RESULT_END);
return 0;
- },
- mkfilter_group_bymember(session, name, filter, sizeof(filter)),
- write_group(fp, entry, NULL, NULL, 0, session)
-)
+ }
+ /* 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)
+ {
+ 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_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(session, dn, filter, sizeof(filter)))
+ {
+ log_log(LOG_WARNING, "nslcd_group_bymember(): filter buffer too small");
+ set_free(seen);
+ set_free(tocheck);
+ return -1;
+ }
+ /* do the LDAP searches */
+ for (i = 0; (base = group_bases[i]) != NULL; i++)
+ {
+ search = myldap_search(session, base, group_scope, filter, group_attrs, NULL);
+ if (search != NULL)
+ {
+ while ((entry = myldap_get_entry(search, NULL)) != NULL)
+ {
+ if (!set_contains(seen, dn = myldap_get_dn(entry)))
+ {
+ 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, NSLCD_ACTION_GROUP_ALL,
diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py
index 57a1be2..b03b8c7 100644
--- a/pynslcd/cfg.py
+++ b/pynslcd/cfg.py
@@ -85,6 +85,7 @@ tls_key = None
pagesize = 0
nss_initgroups_ignoreusers = set()
nss_min_uid = 0
+nss_nested_groups = False
validnames = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ \\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE)
pam_authz_searches = []
pam_password_prohibit_message = None
@@ -176,7 +177,7 @@ def read(filename):
globals()[m.group('keyword').lower()] = int(m.group('value'))
continue
# parse options with a single boolean argument
- m = re.match('(?P<keyword>referrals)\s+(?P<value>%s)' %
+ m = re.match('(?P<keyword>referrals|nss_nested_groups)\s+(?P<value>%s)' %
'|'.join(_boolean_options.keys()),
line, re.IGNORECASE)
if m:
diff --git a/pynslcd/common.py b/pynslcd/common.py
index bbffef4..3a59cbe 100644
--- a/pynslcd/common.py
+++ b/pynslcd/common.py
@@ -82,18 +82,23 @@ class Request(object):
stream."""
pass
+ def get_results(self, parameters):
+ """Provide the result entries by performing a search."""
+ for dn, attributes in self.search(self.conn, parameters=parameters):
+ for values in self.convert(dn, attributes, parameters):
+ yield values
+
def handle_request(self, parameters):
"""This method handles the request based on the parameters read
with read_parameters()."""
try:
#with cache.con:
if True:
- for dn, attributes in self.search(self.conn, parameters=parameters):
- for values in self.convert(dn, attributes, parameters):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.write(*values)
- if self.cache:
- self.cache.store(*values)
+ for values in self.get_results(parameters):
+ self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
+ self.write(*values)
+ if self.cache:
+ self.cache.store(*values)
except ldap.SERVER_DOWN:
if self.cache:
logging.debug('read from cache')
diff --git a/pynslcd/group.py b/pynslcd/group.py
index a43aae5..71a1173 100644
--- a/pynslcd/group.py
+++ b/pynslcd/group.py
@@ -22,9 +22,11 @@ import itertools
import logging
from ldap.filter import escape_filter_chars
+import ldap
from passwd import dn2uid, uid2dn
import cache
+import cfg
import common
import constants
import search
@@ -51,7 +53,7 @@ class Search(search.LDAPSearch):
def __init__(self, *args, **kwargs):
super(Search, self).__init__(*args, **kwargs)
- if 'memberUid' in self.parameters:
+ if 'memberUid' in self.parameters or 'member' in self.parameters:
# set up our own attributes that leave out membership attributes
self.attributes = list(self.attributes)
self.attributes.remove(attmap['memberUid'])
@@ -95,24 +97,39 @@ class GroupRequest(common.Request):
self.fp.write_int32(gid)
self.fp.write_stringlist(members)
- def convert(self, dn, attributes, parameters):
- # get group names and check against requested group name
- names = attributes['cn']
- # get group group password
- passwd = attributes['userPassword'][0]
- # get group id(s)
- gids = [int(x) for x in attributes['gidNumber']]
- # build member list
- members = set()
+ def get_members(self, attributes, members, subgroups, seen):
# add the memberUid values
for member in clean(attributes['memberUid']):
if common.isvalidname(member):
members.add(member)
# translate and add the member values
for memberdn in clean(attributes['member']):
+ if memberdn in seen:
+ continue
+ seen.add(memberdn)
member = dn2uid(self.conn, memberdn)
if member and common.isvalidname(member):
members.add(member)
+ elif cfg.nss_nested_groups:
+ subgroups.append(memberdn)
+
+ def convert(self, dn, attributes, parameters):
+ # get group names and check against requested group name
+ names = attributes['cn']
+ # get group group password
+ passwd = attributes['userPassword'][0]
+ # get group id(s)
+ gids = [int(x) for x in attributes['gidNumber']]
+ # build member list
+ members = set()
+ subgroups = []
+ seen = set([dn])
+ self.get_members(attributes, members, subgroups, seen)
+ # go over subgroups to find more members
+ while subgroups:
+ memberdn = subgroups.pop(0)
+ for dn2, attributes2 in self.search(self.conn, base=memberdn, scope=ldap.SCOPE_BASE):
+ self.get_members(attributes2, members, subgroups, seen)
# actually return the results
for name in names:
if not common.isvalidname(name):
@@ -150,6 +167,24 @@ class GroupByMemberRequest(GroupRequest):
common.validate_name(memberuid)
return dict(memberUid=memberuid)
+ def get_results(self, parameters):
+ seen = set()
+ for dn, attributes in self.search(self.conn, parameters=parameters):
+ seen.add(dn)
+ for values in self.convert(dn, attributes, parameters):
+ yield values
+ if cfg.nss_nested_groups:
+ tocheck = list(seen)
+ # find parent groups
+ while tocheck:
+ group = tocheck.pop(0)
+ for dn, attributes in self.search(self.conn, parameters=dict(member=group)):
+ if dn not in seen:
+ seen.add(dn)
+ tocheck.append(dn)
+ for result in self.convert(dn, attributes, parameters):
+ yield result
+
class GroupAllRequest(GroupRequest):
diff --git a/tests/test.ldif b/tests/test.ldif
index 33a34d7..f8a8b82 100644
--- a/tests/test.ldif
+++ b/tests/test.ldif
@@ -55570,11 +55570,6 @@ modifyTimestamp: 20080215164610Z
entryCSN: 20080215164610.645394Z#000000#000#000000
dn: cn=testgroup2,ou=groups,dc=test,dc=tld
-member: cn=Test User2,ou=people,dc=test,dc=tld
-member: uid=arthur,ou=people,dc=test,dc=tld
-member: cn=testhost,ou=hosts,dc=test,dc=tld
-member: cn=bar,dc=foo,dc=com
-member: cn=Test\2C User4,ou=people,dc=test,dc=tld
sambaSID: 2
sambaGroupType: 2
gidNumber: 6200
@@ -55586,9 +55581,16 @@ cn: testgroup2
objectClass: top
objectClass: groupOfNames
objectClass: sambaGroupMapping
-entryCSN: 20091101122555.190719Z#000000#000#000000
+member: cn=Test User2,ou=people,dc=test,dc=tld
+member: cn=Test\2C User4,ou=people,dc=test,dc=tld
+member: cn=bar,dc=foo,dc=com
+member: cn=testhost,ou=hosts,dc=test,dc=tld
+member:: Y2490JDQkdCSINCT0pDQlNCC0IPQldCBLG91PXBlb3BsZSxkYz10ZXN0LGRjPXRsZA==
+member:: Y2495Y+v5piv5b2T6L+Z5LiqVeebmOWcqCxvdT1wZW9wbGUsZGM9dGVzdCxkYz10bGQ=
+member: uid=arthur,ou=people,dc=test,dc=tld
+entryCSN: 20130123220302.586061Z#000000#000#000000
modifiersName: cn=admin,dc=test,dc=tld
-modifyTimestamp: 20091101122555Z
+modifyTimestamp: 20130123220302Z
dn: cn=tst2netgroup,ou=netgroups,dc=test,dc=tld
objectClass: top
@@ -55865,3 +55867,259 @@ entryCSN: 20110208181844.413002Z#000000#000#000000
modifiersName: cn=admin,dc=test,dc=tld
modifyTimestamp: 20110208181844Z
+dn: ou=policies,dc=test,dc=tld
+objectClass: organizationalUnit
+objectClass: top
+ou: policies
+structuralObjectClass: organizationalUnit
+entryUUID: 4d7b4f58-e7a3-1031-9db7-15080ced11c7
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20121231143709Z
+entryCSN: 20121231143709.943433Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20121231143709Z
+
+dn: cn=default,ou=policies,dc=test,dc=tld
+cn: default
+objectClass: pwdPolicyChecker
+objectClass: pwdPolicy
+objectClass: person
+objectClass: top
+pwdAllowUserChange: TRUE
+pwdAttribute: userPassword
+pwdCheckModule: crackcheck.so
+pwdFailureCountInterval: 30
+pwdLockout: TRUE
+pwdMinLength: 12
+pwdSafeModify: FALSE
+sn: dummy value
+structuralObjectClass: person
+entryUUID: 4db81816-e7a3-1031-9db8-15080ced11c7
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20121231143710Z
+pwdMaxFailure: 3
+pwdCheckQuality: 0
+pwdMinAge: 1
+pwdGraceAuthNLimit: 10
+pwdLockoutDuration: 30
+pwdMustChange: TRUE
+pwdExpireWarning: 600
+pwdMaxAge: 660
+pwdInHistory: 0
+entryCSN: 20130106105309.705361Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130106105309Z
+
+dn:: Y2495Y+v5piv5b2T6L+Z5LiqVeebmOWcqCxvdT1wZW9wbGUsZGM9dGVzdCxkYz10bGQ=
+uid: tstchinese
+uidNumber: 1005
+gidNumber: 100
+homeDirectory: /home/tstchinese
+userPassword:: e01ENX1DWTlyelVZaDAzUEszazZESmllMDlnPT0=
+loginShell: /bin/sh
+sn: User
+cn:: 5Y+v5piv5b2T6L+Z5LiqVeebmOWcqA==
+objectClass: top
+objectClass: posixAccount
+objectClass: shadowAccount
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+pwdChangedTime: 20130123214155Z
+structuralObjectClass: inetOrgPerson
+entryUUID: 73821438-f9f1-1031-95ee-17c50f29b0b1
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130123214155Z
+entryCSN: 20130123214155.416125Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130123214155Z
+
+dn:: Y2490JDQkdCSINCT0pDQlNCC0IPQldCBLG91PXBlb3BsZSxkYz10ZXN0LGRjPXRsZA==
+uid: tstcyrillic
+uidNumber: 1006
+gidNumber: 100
+homeDirectory: /home/tstcyrillic
+userPassword:: e01ENX1DWTlyelVZaDAzUEszazZESmllMDlnPT0=
+loginShell: /bin/sh
+sn: User
+cn:: 0JDQkdCSINCT0pDQlNCC0IPQldCB
+objectClass: top
+objectClass: posixAccount
+objectClass: shadowAccount
+objectClass: person
+objectClass: organizationalPerson
+objectClass: inetOrgPerson
+pwdChangedTime: 20130123220302Z
+structuralObjectClass: inetOrgPerson
+entryUUID: 66e3afe0-f9f4-1031-95ef-17c50f29b0b1
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130123220302Z
+entryCSN: 20130123220302.735610Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130123220302Z
+
+dn: ou=autofs,dc=test,dc=tld
+objectClass: top
+objectClass: organizationalUnit
+ou: autofs
+structuralObjectClass: organizationalUnit
+entryUUID: ce19e9de-07c5-1032-9908-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120445Z
+entryCSN: 20130210120445.828919Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120445Z
+
+dn: ou=auto.master,ou=autofs,dc=test,dc=tld
+objectClass: top
+objectClass: automountMap
+ou: auto.master
+structuralObjectClass: automountMap
+entryUUID: ce3875ac-07c5-1032-9909-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.029108Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=/ldap,ou=auto.master,ou=autofs,dc=test,dc=tld
+objectClass: automount
+cn: /ldap
+automountInformation: ldap://192.168.12.4/ou=auto.indirect,ou=autofs, dc=test,
+ dc=tld
+structuralObjectClass: automount
+entryUUID: ce3ce7ae-07c5-1032-990a-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.058241Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=/-,ou=auto.master,ou=autofs,dc=test,dc=tld
+objectClass: automount
+cn: /-
+automountInformation: ldap://192.168.12.4/ou=auto.direct,ou=autofs, dc=test, d
+ c=tld
+structuralObjectClass: automount
+entryUUID: ce401df2-07c5-1032-990b-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.079292Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: ou=auto.indirect,ou=autofs,dc=test,dc=tld
+objectClass: top
+objectClass: automountMap
+ou: auto.indirect
+structuralObjectClass: automountMap
+entryUUID: ce415fb4-07c5-1032-990c-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.087530Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=bin,ou=auto.indirect,ou=autofs,dc=test,dc=tld
+objectClass: automount
+cn: bin
+automountInformation:: ICBzdGlwcGVyOi9zaGFyZQ==
+structuralObjectClass: automount
+entryUUID: ce48aae4-07c5-1032-990d-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.135327Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: ou=auto.direct,ou=autofs,dc=test,dc=tld
+objectClass: top
+objectClass: automountMap
+ou: auto.direct
+structuralObjectClass: automountMap
+entryUUID: ce4ce1fe-07c5-1032-990e-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.162952Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=/nfs/budgie/man,ou=auto.direct,ou=autofs,dc=test,dc=tld
+objectClass: automount
+cn: /nfs/budgie/man
+automountInformation:: ICBidWRnaWU6L3Vzci9sb2NhbC9tYW4=
+structuralObjectClass: automount
+entryUUID: ce4e24a6-07c5-1032-990f-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.171215Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=/nfs/budgie/bin,ou=auto.direct,ou=autofs,dc=test,dc=tld
+objectClass: automount
+cn: /nfs/budgie/bin
+automountInformation:: ICBidWRnaWU6L2xvY2FsL2RhdGEvYmlu
+structuralObjectClass: automount
+entryUUID: ce4f6d34-07c5-1032-9910-1b06e556a61b
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130210120446Z
+entryCSN: 20130210120446.179627Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130210120446Z
+
+dn: cn=nstgrp1,ou=groups,dc=test,dc=tld
+objectClass: top
+objectClass: groupOfNames
+objectClass: sambaGroupMapping
+cn: nstgrp1
+sambaSID: 3
+sambaGroupType: 2
+gidNumber: 800
+structuralObjectClass: groupOfNames
+entryUUID: 52b454ae-277e-1032-97b8-977873c640f6
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130322205341Z
+member: cn=Test User2,ou=people,dc=test,dc=tld
+entryCSN: 20130323210928.654262Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130323210928Z
+
+dn: cn=nstgrp2,ou=groups,dc=test,dc=tld
+objectClass: top
+objectClass: groupOfNames
+objectClass: sambaGroupMapping
+cn: nstgrp2
+sambaSID: 4
+sambaGroupType: 2
+gidNumber: 801
+structuralObjectClass: groupOfNames
+entryUUID: 52bbd0d0-277e-1032-97b9-977873c640f6
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130322205341Z
+member: cn=Test User2,ou=people,dc=test,dc=tld
+member: cn=Test User3,ou=extra,ou=people,dc=test,dc=tld
+member: cn=nstgrp1,ou=groups,dc=test,dc=tld
+entryCSN: 20130323210928.673771Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130323210928Z
+
+dn: cn=nstgrp3,ou=groups,dc=test,dc=tld
+objectClass: top
+objectClass: groupOfNames
+objectClass: sambaGroupMapping
+cn: nstgrp3
+sambaSID: 5
+sambaGroupType: 2
+gidNumber: 802
+member: cn=nstgrp1,ou=groups,dc=test,dc=tld
+member: cn=nstgrp2,ou=groups,dc=test,dc=tld
+member: cn=nstgrp3,ou=groups,dc=test,dc=tld
+structuralObjectClass: groupOfNames
+entryUUID: 1ae13698-2849-1032-8d63-9f2843fb7873
+creatorsName: cn=admin,dc=test,dc=tld
+createTimestamp: 20130323210515Z
+entryCSN: 20130323210515.920979Z#000000#000#000000
+modifiersName: cn=admin,dc=test,dc=tld
+modifyTimestamp: 20130323210515Z
+
diff --git a/tests/test_nsscmds.sh b/tests/test_nsscmds.sh
index 7f4fa73..676c4a6 100755
--- a/tests/test_nsscmds.sh
+++ b/tests/test_nsscmds.sh
@@ -154,7 +154,7 @@ check "groups arthur | sed 's/^.*://'" << EOM
users testgroup testgroup2 grp4 grp5 grp6 grp7 grp8 grp9 grp10 grp11 grp12 grp13 grp14 grp15 grp16 grp17 grp18
EOM
-check "groups testuser4 | sed 's/^.*://'" << EOM
+check "groups testuser4 | sed 's/^.* *: *//'" << EOM
users testgroup testgroup2
EOM
@@ -165,7 +165,7 @@ users:*:100:arthur,test
EOM
check "getent group | wc -l" << EOM
-`grep -c : /etc/group | awk '{print $1 + 20}'`
+`grep -c : /etc/group | awk '{print $1 + 23}'`
EOM
check "getent group | grep ^largegroup | sortgroup" << EOM
@@ -184,6 +184,26 @@ check "getent group hugegroup | sortgroup" << EOM
hugegroup:*:1006:ablackstock,abortignon,achhor,ademosthenes,adenicola,adishaw,aesbensen,aferge,afredin,afuchs,agarbett,agimm,agordner,ahandy,ajaquess,akertzman,akomsthoeft,akraskouskas,akravetz,alamour,alat,alienhard,amanganelli,amaslyn,amayorga,amccroskey,amcgraw,amckinney,ameisinger,aponcedeleon,apurdon,areid,arosel,ascheno,ascovel,asemons,ashuey,asivley,astrunk,atollefsrud,atonkin,awhitt,aziernicki,badair,baigner,bbeckfield,bbrenton,bcoletta,bcolorado,bdadds,bdaughenbaugh,bdevera,bdominga,behrke,beon,bfishbeck,bgavagan,bguthary,bharnois,bhelverson,bjolly,blovig,bluellen,bmadamba,bmarlin,bmarszalek,bmicklos,bmoling,bouten,bphou,bpinedo,brodgerson,broher,bromano,bscadden,bsibal,bstrede,bswantak,btempel,btheim,bveeneman,bwinterton,bwynes,cabare,carguellez,cbarlup,cbartnick,cbelardo,cbleimehl,cbotdorf,cbourek,cbrechbill,cbrom,ccyganiewicz,cdeckard,cdegravelle,cdickes,cdrumm,cfasone,cflenner,cfleurantin,cgaler,cgalinol,cgaudette,cghianni,charriman,cjody,cjuntunen,ckerska,ckistenmacher,cklem,ckodish,clapenta,clewicki,clouder,cmafnas,cmanno,cmcanulty,cmellberg,cmiramon,cnabzdyk,cnoriego,cpaccione,cpalmios,cparee,cpencil,cpentreath,cpinela,cpluid,critchie,cscullion,csever,csoomaroo,cspilis,cswigert,ctenny,ctetteh,ctuzzo,cwank,cweiss,dasiedu,daubert,dbarriball,dbertels,dblazejewski,dcaltabiano,dciullo,ddeguire,ddigerolamo,denriquez,deshmon,dfirpo,dflore,dfollman,dgiacomazzi,dgivliani,dgosser,dhammontree,dhendon,dhindsman,dholdaway,dlablue,dlanois,dlargo,dledenbach,dlongbotham,dloubier,dmahapatra,dmarchizano,dmcgillen,dminozzi,dnegri,dpebbles,draymundo,dscheurer,dsharr,dsherard,dsteever,dtashjian,dtornow,dtuholski,dwittlinger,dzurek,eaguire,eathey,ebattee,ebeachem,eberkman,ebusk,ecelestin,ecolden,ecordas,ediga,edrinkwater,edurick,egospatrick,egrago,ehathcock,ehindbaugh,ejeppesen,ekalfas,ekenady,ekeuper,eklein,eklunder,ekurter,emanikowski,emargulis,emcquiddy,emehta,eorsten,eparham,epeterson,epoinelli,erathert,erostad,eserrett,esheehan,esonia,esproull,esthill,estockwin,etunby,ewicks,ewilles,ewismer,ewuitschick,eyounglas,eziebert,fagro,faleo,farquette,fbeatrice,fberra,fberyman,fbielecki,fburrough,fcha,fcunard,ffigert,fgoben,fgrashot,fhain,fhalon,fkeef,fmarchi,fmilsaps,fnottage,fparness,fplayfair,fsapien,fsavela,fsirianni,fsplinter,fsunderland,fsymmonds,fthein,fvallian,fvascones,fverfaille,fvinal,fwidhalm,gallanson,gapkin,garchambeault,gbitar,gbolay,gcarlini,gcervantez,gchounlapane,gclapham,gcobane,gconver,gcukaj,gcummer,gcurnutt,gdaub,gdeblasio,gdeyarmond,gdrilling,gearnshaw,gfaire,gfedewa,ggehrke,ggillim,ghann,ghelderman,ghumbles,gishii,gjankowiak,gkerens,glafontaine,gloebs,gmackinder,gmassi,gmilian,gmings,gmoen,gparkersmith,gpomerance,gportolese,greiff,gsantella,gschaumburg,gshrode,gtinnel,guresti,gvollrath,gwaud,habby,hbastidos,hbetterman,hbickford,hbraim,hbrandow,hbrehmer,hbukovsky,hcafourek,hcarrizal,hchaviano,hcintron,hcowles,hcusta,hdoiel,hdyner,hfludd,hgalavis,hhaffey,hhagee,hhartranft,hholyfield,hhysong,hkarney,hkinderknecht,hkippes,hkohlmeyer,hlauchaire,hlemon,hlichota,hliverman,hloftis,hlynema,hmateer,hmatonak,hmiazga,hmogush,hmuscaro,hpalmquist,hpimpare,hpolintan,hrapisura,hrenart,hriech,hsabol,hschelb,hschoepfer,hspiry,hstreitnatter,hsweezer,htilzer,htomlinson,htsuha,hvannette,hveader,hwestermark,hwoodert,hzagami,hzinda,iambrosino,ibeto,ibreitbart,ibuzo,ibyles,ichewning,icoard,ideveyra,ienglert,igizzi,ihalford,ihanneman,ihegener,ihernan,iherrarte,ihimmelwright,ihoa,iiffert,ikadar,ikulbida,ilacourse,ilamberth,ilawbaugh,ileaman,ilevian,imarungo,imcbay,imensah,imicthell,imillin,imuehl,inarain,iogasawara,iroiger,iseipel,isowder,isplonskowski,istallcup,istarring,isteinlicht,ithum,ivanschaack,iweibe,iyorgey,iyorks,jamber,jappleyard,jbielicki,jbjorkman,jcaroll,jdodge,jeuresti,jeverton,jglotzbecker,jherkenratt,jholzmiller,jjumalon,jkimpton,jknight,jlebouf,jlunney,jmartha,jmarugg,jmatty,joligee,jquicksall,jrees,jreigh,jroman,jscheitlin,jseen,jsegundo,jsenavanh,jskafec,jspohn,jsweezy,jvillaire,jwinterton,jzych,kaanerud,kalguire,kbarnthouse,kbartolet,kbattershell,kbrevitz,kbrugal,kcofrancesco,kcomparoni,kconkey,kdevincent,kepps,kfaure,kfend,kgarced,kgremminger,khartness,kheadlon,khovanesian,kjoslyn,klitehiser,klundsten,klurie,kmallach,kmandolfo,kmarzili,kmayoras,kmcardle,kmcguire,kmedcaf,kmeester,kmisove,kmoesch,kmosko,kmuros,kolexa,kottomaniello,kpalka,kpannunzio,kpenale,kpuebla,krahman,kseisler,kshippy,ksiering,ksollitto,ksparling,kstachurski,kthede,ktoni,ktriblett,ktuccio,ktuner,kwidrick,kwinterling,kwirght,laksamit,lautovino,lbanco,lbassin,lbove,lbuchtel,lcanestrini,lcaudell,lcavez,lcocherell,lcoulon,lcremer,leberhardt,lfarraj,lfichtner,lgadomski,lgandee,lgradilla,lhuggler,limbrogno,ljomes,lkimel,llarmore,llasher,lmadruga,lmauracher,lmcgeary,lmichaud,lmuehlberger,lnormand,lparrish,lpeagler,lpintor,lpitek,lpondexter,lrandall,lringuette,lschenkelberg,lschnorbus,lschollmeier,lseabold,lseehafer,lshilling,lsivic,lsobrino,lsous,lspielvogel,lvaleriano,lvanconant,lwedner,lyoula,mallmand,maustine,mbeagley,mbodley,mbravata,mcampagnone,mcaram,mcashett,mcasida,mcoch,mcolehour,mcontreras,mdanos,mdecourcey,mdedon,mdickinson,mdimaio,mdoering,mdyce,meconomides,mespinel,mfaeth,mfeil,mferandez,mfitzherbert,mgavet,mgayden,mground,mheilbrun,mhollings,mjeon,mkibler,mkofoed,mlaverde,mlenning,mlinak,mlinardi,mmangiamele,mmattu,mmcchristian,mmerriwether,mmesidor,mneubacher,moller,moser,mpanahon,mpark,mpellew,mpilon,mpizzaro,mpytko,mquigg,mredd,mrizer,mruppel,mrydelek,mskeele,mstirn,mswogger,mtanzi,mtintle,mvanbergen,mvanpelt,mvas,mvedder,mviverette,myokoyama,nagerton,nasmar,nbuford,nbugtong,ncermeno,nchrisman,nciucci,ndesautels,ndrumgole,nedgin,nendicott,nerbach,nevan,nforti,nfunchess,ngiesler,nglathar,ngrowney,ngullett,nhayer,nhelfinstine,nhija,ninnella,njordon,nkempon,nkubley,nlainhart,nlatchaw,nlemma,nlinarez,nlohmiller,nmccolm,nmoren,nnamanworth,nnickel,nousdahl,nphan,nramones,nranck,nridinger,nriofrio,nrybij,nrysavy,nschmig,nsiemonsma,nslaby,nspolar,nvyhnal,nwescott,nwiker,oahyou,oalthouse,obeaufait,obenallack,obercier,obihl,ocalleo,ochasten,oclunes,oconerly,ocrabbs,oebrani,ofelcher,ohatto,ohearl,ohedlund,ohoffert,ohove,ojerabek,okave,okveton,omalvaez,omasone,omatula,omcdaid,oolivarez,oosterhouse,opeet,opizzuti,opoch,oport,opuglisi,oreiss,osaber,oscarpello,oshough,ovibbert,owhelchel,owhitelow,pahles,pbascom,pbeckerdite,pbiggart,pbondroff,pbrentano,pcaposole,pcornn,pdauterman,pdech,pdischinger,pduitscher,pdulac,pdurando,pfavolise,pgiegerich,pgreenier,pgrybel,phalkett,pheathcock,phyer,pmineo,pminnis,ppedraja,ppeper,pphuaphes,prepasky,prowena,psabado,psalesky,pschrayter,psharits,psiroky,psundeen,pthornberry,ptoenjes,ptraweek,purquilla,pvierthaler,pvirelli,pviviani,pwademan,pwashuk,pwetherwax,pwhitmire,pwohlenhaus,pwutzke,qhanly,ralspach,rbernhagen,rbillingsly,rbloomstrand,rbrisby,rcheshier,rchevrette,rdubs,rdubuisson,redling,rfassinger,rfauerbach,rfidel,rginer,rgoonez,rgramby,rgriffies,rguinane,rheinzmann,rkraszewski,rlambertus,rlatessa,rlosinger,rmandril,rmcstay,rnordby,rpastorin,rpikes,rpinilla,rpitter,rramirez,rrasual,rschkade,rtole,rtooker,saben,sackles,sarndt,saycock,sbemo,sbettridge,sbloise,sbonnie,sbrabyn,scocuzza,sdebry,senrico,sestergard,sgefroh,sgirsh,sgropper,sgunder,sgurski,shaith,sherzberg,showe,sjankauskas,skanjirathinga,skoegler,slaningham,slaudeman,slerew,smccaie,smillian,smullowney,snotari,spolmer,srees,srubenfield,sscheiern,sskone,sskyers,sspagnuolo,sstough,sstuemke,svandewalle,svielle,svogler,svongal,swoodie,tabdelal,tairth,tbagne,tbattista,tboxx,tcacal,tcossa,tcrissinger,tdonathan,teliades,tfalconeri,tfetherston,tgelen,tgindhart,tguinnip,tharr,thelfritz,thoch,thynson,tkeala,tkelly,tkhora,tlana,tlowers,tmalecki,tmarkus,tmccaffity,tmccamish,tmcmickle,tmelland,tmorr,tmurata,tmysinger,tnaillon,tnitzel,tpaa,tplatko,tredfearn,tsablea,tsann,tschnepel,tsearle,tsepulueda,tsowells,tstalworth,tvehrs,tvrooman,tyounglas,ualway,uazatyan,ubenken,ubieniek,ubynum,udatu,uednilao,ueriks,uflander,ugerpheide,ugreenberg,uhayakawa,uholecek,ulanigan,umarbury,umosser,upater,upellam,uransford,urosentrance,uschweyen,usevera,uslavinski,uspittler,uvanmatre,uwalpole,uweyand,vbaldasaro,vbigalow,vbonder,vburton,vchevalier,vcrofton,vdesir,vdolan,veisenhardt,vemily,venfort,vfeigel,vglidden,vkrug,vlubic,vmaynard,vmedici,vnazzal,vnery,vpeairs,vpender,vpiraino,vrodick,vrunyon,vsefcovic,vstirman,vtowell,vtresch,vtrumpp,vwabasha,vwaltmann,vwisinger,vwokwicz,wbrill,wclokecloak,wconces,wconstantino,wcreggett,wdagrella,wdevenish,wdovey,wenglander,werrick,wesguerra,wganther,wkhazaleh,wleiva,wlynch,wmailey,wmendell,wnunziata,wottesen,wselim,wstjean,wtruman,wvalcin,wvermeulen,xeppley,xlantey,xrahaim,yautin,ycerasoli,ycobetto,ycostaneda,yduft,yeven,yfrymoyer,ygockel,yhenriques,ykimbel,yolivier,yschmuff,ysnock,yvdberg,zanderlik,zborgmeyer,zbuscaglia,zculp,zfarler,zhaulk,zkutchera,zmeeker,zneeb,zratti,zscammahorn,zvagt,zwinterbottom
EOM
+check "getent group nstgrp1 | sortgroup" << EOM
+nstgrp1:*:800:testusr2
+EOM
+
+check "getent group nstgrp2 | sortgroup" << EOM
+nstgrp2:*:801:testusr2,testusr3
+EOM
+
+check "getent group nstgrp3 | sortgroup" << EOM
+nstgrp3:*:802:testusr2,testusr3
+EOM
+
+check "groups testusr2 | sed 's/^.* *: *//'" << EOM
+users largegroup testgroup2 nstgrp1 nstgrp2 nstgrp3
+EOM
+
+check "groups testusr3 | sed 's/^.* *: *//'" << EOM
+users largegroup nstgrp2 nstgrp3
+EOM
+
###########################################################################
echo "test_nsscmds.sh: testing hosts..."