summaryrefslogtreecommitdiffstats
path: root/testsuite/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/nsswitch')
-rw-r--r--testsuite/nsswitch/Makefile.longarg5
-rw-r--r--testsuite/nsswitch/bigfd.c38
-rw-r--r--testsuite/nsswitch/bigfd.exp28
-rw-r--r--testsuite/nsswitch/domusers.exp38
-rw-r--r--testsuite/nsswitch/envvar.exp282
-rw-r--r--testsuite/nsswitch/finger.exp39
-rw-r--r--testsuite/nsswitch/getent.c150
-rw-r--r--testsuite/nsswitch/getent.exp148
-rw-r--r--testsuite/nsswitch/getent_grent.c100
-rw-r--r--testsuite/nsswitch/getent_pwent.c112
-rwxr-xr-xtestsuite/nsswitch/getent_r.sh35
-rw-r--r--testsuite/nsswitch/getgrent_r.c84
-rw-r--r--testsuite/nsswitch/getgrent_r.exp41
-rw-r--r--testsuite/nsswitch/getgrgid.c57
-rw-r--r--testsuite/nsswitch/getgrgid.exp50
-rw-r--r--testsuite/nsswitch/getgrnam.c51
-rw-r--r--testsuite/nsswitch/getgrnam.exp28
-rw-r--r--testsuite/nsswitch/getpwent_r.c85
-rw-r--r--testsuite/nsswitch/getpwent_r.exp41
-rw-r--r--testsuite/nsswitch/getpwnam.c37
-rw-r--r--testsuite/nsswitch/getpwnam.exp28
-rw-r--r--testsuite/nsswitch/getpwuid.c43
-rw-r--r--testsuite/nsswitch/getpwuid.exp59
-rw-r--r--testsuite/nsswitch/groupmem_dom.exp33
-rw-r--r--testsuite/nsswitch/initgroups.c42
-rw-r--r--testsuite/nsswitch/initgroups.exp37
-rw-r--r--testsuite/nsswitch/login.exp102
-rw-r--r--testsuite/nsswitch/longarg.exp29
-rw-r--r--testsuite/nsswitch/longarg_getgrnam.c41
-rw-r--r--testsuite/nsswitch/longarg_getpwnam.c41
-rw-r--r--testsuite/nsswitch/longarg_utils.h26
-rw-r--r--testsuite/nsswitch/nss_winbind_syms.c63
-rw-r--r--testsuite/nsswitch/nss_winbind_syms.exp42
-rw-r--r--testsuite/nsswitch/pam_winbind_syms.c55
-rw-r--r--testsuite/nsswitch/pam_winbind_syms.exp44
-rw-r--r--testsuite/nsswitch/wbinfo.exp360
36 files changed, 2494 insertions, 0 deletions
diff --git a/testsuite/nsswitch/Makefile.longarg b/testsuite/nsswitch/Makefile.longarg
new file mode 100644
index 0000000..6cc7ef8
--- /dev/null
+++ b/testsuite/nsswitch/Makefile.longarg
@@ -0,0 +1,5 @@
+#
+# Makefile for null tests
+#
+
+longarg_getpwnam: longarg_getpwnam.o \ No newline at end of file
diff --git a/testsuite/nsswitch/bigfd.c b/testsuite/nsswitch/bigfd.c
new file mode 100644
index 0000000..99e402e
--- /dev/null
+++ b/testsuite/nsswitch/bigfd.c
@@ -0,0 +1,38 @@
+/*
+ * Test maximum number of file descriptors winbind daemon can handle
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+ int i;
+
+ while(1) {
+
+ /* Start getpwent until we get an NT user. This way we know we
+ have at least opened a connection to the winbind daemon */
+
+ setpwent();
+
+ while((pw = getpwent()) != NULL) {
+ if (strchr(pw->pw_name, '/') != NULL) {
+ break;
+ }
+ }
+
+ if (pw != NULL) {
+ i++;
+ printf("got pwent handle %d\n", i);
+ } else {
+ printf("winbind daemon not running?\n");
+ exit(1);
+ }
+
+ sleep(1);
+ }
+}
diff --git a/testsuite/nsswitch/bigfd.exp b/testsuite/nsswitch/bigfd.exp
new file mode 100644
index 0000000..62fc9ea
--- /dev/null
+++ b/testsuite/nsswitch/bigfd.exp
@@ -0,0 +1,28 @@
+#
+# @(#) Test maximum number of clients (file descriptors) for winbindd
+#
+
+load_lib util-defs.exp
+
+# Unimplemented - eek!
+
+untested "bigfd"
+return
+
+# Compile bigfd.c
+
+set output [target_compile "$srcdir/$subdir/bigfd.c" \
+ "$srcdir/$subdir/bigfd" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile bigfd"
+ puts $output
+ return
+}
+
+# Run bigfd
+
+set output [util_start "$srcdir/$subdir/bigfd" "" ""]
+puts $output
+
+pass "bigfd"
diff --git a/testsuite/nsswitch/domusers.exp b/testsuite/nsswitch/domusers.exp
new file mode 100644
index 0000000..3b291ab
--- /dev/null
+++ b/testsuite/nsswitch/domusers.exp
@@ -0,0 +1,38 @@
+#
+# @(#) Test that all users are members of the Domain Users group.
+#
+# Note that this isn't necessarily true all the time but you have to
+# explicitly move people out of that group so it should be OK for te
+#
+
+load_lib util-defs.exp
+load_lib $srcdir/lib/nsswitch-config.exp
+
+# Get list of users and stick usernames in a hash
+
+set user_list [util_start "getent" "passwd" ""]
+
+foreach { user } [split $user_list "\n"] {
+ set user_elts [split $user ":"]
+ set users([lindex $user_elts 0]) 1
+}
+
+# Get list of groups
+
+set group_list [util_start "getent" "group" ""]
+
+foreach { group } [split $group_list "\n"] {
+ set group_elts [split $group ":"]
+
+ # Look for domain users group
+
+ if { ![regexp "Domain Users" [lindex $group_elts 0]] } {
+ continue
+ }
+
+ # Check each member of group was found in getent passwd
+
+ foreach { mem } [split [lindex $group_elts 3] ","] {
+ set mems($mem) 1
+ }
+}
diff --git a/testsuite/nsswitch/envvar.exp b/testsuite/nsswitch/envvar.exp
new file mode 100644
index 0000000..134a8b3
--- /dev/null
+++ b/testsuite/nsswitch/envvar.exp
@@ -0,0 +1,282 @@
+#
+# @(#) Test operation of WINBINDD_DOMAIN environment variable
+#
+
+load_lib "util-defs.exp"
+load_lib "$srcdir/lib/nsswitch-config.exp"
+
+#
+# @(#) Test that there is at least one domain user and domain group
+# @(#) in the output of getent passwd and getent group.
+#
+
+# Get list of users and groups
+
+set user_list [util_start "getent passwd"]
+set group_list [util_start "getent group"]
+
+verbose "user list is:\n$user_list"
+verbose "group list is:\n$group_list"
+
+# Check for domain users
+
+set no_dom 0
+
+if { ![regexp "$domain/" $user_list] } {
+ fail "no domain users in getent"
+ set no_dom 1
+}
+
+# Check for domain groups
+
+if { ![regexp "$domain/" $group_list] } {
+ fail "no domain groups in getent group"
+ set no_dom 1
+}
+
+if { $no_dom } {
+ return
+}
+
+#
+# @(#) Check for "leakage" between different domains using the
+# @(#) WINBINDD_DOMAIN environment variable.
+#
+
+verbose "Domain is $domain"
+
+set output [util_start "bin/wbinfo" "-m"]
+verbose "Trusted domains are $output"
+set trusted_domain_list [split $output "\n"]
+
+# Test simple inclusion by setting $WINBINDD_DOMAIN to each trusted domain
+# in turn and checking there are no users/groups from other domains in the
+# output of getent.
+
+set domain_list $trusted_domain_list
+lappend domain_list $domain
+
+foreach { the_domain } $domain_list {
+
+ set env(WINBINDD_DOMAIN) $the_domain
+
+ set user_out [util_start "getent passwd"]
+ set group_out [util_start "getent group"]
+
+ verbose "users in $the_domain:\n$user_out\n"
+ verbose "groups in $the_domain:\n$group_out\n"
+
+ # Users
+
+ set test_desc "users in WINBINDD_DOMAIN $the_domain"
+ set failed 0
+
+ foreach { user } [split $user_out "\n"] {
+ set user_name [lindex [split $user ":"] 0]
+ if { [regexp "/" $user_name] && ![regexp $the_domain $user_name]} {
+ set failed 1
+ }
+ }
+
+ if { $failed } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ # Groups
+
+ set test_desc "groups in WINBINDD_DOMAIN $the_domain"
+ set failed 0
+
+ foreach { group } [split $group_out "\n"] {
+ set group_name [lindex [split $group ":"] 0]
+ if { [regexp "/" $group_name] && ![regexp $the_domain $group_name]} {
+ set failed 1
+ }
+ }
+
+ if { $failed } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+#
+# @(#) Test inclusion of a dummy domain doesn't generate users/groups
+# @(#) from that domain.
+#
+
+set env(WINBINDD_DOMAIN) "asmithee"
+set user_out [util_start "getent passwd"]
+set group_out [util_start "getent group"]
+
+# Users
+
+set test_desc "users in different WINBINDD_DOMAIN"
+if { [regexp $domain $user_out] } {
+ fail $test_desc
+} else {
+ pass $test_desc
+}
+
+# Groups
+
+set test_desc "groups in different WINBINDD_DOMAIN"
+if { [regexp $domain $group_out] } {
+ fail $test_desc
+} else {
+ pass $test_desc
+}
+
+#
+# @(#) Test comma separated inclusion of dummy domain doesn't generate
+# @(#) users/groups in the dummy domain.
+#
+
+foreach { the_domain } $domain_list {
+ set env(WINBINDD_DOMAIN) "$the_domain,asmithee"
+ set user_out [util_start "getent passwd"]
+ set group_out [util_start "getent group"]
+
+ verbose "users in $the_domain:\n$user_out\n"
+ verbose "groups in $the_domain:\n$group_out\n"
+
+ # Users
+
+ set test_desc "users in comma separated WINBINDD_DOMAIN $the_domain"
+ set failed 0
+
+ foreach { user } [split $user_out "\n"] {
+ set user_name [lindex [split $user ":"] 0]
+ if { [regexp "/" $user_name] && ![regexp $the_domain $user_name]} {
+ set failed 1
+ }
+ }
+
+ if { $failed } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ # Groups
+
+ set test_desc "groups in comma separated WINBINDD_DOMAIN $the_domain"
+ set failed 0
+
+ foreach { group } [split $group_out "\n"] {
+ set group_name [lindex [split $group ":"] 0]
+ if { [regexp "/" $group_name] && ![regexp $the_domain $group_name]} {
+ set failed 1
+ }
+ }
+
+ if { $failed } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+#
+# @(#) Test two comma separated dummy domains do not generate any domain
+# @(#) users or groups.
+#
+
+foreach { the_domain } $domain_list {
+
+ set env(WINBINDD_DOMAIN) "moose,asmithee"
+ set user_out [util_start "getent passwd"]
+ set group_out [util_start "getent group"]
+
+ verbose "users in $the_domain:\n$user_out\n"
+ verbose "groups in $the_domain:\n$group_out\n"
+
+ # Users
+
+ set test_desc "users in comma separated invalid WINBINDD_DOMAIN"
+ if { [regexp $the_domain $user_out] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ # Groups
+
+ set test_desc "groups in comma separated invalid WINBINDD_DOMAIN"
+ if { [regexp $the_domain $group_out] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+set env(WINBINDD_DOMAIN) ""
+
+#
+# @(#) Test _NO_WINBINDD doesn't return any domain users or groups
+#
+
+set env(_NO_WINBINDD) "1"
+set user_out [util_start "getent passwd"]
+set group_out [util_start "getent group"]
+
+verbose "users with _NO_WINBINDD:\n$user_out\n"
+verbose "groups with _NO_WINBINDD:\n$group_out\n"
+
+foreach { the_domain } $domain_list {
+
+ # Users
+
+ set test_desc "users found with _NO_WINBINDD environment variable set"
+ if { [regexp $the_domain $user_out] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ # Groups
+
+ set test_desc "groups found with _NO_WINBINDD environment variable set"
+ if { [regexp $the_domain $group_out] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+# Unset _NO_WINBINDD and make sure everything still works
+
+unset env(_NO_WINBINDD)
+
+set user_out [util_start "getent passwd"]
+set group_out [util_start "getent group"]
+
+verbose "users with _NO_WINBINDD unset:\n$user_out\n"
+verbose "groups with _NO_WINBINDD unset:\n$group_out\n"
+
+# Users
+
+set test_desc "no users found with _NO_WINBINDD environment variable set"
+if { $user_out != $user_list } {
+ fail $test_desc
+} else {
+ pass $test_desc
+}
+
+# Groups
+
+set test_desc "no groups found with _NO_WINBINDD environment variable set"
+if { $group_out != $group_list } {
+ fail $test_desc
+} else {
+ pass $test_desc
+}
+
+# Make sure we unset the environment vars so we don't cause subsequent tests
+# any grief.
+
+catch { unset env(WINBINDD_DOMAIN) } tmp
+catch { unset env(_NO_WINBINDD) } tmp
diff --git a/testsuite/nsswitch/finger.exp b/testsuite/nsswitch/finger.exp
new file mode 100644
index 0000000..36bab8e
--- /dev/null
+++ b/testsuite/nsswitch/finger.exp
@@ -0,0 +1,39 @@
+#
+# @(#) Test default domain users resolve using the finger command
+#
+
+load_lib util-defs.exp
+
+set output [util_start "bin/wbinfo" "-u"]
+if { [regexp "Error" $output] } {
+ fail "error running wbinfo"
+ return
+}
+
+set user_list [split $output "\n"]
+
+# Look up all users using finger -m. This should test getpwnam()
+
+foreach { user } $user_list {
+ set output [util_start "finger" "-m \"$user\"" "" "no such user"]
+ verbose $output
+
+ if { [regexp "no such user" $output] } {
+ fail "finger -m $user"
+ } else {
+ pass "finger -m $user"
+ }
+}
+
+# Run finger without the -m to also test set/get/endpwent()
+
+foreach { user } $user_list {
+ set output [util_start "finger" "\"$user\""]
+ verbose $output
+
+ if { [regexp "no such user" $output] } {
+ fail "finger $user"
+ } else {
+ pass "finger $user"
+ }
+}
diff --git a/testsuite/nsswitch/getent.c b/testsuite/nsswitch/getent.c
new file mode 100644
index 0000000..5babfc5
--- /dev/null
+++ b/testsuite/nsswitch/getent.c
@@ -0,0 +1,150 @@
+/* Cut down version of getent which only returns passwd and group database
+ entries and seems to compile on most systems without too much fuss.
+ Original copyright notice below. */
+
+/* Copyright (c) 1998, 1999, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 3 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
+
+group_keys (int number, char *key[])
+{
+ int result = 0;
+ int i;
+
+ for (i = 0; i < number; ++i)
+ {
+ struct group *grp;
+
+ if (isdigit (key[i][0]))
+ grp = getgrgid (atol (key[i]));
+ else
+ grp = getgrnam (key[i]);
+
+ if (grp == NULL)
+ result = 2;
+ else
+ print_group (grp);
+ }
+
+ return result;
+}
+
+passwd_keys (int number, char *key[])
+{
+ int result = 0;
+ int i;
+
+ for (i = 0; i < number; ++i)
+ {
+ struct passwd *pwd;
+
+ if (isdigit (key[i][0]))
+ pwd = getpwuid (atol (key[i]));
+ else
+ pwd = getpwnam (key[i]);
+
+ if (pwd == NULL)
+ result = 2;
+ else
+ print_passwd (pwd);
+ }
+
+ return result;
+}
+
+print_group (struct group *grp)
+{
+ unsigned int i = 0;
+
+ printf ("%s:%s:%ld:", grp->gr_name ? grp->gr_name : "",
+ grp->gr_passwd ? grp->gr_passwd : "",
+ (unsigned long)grp->gr_gid);
+
+ while (grp->gr_mem[i] != NULL)
+ {
+ fputs (grp->gr_mem[i], stdout);
+ ++i;
+ if (grp->gr_mem[i] != NULL)
+ fputs (",", stdout);
+ }
+ fputs ("\n", stdout);
+}
+
+print_passwd (struct passwd *pwd)
+{
+ printf ("%s:%s:%ld:%ld:%s:%s:%s\n",
+ pwd->pw_name ? pwd->pw_name : "",
+ pwd->pw_passwd ? pwd->pw_passwd : "",
+ (unsigned long)pwd->pw_uid,
+ (unsigned long)pwd->pw_gid,
+ pwd->pw_gecos ? pwd->pw_gecos : "",
+ pwd->pw_dir ? pwd->pw_dir : "",
+ pwd->pw_shell ? pwd->pw_shell : "");
+}
+
+int main(int argc, char **argv)
+{
+ switch(argv[1][0])
+ {
+ case 'g': /* group */
+ if (strcmp (argv[1], "group") == 0)
+ {
+ if (argc == 2)
+ {
+ struct group *grp;
+
+ setgrent ();
+ while ((grp = getgrent()) != NULL)
+ print_group (grp);
+ endgrent ();
+ }
+ else
+ return group_keys (argc - 2, &argv[2]);
+ }
+ else
+ goto error;
+ break;
+
+ case 'p': /* passwd, protocols */
+ if (strcmp (argv[1], "passwd") == 0)
+ {
+ if (argc == 2)
+ {
+ struct passwd *pwd;
+
+ setpwent ();
+ while ((pwd = getpwent()) != NULL)
+ print_passwd (pwd);
+ endpwent ();
+ }
+ else
+ return passwd_keys (argc - 2, &argv[2]);
+ }
+ else
+ goto error;
+ break;
+ default:
+ error:
+ fprintf (stderr, "Unknown database: %s\n", argv[1]);
+ return 1;
+ }
+ return 0;
+}
diff --git a/testsuite/nsswitch/getent.exp b/testsuite/nsswitch/getent.exp
new file mode 100644
index 0000000..72bf2ea
--- /dev/null
+++ b/testsuite/nsswitch/getent.exp
@@ -0,0 +1,148 @@
+#
+# @(#) Test the getent command returns domain/local users and groups
+#
+
+load_lib util-defs.exp
+load_lib compile.exp
+load_lib $srcdir/lib/nsswitch-config.exp
+
+#
+# @(#) Test getent passwd returns domain users
+#
+
+set wbinfo_output [util_start "bin/wbinfo" "-u"]
+set getent_output [util_start "getent" "passwd" ""]
+
+if { ![regexp "$domain/" $getent_output] } {
+ fail "no domain users in getent passwd"
+ return
+}
+
+if { [regexp "Error" $wbinfo_output] } {
+ fail "wbinfo -u failed"
+ return
+}
+
+#
+# @(#) Test each user in the output of wbinfo is also in the output of
+# @(#) getent.
+#
+
+# Test wbinfo user names are in getent user names
+
+foreach { user } [split $wbinfo_output "\n"] {
+
+ verbose "looking for $user"
+
+ set test_desc "getent passwd does not contain $user"
+
+ if { ![regexp "$user" $getent_output] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+# Test getent user names are in wbinfo user names
+
+foreach { user } [split $getent_output "\n"] {
+
+ set user_info [split $user ":"]
+ set username [lindex $user_info 0]
+
+ if { [regexp {^[^/]+/} $username] } {
+
+ set test_desc "wbinfo -u does not contain $username"
+
+ if { ![regexp "$username" $wbinfo_output] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+ } else {
+ verbose "ignoring non-domain user $username"
+ }
+}
+
+#
+# @(#) Test each group in the output of wbinfo is also in the output of
+# @(#) getent.
+#
+
+set wbinfo_output [util_start "bin/wbinfo" "-g"]
+set getent_output [util_start "getent" "group" ""]
+
+if { ![regexp "$domain/" $getent_output] } {
+ fail "no domain groups in getent passwd"
+ return
+}
+
+if { [regexp "Error" $wbinfo_output] } {
+ fail "wbinfo -g failed"
+ return
+}
+
+# Test wbinfo group names are in getent group names
+
+foreach { group } [split $wbinfo_output "\n"] {
+
+ verbose "looking for $group"
+
+ set test_desc "getent group does not contain $group"
+
+ if { ![regexp "$group" $getent_output] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+# Test getent group names are in wbinfo group names
+
+foreach { group } [split $getent_output "\n"] {
+
+ set group_info [split $group ":"]
+ set groupname [lindex $group_info 0]
+
+ if { [regexp {^[^/]+/} $groupname] } {
+
+ set test_desc "wbinfo -g does not contain $groupname"
+
+ if { ![regexp "$groupname" $wbinfo_output] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+ } else {
+ verbose "ignoring non-domain group $groupname"
+ }
+}
+
+#
+# @(#) Test out of order and repeat calls of pwent functions
+# @(#) Test out of order and repeat calls of grent functions
+#
+
+set getent_tests [list \
+ { "out of order pwent operations" "getent_pwent" } \
+ { "out of order grent operations" "getent_grent" } \
+ ]
+
+# Compile and run each test
+
+foreach { test } $getent_tests {
+ set test_desc [lindex $test 0]
+ set test_file [lindex $test 1]
+
+ simple_compile $test_file
+ set output [util_start "$srcdir/$subdir/$test_file" ]
+
+ if { [regexp "PASS" $output] } {
+ pass $test_desc
+ file delete "$srcdir/$subdir/$test_file" "$srcdir/$subdir/$test_file.o"
+ } else {
+ fail $test_desc
+ puts $output
+ }
+
+}
diff --git a/testsuite/nsswitch/getent_grent.c b/testsuite/nsswitch/getent_grent.c
new file mode 100644
index 0000000..4660b6a
--- /dev/null
+++ b/testsuite/nsswitch/getent_grent.c
@@ -0,0 +1,100 @@
+/* Test out of order operations with {set,get,end}grent */
+
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Security context tests
+ Copyright (C) Tim Potter 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <grp.h>
+
+int main (int argc, char **argv)
+{
+ struct group *gr;
+ int found = 0;
+ int num_users, i;
+
+ /* Test getgrent() without setgrent() */
+
+ for (i = 0; i < 100; i++) {
+ gr = getgrent();
+
+ /* This is supposed to work */
+
+#if 0
+ if (gr != NULL) {
+ printf("FAIL: getgrent() with no setgrent()\n");
+ return 1;
+ }
+#endif
+ }
+
+ /* Work out how many user till first domain group */
+
+ num_users = 0;
+ setgrent();
+
+ while (1) {
+ gr = getgrent();
+ num_users++;
+
+ if (gr == NULL) break;
+
+ if (strchr(gr->gr_name, '/')) {
+ found = 1;
+ break;
+ }
+
+ }
+
+ if (!found) {
+ printf("FAIL: could not find any domain groups\n");
+ return 1;
+ }
+
+ /* Test stopping getgrent in the middle of a set of users */
+
+ endgrent();
+
+ /* Test setgrent() without any getgrent() calls */
+
+ setgrent();
+
+ for (i = 0; i < (num_users - 1); i++) {
+ getgrent();
+ }
+
+ endgrent();
+
+ /* Test lots of setgrent() calls */
+
+ for (i = 0; i < 100; i++) {
+ setgrent();
+ }
+
+ /* Test lots of endgrent() calls */
+
+ for (i = 0; i < 100; i++) {
+ endgrent();
+ }
+
+ /* Everything's cool */
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getent_pwent.c b/testsuite/nsswitch/getent_pwent.c
new file mode 100644
index 0000000..14200b0
--- /dev/null
+++ b/testsuite/nsswitch/getent_pwent.c
@@ -0,0 +1,112 @@
+/* Test out of order operations with {set,get,end}pwent */
+
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Security context tests
+ Copyright (C) Tim Potter 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <pwd.h>
+
+int main (int argc, char **argv)
+{
+ struct passwd *pw;
+ int found = 0;
+ int num_users, i;
+
+ /* Test getpwent() without setpwent() */
+
+ for (i = 0; i < 100; i++) {
+ pw = getpwent();
+
+ /* This is supposed to work */
+
+#if 0
+ if (pw != NULL) {
+ printf("FAIL: getpwent() with no setpwent()\n");
+ return 1;
+ }
+#endif
+ }
+
+ /* Work out how many user till first domain user */
+
+ num_users = 0;
+ setpwent();
+
+ while (1) {
+ pw = getpwent();
+ num_users++;
+
+ if (pw == NULL) break;
+
+ if (strchr(pw->pw_name, '/')) {
+ found = 1;
+ break;
+ }
+
+ }
+
+ if (!found) {
+ printf("FAIL: could not find any domain users\n");
+ return 1;
+ }
+
+ /* Test stopping getpwent in the middle of a set of users */
+
+ endpwent();
+
+ /* Test setpwent() without any getpwent() calls */
+
+ setpwent();
+
+ for (i = 0; i < (num_users - 1); i++) {
+ getpwent();
+ }
+
+ endpwent();
+
+ /* Test lots of setpwent() calls */
+
+ setpwent();
+
+ for (i = 0; i < (num_users - 1); i++) {
+ getpwent();
+ }
+
+ for (i = 0; i < 100; i++) {
+ setpwent();
+ }
+
+ /* Test lots of endpwent() calls */
+
+ setpwent();
+
+ for (i = 0; i < (num_users - 1); i++) {
+ getpwent();
+ }
+
+ for (i = 0; i < 100; i++) {
+ endpwent();
+ }
+
+ /* Everything's cool */
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getent_r.sh b/testsuite/nsswitch/getent_r.sh
new file mode 100755
index 0000000..75dc603
--- /dev/null
+++ b/testsuite/nsswitch/getent_r.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Verify test output. Basically we check to see if all the files generated
+# in /tmp by the get{pw,gr}ent_r.c and program are identical. If there is
+# some problem with the re-entrancy of the code then the information in the
+# two files will be different.
+#
+
+TYPE=$1
+ID=$2
+FILES="/tmp/${TYPE}_r-${ID}.out-*"
+
+# Sort files
+
+for file in $FILES; do
+ cat $file | sort > $file.sorted
+done
+
+# Diff files
+
+SORTED="/tmp/${TYPE}_r-${ID}.out-*.sorted"
+failed=0
+
+for file1 in $SORTED; do
+ for file2 in $SORTED; do
+ if [ $file1 != $file2 ]; then
+ diff $file1 $file2
+ fi
+ done
+done
+
+# Clean up
+
+rm -f $SORTED
+
diff --git a/testsuite/nsswitch/getgrent_r.c b/testsuite/nsswitch/getgrent_r.c
new file mode 100644
index 0000000..883c897
--- /dev/null
+++ b/testsuite/nsswitch/getgrent_r.c
@@ -0,0 +1,84 @@
+/*
+ * Use set/get/endgrent calls from two processes to iterate over the
+ * password database. This checks the multithreaded stuff works.
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wait.h>
+
+void dump_grent(char *id)
+{
+ struct group *gr;
+ char fname[255];
+ FILE *fptr;
+
+ /* Open results file */
+
+ sprintf(fname, "/tmp/getgrent_r-%s.out-%d", id, getpid());
+
+ if ((fptr = fopen(fname, "w")) == NULL) {
+ fprintf(stderr, "ERROR: could not open file %s: %s\n", fname,
+ sys_errlist[errno]);
+ return;
+ }
+
+ /* Dump group database */
+
+ setgrent();
+
+ while((gr = getgrent()) != NULL) {
+ fprintf(fptr,"%s:%s:%d\n", gr->gr_name, gr->gr_passwd,
+ gr->gr_gid);
+ }
+
+ endgrent();
+
+ /* Close results file */
+
+ fclose(fptr);
+}
+
+int main(int argc, char **argv)
+{
+ pid_t pid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: must specify output file identifier\n");
+ return 1;
+ }
+
+ /* Fork child process */
+
+ if ((pid = fork()) == -1) {
+ printf("ERROR: unable to fork\n");
+ return 1;
+ }
+
+ /* Handle test case */
+
+ if (pid > 0) {
+ int status;
+
+ /* Parent */
+
+ dump_grent(argv[1]);
+ wait(&status);
+
+ } else {
+
+ /* Child */
+
+ dump_grent(argv[1]);
+ return 0;
+ }
+
+ printf("PASS: run getgrent_r.c\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getgrent_r.exp b/testsuite/nsswitch/getgrent_r.exp
new file mode 100644
index 0000000..c03237c
--- /dev/null
+++ b/testsuite/nsswitch/getgrent_r.exp
@@ -0,0 +1,41 @@
+#
+# @(#) Test multiple threads can enumerate groups correctly
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/lib/nsswitch-config.exp"
+
+# Compile getgrent_r.c
+
+set output [target_compile "$srcdir/$subdir/getgrent_r.c" \
+ "$srcdir/$subdir/getgrent_r" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getgrent_r"
+ puts $output
+ return
+}
+
+# Clean up output from previous tests
+
+set pid [pid]
+file delete [glob -nocomplain "/tmp/getgrent_r-$pid.out-*"]
+
+# Run test proggy
+
+set output [util_start "$srcdir/$subdir/getgrent_r" "$pid" ""]
+if {![regexp "^PASS:" $output]} {
+ perror "run getgrent_r"
+ puts $output
+ return -1
+}
+
+# Sort and compare output
+
+set output [util_start "$srcdir/$subdir/getent_r.sh" "getgrent $pid" ""]
+if {$output == ""} {
+ pass "getgrent_r"
+} else {
+ fail "getgrent_r"
+ puts $output
+}
diff --git a/testsuite/nsswitch/getgrgid.c b/testsuite/nsswitch/getgrgid.c
new file mode 100644
index 0000000..947dd0a
--- /dev/null
+++ b/testsuite/nsswitch/getgrgid.c
@@ -0,0 +1,57 @@
+/*
+ * Lookup a group by gid.
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct group *gr;
+ gid_t gid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ if ((gid = atoi(argv[1])) == 0) {
+ printf("ERROR: invalid gid specified\n");
+ exit(1);
+ }
+
+ /* Do getgrgid() */
+
+ if ((gr = getgrgid(gid)) == NULL) {
+ printf("FAIL: gid %d does not exist\n", gid);
+ exit(1);
+ }
+
+ /* Print group info */
+
+ printf("PASS: gid %d exists\n", gid);
+ printf("gr_name = %s\n", gr->gr_name);
+ printf("gr_passwd = %s\n", gr->gr_passwd);
+ printf("gr_gid = %d\n", gr->gr_gid);
+
+ /* Group membership */
+
+ if (gr->gr_mem != NULL) {
+ int i = 0;
+
+ printf("gr_mem = ");
+ while(gr->gr_mem[i] != NULL) {
+ printf("%s", gr->gr_mem[i]);
+ i++;
+ if (gr->gr_mem != NULL) {
+ printf(",");
+ }
+ }
+ printf("\n");
+ }
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getgrgid.exp b/testsuite/nsswitch/getgrgid.exp
new file mode 100644
index 0000000..c53749f
--- /dev/null
+++ b/testsuite/nsswitch/getgrgid.exp
@@ -0,0 +1,50 @@
+#
+# @(#) Test reverse lookup of group ids from getent match getgrgid() output
+#
+
+load_lib util-defs.exp
+load_lib compile.exp
+
+# Compile getgruid.c
+
+simple_compile "getgrgid"
+
+# Get list of gids using getent
+
+set output [util_start "getent" "group" ""]
+set got_entries 0
+
+verbose $output
+
+foreach {line} [split $output "\n"] {
+
+ # Process user
+
+ set grp_entry [split $line ":"]
+ set group [lindex $grp_entry 0]
+
+ if {[regexp {^[^/]+/} $group]} {
+
+ set got_entries 1
+
+ # Only lookup winbindd users
+
+ set gid [lindex $grp_entry 2]
+
+ # Test lookup of gid succeeds
+
+ set output [util_start "$srcdir/$subdir/getgrgid" "$gid" ""]
+ verbose $output
+
+ if {[regexp "PASS:" $output]} {
+ pass "getgrgid $gid ($group)"
+ } else {
+ fail "getgrgid $gid ($group)"
+ }
+ }
+
+}
+
+if {!$got_entries} {
+ perror "No domain groups returned from getent"
+}
diff --git a/testsuite/nsswitch/getgrnam.c b/testsuite/nsswitch/getgrnam.c
new file mode 100644
index 0000000..8ab4046
--- /dev/null
+++ b/testsuite/nsswitch/getgrnam.c
@@ -0,0 +1,51 @@
+/*
+ * Lookup a group by name
+ */
+
+#include <stdio.h>
+#include <grp.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct group *gr;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ /* Do getgrnam() */
+
+ if ((gr = getgrnam(argv[1])) == NULL) {
+ printf("FAIL: group %s does not exist\n", argv[1]);
+ exit(1);
+ }
+
+ /* Print group info */
+
+ printf("PASS: group %s exists\n", argv[1]);
+ printf("gr_name = %s\n", gr->gr_name);
+ printf("gr_passwd = %s\n", gr->gr_passwd);
+ printf("gr_gid = %d\n", gr->gr_gid);
+
+ /* Group membership */
+
+ if (gr->gr_mem != NULL) {
+ int i = 0;
+
+ printf("gr_mem = ");
+ while(gr->gr_mem[i] != NULL) {
+ printf("%s", gr->gr_mem[i]);
+ i++;
+ if (gr->gr_mem != NULL) {
+ printf(",");
+ }
+ }
+ printf("\n");
+ }
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getgrnam.exp b/testsuite/nsswitch/getgrnam.exp
new file mode 100644
index 0000000..92c5b76
--- /dev/null
+++ b/testsuite/nsswitch/getgrnam.exp
@@ -0,0 +1,28 @@
+#
+# @(#) Test domain groups resolve using getgrnam()
+#
+
+load_lib "util-defs.exp"
+load_lib "compile.exp"
+
+# Compile getgrnam.c
+
+simple_compile "getgrnam"
+
+# Test domain groups
+
+set group_list [split [util_start "bin/wbinfo" "-g"] "\n"]
+
+verbose $group_list
+
+foreach {group} $group_list {
+ set output [util_start "$srcdir/$subdir/getgrnam" "\"$group\"" ""]
+
+ verbose $output
+
+ if {[regexp "PASS:" $output]} {
+ pass "getgrnam $group"
+ } else {
+ fail "getgrnam $group"
+ }
+}
diff --git a/testsuite/nsswitch/getpwent_r.c b/testsuite/nsswitch/getpwent_r.c
new file mode 100644
index 0000000..5e77491
--- /dev/null
+++ b/testsuite/nsswitch/getpwent_r.c
@@ -0,0 +1,85 @@
+/*
+ * Use set/get/endpwent calls from two processes to iterate over the
+ * password database. This checks the multithreaded stuff works.
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wait.h>
+
+void dump_pwent(char *id)
+{
+ struct passwd *pw;
+ char fname[255];
+ FILE *fptr;
+
+ /* Open results file */
+
+ sprintf(fname, "/tmp/getpwent_r-%s.out-%d", id, getpid());
+
+ if ((fptr = fopen(fname, "w")) == 0) {
+ fprintf(stderr, "ERROR: could not open file %s: %s\n", fname,
+ sys_errlist[errno]);
+ return;
+ }
+
+ /* Dump passwd database */
+
+ setpwent();
+
+ while((pw = getpwent()) != NULL) {
+ fprintf(fptr,"%s:%s:%s:%d:%d\n", pw->pw_name, pw->pw_passwd,
+ pw->pw_gecos, pw->pw_uid, pw->pw_gid);
+ }
+
+ endpwent();
+
+ /* Close results file */
+
+ fclose(fptr);
+}
+
+#define NUM_FORKS 2
+
+int main(int argc, char **argv)
+{
+ pid_t pids[NUM_FORKS];
+ int i, status;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: must specify output file identifier\n");
+ return 1;
+ }
+
+ for(i = 0; i < NUM_FORKS; i++) {
+
+ /* Fork off lots */
+
+ if ((pids[i] = fork()) == -1) {
+ perror("fork");
+ return 1;
+ }
+
+ /* Child does tests */
+
+ if (pids[i] == 0) {
+ dump_pwent(argv[1]);
+ return 0;
+ }
+ }
+
+ /* Wait for everyone to finish */
+
+ for (i = 0; i < NUM_FORKS; i++) {
+ waitpid(pids[i], &status, 0);
+ }
+
+ printf("PASS: getpwent_r.c\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/getpwent_r.exp b/testsuite/nsswitch/getpwent_r.exp
new file mode 100644
index 0000000..95c155d
--- /dev/null
+++ b/testsuite/nsswitch/getpwent_r.exp
@@ -0,0 +1,41 @@
+#
+# @(#) Test multiple threads can enumerate users correctly
+#
+
+load_lib util-defs.exp
+load_lib "$srcdir/lib/nsswitch-config.exp"
+
+# Compile getpwent_r.c
+
+set output [target_compile "$srcdir/$subdir/getpwent_r.c" \
+ "$srcdir/$subdir/getpwent_r" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getpwent_r"
+ puts $output
+ fail ""
+}
+
+# Clean up output from previous tests
+
+set pid [pid]
+file delete [glob -nocomplain "/tmp/getpwent_r-$pid.out-*"]
+
+# Run test proggy
+
+set output [util_start "$srcdir/$subdir/getpwent_r" "$pid" ""]
+if {![regexp "^PASS:" $output]} {
+ perror "run getpwent_r"
+ puts $output
+ return -1
+}
+
+# Sort and compare output
+
+set output [util_start "$srcdir/$subdir/getent_r.sh" "getpwent $pid" ""]
+if {$output == ""} {
+ pass "getpwent_r"
+} else {
+ fail "getpwent_r"
+ puts $output
+}
diff --git a/testsuite/nsswitch/getpwnam.c b/testsuite/nsswitch/getpwnam.c
new file mode 100644
index 0000000..e7dd291
--- /dev/null
+++ b/testsuite/nsswitch/getpwnam.c
@@ -0,0 +1,37 @@
+/*
+ * Lookup a user by name
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ /* Do getpwnam() */
+
+ if ((pw = getpwnam(argv[1])) == NULL) {
+ printf("FAIL: user %s does not exist\n", argv[1]);
+ exit(1);
+ }
+
+ printf("PASS: user %s exists\n", argv[1]);
+ printf("pw_name = %s\n", pw->pw_name);
+ printf("pw_passwd = %s\n", pw->pw_passwd);
+ printf("pw_uid = %d\n", pw->pw_uid);
+ printf("pw_gid = %d\n", pw->pw_gid);
+ printf("pw_gecos = %s\n", pw->pw_gecos);
+ printf("pw_dir = %s\n", pw->pw_dir);
+ printf("pw_shell = %s\n", pw->pw_shell);
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getpwnam.exp b/testsuite/nsswitch/getpwnam.exp
new file mode 100644
index 0000000..5f6b234
--- /dev/null
+++ b/testsuite/nsswitch/getpwnam.exp
@@ -0,0 +1,28 @@
+#
+# @(#) Test domain users resolve using getpwnam()
+#
+
+load_lib util-defs.exp
+load_lib "compile.exp"
+
+# Compile getpwnam.c
+
+simple_compile "getpwnam"
+
+# Test domain users
+
+set user_list [split [util_start "bin/wbinfo" "-u"] "\n"]
+
+verbose $user_list
+
+foreach { user } $user_list {
+ set output [util_start "$srcdir/$subdir/getpwnam" "\"$user\"" ""]
+
+ verbose $output
+
+ if {[regexp "PASS:" $output]} {
+ pass "getpwnam $user"
+ } else {
+ fail "getpwnam $user"
+ }
+}
diff --git a/testsuite/nsswitch/getpwuid.c b/testsuite/nsswitch/getpwuid.c
new file mode 100644
index 0000000..3f364df
--- /dev/null
+++ b/testsuite/nsswitch/getpwuid.c
@@ -0,0 +1,43 @@
+/*
+ * Lookup a user by uid.
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ struct passwd *pw;
+ uid_t uid;
+
+ /* Check args */
+
+ if (argc != 2) {
+ printf("ERROR: no arg specified\n");
+ exit(1);
+ }
+
+ if ((uid = atoi(argv[1])) == 0) {
+ printf("ERROR: invalid uid specified\n");
+ exit(1);
+ }
+
+ /* Do getpwuid() */
+
+ if ((pw = getpwuid(uid)) == NULL) {
+ printf("FAIL: uid %d does not exist\n", uid);
+ exit(1);
+ }
+
+ printf("PASS: uid %d exists\n", uid);
+ printf("pw_name = %s\n", pw->pw_name);
+ printf("pw_passwd = %s\n", pw->pw_passwd);
+ printf("pw_uid = %d\n", pw->pw_uid);
+ printf("pw_gid = %d\n", pw->pw_gid);
+ printf("pw_gecos = %s\n", pw->pw_gecos);
+ printf("pw_dir = %s\n", pw->pw_dir);
+ printf("pw_shell = %s\n", pw->pw_shell);
+
+ exit(0);
+}
diff --git a/testsuite/nsswitch/getpwuid.exp b/testsuite/nsswitch/getpwuid.exp
new file mode 100644
index 0000000..be6a01c
--- /dev/null
+++ b/testsuite/nsswitch/getpwuid.exp
@@ -0,0 +1,59 @@
+#
+# @(#) Test reverse lookup of user ids from getent match getpwuid() output
+#
+
+load_lib util-defs.exp
+
+# Compile getpwuid.c
+
+set output [target_compile "$srcdir/$subdir/getpwuid.c" \
+ "$srcdir/$subdir/getpwuid" executable {additional_flags="-g"}]
+
+if {$output != ""} {
+ perror "compile getpwuid"
+ puts $output
+ return
+}
+
+# Get list of uids using getent
+
+set output [util_start "getent" "passwd" ""]
+set got_entries 0
+
+verbose $output
+
+foreach {line} [split $output "\n"] {
+
+ # Process user
+
+ set pwd_entry [split $line ":"]
+ set user [lindex $pwd_entry 0]
+
+ if {[regexp {^[^/]+/} $user]} {
+
+ set got_entries 1
+
+ # Only lookup winbindd users
+
+ set uid [lindex $pwd_entry 2]
+ set gid [lindex $pwd_entry 3]
+
+ # Test lookup of uid succeeds
+
+ set output [util_start "$srcdir/$subdir/getpwuid" "$uid" ""]
+
+ verbose $output
+
+ set test_desc "getpwuid $uid ($user)"
+
+ if {[regexp "PASS:" $output]} {
+ pass $test_desc
+ } else {
+ fail $test_desc
+ }
+ }
+}
+
+if {!$got_entries} {
+ perror "No domain users returned from getent"
+}
diff --git a/testsuite/nsswitch/groupmem_dom.exp b/testsuite/nsswitch/groupmem_dom.exp
new file mode 100644
index 0000000..3ba34bb
--- /dev/null
+++ b/testsuite/nsswitch/groupmem_dom.exp
@@ -0,0 +1,33 @@
+#
+# @(#) Test whether members of domain groups all have domain names
+#
+
+load_lib util-defs.exp
+
+set group_list [split [util_start "getent group" ""] "\n"]
+set failed 0
+
+foreach { group } $group_list {
+ set group_entry [split $group ":"]
+
+ set group_name [lindex $group_entry 0]
+ set group_members [split [lindex $group_entry 3] ","]
+
+ if { [regexp {^[^/]+/} $group_name] } {
+
+ verbose "group $group_name has members $group_members"
+
+ foreach { user } $group_members {
+ if { ![regexp {^[^/]+/} $user] } {
+ fail "group $group has non-domain user $user"
+ set failed 1
+ }
+ }
+ } else {
+ verbose "ignoring non-domain group $group_name"
+ }
+}
+
+if { !$failed } {
+ pass "domain groups contain only domain members"
+}
diff --git a/testsuite/nsswitch/initgroups.c b/testsuite/nsswitch/initgroups.c
new file mode 100644
index 0000000..b7d9c50
--- /dev/null
+++ b/testsuite/nsswitch/initgroups.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv)
+{
+ int result, ngroups, i;
+ gid_t *groups;
+ struct passwd *pw;
+
+ if (!(pw = getpwnam(argv[1]))) {
+ printf("FAIL: no passwd entry for %s\n", argv[1]);
+ return 1;
+ }
+
+ result = initgroups(argv[1], pw->pw_gid);
+
+ if (result == -1) {
+ printf("FAIL");
+ return 1;
+ }
+
+ ngroups = getgroups(0, NULL);
+
+ groups = (gid_t *)malloc(sizeof(gid_t) * ngroups);
+ ngroups = getgroups(ngroups, groups);
+
+ printf("%s is a member of groups:\n", argv[1]);
+
+ for (i = 0; i < ngroups; i++) {
+ struct group *grp;
+
+ grp = getgrgid(groups[i]);
+
+ printf("%d (%s)\n", groups[i], grp ? grp->gr_name : "?");
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/testsuite/nsswitch/initgroups.exp b/testsuite/nsswitch/initgroups.exp
new file mode 100644
index 0000000..ab21bcc
--- /dev/null
+++ b/testsuite/nsswitch/initgroups.exp
@@ -0,0 +1,37 @@
+#
+# @(#) Test initgroups function
+#
+
+load_lib util-defs.exp
+load_lib compile.exp
+
+if { [util_start "id -u"] != 0 } {
+ set test_desc "must be userid 0 to run"
+ note $test_desc
+ untested $test_desc
+ return
+}
+
+# Compile test program
+
+simple_compile "initgroups"
+
+# Test domain users
+
+set user_list [split [util_start "bin/wbinfo" "-u"] "\n"]
+
+verbose $user_list
+
+foreach { user } $user_list {
+ set output [util_start "$srcdir/$subdir/initgroups" "\"$user\"" ""]
+
+ verbose $output
+
+ set test_desc "initgroups $user"
+
+ if { [regexp "PASS" $output] } {
+ pass $test_desc
+ } else {
+ fail $test_desc
+ }
+}
diff --git a/testsuite/nsswitch/login.exp b/testsuite/nsswitch/login.exp
new file mode 100644
index 0000000..c2bb0e5
--- /dev/null
+++ b/testsuite/nsswitch/login.exp
@@ -0,0 +1,102 @@
+#
+# @(#) Test logins using pam_winbind.so module using telnet
+#
+
+load_lib util-defs.exp
+load_lib nsswitch-config.exp
+
+#
+# @(#) Test user can login
+#
+
+spawn telnet localhost
+
+set test_desc "telnet localhost (login)"
+
+expect {
+ "login:" { }
+ timeout { fail "timed out in $test_desc"; return }
+ eof { fail "end of file in $test_desc"; return }
+}
+
+send "$domain/$USER\r"
+
+set test_desc "telnet localhost (password)"
+
+expect {
+ "Password:" { }
+ timeout { fail "timed out in $test_desc"; return }
+ eof { fail "end of file in $test_desc"; return }
+}
+
+send "$PASSWORD\r"
+
+expect {
+ "$ " { }
+ "Login incorrect" { fail "login incorrect"; return }
+ timeout { fail "timed out in $test_desc"; return }
+ eof { fail "end of file in $test_desc"; return }
+}
+
+pass "login $domain/$USER"
+
+#
+# @(#) Check supplementary group membership
+#
+
+set test_desc "supplementary groups"
+
+# Get list of groups
+
+send "id -G\r"
+
+expect {
+ -re "((\[0-9]+ )*\[0-9]+\r)" { exp_continue; }
+ "$ " { }
+ timeout { fail "timed out in $test_desc"; return }
+ eof { fail "end of file in $test_desc"; return }
+}
+
+set groups $expect_out(1,string)
+set wb_groups [util_start "bin/wbinfo" "-r $domain/$USER"]
+
+verbose "id groups are $groups"
+verbose "wbinfo groups are $wb_groups"
+
+# Check all groups from id are in wbinfo and vice-versa
+
+set failed 0
+
+foreach { group } $groups {
+ set got_group 0
+ foreach { wb_group } $wb_groups {
+ if { $wb_group == $group } {
+ set got_group 1
+ break
+ }
+ }
+
+ if { !$got_group } {
+ fail "group $group not in output of wbinfo -r"
+ set failed 1
+ }
+}
+
+foreach { wb_group } $wb_groups {
+ set got_group 0
+ foreach { group } $groups {
+ if { $group == $wb_group } {
+ set got_group 1
+ break
+ }
+ }
+
+ if { !$got_group } {
+ fail "group $group not in output of id -G"
+ set failed 1
+ }
+}
+
+if { !$failed } {
+ pass "id/wbinfo groups match"
+}
diff --git a/testsuite/nsswitch/longarg.exp b/testsuite/nsswitch/longarg.exp
new file mode 100644
index 0000000..e1d0eda
--- /dev/null
+++ b/testsuite/nsswitch/longarg.exp
@@ -0,0 +1,29 @@
+#
+# @(#) Test handling of long arguments passed to various nss functions
+#
+
+load_lib compile.exp
+load_lib util-defs.exp
+
+# Run tests from C source files
+
+set longarg_tests [list \
+ { "long arg to getpwnam()" "longarg_getpwnam" } \
+ { "long arg to getgrnam()" "longarg_getgrnam" } \
+ ]
+
+foreach { test } $longarg_tests {
+ set test_desc [lindex $test 0]
+ set test_file [lindex $test 1]
+
+ simple_make "longarg" $test_file
+ set output [util_start "$srcdir/$subdir/$test_file" ]
+
+ if { [regexp "PASS" $output] } {
+ pass $test_desc
+ file delete "$srcdir/$subdir/$test_file" "$srcdir/$subdir/$test_file.o"
+ } else {
+ fail $test_desc
+ puts $output
+ }
+}
diff --git a/testsuite/nsswitch/longarg_getgrnam.c b/testsuite/nsswitch/longarg_getgrnam.c
new file mode 100644
index 0000000..4128424
--- /dev/null
+++ b/testsuite/nsswitch/longarg_getgrnam.c
@@ -0,0 +1,41 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Security context tests
+ Copyright (C) Tim Potter 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <sys/types.h>
+
+#include "longarg_utils.h"
+
+int main(void)
+{
+ struct group *grp;
+ char *domain = getenv("TEST_WORKGROUP");
+ char long_name[65535];
+ int failed = 0;
+
+ sprintf(long_name, "%s/%s", domain, LONG_STRING);
+
+ grp = getgrnam(long_name);
+ printf("%s\n", !grp ? "PASS" : "FAIL");
+
+ return grp == NULL;
+}
diff --git a/testsuite/nsswitch/longarg_getpwnam.c b/testsuite/nsswitch/longarg_getpwnam.c
new file mode 100644
index 0000000..1b6f544
--- /dev/null
+++ b/testsuite/nsswitch/longarg_getpwnam.c
@@ -0,0 +1,41 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Security context tests
+ Copyright (C) Tim Potter 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+#include "longarg_utils.h"
+
+int main(void)
+{
+ struct passwd *pwd;
+ char *domain = getenv("TEST_WORKGROUP");
+ char long_name[65535];
+ int failed = 0;
+
+ sprintf(long_name, "%s/%s", domain, LONG_STRING);
+
+ pwd = getpwnam(long_name);
+ printf("%s\n", !pwd ? "PASS" : "FAIL");
+
+ return pwd == NULL;
+}
diff --git a/testsuite/nsswitch/longarg_utils.h b/testsuite/nsswitch/longarg_utils.h
new file mode 100644
index 0000000..9c6088e
--- /dev/null
+++ b/testsuite/nsswitch/longarg_utils.h
@@ -0,0 +1,26 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Security context tests
+ Copyright (C) Tim Potter 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LONGARG_UTILS_H
+#define _LONGARG_UTILS_H
+
+#define LONG_STRING "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+#endif
diff --git a/testsuite/nsswitch/nss_winbind_syms.c b/testsuite/nsswitch/nss_winbind_syms.c
new file mode 100644
index 0000000..29d1da9
--- /dev/null
+++ b/testsuite/nsswitch/nss_winbind_syms.c
@@ -0,0 +1,63 @@
+/*
+ * Test required functions are exported from the libnss_winbind.so library
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+/* Symbol list to check */
+
+static char *symlist[] = {
+ "_nss_winbind_getgrent_r",
+ "_nss_winbind_endgrent",
+ "_nss_winbind_endpwent",
+ "_nss_winbind_getgrgid_r",
+ "_nss_winbind_getgrnam_r",
+ "_nss_winbind_getpwent_r",
+ "_nss_winbind_getpwnam_r",
+ "_nss_winbind_getpwuid_r",
+ "_nss_winbind_setgrent",
+ "_nss_winbind_setpwent",
+ "_nss_winbind_initgroups",
+ NULL
+};
+
+/* Main function */
+
+int main(int argc, char **argv)
+{
+ void *handle, *sym;
+ int i, y;
+
+ /* Open library */
+
+ if (argc != 2) {
+ printf("FAIL: usage '%s sharedlibname'\n", argv[0]);
+ return 1;
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW);
+
+ if (handle == NULL) {
+ printf("FAIL: could not dlopen library: %s\n", dlerror());
+ return 1;
+ }
+
+ /* Read symbols */
+
+ for (i = 0; symlist[i] != NULL; i++) {
+ sym = dlsym(handle, symlist[i]);
+ if (sym == NULL) {
+ printf("FAIL: could not resolve symbol '%s': %s\n",
+ symlist[i], dlerror());
+ return 1;
+ } else {
+ printf("loaded symbol '%s' ok\n", symlist[i]);
+ }
+ }
+
+ /* Clean up */
+
+ dlclose(handle);
+ return 0;
+}
diff --git a/testsuite/nsswitch/nss_winbind_syms.exp b/testsuite/nsswitch/nss_winbind_syms.exp
new file mode 100644
index 0000000..ab84cc5
--- /dev/null
+++ b/testsuite/nsswitch/nss_winbind_syms.exp
@@ -0,0 +1,42 @@
+#
+# @(#) Test nss functions are exported from the libnss_winbind.so library
+# @(#) Test there are no external dependencies in the libnss_winbind.so library
+#
+# We expect the following symbols to be exported:
+#
+# _nss_winbind_getgrent_r
+# _nss_winbind_endgrent
+# _nss_winbind_endpwent
+# _nss_winbind_getgrgid_r
+# _nss_winbind_getgrnam_r
+# _nss_winbind_getpwent_r
+# _nss_winbind_getpwnam_r
+# _nss_winbind_getpwuid_r
+# _nss_winbind_setgrent
+# _nss_winbind_setpwent
+# _nss_winbind_initgroups
+#
+# This test also has the nice side-effect of showing any unresolved symbols
+# in the library.
+#
+
+load_lib util-defs.exp
+load_lib compile.exp
+
+simple_compile "nss_winbind_syms" "-ldl"
+
+set output [util_start "$srcdir/$subdir/nss_winbind_syms" \
+ "nsswitch/libnss_winbind.so"]
+
+verbose $output
+
+if { [regexp "FAIL:" $output] } {
+ fail "run nss_winbind_syms"
+ return
+}
+
+pass "nss_winbind_syms"
+
+# Clean up
+
+file delete "$srcdir/$subdir/nss_winbind_syms"
diff --git a/testsuite/nsswitch/pam_winbind_syms.c b/testsuite/nsswitch/pam_winbind_syms.c
new file mode 100644
index 0000000..1264bdb
--- /dev/null
+++ b/testsuite/nsswitch/pam_winbind_syms.c
@@ -0,0 +1,55 @@
+/*
+ * Test required functions are exported from the pam_winbind.so library
+ */
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+/* Symbol list to check */
+
+static char *symlist[] = {
+ "pam_sm_acct_mgmt",
+ "pam_sm_authenticate",
+ "pam_sm_setcred",
+ NULL
+};
+
+/* Main function */
+
+int main(int argc, char **argv)
+{
+ void *handle, *sym;
+ int i, y;
+
+ /* Open library */
+
+ if (argc != 2) {
+ printf("FAIL: usage '%s sharedlibname'\n", argv[0]);
+ return 1;
+ }
+
+ handle = dlopen(argv[1], RTLD_NOW);
+
+ if (handle == NULL) {
+ printf("FAIL: could not dlopen library: %s\n", dlerror());
+ return 1;
+ }
+
+ /* Read symbols */
+
+ for (i = 0; symlist[i] != NULL; i++) {
+ sym = dlsym(handle, symlist[i]);
+ if (sym == NULL) {
+ printf("FAIL: could not resolve symbol '%s': %s\n",
+ symlist[i], dlerror());
+ return 1;
+ } else {
+ printf("loaded symbol '%s' ok\n", symlist[i]);
+ }
+ }
+
+ /* Clean up */
+
+ dlclose(handle);
+ return 0;
+}
diff --git a/testsuite/nsswitch/pam_winbind_syms.exp b/testsuite/nsswitch/pam_winbind_syms.exp
new file mode 100644
index 0000000..7c85a2d
--- /dev/null
+++ b/testsuite/nsswitch/pam_winbind_syms.exp
@@ -0,0 +1,44 @@
+#
+# @(#) Test nss functions are exported from the pam_winbind.so library
+# @(#) Test there are no external dependencies in the pam_winbind.so library
+#
+# We expect the following symbols to be exported:
+#
+# pam_sm_acct_mgmt
+# pam_sm_authenticate
+# pam_sm_setcred
+#
+# This test also has the nice side-effect of showing any unresolved symbols
+# in the library.
+#
+
+load_lib util-defs.exp
+
+# Compile pam_winbind_syms.c
+
+set output [target_compile "$srcdir/$subdir/pam_winbind_syms.c" \
+ "$srcdir/$subdir/pam_winbind_syms" executable \
+ {"libs=-ldl -lpam" "additional_flags=-g"}]
+
+if {$output != ""} {
+ perror "compile pam_winbind_syms.c"
+ puts $output
+ return
+}
+
+# Run load-dl.c
+
+set output [util_start "$srcdir/$subdir/pam_winbind_syms" \
+ "bin/pam_winbind.so"]
+
+if {[regexp "FAIL:" $output]} {
+ fail "run pam_winbind_syms"
+ puts $output
+ return
+}
+
+pass "pam_winbind_syms"
+
+# Clean up
+
+file delete "$srcdir/$subdir/pam_winbind_syms"
diff --git a/testsuite/nsswitch/wbinfo.exp b/testsuite/nsswitch/wbinfo.exp
new file mode 100644
index 0000000..8be25b2
--- /dev/null
+++ b/testsuite/nsswitch/wbinfo.exp
@@ -0,0 +1,360 @@
+#
+# @(#) Test wbinfo client access to winbind daemon
+#
+
+load_lib "util-defs.exp"
+load_lib "$srcdir/lib/nsswitch-config.exp"
+load_lib "$srcdir/lib/default-nt-names.exp"
+
+# Name types
+
+set SID_NAME_USER 1
+set SID_NAME_DOM_GRP 2
+set SID_NAME_DOMAIN 3
+set SID_NAME_ALIAS 4
+set SID_NAME_UNKNOWN 8
+
+# Get list of users and groups
+
+set user_list [util_start "bin/wbinfo" "-u"]
+set group_list [util_start "bin/wbinfo" "-g"]
+
+verbose "user list is:\n$user_list"
+verbose "group list is:\n$group_list"
+
+set user_list [split $user_list "\n"]
+set group_list [split $group_list "\n"]
+
+#
+# @(#) Check list of users and groups contain default NT user and group
+# @(#) names
+#
+
+# Users
+
+foreach { user } $domain_users {
+ set test_desc "user $user in wbinfo domain users"
+ if {![regexp $user $user_list]} {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+# Groups
+
+foreach { group } $domain_groups {
+ set test_desc "group $group in wbinfo domain groups"
+ if {![regexp $group $group_list]} {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+#
+# @(#) Lookup sids for all user and group names returned by wbinfo
+#
+
+# Users
+
+foreach { user } $user_list {
+ set test_desc "get sid for user $user"
+ set output [util_start "bin/wbinfo" "-n \"$user\""]
+
+ verbose $output
+
+ # Split output into name and name_type
+
+ set list [split $output " "]
+ set sid_type [lindex $list [expr [llength $list] - 1]]
+ set sid [join [lrange $list 0 [expr [llength $list] - 2]] " "]
+
+ if { ![regexp "S-" $sid] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "sid type for user $user"
+ if { $sid_type != $SID_NAME_USER } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ lappend user_sid_list $sid
+}
+
+# Groups
+
+foreach { group } $group_list {
+ set test_desc "get sid for group $group"
+ set output [util_start "bin/wbinfo" "-n \"$group\""]
+
+ verbose $output
+
+ # Split output into sid and sid type
+
+ set list [split $output " "]
+ set sid_type [lindex $list [expr [llength $list] - 1]]
+ set sid [join [lrange $list 0 [expr [llength $list] - 2]] " "]
+
+ if { ![regexp "S-" $sid] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "sid type for group group"
+ if { $sid_type != $SID_NAME_DOM_GRP } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ lappend group_sid_list $sid
+}
+
+#
+# @(#) Check reverse lookup of sids to names
+#
+
+# Users
+
+set count 0
+
+foreach { sid } $user_sid_list {
+ set test_desc "reverse user name lookup for sid $sid"
+ set output [util_start "bin/wbinfo" "-s $sid"]
+
+ verbose $output
+
+ # Split output into name and name_type
+
+ set list [split $output " "]
+ set name_type [lindex $list [expr [llength $list] - 1]]
+ set name [join [lrange $list 0 [expr [llength $list] - 2]] " "]
+
+ if { $name != [lindex $user_list $count] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "reverse user name type lookup for sid $sid"
+
+ if { $name_type != 1 } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ incr count
+}
+
+# Groups
+
+set count 0
+
+foreach { sid } $group_sid_list {
+ set test_desc "reverse group name lookup for sid $sid"
+ set output [util_start "bin/wbinfo" "-s $sid"]
+
+ verbose $output
+
+ # Split output into name and name_type
+
+ set list [split $output " "]
+ set name_type [lindex $list [expr [llength $list] - 1]]
+ set name [join [lrange $list 0 [expr [llength $list] - 2]] " "]
+
+ if { $name != [lindex $group_list $count] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "reverse group name type lookup for sid $sid"
+
+ if { $name_type != 2 } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ incr count
+}
+
+#
+# @(#) Cross-check the output of wbinfo -n, getent passwd/group and
+# @(#) wbinfo -S
+#
+
+# Get mapped list of uids from winbindd
+
+set output [util_start "getent" "passwd"]
+set user_list [split $output "\n"]
+
+foreach { user_entry } $user_list {
+ if { [regexp $domain $user_entry] } {
+ set field_list [split $user_entry ":"]
+ set name_output [util_start "bin/wbinfo" \
+ "-n \"[lindex $field_list 0]\""]
+ set list [split $name_output " "]
+ set name_type [lindex $list [expr [llength $list] - 1]]
+ set name [join [lrange $list 0 [expr [llength $list] - 2]] " "]
+ set username_uid_sid [lappend username_uid_sid [list \
+ [lindex $field_list 0] \
+ [lindex $field_list 2] \
+ $name]]
+ }
+}
+
+# Get mapped list of gids from winbindd
+
+set output [util_start "getent" "group"]
+set group_list [split $output "\n"]
+
+foreach { group_entry } $group_list {
+ if { [regexp $domain $group_entry] } {
+ set field_list [split $group_entry ":"]
+ set groupname_gid_sid [lappend groupname_gid_sid [list \
+ [lindex $field_list 0] \
+ [lindex $field_list 2] \
+ [util_start "bin/wbinfo" "-n \"[lindex $field_list 0]\""]]]
+ }
+}
+
+# OK, now we have enough info to cross-check the uid/gid -> sid and
+# sid -> uid/gid functions
+
+foreach { user } $username_uid_sid {
+ set sid [util_start "bin/wbinfo" "-U [lindex $user 1]"]
+ set uid [util_start "bin/wbinfo" "-S [lindex $user 2]"]
+
+ set test_desc "lookup sid by uid [lindex $user 1]"
+
+ if { $sid != [lindex $user 2] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "lookup uid by sid [lindex $user 2]"
+
+ if { $uid != [lindex $user 1] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+foreach { group } $groupname_gid_sid {
+ set sid [util_start "bin/wbinfo" "-G [lindex $group 1]"]
+ set gid [util_start "bin/wbinfo" "-Y [lindex $group 2]"]
+
+ set test_desc "lookup sid by gid [lindex $group 1]"
+
+ if { $sid != [lindex [split [lindex $group 2] " "] 0] ||
+ [lindex [split [lindex $group 2] " " ] 1] != 2 } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+
+ set test_desc "lookup gid by sid [lindex $group 2]"
+
+ if { $gid != [lindex $group 1] } {
+ fail $test_desc
+ } else {
+ pass $test_desc
+ }
+}
+
+# Check exit codes
+
+proc check_errcode { args } {
+ global errorCode
+ set test_desc [lindex $args 0]
+ set cmd [lindex $args 1]
+ set result [lindex $args 2]
+
+ set errorCode ""
+ verbose "Spawning $cmd"
+ catch "exec $cmd" output
+ set exit_code [lindex $errorCode 2]
+ if { $exit_code == "" } { set exit_code 0 }
+
+ if { $exit_code == $result } {
+ verbose "process returned correct exit code $exit_code"
+ pass $test_desc
+ } else {
+ verbose "process returned bad exit code $exit_code instead of $result"
+ fail $test_desc
+ }
+}
+
+set gooduser_name [lindex [split [lindex $user_list 0] ":"] 0]
+set gooduser_sid [util_start "bin/wbinfo" "-n $gooduser_name"]
+
+set goodgroup_name [lindex [split [lindex $group_list 0] ":"] 0]
+set goodgroup_sid [util_start "bin/wbinfo" "-n $goodgroup_name"]
+
+# Some conditions not tested:
+# - bad list users/groups
+# - good uid/gid to sid
+
+set errcode_tests [list \
+ { "exit code, no arg" "bin/wbinfo" 1 } \
+ { "exit code, invalid arg" "bin/wbinfo -@" 1 } \
+ { "exit code, list users" "bin/wbinfo -u" 0 } \
+ { "exit code, list groups" "bin/wbinfo -g" 0 } \
+ { "exit code, good name to sid" "bin/wbinfo -n $gooduser_name" 0 } \
+ { "exit code, bad name to sid" "bin/wbinfo -n asmithee" 1 } \
+ { "exit code, good sid to name" "bin/wbinfo -s $gooduser_sid" 0 } \
+ { "exit code, bad sid to name" "bin/wbinfo -s S-1234" 1 } \
+ { "exit code, bad uid to sid" "bin/wbinfo -U 0" 1 } \
+ { "exit code, bad gid to sid" "bin/wbinfo -G 0" 1} \
+ { "exit code, good sid to uid" "bin/wbinfo -S $gooduser_sid" 0 } \
+ { "exit code, bad sid to uid" "bin/wbinfo -S S-1234" 1 } \
+ { "exit code, good sid to gid" "bin/wbinfo -Y $goodgroup_sid" 0 } \
+ { "exit code, bad sid to gid" "bin/wbinfo -Y S-1234" 1 } \
+ ]
+
+foreach { test } $errcode_tests {
+ check_errcode [lindex $test 0] [lindex $test 1] [lindex $test 2]
+}
+
+# Test enumerate trusted domains
+
+set test_desc "enumerate trusted domains"
+set output [util_start "bin/wbinfo" "-m"]
+
+verbose $output
+
+foreach { the_domain } $output {
+ if { $the_domain == $domain} {
+ fail "own domain appears in trusted list"
+ }
+}
+
+if {[regexp "Usage" $output] || [regexp "Could not" $output]} {
+ fail $test_desc
+} else {
+ pass $test_desc
+}
+
+# Test check machine account
+
+set test_desc "check machine account"
+set output [util_start "bin/wbinfo" "-t"]
+
+verbose $output
+
+if {[regexp "Usage" $output] || [regexp "Could not" $output] || \
+ ![regexp "(good|bad)" $output]} {
+ fail $test_desc
+} else {
+ pass $test_desc
+}