]> granicus.if.org Git - sudo/commitdiff
Use nss_search() to implement getgrouplist() where available. Tested
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 22 Jan 2013 20:41:15 +0000 (15:41 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 22 Jan 2013 20:41:15 +0000 (15:41 -0500)
on Solaris and HP-UX.  We need to include a compatibility header
for HP-UX which uses the Solaris nsswitch implementation but doesn't
ship nss_dbdefs.h.

MANIFEST
compat/getgrouplist.c
compat/nss_dbdefs.h [new file with mode: 0644]
config.h.in
configure
configure.in

index aeb9661d60a0daf9bf64b98b18e9c1e3c1558818..0253da6b5bb135239998b12827ec276a9b1432f4 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -47,6 +47,7 @@ compat/mksigname.c
 compat/mksigname.h
 compat/mktemp.c
 compat/nanosleep.c
+compat/nss_dbdefs.h
 compat/pw_dup.c
 compat/regress/fnmatch/fnm_test.c
 compat/regress/fnmatch/fnm_test.in
index cea72f5110fa5f5e757969da410f311fe315416f..d1327e092e12195fd829ea40d8592b4bf0777fe3 100644 (file)
 # include <strings.h>
 #endif /* HAVE_STRINGS_H */
 #include <grp.h>
+#ifdef HAVE_NSS_SEARCH
+# include <limits.h>
+# include <nsswitch.h>
+# ifdef HAVE_NSS_DBDEFS_H
+#  include <nss_dbdefs.h>
+# else
+#  include "compat/nss_dbdefs.h"
+# endif
+#endif
 
 #include "missing.h"
 
@@ -79,31 +88,169 @@ done:
     return rval;
 }
 
-#elif defined(HAVE__GETGROUPSBYMEMBER)
+#elif defined(HAVE_NSS_SEARCH)
+
+#ifndef GID_MAX
+# define GID_MAX       UID_MAX
+#endif
+
+#ifndef ALIGNBYTES
+# define ALIGNBYTES    (sizeof(long) - 1L)
+#endif
+#ifndef ALIGN
+# define ALIGN(p)      (((unsigned long)(p) + ALIGNBYTES) & ~ALIGNBYTES)
+#endif
+
+extern void _nss_initf_group(nss_db_params_t *);
 
 /*
- * BSD-compatible getgrouplist(3) using _getgroupsbymember(3)
+ * Convert a groups file string (instr) to a struct group (ent) using
+ * buf for storage.  
  */
-int
-getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp)
+static int
+str2grp(const char *instr, int inlen, void *ent, char *buf, int buflen)
 {
-    int ngroups, grpsize = *ngroupsp;
-    int rval = -1;
+    struct group *grp = ent;
+    char *cp, *ep, *fieldsep = buf;
+    char **gr_mem, **gr_end;
+    int yp = 0;
+    unsigned long gid;
 
-    if (grpsize > 0) {
-       /* We support BSD semantics where the first element is the base gid */
-       groups[0] = basegid;
+    /* Must at least have space to copy instr -> buf. */
+    if (inlen >= buflen)
+       return NSS_STR_PARSE_ERANGE;
 
-       /* The last arg is 1 because we already filled in the base gid. */
-       ngroups = _getgroupsbymember(name, groups, grpsize, 1);
-       if (ngroups != -1) {
-           rval = 0;
-           *ngroupsp = ngroups;
+    /* Paranoia: buf and instr should be distinct. */
+    if (buf != instr) {
+       memmove(buf, instr, inlen);
+       buf[inlen] = '\0';
+    }
+
+    if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+       return NSS_STR_PARSE_PARSE;
+    *fieldsep++ = '\0';
+    grp->gr_name = cp;
+
+    /* Check for YP inclusion/exclusion entries. */
+    if (*cp == '+' || *cp == '-') {
+       /* Only the name is required for YP inclusion/exclusion entries. */
+       grp->gr_passwd = "";
+       grp->gr_gid = 0;
+       grp->gr_mem = NULL;
+       yp = 1;
+    }
+
+    if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+       return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
+    *fieldsep++ = '\0';
+    grp->gr_passwd = cp;
+
+    if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+       return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
+    *fieldsep++ = '\0';
+    gid = strtoul(cp, &ep, 10);
+    if (*cp == '\0' || *ep != '\0')
+       return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
+    if (gid > GID_MAX || (gid == ULONG_MAX && errno == ERANGE))
+       return NSS_STR_PARSE_ERANGE;
+    grp->gr_gid = (gid_t)gid;
+
+    /* Store group members, taking care to use proper alignment. */
+    grp->gr_mem = NULL;
+    if (*fieldsep != '\0') {
+       grp->gr_mem = gr_mem = (char **)ALIGN(buf + inlen + 1);
+       gr_end = (char **)((unsigned long)(buf + buflen) & ~ALIGNBYTES);
+       for (;;) {
+           if (gr_mem == gr_end)
+               return NSS_STR_PARSE_ERANGE;    /* out of space! */
+           *gr_mem++ = cp;
+           if (fieldsep == NULL)
+               break;
+           if ((fieldsep = strchr(cp = fieldsep, ',')) != NULL)
+               *fieldsep++ = '\0';
        }
+       *gr_mem = NULL;
     }
+    return NSS_STR_PARSE_SUCCESS;
+}
+
+static nss_status_t
+process_cstr(const char *instr, int inlen, struct nss_groupsbymem *gbm)
+{
+    const char *user = gbm->username;
+    nss_status_t rval = NSS_NOTFOUND;
+    nss_XbyY_buf_t *buf;
+    struct group *grp;
+    char **gr_mem;
+    int        error, i;
+
+    buf = _nss_XbyY_buf_alloc(sizeof(struct group), NSS_BUFLEN_GROUP);
+    if (buf == NULL)
+       return NSS_UNAVAIL;
+
+    /* Parse groups file string -> struct group. */
+    grp = buf->result;
+    error = (*gbm->str2ent)(instr, inlen, grp, buf->buffer, buf->buflen);
+    if (error || grp->gr_mem == NULL)
+       goto done;
+
+    for (gr_mem = grp->gr_mem; *gr_mem != NULL; gr_mem++) {
+       if (strcmp(*gr_mem, user) == 0) {
+           /* Append to gid_array unless gr_gid is a dupe. */
+           for (i = 0; i < gbm->numgids; i++) {
+               if (gbm->gid_array[i] == grp->gr_gid)
+                   goto done;                  /* already present */
+           }
+           /* Store gid if there is space. */
+           if (i < gbm->maxgids)
+               gbm->gid_array[i] = grp->gr_gid;
+           /* Always increment numgids so we can detect when out of space. */
+           gbm->numgids++;
+           goto done;
+       }
+    }
+done:
+    _nss_XbyY_buf_free(buf);
     return rval;
 }
 
+/*
+ * BSD-compatible getgrouplist(3) using nss_search(3)
+ */
+int
+getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp)
+{
+    struct nss_groupsbymem gbm;
+    static DEFINE_NSS_DB_ROOT(db_root);
+
+    /* We support BSD semantics where the first element is the base gid */
+    if (*ngroupsp <= 0)
+       return -1;
+    groups[0] = basegid;
+
+    memset(&gbm, 0, sizeof(gbm));
+    gbm.username = name;
+    gbm.gid_array = groups;
+    gbm.maxgids = *ngroupsp;
+    gbm.numgids = 1; /* for basegid */
+    gbm.force_slow_way = 1;
+    gbm.str2ent = str2grp;
+    gbm.process_cstr = process_cstr;
+
+    /*
+     * Can't use nss_search return value since it may return NSS_UNAVAIL
+     * when no nsswitch.conf entry (e.g. compat mode).
+     */
+    (void)nss_search(&db_root, _nss_initf_group, NSS_DBOP_GROUP_BYMEMBER, &gbm);
+
+    if (gbm.numgids <= gbm.maxgids) {
+        *ngroupsp = gbm.numgids;
+        return 0;
+    }
+    *ngroupsp = gbm.maxgids;
+    return -1;
+}
+
 #else /* !HAVE_GETGRSET && !HAVE__GETGROUPSBYMEMBER */
 
 /*
diff --git a/compat/nss_dbdefs.h b/compat/nss_dbdefs.h
new file mode 100644 (file)
index 0000000..7ac9113
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _COMPAT_NSS_DBDEFS_H
+#define _COMPAT_NSS_DBDEFS_H
+
+/*
+ * Bits of nss_dbdefs.h and nss_common.h needed to implement
+ * getgrouplist(3) using nss_search(3).
+ *
+ * HP-UX does not ship those headers so we need this compatibility header.
+ * It may also work on other systems that use a Solaris-derived nsswitch
+ * API.
+ */
+
+#ifdef NEED_HPUX_MUTEX
+# include <synch.h>
+#endif
+
+typedef enum {
+    NSS_SUCCESS,
+    NSS_NOTFOUND,
+    NSS_UNAVAIL
+} nss_status_t;
+
+typedef struct nss_db_params {
+    const char *name;
+    const char *config_name;
+    const char *default_config;
+    unsigned int max_active_per_src;
+    unsigned int max_dormant_per_src;  
+    int flags;
+    void *finders;
+    void *private;
+    void (*cleanup)(struct nss_db_params *);
+} nss_db_params_t;
+
+struct nss_groupsbymem {
+    const char *username;
+    gid_t *gid_array;
+    int maxgids;
+    int force_slow_way;
+    int (*str2ent)(const char *, int, void *, char *, int);
+    nss_status_t (*process_cstr)(const char *, int, struct nss_groupsbymem *);
+    int numgids;
+};
+
+typedef struct {
+    void *result;      /* group struct to fill in. */
+    char *buffer;      /* string buffer for above */
+    size_t buflen;     /* string buffer size */
+} nss_XbyY_buf_t;
+
+typedef struct {
+    void *state;       /* really struct nss_db_state * */
+#ifdef NEED_HPUX_MUTEX
+    lwp_mutex_t lock;
+#endif
+} nss_db_root_t;
+
+#ifdef NEED_HPUX_MUTEX
+# define NSS_DB_ROOT_INIT              { 0, LWP_MUTEX_INITIALIZER }
+#else
+# define NSS_DB_ROOT_INIT              { 0 }
+#endif
+# define DEFINE_NSS_DB_ROOT(name)      nss_db_root_t name = NSS_DB_ROOT_INIT
+
+/* Backend function to find all groups a user belongs to for initgroups(). */
+#define NSS_DBOP_GROUP_BYMEMBER                6
+
+/* str2ent function return values */
+#define NSS_STR_PARSE_SUCCESS  0
+#define NSS_STR_PARSE_PARSE    1
+#define NSS_STR_PARSE_ERANGE   2
+
+/* Max length for an /etc/group file line. */
+#define NSS_BUFLEN_GROUP               8192
+
+/* HP-UX uses an extra underscore for these functions. */
+#ifdef HAVE___NSS_INITF_GROUP
+# define _nss_initf_group       __nss_initf_group
+#endif
+#ifdef HAVE__NSS_XBYY_BUF_ALLOC
+# define _nss_XbyY_buf_alloc    __nss_XbyY_buf_alloc
+# define _nss_XbyY_buf_free     __nss_XbyY_buf_free
+#endif
+
+typedef void (*nss_db_initf_t)(nss_db_params_t *);
+extern nss_status_t nss_search(nss_db_root_t *, nss_db_initf_t, int, void *);
+extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int, int);
+extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *);
+
+#endif /* _COMPAT_NSS_DBDEFS_H */
index 3483ac225cce2e3c6a4c885b35134d3860a171fc..45e8088ced9578947bf95526906b41aed9f02310 100644 (file)
 /* Define to 1 if you have the `nl_langinfo' function. */
 #undef HAVE_NL_LANGINFO
 
+/* Define to 1 if you have the <nss_dbdefs.h> header file. */
+#undef HAVE_NSS_DBDEFS_H
+
+/* Define to 1 if you have the `nss_search' function. */
+#undef HAVE_NSS_SEARCH
+
 /* Define to 1 if you have the `openpty' function. */
 #undef HAVE_OPENPTY
 
 /* Define to 1 if the system has the type `_Bool'. */
 #undef HAVE__BOOL
 
-/* Define to 1 if you have the `_getgroupsbymember' function. */
-#undef HAVE__GETGROUPSBYMEMBER
-
 /* Define to 1 if you have the `_getpty' function. */
 #undef HAVE__GETPTY
 
 /* Define to 1 if you have the `_innetgr' function. */
 #undef HAVE__INNETGR
 
+/* Define to 1 if you have the `_nss_initf_group' function. */
+#undef HAVE__NSS_INITF_GROUP
+
+/* Define to 1 if you have the `_nss_XbyY_buf_alloc' function. */
+#undef HAVE__NSS_XBYY_BUF_ALLOC
+
 /* Define to 1 if you have the `_ttyname_dev' function. */
 #undef HAVE__TTYNAME_DEV
 
 /* Define to 1 if the compiler supports the C99 __func__ variable. */
 #undef HAVE___FUNC__
 
+/* Define to 1 if you have the `__nss_initf_group' function. */
+#undef HAVE___NSS_INITF_GROUP
+
+/* Define to 1 if you have the `__nss_XbyY_buf_alloc' function. */
+#undef HAVE___NSS_XBYY_BUF_ALLOC
+
 /* Define to 1 if your crt0.o defines the __progname symbol for you. */
 #undef HAVE___PROGNAME
 
index 5018c023ee7d3fa029ab9bda5bc18551c587e049..e69ae7cbc8c541cd0c1f016eb2edd3deea523d59 100755 (executable)
--- a/configure
+++ b/configure
@@ -13927,19 +13927,6 @@ case "$host" in
                OS_INIT=os_init_solaris
                SUDO_OBJS="${SUDO_OBJS} solaris.o"
 
-               # For implementing getgrouplist()
-               for ac_func in _getgroupsbymember
-do :
-  ac_fn_c_check_func "$LINENO" "_getgroupsbymember" "ac_cv_func__getgroupsbymember"
-if test "x$ac_cv_func__getgroupsbymember" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE__GETGROUPSBYMEMBER 1
-_ACEOF
-
-fi
-done
-
-
                # To get the crypt(3) prototype (so we pass -Wall)
                OSDEFS="${OSDEFS} -D__EXTENSIONS__"
                # AFS support needs -lucb
                    with_netsvc="/etc/netsvc.conf"
                fi
 
-               # For implementing getgrouplist()
-               for ac_func in getgrset
-do :
-  ac_fn_c_check_func "$LINENO" "getgrset" "ac_cv_func_getgrset"
-if test "x$ac_cv_func_getgrset" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_GETGRSET 1
-_ACEOF
-
-fi
-done
-
-
                # LDR_PRELOAD is only supported in AIX 5.3 and later
                if test $OSMAJOR -lt 5; then
                    with_noexec=no
@@ -16665,19 +16639,124 @@ _ACEOF
 fi
 done
 
-ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist"
+for ac_func in getgrouplist
+do :
+  ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist"
 if test "x$ac_cv_func_getgrouplist" = xyes; then :
-  $as_echo "#define HAVE_GETGROUPLIST 1" >>confdefs.h
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETGROUPLIST 1
+_ACEOF
 
 else
-  case " $LIBOBJS " in
+
+    case "$host" in
+    *-*-aix*)
+       for ac_func in getgrset
+do :
+  ac_fn_c_check_func "$LINENO" "getgrset" "ac_cv_func_getgrset"
+if test "x$ac_cv_func_getgrset" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETGRSET 1
+_ACEOF
+ case " $LIBOBJS " in
   *" getgrouplist.$ac_objext "* ) ;;
   *) LIBOBJS="$LIBOBJS getgrouplist.$ac_objext"
  ;;
 esac
 
+fi
+done
+
+       ;;
+    *)
+       ac_fn_c_check_func "$LINENO" "nss_search" "ac_cv_func_nss_search"
+if test "x$ac_cv_func_nss_search" = xyes; then :
+
+           ac_fn_c_check_func "$LINENO" "_nss_XbyY_buf_alloc" "ac_cv_func__nss_XbyY_buf_alloc"
+if test "x$ac_cv_func__nss_XbyY_buf_alloc" = xyes; then :
+
+               # Solaris
+               ac_fn_c_check_func "$LINENO" "_nss_initf_group" "ac_cv_func__nss_initf_group"
+if test "x$ac_cv_func__nss_initf_group" = xyes; then :
+
+                   for ac_header in nss_dbdefs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "nss_dbdefs.h" "ac_cv_header_nss_dbdefs_h" "$ac_includes_default"
+if test "x$ac_cv_header_nss_dbdefs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NSS_DBDEFS_H 1
+_ACEOF
+
 fi
 
+done
+
+                   $as_echo "#define HAVE_NSS_SEARCH 1" >>confdefs.h
+
+                   $as_echo "#define HAVE__NSS_XBYY_BUF_ALLOC 1" >>confdefs.h
+
+                   $as_echo "#define HAVE__NSS_INITF_GROUP 1" >>confdefs.h
+
+                   case " $LIBOBJS " in
+  *" getgrouplist.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS getgrouplist.$ac_objext"
+ ;;
+esac
+
+
+fi
+
+
+else
+
+               # HP-UX
+               ac_fn_c_check_func "$LINENO" "__nss_XbyY_buf_alloc" "ac_cv_func___nss_XbyY_buf_alloc"
+if test "x$ac_cv_func___nss_XbyY_buf_alloc" = xyes; then :
+
+                   ac_fn_c_check_func "$LINENO" "__nss_initf_group" "ac_cv_func___nss_initf_group"
+if test "x$ac_cv_func___nss_initf_group" = xyes; then :
+
+                       for ac_header in nss_dbdefs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "nss_dbdefs.h" "ac_cv_header_nss_dbdefs_h" "$ac_includes_default"
+if test "x$ac_cv_header_nss_dbdefs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NSS_DBDEFS_H 1
+_ACEOF
+
+fi
+
+done
+
+                       $as_echo "#define HAVE_NSS_SEARCH 1" >>confdefs.h
+
+                       $as_echo "#define HAVE___NSS_XBYY_BUF_ALLOC 1" >>confdefs.h
+
+                       $as_echo "#define HAVE___NSS_INITF_GROUP 1" >>confdefs.h
+
+                       case " $LIBOBJS " in
+  *" getgrouplist.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS getgrouplist.$ac_objext"
+ ;;
+esac
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+       ;;
+    esac
+
+fi
+done
 
 for ac_func in getline
 do :
@@ -17117,13 +17196,12 @@ if test "x$ac_cv_func_setreuid" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_SETREUID 1
 _ACEOF
- SKIP_SETEUID=yes
+
 fi
 done
 
 fi
-if test -z "$SKIP_SETEUID"; then
-    for ac_func in seteuid
+for ac_func in seteuid
 do :
   ac_fn_c_check_func "$LINENO" "seteuid" "ac_cv_func_seteuid"
 if test "x$ac_cv_func_seteuid" = xyes; then :
@@ -17134,7 +17212,6 @@ _ACEOF
 fi
 done
 
-fi
 if test X"$with_interfaces" != X"no"; then
     for ac_func in getifaddrs
 do :
 
 
 
+
+
+
+
+
 
 
 
index c9b589d70c73008a796c1ea2368d139e928b0a8d..246d65406727a6232eda228759e71d81851371be 100644 (file)
@@ -1573,9 +1573,6 @@ case "$host" in
                OS_INIT=os_init_solaris
                SUDO_OBJS="${SUDO_OBJS} solaris.o"
 
-               # For implementing getgrouplist()
-               AC_CHECK_FUNCS(_getgroupsbymember)
-
                # To get the crypt(3) prototype (so we pass -Wall)
                OSDEFS="${OSDEFS} -D__EXTENSIONS__"
                # AFS support needs -lucb
@@ -1632,9 +1629,6 @@ case "$host" in
                    with_netsvc="/etc/netsvc.conf"
                fi
 
-               # For implementing getgrouplist()
-               AC_CHECK_FUNCS(getgrset)
-
                # LDR_PRELOAD is only supported in AIX 5.3 and later
                if test $OSMAJOR -lt 5; then
                    with_noexec=no
@@ -2228,7 +2222,39 @@ AC_FUNC_GETGROUPS
 AC_CHECK_FUNCS(glob strrchr sysconf tzset strftime setenv \
               regcomp nl_langinfo mbr_check_membership \
               setrlimit64)
-AC_REPLACE_FUNCS(getgrouplist)
+dnl AC_REPLACE_FUNCS(getgrouplist)
+AC_CHECK_FUNCS(getgrouplist, [], [
+    case "$host" in
+    *-*-aix*)
+       AC_CHECK_FUNCS(getgrset, [AC_LIBOBJ(getgrouplist)])
+       ;;
+    *)
+       AC_CHECK_FUNC(nss_search, [
+           AC_CHECK_FUNC(_nss_XbyY_buf_alloc, [
+               # Solaris
+               AC_CHECK_FUNC(_nss_initf_group, [
+                   AC_CHECK_HEADERS(nss_dbdefs.h)
+                   AC_DEFINE([HAVE_NSS_SEARCH])
+                   AC_DEFINE([HAVE__NSS_XBYY_BUF_ALLOC])
+                   AC_DEFINE([HAVE__NSS_INITF_GROUP])
+                   AC_LIBOBJ(getgrouplist)
+               ])
+           ], [
+               # HP-UX
+               AC_CHECK_FUNC(__nss_XbyY_buf_alloc, [
+                   AC_CHECK_FUNC(__nss_initf_group, [
+                       AC_CHECK_HEADERS(nss_dbdefs.h)
+                       AC_DEFINE([HAVE_NSS_SEARCH])
+                       AC_DEFINE([HAVE___NSS_XBYY_BUF_ALLOC])
+                       AC_DEFINE([HAVE___NSS_INITF_GROUP])
+                       AC_LIBOBJ(getgrouplist)
+                   ])
+               ])
+           ])
+       ])
+       ;;
+    esac
+])
 AC_CHECK_FUNCS(getline, [], [
     AC_LIBOBJ(getline)
     AC_CHECK_FUNCS(fgetln)
@@ -2304,11 +2330,9 @@ if test -z "$SKIP_SETRESUID"; then
     ])
 fi
 if test -z "$SKIP_SETREUID"; then
-    AC_CHECK_FUNCS(setreuid, [SKIP_SETEUID=yes])
-fi
-if test -z "$SKIP_SETEUID"; then
-    AC_CHECK_FUNCS(seteuid)
+    AC_CHECK_FUNCS(setreuid)
 fi
+AC_CHECK_FUNCS(seteuid)
 if test X"$with_interfaces" != X"no"; then
     AC_CHECK_FUNCS(getifaddrs, [AC_CHECK_FUNCS(freeifaddrs)])
 fi
@@ -3697,6 +3721,11 @@ AH_TEMPLATE(RTLD_PRELOAD_DELIM, [The delimiter to use when defining multiple pre
 AH_TEMPLATE(RTLD_PRELOAD_DEFAULT, [The default value of preloaded objects (if any).])
 AH_TEMPLATE(HAVE_DSO_VISIBILITY, [Define to 1 if the compiler supports the __visibility__ attribute.])
 AH_TEMPLATE(HAVE_SYS_SIGABBREV, [Define to 1 if your libc has the `sys_sigabbrev' symbol.])
+AH_TEMPLATE(HAVE_NSS_SEARCH, [Define to 1 if you have the `nss_search' function.])
+AH_TEMPLATE(HAVE__NSS_INITF_GROUP, [Define to 1 if you have the `_nss_initf_group' function.])
+AH_TEMPLATE(HAVE___NSS_INITF_GROUP, [Define to 1 if you have the `__nss_initf_group' function.])
+AH_TEMPLATE(HAVE__NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the `_nss_XbyY_buf_alloc' function.])
+AH_TEMPLATE(HAVE___NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the `__nss_XbyY_buf_alloc' function.])
 
 dnl
 dnl Bits to copy verbatim into config.h.in