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
# 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"
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 */
/*
--- /dev/null
+/*
+ * 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 */
/* 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
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
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 :
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 :
fi
done
-fi
if test X"$with_interfaces" != X"no"; then
for ac_func in getifaddrs
do :
+
+
+
+
+
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
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
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)
])
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
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