diff options
25 files changed, 2255 insertions, 0 deletions
diff --git a/docs/OID/allocated-arcs.txt b/docs/OID/allocated-arcs.txt new file mode 100644 index 00000000000..7a7cd8057b6 --- /dev/null +++ b/docs/OID/allocated-arcs.txt @@ -0,0 +1,16 @@ +!=========================================================================================== +!== +!== Allocated Arcs from the Samba Team Private Enterprise Number +!== ISO(1) org(3) dod(6) internet(1) experimental(3) private(4) enterprise(1) Samba(7165) +!== +!== Arc allocation is maintained by jerry carter <jerry@samba.org>. Please notify +!== me if you need an OID and update this file. +!== +!== File Created : Tue May 8 09:33:31 CDT 2001 +!== +!=========================================================================================== + +ARC Owner Contact Purpose +--- ----- ------- ------- +.1 Plainjoe.org Jerry Carter <jerry@samba.org> Use for Plainjoe.org domain + and examples in O'Reilly LDAP book diff --git a/docs/OID/samba-oid.mail b/docs/OID/samba-oid.mail new file mode 100644 index 00000000000..d1ad668f880 --- /dev/null +++ b/docs/OID/samba-oid.mail @@ -0,0 +1,27 @@ +From gruiz@icann.org Tue May 8 04:27:07 2001 +Date: Tue, 26 Sep 2000 15:29:02 -0700 +From: GIGI RUIZ <gruiz@icann.org> +To: jerry@samba.org +Cc: "Iana-Mib (E-mail)" <iana-mib@iana.org> +Subject: PEN 7165 RE: Application for Enterprise-number + + [ The following text is in the "iso-8859-1" character set. ]
+ [ Your display is set for the "US-ASCII" character set. ]
+ [ Some characters may be displayed incorrectly. ] + +Gerald, + +We have assigned Private Enterprise Number 7165 to SAMBA Team, with you as +the point of contact. Please confirm the information listed below. + +7165 SAMBA Team Gerald Carter jerry@samba.org + +Sincerely, + +Gigi Ruiz +Internet Assigned Numbers Authority - MIB + +Voice: (310) 823-9358 +Fax: (310) 823-8649 +EMAIL: iana-mib@iana.org + diff --git a/examples/VFS/block/Makefile b/examples/VFS/block/Makefile new file mode 100644 index 00000000000..dcc7c077936 --- /dev/null +++ b/examples/VFS/block/Makefile @@ -0,0 +1,37 @@ +# +# Makefile for samba-vfs examples +# +# + +# Variables + +CC = gcc +LIBTOOL = libtool + +SAMBA_SRC = /usr/local/src/samba/samba-2.2.0-ron/source +SAMBA_INCL = ${SAMBA_SRC}/include +UBIQX_SRC = ${SAMBA_SRC}/ubiqx +SMBWR_SRC = ${SAMBA_SRC}/smbwrapper +CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g -D_LARGEFILE63_SOURCE -D_GNU_SOURCE -fno-builtin + + +VFS_OBJS = block.so + +# Default target + +default: $(VFS_OBJS) + +# Pattern rules + +%.so: %.lo + $(LIBTOOL) $(CC) -shared -o $@ $< $(LDFLAGS) + +%.lo: %.c + $(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< + +# Misc targets + +clean: + rm -rf .libs + rm -f core *~ *% *.bak \ + $(VFS_OBJS) $(VFS_OBJS:.so=.o) $(VFS_OBJS:.so=.lo) diff --git a/examples/VFS/block/block.c b/examples/VFS/block/block.c new file mode 100644 index 00000000000..3c4f736e849 --- /dev/null +++ b/examples/VFS/block/block.c @@ -0,0 +1,546 @@ +/* + * + * Block access from links to dev mount points specified in PARAMCONF file + * + * Copyright (C) Ronald Kuetemeier, 2001 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + + +#ifdef HAVE_UTIME_H +#include <utime.h> +#endif +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <syslog.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + + +#include <includes.h> +#include <vfs.h> + + + +DIR *block_opendir(struct connection_struct *conn, char *fname); +int block_connect(struct connection_struct *conn, char *service, char *user); +void block_disconnect(struct connection_struct *conn); + + +/* VFS operations */ + + +extern struct vfs_ops default_vfs_ops; /* For passthrough operation */ + +struct vfs_ops execute_vfs_ops = { + + /* Disk operations */ + + block_connect, + block_disconnect, + NULL, /* disk free */ + + /* Directory operations */ + + block_opendir, + NULL, /* readdir */ + NULL, + NULL, + NULL, /* closedir */ + + /* File operations */ + + NULL, + NULL, + NULL, /* read */ + NULL, /* write */ + NULL, /* lseek */ + NULL, + NULL, /* fsync */ + NULL, /* stat */ + NULL, /* fstat */ + NULL, /* lstat */ + NULL, + NULL, + NULL, + NULL, /* chown */ + NULL, + NULL, /* chdir */ + NULL, /* getwd */ + NULL, /* utime */ + NULL, /* ftruncate */ + NULL, /* lock */ + NULL, /* fget_nt_acl */ + NULL, /* get_nt_acl */ + NULL, /* fset_nt_acl */ + NULL, /* set_nt_acl */ + NULL, + NULL +}; + + +#ifndef PARAMCONF +#define PARAMCONF "/etc/samba-block.conf" +#endif + +extern BOOL pm_process(char *FileName, BOOL (*sfunc)(char *), BOOL(*pfunc)(char * , char *)); + +//functions + +BOOL enter_pblock_mount(char *dir); +BOOL get_section(char *sect); +BOOL get_parameter_value(char *param, char *value); +BOOL load_param(void); +BOOL search(struct stat *stat_buf); +BOOL dir_search(char *link, char *dir); +BOOL enter_pblock_dir(char *dir); + + + +typedef struct block_dir +{ + dev_t st_dev; + int str_len; + char *dir_name; + struct block_dir *next; +} block_dir; + + +static char *params[] = {"mount_point","dir_name"}; +enum { MOUNT_POINT , DIR_NAME }; + +static struct block_dir *pblock_mountp = NULL; +static struct block_dir *pblock_dir = NULL; + + + +/* + * Load the conf file into a table + */ + +BOOL load_param(void) +{ + + if ((pm_process(PARAMCONF,&get_section,&get_parameter_value)) == TRUE) + { + return TRUE; + + } + return FALSE; +} + + + +/* + * Enter the key and data into the list + * + */ + +BOOL enter_pblock_mount(char *dir) +{ + struct stat stat_buf; + static struct block_dir *tmp_pblock; + + + if((stat(dir,&stat_buf)) != 0) + { + return FALSE; + } + + if(pblock_mountp == NULL) + { + pblock_mountp = calloc(1, sizeof(block_dir)); + if( pblock_mountp == NULL) + { + return FALSE; + } + tmp_pblock = pblock_mountp; + tmp_pblock->next = NULL; + + }else + { + tmp_pblock->next = calloc(1, sizeof(block_dir)); + if(tmp_pblock->next == NULL) + { + return FALSE; + } + tmp_pblock = tmp_pblock->next; + tmp_pblock->next = NULL; + + } + + + tmp_pblock->st_dev = stat_buf.st_dev; + tmp_pblock->dir_name = strdup(dir); + + + return TRUE; + +} + + +/* + * Enter the key and data into the list + * + */ + +BOOL enter_pblock_dir(char *dir) +{ + static struct block_dir *tmp_pblock; + + + if(pblock_dir == NULL) + { + pblock_dir = calloc(1, sizeof(block_dir)); + if( pblock_dir == NULL) + { + return FALSE; + } + tmp_pblock = pblock_dir; + tmp_pblock->next = NULL; + + }else + { + tmp_pblock->next = calloc(1, sizeof(block_dir)); + if(tmp_pblock->next == NULL) + { + return FALSE; + } + tmp_pblock = tmp_pblock->next; + tmp_pblock->next = NULL; + + } + + + tmp_pblock->dir_name = strdup(dir); + tmp_pblock->str_len = strlen(dir); + + + return TRUE; + +} + + + + +/* + * Function callback for config section names + */ + +BOOL get_section(char *sect) +{ + return TRUE; +} + + + +/* + * Function callback for config parameter value pairs + * + */ + +BOOL get_parameter_value(char *param, char *value) +{ + int i = 0, maxargs = sizeof(params) / sizeof(char *); + + + for( i= 0; i < maxargs; i++) + { + if (strcmp(param,params[i]) == 0) + { + switch(i) + { + case MOUNT_POINT : + enter_pblock_mount(value); + break; + case DIR_NAME : + enter_pblock_dir(value); + break; + default : + break; + } + } + } + + return TRUE; + +} + + + + +/* VFS initialisation function. Return initialised vfs_ops structure + back to SAMBA. */ + +struct vfs_ops *vfs_init(int *vfs_version) +{ + *vfs_version = SMB_VFS_INTERFACE_VERSION; + + return(&execute_vfs_ops); +} + + +/* + * VFS connect and param file loading + */ + +int block_connect(struct connection_struct *conn, char *service, char *user) +{ + if((load_param()) == FALSE) + { + + return -1; + + } + + DEBUG(0,("%s connecting \n",conn->user)); + + return (default_vfs_ops.connect(conn, service,user)); +} + +/* + * Free allocated structures and disconnect + * + */ + + +void block_disconnect(struct connection_struct *conn) +{ + + struct block_dir *tmp_pblock = (pblock_mountp == NULL ? pblock_dir : pblock_mountp); + struct block_dir *free_pblock = NULL; + + while(tmp_pblock != NULL) + { + free(tmp_pblock->dir_name); + free_pblock = tmp_pblock; + tmp_pblock = tmp_pblock->next; + free(free_pblock); + + if(tmp_pblock == NULL && pblock_dir != NULL) + { + tmp_pblock = (pblock_mountp == NULL ? pblock_dir : NULL); + pblock_dir = NULL; + + } + + } + + + + default_vfs_ops.disconnect(conn); +} + +/* + * VFS opendir + */ + +DIR *block_opendir(struct connection_struct *conn, char *fname) +{ + + char *dir_name = NULL; + struct stat stat_buf; + + dir_name = alloca((strlen(conn->origpath) + strlen(fname) + 2) * sizeof(char)); + + pstrcpy(dir_name,conn->origpath); + pstrcat(dir_name, "/"); + strncat(dir_name, fname, strcspn(fname,"/")); + + if((lstat(dir_name,&stat_buf)) == 0) + { + if((S_ISLNK(stat_buf.st_mode)) == 1) + { + stat(dir_name,&stat_buf); + if((search(&stat_buf) || dir_search(dir_name, fname) ) == TRUE) + { + DEBUG(0,("%s used link to blocked dir: %s \n", conn->user, dir_name)); + errno = EACCES; + return NULL; + } + } + } + + return (default_vfs_ops.opendir(conn, fname)); +} + + +/* + * Find mount point to block in list + */ + +BOOL search(struct stat *stat_buf) +{ + struct block_dir *tmp_pblock = pblock_mountp; + + while(tmp_pblock != NULL) + { + + if(tmp_pblock->st_dev == stat_buf->st_dev) + { + return TRUE; + } + tmp_pblock = tmp_pblock->next; + } + + return FALSE; + +} + +/* + * Find dir in list to block id the starting point is link from a share + */ + +BOOL dir_search(char *link, char *dir) +{ + char buf[PATH_MAX +1], *ext_path; + int len = 0; + struct block_dir *tmp_pblock = pblock_dir; + + if((len = readlink(link,buf,sizeof(buf))) == -1) + { + return TRUE; + + }else + { + buf[len] = '\0'; + } + + + if((ext_path = strchr(dir,'/')) != NULL) + { + pstrcat(buf,&ext_path[1]); + len = strlen(buf); + } + + while(tmp_pblock != NULL) + { + if(len < tmp_pblock->str_len) + { + tmp_pblock = tmp_pblock->next; + continue; + } + + if((strstr(buf,tmp_pblock->dir_name)) != NULL) + { + return TRUE; + } + tmp_pblock = tmp_pblock->next; + } + + + return FALSE; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/VFS/block/samba-block.conf b/examples/VFS/block/samba-block.conf new file mode 100644 index 00000000000..7a137980b73 --- /dev/null +++ b/examples/VFS/block/samba-block.conf @@ -0,0 +1,6 @@ +[ blocked ] +mount_point = / +mount_point = /boot +mount_point = /proc +dir_name = /usr/local/src/samba +dir_name = /usr/bin diff --git a/examples/VFS/block/smb.conf b/examples/VFS/block/smb.conf new file mode 100644 index 00000000000..368155f1f83 --- /dev/null +++ b/examples/VFS/block/smb.conf @@ -0,0 +1,13 @@ +[homes] + comment = Home Directories + vfs object = /usr/local/samba/lib/block.so + browseable = yes + writable = yes + + + + + + + + diff --git a/source/include/mapping.h b/source/include/mapping.h new file mode 100644 index 00000000000..f3e0be6e4a7 --- /dev/null +++ b/source/include/mapping.h @@ -0,0 +1,48 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Jean François Micouleau 1998-2001. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +typedef struct _GROUP_MAP { + gid_t gid; + DOM_SID sid; + enum SID_NAME_USE sid_name_use; + fstring nt_name; + fstring comment; + uint32 privilege; +} GROUP_MAP; + +typedef struct _PRIVS { + uint32 se_priv; + char *priv; + char *description; +} PRIVS; + +#define SE_PRIV_NONE 0x0000 +#define SE_PRIV_ADD_USERS 0x0001 +#define SE_PRIV_ADD_MACHINES 0x0002 +#define SE_PRIV_PRINT_OPERATOR 0x0004 +#define SE_PRIV_ALL 0xffff + +#define PRIV_ALL_INDEX 4 + + +#define ENUM_ONLY_MAPPED True +#define ENUM_ALL_MAPPED False diff --git a/source/nsswitch/.cvsignore b/source/nsswitch/.cvsignore new file mode 100644 index 00000000000..6d609cec52b --- /dev/null +++ b/source/nsswitch/.cvsignore @@ -0,0 +1 @@ +*.po diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c new file mode 100644 index 00000000000..bc014f26918 --- /dev/null +++ b/source/nsswitch/winbindd_sid.c @@ -0,0 +1,244 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + + Winbind daemon - sid related functions + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "winbindd.h" +#include "sids.h" + +/* Convert a string */ + +enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state) +{ + extern DOM_SID global_sid_Builtin; + enum SID_NAME_USE type; + DOM_SID sid, tmp_sid; + uint32 rid; + fstring name; + + DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid, + state->request.data.sid)); + + /* Lookup sid from PDC using lsa_lookup_sids() */ + + string_to_sid(&sid, state->request.data.sid); + + /* Don't look up BUILTIN sids */ + + sid_copy(&tmp_sid, &sid); + sid_split_rid(&tmp_sid, &rid); + + if (sid_equal(&tmp_sid, &global_sid_Builtin)) { + return WINBINDD_ERROR; + } + + /* Lookup the sid */ + + if (!winbindd_lookup_name_by_sid(&sid, name, &type)) { + return WINBINDD_ERROR; + } + + string_sub(name, "\\", lp_winbind_separator(), sizeof(fstring)); + fstrcpy(state->response.data.name.name, name); + state->response.data.name.type = type; + + return WINBINDD_OK; +} + +/* Convert a sid to a string */ + +enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) +{ + enum SID_NAME_USE type; + fstring sid_str, name_domain, name_user, name; + DOM_SID sid; + + DEBUG(3, ("[%5d]: lookupname %s\n", state->pid, + state->request.data.name)); + + parse_domain_user(state->request.data.name, name_domain, name_user); + + snprintf(name, sizeof(name), "%s\\%s", name_domain, name_user); + + /* Lookup name from PDC using lsa_lookup_names() */ + + if (!winbindd_lookup_sid_by_name(name, &sid, &type)) { + return WINBINDD_ERROR; + } + + sid_to_string(sid_str, &sid); + fstrcpy(state->response.data.sid.sid, sid_str); + state->response.data.sid.type = type; + + return WINBINDD_OK; +} + +/* Convert a sid to a uid. We assume we only have one rid attached to the + sid. */ + +enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) +{ + DOM_SID sid; + uint32 user_rid; + struct winbindd_domain *domain; + + DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid, + state->request.data.sid)); + + /* Split sid into domain sid and user rid */ + + string_to_sid(&sid, state->request.data.sid); + sid_split_rid(&sid, &user_rid); + + /* Find domain this sid belongs to */ + + if ((domain = find_domain_from_sid(&sid)) == NULL) { + fstring sid_str; + + sid_to_string(sid_str, &sid); + DEBUG(1, ("Could not find domain for sid %s\n", sid_str)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it */ + + if (!winbindd_idmap_get_uid_from_rid(domain->name, user_rid, + &state->response.data.uid)) { + DEBUG(1, ("Could not get uid for sid %s\n", + state->request.data.sid)); + return WINBINDD_ERROR; + } + + return WINBINDD_OK; +} + +/* Convert a sid to a gid. We assume we only have one rid attached to the + sid.*/ + +enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) +{ + DOM_SID sid; + uint32 group_rid; + struct winbindd_domain *domain; + + DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid, + state->request.data.sid)); + + /* Split sid into domain sid and user rid */ + + string_to_sid(&sid, state->request.data.sid); + sid_split_rid(&sid, &group_rid); + + /* Find domain this sid belongs to */ + + if ((domain = find_domain_from_sid(&sid)) == NULL) { + fstring sid_str; + + sid_to_string(sid_str, &sid); + DEBUG(1, ("Could not find domain for sid %s\n", sid_str)); + return WINBINDD_ERROR; + } + + /* Find uid for this sid and return it */ + + if (!winbindd_idmap_get_gid_from_rid(domain->name, group_rid, + &state->response.data.gid)) { + DEBUG(1, ("Could not get gid for sid %s\n", + state->request.data.sid)); + return WINBINDD_ERROR; + } + + return WINBINDD_OK; +} + +/* Convert a uid to a sid */ + +enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + uint32 user_rid; + DOM_SID sid; + + /* Bug out if the uid isn't in the winbind range */ + + if ((state->request.data.uid < server_state.uid_low ) || + (state->request.data.uid > server_state.uid_high)) { + return WINBINDD_ERROR; + } + + DEBUG(3, ("[%5d]: uid to sid %d\n", state->pid, + state->request.data.uid)); + + /* Lookup rid for this uid */ + + if (!winbindd_idmap_get_rid_from_uid(state->request.data.uid, + &user_rid, &domain)) { + DEBUG(1, ("Could not convert uid %d to rid\n", + state->request.data.uid)); + return WINBINDD_ERROR; + } + + /* Construct sid and return it */ + + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, user_rid); + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_USER; + + return WINBINDD_OK; +} + +/* Convert a gid to a sid */ + +enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) +{ + struct winbindd_domain *domain; + uint32 group_rid; + DOM_SID sid; + + /* Bug out if the gid isn't in the winbind range */ + + if ((state->request.data.gid < server_state.gid_low) || + (state->request.data.gid > server_state.gid_high)) { + return WINBINDD_ERROR; + } + + DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid, + state->request.data.gid)); + + /* Lookup rid for this uid */ + + if (!winbindd_idmap_get_rid_from_gid(state->request.data.gid, + &group_rid, &domain)) { + DEBUG(1, ("Could not convert gid %d to rid\n", + state->request.data.gid)); + return WINBINDD_ERROR; + } + + /* Construct sid and return it */ + + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, group_rid); + sid_to_string(state->response.data.sid.sid, &sid); + state->response.data.sid.type = SID_NAME_DOM_GRP; + + return WINBINDD_OK; +} diff --git a/testsuite/lib/default-nt-names.exp b/testsuite/lib/default-nt-names.exp new file mode 100644 index 00000000000..5d01d2a5bb3 --- /dev/null +++ b/testsuite/lib/default-nt-names.exp @@ -0,0 +1,20 @@ +# +# A list of default domain/local users/groups. Unfortunately this is tied +# to the English language version of Windows NT. +# + +global domain + +# Domain users and groups + +set domain_users [list "$domain/Administrator" "$domain/Guest"] + +set domain_groups [list "$domain/Domain Admins" "$domain/Domain Guests" \ + "$domain/Domain Users"] + +# Local groups + +set local_groups [list "BUILTIN/Replicator" "BUILTIN/Server Operators" \ + "BUILTIN/Account Operators" "BUILTIN/Backup Operators" \ + "BUILTIN/Print Operators" "BUILTIN/Guests" "BUILTIN/Users" \ + "BUILTIN/Administrators"] diff --git a/testsuite/lib/nsswitch-config.exp b/testsuite/lib/nsswitch-config.exp new file mode 100644 index 00000000000..38342685dfa --- /dev/null +++ b/testsuite/lib/nsswitch-config.exp @@ -0,0 +1,21 @@ +# +# Load environment variables +# + +global tool + +if { [file exists "deja-$tool.tcl"] } { + source "deja-$tool.tcl" +} + +# Required options + +if { ![info exists WORKGROUP] } { + error "\$WORKGROUP not set in config file" +} + +if { ![info exists PDC] } { + error "\$PDC not set in config file" +} + +set domain $WORKGROUP diff --git a/testsuite/nsswitch/.cvsignore b/testsuite/nsswitch/.cvsignore new file mode 100644 index 00000000000..1c30875a884 --- /dev/null +++ b/testsuite/nsswitch/.cvsignore @@ -0,0 +1,12 @@ +initgroups +nss_winbind_syms +getgrent_r +getgrgid +getgrnam +getpwent_r +getpwnam +wbtorture +leaktest? +getpwuid +getent_pwent +getent_grent diff --git a/testsuite/nsswitch/Makefile.longarg b/testsuite/nsswitch/Makefile.longarg new file mode 100644 index 00000000000..6cc7ef8306d --- /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/envvar.exp b/testsuite/nsswitch/envvar.exp new file mode 100644 index 00000000000..134a8b37a85 --- /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/getent.c b/testsuite/nsswitch/getent.c new file mode 100644 index 00000000000..b4c4e50c6fe --- /dev/null +++ b/testsuite/nsswitch/getent.c @@ -0,0 +1,151 @@ +/* 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#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_grent.c b/testsuite/nsswitch/getent_grent.c new file mode 100644 index 00000000000..782cc0c86b7 --- /dev/null +++ b/testsuite/nsswitch/getent_grent.c @@ -0,0 +1,101 @@ +/* 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#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 00000000000..96c804433a4 --- /dev/null +++ b/testsuite/nsswitch/getent_pwent.c @@ -0,0 +1,113 @@ +/* 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#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/groupmem_dom.exp b/testsuite/nsswitch/groupmem_dom.exp new file mode 100644 index 00000000000..3ba34bb810e --- /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 00000000000..b7d9c50eaa3 --- /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 00000000000..ab21bcc9e7b --- /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/longarg.exp b/testsuite/nsswitch/longarg.exp new file mode 100644 index 00000000000..e1d0eda9ccb --- /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 00000000000..84083d2620e --- /dev/null +++ b/testsuite/nsswitch/longarg_getgrnam.c @@ -0,0 +1,42 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#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 00000000000..f2a0a73ddca --- /dev/null +++ b/testsuite/nsswitch/longarg_getpwnam.c @@ -0,0 +1,42 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#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 00000000000..1f2f2a7065d --- /dev/null +++ b/testsuite/nsswitch/longarg_utils.h @@ -0,0 +1,27 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _LONGARG_UTILS_H +#define _LONGARG_UTILS_H + +#define LONG_STRING "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +#endif diff --git a/testsuite/nsswitch/wbinfo.exp b/testsuite/nsswitch/wbinfo.exp new file mode 100644 index 00000000000..3518db387be --- /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 \ + { "no arg" "bin/wbinfo" 1 } \ + { "invalid arg" "bin/wbinfo -@" 1 } \ + { "list users" "bin/wbinfo -u" 0 } \ + { "list groups" "bin/wbinfo -g" 0 } \ + { "good name to sid" "bin/wbinfo -n $gooduser_name" 0 } \ + { "bad name to sid" "bin/wbinfo -n asmithee" 0 } \ + { "good sid to name" "bin/wbinfo -s $gooduser_sid" 0 } \ + { "bad sid to name" "bin/wbinfo -s S-1234" 1 } \ + { "bad uid to sid" "bin/wbinfo -U 0" 1 } \ + { "bad gid to sid" "bin/wbinfo -G 0" 1} \ + { "good sid to uid" "bin/wbinfo -S $gooduser_sid" 0 } \ + { "bad sid to uid" "bin/wbinfo -S S-1234" 1 } \ + { "good sid to gid" "bin/wbinfo -Y $goodgroup_sid" 0 } \ + { "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 +} |