]> granicus.if.org Git - sudo/commitdiff
Replace built-in non-unix group support with a sudoers group plugin.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Jul 2010 15:11:25 +0000 (11:11 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Jul 2010 15:11:25 +0000 (11:11 -0400)
Include a sample plugin that can read Unix-format group files.

26 files changed:
INSTALL
MANIFEST
Makefile.in
config.h.in
configure
configure.in
doc/LICENSE
doc/license.pod
include/sudo_plugin.h
plugins/sample_group/Makefile.in [new file with mode: 0644]
plugins/sample_group/getgrent.c [new file with mode: 0644]
plugins/sample_group/sample_group.c [new file with mode: 0644]
plugins/sudoers/Makefile.in
plugins/sudoers/def_data.c
plugins/sudoers/def_data.h
plugins/sudoers/def_data.in
plugins/sudoers/group_plugin.c [new file with mode: 0644]
plugins/sudoers/match.c
plugins/sudoers/nonunix.h [deleted file]
plugins/sudoers/set_perms.c
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h
plugins/sudoers/testsudoers.c
plugins/sudoers/vasgroups.c [deleted file]
plugins/sudoers/visudo.c
src/sudo.c

diff --git a/INSTALL b/INSTALL
index 4562f982854942dd35630e9f28c2802d0dbcdb7c..bce53efedb40b6cd17c6651870c015cf1b5098da 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -340,16 +340,6 @@ Special features/options:
        Enable support for role based access control (RBAC) on
        systems that support SELinux.
 
-  --with-libvas=[NAME]
-        Enable non-Unix group support using Quest Authentication
-        Services.  If NAME is specified, it should be the name of
-       the shared library providing QAS support (libvas.so by default).
-
-  --with-libvas-rpath=[PATH]
-       The path to search when loading libvas.so (or an alternate
-       name as specified by --with-libvas).  This option only has
-       an effect when --with-libvas is specified.
-
 The following options are also configurable at runtime:
 
   --with-long-otp-prompt
index d6889cf022cc8769f53237e645eb7b79e21c3d3c..d4c27925db08463015e548ebd5cc5c57fce067a2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -101,6 +101,9 @@ mkinstalldirs
 pathnames.h.in
 plugins/sample/Makefile.in
 plugins/sample/sample_plugin.c
+plugins/sample_group/Makefile.in
+plugins/sample_group/getgrent.c
+plugins/sample_group/sample_group.c
 plugins/sudoers/Makefile.in
 plugins/sudoers/aixcrypt.exp
 plugins/sudoers/alias.c
@@ -140,6 +143,7 @@ plugins/sudoers/goodpath.c
 plugins/sudoers/gram.c
 plugins/sudoers/gram.h
 plugins/sudoers/gram.y
+plugins/sudoers/group_plugin.c
 plugins/sudoers/ins_2001.h
 plugins/sudoers/ins_classic.h
 plugins/sudoers/ins_csops.h
@@ -155,7 +159,6 @@ plugins/sudoers/logging.c
 plugins/sudoers/logging.h
 plugins/sudoers/match.c
 plugins/sudoers/mkdefaults
-plugins/sudoers/nonunix.h
 plugins/sudoers/parse.c
 plugins/sudoers/parse.h
 plugins/sudoers/plugin_error.c
@@ -175,7 +178,6 @@ plugins/sudoers/timestr.c
 plugins/sudoers/toke.c
 plugins/sudoers/toke.l
 plugins/sudoers/tsgetgrpw.c
-plugins/sudoers/vasgroups.c
 plugins/sudoers/visudo.c
 src/Makefile.in
 src/conversation.c
index 664a41e4c57d79aa6d0b07163f9a7ba8dc6ecc44..079800fceb4917df3d5cfe37688528681ad47880 100644 (file)
@@ -20,7 +20,8 @@ devdir = @devdir@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 
-SUBDIRS = compat common src plugins/sample plugins/sudoers include doc
+SUBDIRS = compat common src plugins/sample plugins/sample_group \
+         plugins/sudoers include doc
 
 VERSION = @PACKAGE_VERSION@
 
index 277b675427ac9c52491fb8deb420121b8a82ebac..be9ca3776d2f783d5663d6c1ca47f658b0906b69 100644 (file)
 /* The message given when a bad password is entered. */
 #undef INCORRECT_PASSWORD
 
-/* The name of libvas.so */
-#undef LIBVAS_SO
-
 /* The syslog facility sudo will use. */
 #undef LOGFAC
 
 /* Define to 1 if you want a different ticket file for each tty. */
 #undef USE_TTY_TICKETS
 
-/* Define to 1 if using a non-Unix group lookup implementation. */
-#undef USING_NONUNIX_GROUPS
-
 /* Define to avoid using the passwd/shadow file for authentication. */
 #undef WITHOUT_PASSWD
 
index 558ef7463408d58a475d45d59fc8881630a8b3da..61f990c2849966f9ba8c326d3bd4c69dac2fed7d 100755 (executable)
--- a/configure
+++ b/configure
@@ -978,8 +978,6 @@ with_secure_path
 with_interfaces
 with_stow
 with_askpass
-with_libvas
-with_libvas_rpath
 with_plugin_dir
 enable_authentication
 enable_root_mailer
@@ -1741,10 +1739,6 @@ Optional Packages:
   --without-interfaces    don't try to read the ip addr of ether interfaces
   --with-stow             properly handle GNU stow packaging
   --with-askpass=PATH     Fully qualified pathname of askpass helper
-  --with-libvas=NAME      Name of the libvas shared library
-                          (default=libvas.so)
-  --with-libvas-rpath=PATH
-                          Path to look for libvas in [default=/opt/quest/lib]
   --with-plugin_dir       set directory to load plugins from
   --with-selinux          enable SELinux support
   --with-pic              try to use only PIC/non-PIC objects [default=use
@@ -5093,42 +5087,6 @@ $as_echo "no" >&6; }
 fi
 
 
-
-# Check whether --with-libvas was given.
-if test "${with_libvas+set}" = set; then :
-  withval=$with_libvas; case $with_libvas in
-    yes)       with_libvas=libvas.so
-               ;;
-    no)                ;;
-    *)
-cat >>confdefs.h <<_ACEOF
-#define LIBVAS_SO "$with_libvas"
-_ACEOF
-
-               ;;
-esac
-if test X"$with_libvas" != X"no"; then
-
-cat >>confdefs.h <<_ACEOF
-#define LIBVAS_SO "$with_libvas"
-_ACEOF
-
-    $as_echo "#define USING_NONUNIX_GROUPS 1" >>confdefs.h
-
-    NONUNIX_GROUPS_IMPL="vasgroups.o"
-
-# Check whether --with-libvas-rpath was given.
-if test "${with_libvas_rpath+set}" = set; then :
-  withval=$with_libvas_rpath; LIBVAS_RPATH=$withval
-else
-  LIBVAS_RPATH=/opt/quest/lib
-fi
-
-fi
-
-fi
-
-
 with_plugindir="$libexecdir"
 
 # Check whether --with-plugin_dir was given.
@@ -6968,13 +6926,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:6971: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:6929: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:6974: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:6932: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:6977: output\"" >&5)
+  (eval echo "\"\$as_me:6935: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -8179,7 +8137,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 8182 "configure"' > conftest.$ac_ext
+  echo '#line 8140 "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -9440,11 +9398,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9443: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9401: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9447: \$? = $ac_status" >&5
+   echo "$as_me:9405: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9779,11 +9737,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9782: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9740: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9786: \$? = $ac_status" >&5
+   echo "$as_me:9744: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9884,11 +9842,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9887: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9845: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9891: \$? = $ac_status" >&5
+   echo "$as_me:9849: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -9939,11 +9897,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9942: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9900: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9946: \$? = $ac_status" >&5
+   echo "$as_me:9904: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12306,7 +12264,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12309 "configure"
+#line 12267 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12402,7 +12360,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12405 "configure"
+#line 12363 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
        ;;
 esac
 
-if test X"$LIBVAS_RPATH" != X""; then
-    if test -n "$blibpath"; then
-       blibpath_add="${blibpath_add}:$LIBVAS_RPATH"
-    else
-       case "$host" in
-           *-*-hpux*)  LDFLAGS="$LDFLAGS -Wl,+b,$LIBVAS_RPATH"
-                       ;;
-           *)          LDFLAGS="$LDFLAGS -Wl,-R$LIBVAS_RPATH"
-                       ;;
-       esac
-    fi
-fi
-
 if test -n "$blibpath"; then
     if test -n "$blibpath_add"; then
        SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}"
@@ -18312,7 +18257,7 @@ EOF
     exec_prefix="$oexec_prefix"
 fi
 
-ac_config_files="$ac_config_files Makefile common/Makefile compat/Makefile doc/Makefile include/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/sudoers/Makefile"
+ac_config_files="$ac_config_files Makefile common/Makefile compat/Makefile doc/Makefile include/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/sample_group/Makefile plugins/sudoers/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -19270,6 +19215,7 @@ do
     "src/sudo_usage.h") CONFIG_FILES="$CONFIG_FILES src/sudo_usage.h" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "plugins/sample/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample/Makefile" ;;
+    "plugins/sample_group/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample_group/Makefile" ;;
     "plugins/sudoers/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/Makefile" ;;
 
   *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -20574,6 +20520,5 @@ fi
 
 
 
-
 
 
index de7adf5f6fe2e0922db183e0284d5f55f69c6f4c..1d72b5882f1740208140e0875a8e4b620ba13942 100644 (file)
@@ -1087,29 +1087,6 @@ AC_ARG_WITH(askpass, [AS_HELP_STRING([--with-askpass=PATH], [Fully qualified pat
                ;;
 esac], AC_MSG_RESULT(no))
 
-dnl
-dnl If enabled, set LIBVAS_SO, LIBVAS_RPATH and USING_NONUNIX_GROUPS
-dnl
-AC_ARG_WITH(libvas, [AS_HELP_STRING([--with-libvas=NAME], [Name of the libvas shared library (default=libvas.so)])],
-[case $with_libvas in
-    yes)       with_libvas=libvas.so
-               ;;
-    no)                ;;
-    *)         AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_libvas"], [The name of libvas.so])
-               ;;
-esac
-if test X"$with_libvas" != X"no"; then
-    AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_libvas"], [The name of libvas.so])
-    AC_DEFINE(USING_NONUNIX_GROUPS)
-    NONUNIX_GROUPS_IMPL="vasgroups.o"
-    AC_ARG_WITH([libvas-rpath],
-       [AS_HELP_STRING([--with-libvas-rpath=PATH],
-                      [Path to look for libvas in [default=/opt/quest/lib]])],
-       [LIBVAS_RPATH=$withval],
-       [LIBVAS_RPATH=/opt/quest/lib])
-fi
-])
-
 with_plugindir="$libexecdir"
 AC_ARG_WITH(plugin_dir, [AS_HELP_STRING([--with-plugin_dir], [set directory to load plugins from])],
 [case $with_plugin_dir in
@@ -2671,23 +2648,6 @@ case "$host" in
        ;;
 esac
 
-dnl
-dnl Add LIBVAS_RPATH to LDFLAGS
-dnl GNU ld accepts -R/path/ as an alias for -rpath /path/
-dnl
-if test X"$LIBVAS_RPATH" != X""; then
-    if test -n "$blibpath"; then
-       blibpath_add="${blibpath_add}:$LIBVAS_RPATH"
-    else
-       case "$host" in
-           *-*-hpux*)  LDFLAGS="$LDFLAGS -Wl,+b,$LIBVAS_RPATH"
-                       ;;
-           *)          LDFLAGS="$LDFLAGS -Wl,-R$LIBVAS_RPATH"
-                       ;;
-       esac
-    fi
-fi
-
 dnl
 dnl Add $blibpath to SUDOERS_LDFLAGS if specified by the user or if we
 dnl added -L dirpaths to SUDOERS_LDFLAGS.
@@ -2779,7 +2739,7 @@ dnl
 dnl Substitute into the Makefile and man pages
 dnl
 dnl AC_CONFIG_FILES([doc/sudo.man doc/visudo.man doc/sudoers.man doc/sudoers.ldap.man doc/sudoreplay.man src/Makefile src/sudo_usage.h])
-AC_CONFIG_FILES([Makefile common/Makefile compat/Makefile doc/Makefile include/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/sudoers/Makefile])
+AC_CONFIG_FILES([Makefile common/Makefile compat/Makefile doc/Makefile include/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/sample_group/Makefile plugins/sudoers/Makefile])
 AC_OUTPUT
 
 dnl
@@ -2875,7 +2835,6 @@ AH_TEMPLATE(USE_TTY_TICKETS, [Define to 1 if you want a different ticket file fo
 AH_TEMPLATE(WITHOUT_PASSWD, [Define to avoid using the passwd/shadow file for authentication.])
 AH_TEMPLATE(sig_atomic_t, [Define to `int' if <signal.h> does not define.])
 AH_TEMPLATE(__signed, [Define to `signed' or nothing if compiler does not support a signed type qualifier.])
-AH_TEMPLATE(USING_NONUNIX_GROUPS, [Define to 1 if using a non-Unix group lookup implementation.])
 
 dnl
 dnl Bits to copy verbatim into config.h.in
index 6e9a547ab4583b30b07b6e8559efa9615edbb53c..9032932ddb677c5ccc372b4ef9389deaf91c0cd8 100644 (file)
@@ -48,31 +48,3 @@ bear the following UCB license:
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.
-
-nonunix.h and vasgroups.c bear the following license:
-
-   Copyright (c) 2006 Quest Software, Inc.  All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-
-   1. Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-   2. Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-   3. Neither the name of Quest Software, Inc. nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-   POSSIBILITY OF SUCH DAMAGE.
index a5fdb7bdc98aa560d4b7ec4882c387cfe15cb63f..ef509ffd7c206167277f576eebd00503bd947005 100644 (file)
@@ -52,32 +52,3 @@ bear the following UCB license:
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.
-
-=head3
-nonunix.h and vasgroups.c bear the following license:
-
-   Copyright (c) 2006 Quest Software, Inc.  All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-
-   1. Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-   2. Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-   3. Neither the name of Quest Software, Inc. nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-   POSSIBILITY OF SUCH DAMAGE. 
index ef7ccf2eb787a815fb557d63dfb28e4783389e60..7eb871e3f54c6597e5ddef5ded6ec5a6ddf27117 100644 (file)
@@ -104,4 +104,33 @@ struct generic_plugin {
     /* the rest depends on the type... */
 };
 
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | GROUP_API_VERSION_MINOR)
+
+/* Getters and setters for group version */
+#define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+#define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \
+    *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \
+} while(0)
+#define GROUP_API_VERSION_SET_MINOR(vp, n) do { \
+    *(vp) = (*(vp) & 0xffff0000) | (n); \
+} while(0)
+
+/*
+ * version: for compatibility checking
+ * group_init: return 1 on success, 0 if unconfigured, -1 on error.
+ * group_cleanup: called to clean up resources used by provider
+ * user_in_group: returns 1 if user is in group, 0 if not.
+ *                note that pwd may be NULL if the user is not in passwd.
+ */
+struct sudoers_group_plugin {
+    unsigned int version;
+    int (*init)(int version, sudo_printf_t sudo_printf, char *const argv[]);
+    void (*cleanup)(void);
+    int (*query)(const char *user, const char *group, const struct passwd *pwd);
+};
+
 #endif /* _SUDO_PLUGIN_H */
diff --git a/plugins/sample_group/Makefile.in b/plugins/sample_group/Makefile.in
new file mode 100644 (file)
index 0000000..fe12ab8
--- /dev/null
@@ -0,0 +1,120 @@
+#
+# Copyright (c) 2010 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.
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+devdir = @devdir@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+incdir = $(top_srcdir)/include
+
+# For out of tree builds
+VPATH = $(srcdir)
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@ --tag=disable-static
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(top_srcdir)/install-sh -c
+
+# Libraries
+LIBS = $(LIBOBJDIR)/libreplace.la
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS =
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+plugindir = @PLUGINDIR@
+
+# OS dependent defines
+DEFS = @OSDEFS@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = sample_group.lo getgrent.lo
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: sample_group.la
+
+.SUFFIXES: .o .c .h .lo
+
+.c.o:
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $<
+
+.c.lo:
+       $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $<
+
+getgrent.lo: $(srcdir)/getgrent.c
+
+sample_group.lo: $(srcdir)/sample_group.c
+
+sample_group.la: $(OBJS)
+       $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir)
+
+install: install-dirs install-plugin
+
+install-dirs:
+       $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-man:
+
+install-plugin: install-dirs sample_group.la
+       $(LIBTOOL) --mode=install --quiet $(INSTALL) sample_group.la $(plugindir)
+
+check:
+       @echo nothing to check
+
+clean:
+       -$(LIBTOOL) --mode=clean rm -f *.lo *.o *.la *.a stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+       -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+       rm -f TAGS tags
+
+cleandir: realclean
diff --git a/plugins/sample_group/getgrent.c b/plugins/sample_group/getgrent.c
new file mode 100644 (file)
index 0000000..f2a65f4
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2005, 2008, 2010 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.
+ */
+
+/*
+ * Trivial replacements for the libc getgr{uid,nam}() routines.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <compat.h>
+#include <missing.h>
+
+#ifndef LINE_MAX
+# define LINE_MAX 2048
+#endif
+
+#undef GRMEM_MAX
+#define GRMEM_MAX 200
+
+static FILE *grf;
+static const char *grfile = "/etc/group";
+static int gr_stayopen;
+
+void mysetgrfile(const char *);
+void mysetgrent(void);
+void myendgrent(void);
+struct group *mygetgrent(void);
+struct group *mygetgrnam(const char *);
+struct group *mygetgrgid(gid_t);
+
+void
+mysetgrfile(const char *file)
+{
+    grfile = file;
+    if (grf != NULL)
+       myendgrent();
+}
+
+void
+mysetgrent(void)
+{
+    if (grf == NULL) {
+       grf = fopen(grfile, "r");
+       if (grf != NULL)
+           fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
+    } else {
+       rewind(grf);
+    }
+    gr_stayopen = 1;
+}
+
+void
+myendgrent(void)
+{
+    if (grf != NULL) {
+       fclose(grf);
+       grf = NULL;
+    }
+    gr_stayopen = 0;
+}
+
+struct group *
+mygetgrent(void)
+{
+    static struct group gr;
+    static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
+    size_t len;
+    char *cp, *colon;
+    int n;
+
+    if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
+       return(NULL);
+
+    memset(&gr, 0, sizeof(gr));
+    if ((colon = strchr(cp = colon, ':')) == NULL)
+       return(NULL);
+    *colon++ = '\0';
+    gr.gr_name = cp;
+    if ((colon = strchr(cp = colon, ':')) == NULL)
+       return(NULL);
+    *colon++ = '\0';
+    gr.gr_passwd = cp;
+    if ((colon = strchr(cp = colon, ':')) == NULL)
+       return(NULL);
+    *colon++ = '\0';
+    gr.gr_gid = atoi(cp);
+    len = strlen(colon);
+    if (len > 0 && colon[len - 1] == '\n')
+       colon[len - 1] = '\0';
+    if (*colon != '\0') {
+       gr.gr_mem = gr_mem;
+       cp = strtok(colon, ",");
+       for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
+           gr.gr_mem[n] = cp;
+           cp = strtok(NULL, ",");
+       }
+       gr.gr_mem[n++] = NULL;
+    } else
+       gr.gr_mem = NULL;
+    return(&gr);
+}
+
+struct group *
+mygetgrnam(const char *name)
+{
+    struct group *gr;
+
+    if (grf == NULL) {
+       if ((grf = fopen(grfile, "r")) == NULL)
+           return(NULL);
+       fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
+    } else {
+       rewind(grf);
+    }
+    while ((gr = mygetgrent()) != NULL) {
+       if (strcmp(gr->gr_name, name) == 0)
+           break;
+    }
+    if (!gr_stayopen) {
+       fclose(grf);
+       grf = NULL;
+    }
+    return(gr);
+}
+
+struct group *
+mygetgrgid(gid_t gid)
+{
+    struct group *gr;
+
+    if (grf == NULL) {
+       if ((grf = fopen(grfile, "r")) == NULL)
+           return(NULL);
+       fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
+    } else {
+       rewind(grf);
+    }
+    while ((gr = mygetgrent()) != NULL) {
+       if (gr->gr_gid == gid)
+           break;
+    }
+    if (!gr_stayopen) {
+       fclose(grf);
+       grf = NULL;
+    }
+    return(gr);
+}
diff --git a/plugins/sample_group/sample_group.c b/plugins/sample_group/sample_group.c
new file mode 100644 (file)
index 0000000..133a664
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include <sudo_plugin.h>
+#include <compat.h>
+#include <missing.h>
+
+/*
+ * Sample sudoers group plugin that uses an extra group file with the
+ * same format as /etc/group.
+ */
+
+#undef TRUE
+#define TRUE 1
+#undef FALSE
+#define FALSE 0
+#undef ERROR
+#define ERROR -1
+
+static sudo_printf_t sudo_log;
+
+extern void mysetgrfile(const char *);
+extern void mysetgrent(void);
+extern void myendgrent(void);
+extern struct group *mygetgrnam(const char *);
+
+static int sample_init(int version, sudo_printf_t sudo_printf, char *const argv[])
+{
+    struct stat sb;
+
+    sudo_log = sudo_printf;
+
+    if (GROUP_API_VERSION_GET_MAJOR(version) != GROUP_API_VERSION_MAJOR) {
+       sudo_log(SUDO_CONV_ERROR_MSG,
+           "sample_group: incompatible major version %d, expected %d\n",
+           GROUP_API_VERSION_GET_MAJOR(version),
+           GROUP_API_VERSION_MAJOR);
+       return ERROR;
+    }
+
+    /* Sanity check the specified group file. */
+    if (argv == NULL || argv[0] == NULL) {
+       sudo_log(SUDO_CONV_ERROR_MSG,
+           "sample_group: path to group file not specified\n");
+       return ERROR;
+    }
+    if (stat(argv[0], &sb) != 0) {
+       sudo_log(SUDO_CONV_ERROR_MSG,
+           "sample_group: %s: %s\n", argv[0], strerror(errno));
+       return ERROR;
+    }
+    if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+       sudo_log(SUDO_CONV_ERROR_MSG,
+           "%s must be only be writable by owner\n", argv[0]);
+       return ERROR;
+    }
+
+    mysetgrfile(argv[0]);
+    mysetgrent();
+
+    return TRUE;
+}
+
+static void sample_cleanup(void)
+{
+    myendgrent();
+}
+
+/*
+ * Returns TRUE if "user" is a member of "group", else FALSE.
+ */
+static int sample_query(const char *user, const char *group, const struct passwd *pwd)
+{
+    struct group *grp;
+    char **member;
+
+    grp = mygetgrnam(group);
+    if (grp != NULL) {
+       for (member = grp->gr_mem; *member != NULL; member++) {
+           if (strcasecmp(user, *member) == 0)
+               return TRUE;
+       }
+    }
+
+    return FALSE;
+}
+
+struct sudoers_group_plugin group_plugin = {
+    GROUP_API_VERSION,
+    sample_init,
+    sample_cleanup,
+    sample_query
+};
index c599b28840160c392531ab019657f90f12d97694..5f257ade192ba2218f7d476da6e40e045f100d36 100644 (file)
@@ -105,7 +105,7 @@ LIBSUDOERS_OBJS = alias.lo audit.lo defaults.lo gram.lo match.lo pwutil.lo \
 
 SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo \
               plugin_error.lo env.lo getspwuid.lo \
-              goodpath.lo find_path.lo interfaces.lo \
+              goodpath.lo group_plugin.lo find_path.lo interfaces.lo \
               logging.lo parse.lo set_perms.lo sudoers.lo sudo_nss.lo \
               iolog.lo @SUDOERS_OBJS@
 
@@ -113,7 +113,7 @@ VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o
 
 REPLAY_OBJS = getdate.o sudoreplay.o error.o
 
-TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o error.o
+TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o error.o group_plugin.o
 
 VERSION = @PACKAGE_VERSION@
 
@@ -197,6 +197,7 @@ getspwuid.lo: $(srcdir)/getspwuid.c $(SUDODEP)
 goodpath.lo: $(srcdir)/goodpath.c $(SUDODEP)
 gram.lo: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(devdir)/gram.h
        $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(devdir)/gram.c
+group_plugin.lo: $(srcdir)/group_plugin.c $(SUDODEP)
 interfaces.lo: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h
 iolog.lo: $(srcdir)/iolog.c $(SUDODEP)
 ldap.lo: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h
@@ -213,7 +214,6 @@ timestr.lo: $(srcdir)/timestr.c $(incdir)/compat.h $(top_builddir)/config.h
 toke.lo: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(devdir)/gram.h
        $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(devdir)/toke.c
 tsgetgrpw.lo: $(srcdir)/tsgetgrpw.c $(SUDODEP)
-vasgroups.lo: $(srcdir)/vasgroups.c $(srcdir)/nonunix.h $(SUDODEP)
 plugin_error.lo: $(srcdir)/plugin_error.c $(incdir)/error.h $(incdir)/compat.h $(top_builddir)/config.h
 
 # Auth dependencies
index 81c03f43262a6e688c01c5c7df31829748a43910..79e99ea37c9ecc344c367a3649d443d00f5de6fb 100644 (file)
@@ -326,6 +326,10 @@ struct sudo_defs_types sudo_defs_table[] = {
        "use_pty", T_FLAG,
        "Always run commands in a pseudo-tty",
        NULL,
+    }, {
+       "group_plugin", T_STR,
+       "Plugin for non-Unix group support",
+       NULL,
     }, {
        NULL, 0, NULL
     }
index ec1014ab97e771934b7df2d375c750081504fc16..76b9f12e2612977b7bbaaa51e5d7230bd79dcdd7 100644 (file)
 #define I_COMPRESS_IO           74
 #define def_use_pty             (sudo_defs_table[75].sd_un.flag)
 #define I_USE_PTY               75
+#define def_group_plugin        (sudo_defs_table[76].sd_un.str)
+#define I_GROUP_PLUGIN          76
 
 enum def_tupple {
        never,
index 203fd1d0c05fa5f1d039a0e43c95cb59bc06c242..9dd7699518b5b58645569afc97201eb0fca56212 100644 (file)
@@ -241,3 +241,6 @@ compress_io
 use_pty
        T_FLAG
        "Always run commands in a pseudo-tty"
+group_plugin
+       T_STR
+       "Plugin for non-Unix group support"
diff --git a/plugins/sudoers/group_plugin.c b/plugins/sudoers/group_plugin.c
new file mode 100644 (file)
index 0000000..a187105
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if TIME_WITH_SYS_TIME
+# include <time.h>
+#endif
+#include <ctype.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <pwd.h>
+
+#include "sudoers.h"
+
+static void *group_handle;
+static struct sudoers_group_plugin *group_plugin;
+
+/*
+ * Load the specified plugin and run its init function.
+ * Returns -1 if unable to open the plugin, else it returns
+ * the value from the plugin's init function.
+ */
+int
+group_plugin_load(char *plugin_info)
+{
+    struct stat sb;
+    char *args, path[PATH_MAX], savedch;
+    char **argv = NULL;
+    size_t len;
+    int rc;
+
+    /*
+     * Fill in .so path and split out args (if any).
+     */
+    path[0] = '\0';
+    if (plugin_info[0] != '/')
+       strlcpy(path, _PATH_SUDO_PLUGIN_DIR, sizeof(path));
+    if ((args = strpbrk(plugin_info, " \t")) != NULL) {
+       savedch = *args;
+       *args = '\0';
+    }
+    len = strlcat(path, plugin_info, sizeof(path));
+    if (args != NULL)
+       *args++ = savedch;
+    if (len >= sizeof(path)) {
+       warningx("%s%s: %s", _PATH_SUDO_PLUGIN_DIR, plugin_info,
+           strerror(ENAMETOOLONG));
+       return -1;
+    }
+
+    /* Sanity check plugin path. */
+    if (stat(path, &sb) != 0) {
+       warning("%s", path);
+       return -1;
+    }
+    if (sb.st_uid != ROOT_UID) {
+       warningx("%s must be owned by uid %d", path, ROOT_UID);
+       return -1;
+    }
+    if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+       warningx("%s must be only be writable by owner", path);
+       return -1;
+    }
+
+    /* Open plugin and map in symbol. */
+    group_handle = dlopen(path, RTLD_NOW);
+    if (!group_handle) {
+       warningx("unable to dlopen %s: %s", path, dlerror());
+       return -1;
+    }
+    group_plugin = dlsym(group_handle, "group_plugin");
+    if (group_plugin == NULL) {
+       warningx("unable to find symbol \"group_plugin\" in %s", path);
+       return -1;
+    }
+
+    if (GROUP_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
+       warningx("%s: incompatible group plugin major version %d, expected %d",
+           path, GROUP_API_VERSION_GET_MAJOR(group_plugin->version),
+           GROUP_API_VERSION_MAJOR);
+       return -1;
+    }
+
+    /*
+     * Split args into a vector if specified.
+     */
+    if (args != NULL) {
+       int ac = 0, wasblank = TRUE;
+       char *cp;
+
+        for (cp = args; *cp != '\0'; cp++) {
+            if (isblank((unsigned char)*cp)) {
+                wasblank = TRUE;
+            } else if (wasblank) {
+                wasblank = FALSE;
+                ac++;
+            }
+        }
+       if (ac != 0)    {
+           argv = emalloc2(ac, sizeof(char *));
+           ac = 0;
+           for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t")))
+               argv[ac++] = cp;
+       }
+    }
+
+    rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv);
+
+    efree(argv);
+
+    return rc;
+}
+
+void
+group_plugin_unload(void)
+{
+    (group_plugin->cleanup)();
+    dlclose(group_handle);
+    group_handle = NULL;
+}
+
+int
+group_plugin_query(const char *user, const char *group,
+    const struct passwd *pwd)
+{
+    return (group_plugin->query)(user, group, pwd);
+}
index c1978026ec15ec5669fecba14217c7601dd9c5aa..6093b8893d632199853aa36b47b3f2aed4d9bc08 100644 (file)
@@ -88,9 +88,6 @@
 #ifndef HAVE_EXTENDED_GLOB
 # include <compat/glob.h>
 #endif /* HAVE_EXTENDED_GLOB */
-#ifdef USING_NONUNIX_GROUPS
-# include "nonunix.h"
-#endif /* USING_NONUNIX_GROUPS */
 
 static struct member_list empty;
 
@@ -778,10 +775,8 @@ usergr_matches(char *group, char *user, struct passwd *pw)
     if (*group++ != '%')
        return(FALSE);
 
-#ifdef USING_NONUNIX_GROUPS
-    if (*group == ':')
-       return(sudo_nonunix_groupcheck(++group, user, pw));   
-#endif /* USING_NONUNIX_GROUPS */
+    if (*group == ':' && def_group_plugin)
+       return(group_plugin_query(user, group + 1, pw));
 
     /* look up user's primary gid in the passwd file */
     if (pw == NULL && (pw = sudo_getpwnam(user)) == NULL)
@@ -790,12 +785,9 @@ usergr_matches(char *group, char *user, struct passwd *pw)
     if (user_in_group(pw, group))
        return(TRUE);
 
-#ifdef USING_NONUNIX_GROUPS
-    /* not a Unix group, could be an AD group */
-    if (sudo_nonunix_groupcheck_available() &&
-       sudo_nonunix_groupcheck(group, user, pw))
+    /* not a Unix group, could be an external group */
+    if (def_group_plugin && group_plugin_query(user, group, pw))
        return(TRUE);
-#endif /* USING_NONUNIX_GROUPS */
 
     return(FALSE);
 }
diff --git a/plugins/sudoers/nonunix.h b/plugins/sudoers/nonunix.h
deleted file mode 100644 (file)
index 09cd450..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * (c) 2006 Quest Software, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- *   3. Neither the name of Quest Software, Inc. nor the names of its
- *   contributors may be used to endorse or promote products derived from this
- *   software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef _NONUNIX_H
-#define _NONUNIX_H
-
-void sudo_nonunix_groupcheck_init(void);
-void sudo_nonunix_groupcheck_cleanup(void);
-int sudo_nonunix_groupcheck(const char *group, const char *user,
-    const struct passwd *pwd);
-int sudo_nonunix_groupcheck_available(void);
-
-#endif /* _NONUNIX_H */
index d91b3dabf5bbacbcaa0e1482749f295fd11a4c3f..46253a6c2d26b059eba646d97e402079fe1f7fa5 100644 (file)
 
 #include "sudoers.h"
 
-#ifdef __TANDEM
-# define ROOT_UID      65535
-#else
-# define ROOT_UID      0
-#endif
-
 /*
  * Prototypes
  */
index db577dbdfbe00fdc53feb38bb56844a8ea637e45..8c4033dde65e77b9186c377eed6477f4ba499e40 100644 (file)
 #include "interfaces.h"
 #include "auth/sudo_auth.h"
 
-#ifdef USING_NONUNIX_GROUPS
-# include "nonunix.h"
-#endif
-
 /*
  * Prototypes
  */
@@ -223,10 +219,6 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
 
     init_vars(envp);           /* XXX - move this later? */
 
-#ifdef USING_NONUNIX_GROUPS
-    sudo_nonunix_groupcheck_init();    /* initialise nonunix groups impl */
-#endif /* USING_NONUNIX_GROUPS */
-
     /* Parse nsswitch.conf for sudoers order. */
     snl = sudo_read_nss();
 
@@ -246,6 +238,18 @@ sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
 
     /* XXX - collect post-sudoers parse settings into a function */
 
+    /*
+     * Initialize external group plugin.
+     */
+    if (def_group_plugin) {
+       switch (group_plugin_load(def_group_plugin)) {
+       case -1:
+           return -1;
+       case FALSE:
+           def_group_plugin = NULL;
+       }
+    }
+
     /*
      * Set runas passwd/group entries based on command line or sudoers.
      * Note that if runas_group was specified without runas_user we
@@ -343,10 +347,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
     if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
        NewArgv[0] = runas_pw->pw_shell;
 
-#ifdef USING_NONUNIX_GROUPS
-    sudo_nonunix_groupcheck_init();     /* initialise nonunix groups impl */
-#endif /* USING_NONUNIX_GROUPS */
-
     /* Find command in path */
     cmnd_status = set_cmnd(sudo_mode);
     if (cmnd_status == -1) {
@@ -527,11 +527,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
     tq_foreach_fwd(snl, nss) {
        nss->close(nss);
     }
-
-#ifdef USING_NONUNIX_GROUPS
-    /* Finished with the groupcheck code */
-    sudo_nonunix_groupcheck_cleanup();
-#endif
+    if (def_group_plugin)
+       group_plugin_unload();
 
     if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST)))
        goto done;
@@ -1138,9 +1135,8 @@ cleanup(int gotsignal)
            tq_foreach_fwd(snl, nss)
                nss->close(nss);
        }
-#ifdef USING_NONUNIX_GROUPS
-       sudo_nonunix_groupcheck_cleanup();
-#endif
+       if (def_group_plugin)
+           group_plugin_unload();
        sudo_endpwent();
        sudo_endgrent();
     }
index 319409152519087a23446baa12f110822e7ef8b1..f2ec62eb4990eae193b52d0be45b2070c3302947 100644 (file)
@@ -177,6 +177,12 @@ struct sudo_user {
 #define user_type              (sudo_user.type)
 #define user_closefrom         (sudo_user.closefrom)
 
+#ifdef __TANDEM
+# define ROOT_UID       65535
+#else
+# define ROOT_UID       0
+#endif
+
 /*
  * We used to use the system definition of PASS_MAX or _PASSWD_LEN,
  * but that caused problems with various alternate authentication
@@ -299,6 +305,12 @@ FILE *open_sudoers(const char *, int, int *);
 void aix_restoreauthdb(void);
 void aix_setauthdb(char *user);
 
+/* group_plugin.c */
+int group_plugin_load(char *plugin_info);
+void group_plugin_unload(void);
+int group_plugin_query(const char *user, const char *group,
+    const struct passwd *pwd);
+
 #ifndef _SUDO_MAIN
 extern struct sudo_user sudo_user;
 extern struct passwd *auth_pw, *list_pw;
index e2c607a902c604241f604a8f7012b8ccadf53291..f72684523465ae2dced06f45c501268167a60ddb 100644 (file)
@@ -248,6 +248,9 @@ main(int argc, char *argv[])
        (void) fputs(" (problem with defaults entries)", stdout);
     puts(".");
 
+    if (def_group_plugin && group_plugin_load(def_group_plugin) != TRUE)
+       def_group_plugin = NULL;
+
     /*
      * Set runas passwd/group entries based on command line or sudoers.
      * Note that if runas_group was specified without runas_user we
diff --git a/plugins/sudoers/vasgroups.c b/plugins/sudoers/vasgroups.c
deleted file mode 100644 (file)
index ed614de..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * (c) 2006 Quest Software, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- *   3. Neither the name of Quest Software, Inc. nor the names of its
- *   contributors may be used to endorse or promote products derived from this
- *   software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <dlfcn.h>
-
-#include <vas.h>
-
-#include "nonunix.h"
-#include "sudoers.h"
-#include "parse.h"
-
-
-/* Pseudo-boolean types */
-#undef TRUE
-#undef FALSE
-#define FALSE 0
-#define TRUE  1
-
-
-static vas_ctx_t *sudo_vas_ctx;
-static vas_id_t  *sudo_vas_id;
-/* Don't use VAS_NAME_FLAG_NO_CACHE or lookups just won't work.
- * -tedp, 2006-08-29 */
-static const int update_flags = 0;
-static int sudo_vas_available = 0;
-static char *err_msg = NULL;
-static void *libvas_handle = NULL;
-
-/* libvas functions */
-static vas_err_t       (*v_ctx_alloc) (vas_ctx_t **ctx);
-static void            (*v_ctx_free) (vas_ctx_t *ctx);
-static vas_err_t       (*v_id_alloc) (vas_ctx_t *ctx, const char *name, vas_id_t **id);
-static void            (*v_id_free) (vas_ctx_t *ctx, vas_id_t *id);
-static vas_err_t       (*v_id_establish_cred_keytab) (vas_ctx_t *ctx, vas_id_t *id, int credflags, const char *keytab);
-static vas_err_t       (*v_user_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_user_t **user);
-static void            (*v_user_free) (vas_ctx_t *ctx, vas_user_t *user);
-static vas_err_t       (*v_group_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_group_t **group);
-static void            (*v_group_free) (vas_ctx_t *ctx, vas_group_t *group);
-static vas_err_t       (*v_user_is_member) (vas_ctx_t *ctx, vas_id_t *id, vas_user_t *user, vas_group_t *group);
-static const char*     (*v_err_get_string) (vas_ctx_t *ctx, int with_cause);
-
-
-static int     resolve_vas_funcs(void);
-
-
-/**
- * Whether nonunix group lookups are available.
- * @return 1 if available, 0 if not.
- */
-int
-sudo_nonunix_groupcheck_available(void)
-{
-    return sudo_vas_available;
-}
-
-
-/**
- * Check if the user is in the group
- * @param group group name which can be in DOMAIN\sam format or just the group
- *              name
- * @param user user name
- * @param pwd (unused)
- * @return 1 if user is a member of the group, 0 if not (or error occurred)
- */
-int
-sudo_nonunix_groupcheck( const char* group, const char* user, const struct passwd* pwd )
-{
-    static int          error_cause_shown = FALSE;
-    int                 rval = FALSE;
-    vas_err_t           vaserr;
-    vas_user_t*         vas_user = NULL;
-    vas_group_t*        vas_group = NULL;
-
-    if (!sudo_vas_available) {
-       if (error_cause_shown == FALSE) {
-           /* Produce the saved error reason */
-           warningx("Non-unix group checking unavailable: %s",
-                   err_msg ? err_msg
-                   : "(unknown cause)");
-           error_cause_shown = TRUE;
-       }
-       return 0;
-    }
-
-    /* resolve the user and group. The user will be a real Unix account name,
-     * while the group may be a unix name, or any group name accepted by
-     * vas_name_to_dn, which means any of:
-     * - Group Name
-     * - Group Name@FULLY.QUALIFIED.DOMAIN
-     * - CN=sudoers,CN=Users,DC=rcdev,DC=vintela,DC=com
-     * - S-1-2-34-5678901234-5678901234-5678901234-567
-     *
-     * XXX - we may get non-VAS user accounts here. You can add local users to an
-     * Active Directory group through override files. Should we handle that case?
-     * */
-    if( (vaserr = v_user_init( sudo_vas_ctx, sudo_vas_id, user, update_flags, &vas_user )) != VAS_ERR_SUCCESS ) {
-       if (vaserr == VAS_ERR_NOT_FOUND) {
-            /* No such user in AD. Probably a local user. */
-           vaserr = VAS_ERR_SUCCESS;
-       }
-        goto FINISHED;
-    }
-        
-    if( (vaserr = v_group_init( sudo_vas_ctx, sudo_vas_id, group, update_flags, &vas_group )) != VAS_ERR_SUCCESS ) {
-        goto FINISHED;
-    }
-
-    /* do the membership check */
-    if( (vaserr = v_user_is_member( sudo_vas_ctx, sudo_vas_id, vas_user, vas_group )) == VAS_ERR_SUCCESS ) {
-        rval = TRUE;
-    }
-    else if (vaserr == VAS_ERR_NOT_FOUND) {
-       /* fake the vaserr code so no error is triggered */
-       vaserr = VAS_ERR_SUCCESS;
-    }
-
-
-FINISHED: /* cleanups */
-    if (vaserr != VAS_ERR_SUCCESS && vaserr != VAS_ERR_NOT_FOUND ) {
-       warningx("Error while checking group membership "
-               "for user \"%s\", group \"%s\", error: %s%s.", user, group,
-               v_err_get_string(sudo_vas_ctx, 1),
-               /* A helpful hint if there seems to be a non-FQDN as the domain */
-               (strchr(group, '@') && !strchr(group, '.'))
-                ? "\nMake sure the fully qualified domain name is specified"
-                : "");
-    }
-    if( vas_group )              v_group_free( sudo_vas_ctx, vas_group );
-    if( vas_user )              v_user_free( sudo_vas_ctx, vas_user );
-
-    return(rval);
-}
-
-
-static void
-set_err_msg(const char *msg, ...) {
-    va_list ap;
-
-    if (!msg) /* assert */
-       return;
-
-    if (err_msg)
-       free(err_msg);
-
-    va_start(ap, msg);
-
-    if (vasprintf(&err_msg, msg, ap) == -1)
-       err_msg = NULL;
-       
-    va_end(ap);
-}
-
-
-/**
- * Initialise nonunix_groupcheck state.
- */
-void
-sudo_nonunix_groupcheck_init(void)
-{
-    vas_err_t vaserr;
-    void *libvas;
-
-    if (err_msg) {
-       free(err_msg);
-       err_msg = NULL;
-    }
-
-    libvas = dlopen(LIBVAS_SO, RTLD_LAZY);
-    if (!libvas) {
-       set_err_msg("dlopen() failed: %s", dlerror());
-       return;
-    }
-
-    libvas_handle = libvas;
-
-    if (resolve_vas_funcs() != 0)
-       return;
-
-    if (VAS_ERR_SUCCESS == (vaserr = v_ctx_alloc(&sudo_vas_ctx))) {
-
-       if (VAS_ERR_SUCCESS == (vaserr = v_id_alloc(sudo_vas_ctx, "host/", &sudo_vas_id))) {
-       
-           if (update_flags & VAS_NAME_FLAG_NO_LDAP) {
-               sudo_vas_available = 1;
-               return; /* OK */
-           } else { /* Get a keytab */
-               if ((vaserr = v_id_establish_cred_keytab( sudo_vas_ctx,
-                                                   sudo_vas_id,
-                                                     VAS_ID_FLAG_USE_MEMORY_CCACHE
-                                                   | VAS_ID_FLAG_KEEP_COPY_OF_CRED
-                                                   | VAS_ID_FLAG_NO_INITIAL_TGT,
-                                                   NULL )) == VAS_ERR_SUCCESS) {
-                   sudo_vas_available = 1;
-                   return; /* OK */
-               }
-
-               if (!err_msg)
-                   set_err_msg("unable to establish creds: %s",
-                           v_err_get_string(sudo_vas_ctx, 1));
-           }
-
-           v_id_free(sudo_vas_ctx, sudo_vas_id);
-           sudo_vas_id = NULL;
-       }
-
-       /* This is the last opportunity to get an error message from libvas */
-       if (!err_msg)
-           set_err_msg("Error initializing non-unix group checking: %s",
-                   v_err_get_string(sudo_vas_ctx, 1));
-
-       v_ctx_free(sudo_vas_ctx);
-       sudo_vas_ctx = NULL;
-    }
-
-    if (!err_msg)
-       set_err_msg("Failed to get a libvas handle for non-unix group checking (unknown cause)");
-
-    sudo_vas_available = 0;
-}
-
-
-/**
- * Clean up nonunix_groupcheck state.
- */
-void
-sudo_nonunix_groupcheck_cleanup(void)
-{
-    if (err_msg) {
-       free(err_msg);
-       err_msg = NULL;
-    }
-
-    if (sudo_vas_available) {
-       v_id_free(sudo_vas_ctx, sudo_vas_id);
-       sudo_vas_id = NULL;
-
-       v_ctx_free(sudo_vas_ctx);
-       sudo_vas_ctx = NULL;
-
-       sudo_vas_available = FALSE;
-    }
-
-    if (libvas_handle) {
-       if (dlclose(libvas_handle) != 0)
-           warningx("dlclose() failed: %s", dlerror());
-       libvas_handle = NULL;
-    }
-}
-
-#define RESOLVE_OR_ERR(fptr, sym) \
-    do { \
-       void *_fptr = dlsym(libvas_handle, (sym)); \
-       if (!_fptr) { \
-           set_err_msg("dlsym() failed: %s", dlerror()); \
-           return -1; \
-       } \
-       fptr = _fptr; \
-    } while (0)
-
-
-/**
- * Resolve all the libvas functions.
- * Returns -1 and sets err_msg if something went wrong, or 0 on success.
- */
-int
-resolve_vas_funcs(void)
-{
-    if (!libvas_handle) /* assert */
-       return -1;
-
-    RESOLVE_OR_ERR(v_ctx_alloc,        "vas_ctx_alloc");
-    RESOLVE_OR_ERR(v_ctx_free, "vas_ctx_free");
-    RESOLVE_OR_ERR(v_id_alloc, "vas_id_alloc");
-    RESOLVE_OR_ERR(v_id_free,  "vas_id_free");
-    RESOLVE_OR_ERR(v_id_establish_cred_keytab, "vas_id_establish_cred_keytab");
-    RESOLVE_OR_ERR(v_user_init,        "vas_user_init");
-    RESOLVE_OR_ERR(v_user_free,        "vas_user_free");
-    RESOLVE_OR_ERR(v_group_init,       "vas_group_init");
-    RESOLVE_OR_ERR(v_group_free,       "vas_group_free");
-    RESOLVE_OR_ERR(v_user_is_member,   "vas_user_is_member");
-    RESOLVE_OR_ERR(v_err_get_string,   "vas_err_get_string");
-
-    return 0;
-}
index cd0f5c6df83a8df47464c322cf9fdd2573d164dd..c56ffe030525445e14136525d900d5b3ce73381e 100644 (file)
@@ -573,6 +573,13 @@ sudo_endspent(void)
     return;
 }
 
+/* STUB */
+int
+group_plugin_query(const char *user, const char *group, const struct passwd *pw)
+{
+    return FALSE;
+}
+
 char *
 sudo_getepw(const struct passwd *pw)
 {
index b330b709df1263f4b2ca694b86f337a4f405ab5b..e3097a0db2a635875845a457fe05a77916a4b8c9 100644 (file)
 #include "sudo_plugin_int.h"
 #include <sudo_usage.h>
 
-#ifdef USING_NONUNIX_GROUPS
-# include "nonunix.h"
-#endif
-
 /*
  * Local variables
  */