diff options
Diffstat (limited to 'source4/selftest')
52 files changed, 4914 insertions, 0 deletions
diff --git a/source4/selftest/README b/source4/selftest/README new file mode 100644 index 0000000000..1eb7e7943c --- /dev/null +++ b/source4/selftest/README @@ -0,0 +1,13 @@ +This directory contains test scripts that are useful for running a +bunch of tests all at once. + +The following environments are currently available: + + - none: No server set up + - dc: Domain controller set up. The following environment variables will + be set: + * USERNAME + * PASSWORD + * DOMAIN + * REALM + * SERVER diff --git a/source4/selftest/Samba3.pm b/source4/selftest/Samba3.pm new file mode 100644 index 0000000000..b12208bd9f --- /dev/null +++ b/source4/selftest/Samba3.pm @@ -0,0 +1,315 @@ +#!/usr/bin/perl +# Bootstrap Samba and run a number of tests against it. +# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL, v3 or later. + +package Samba3; + +use strict; +use Cwd qw(abs_path); +use FindBin qw($RealBin); + +sub binpath($$) +{ + my ($self, $binary) = @_; + + if (defined($self->{bindir})) { + my $path = "$self->{bindir}/$binary"; + -f $path or die("File $path doesn't exist"); + return $path; + } + + return $binary; +} + +sub new($$) { + my ($classname, $bindir) = @_; + my $self = { bindir => $bindir }; + bless $self; + return $self; +} + +sub teardown_env($$) +{ + my ($self, $envvars) = @_; + + $self->samba3_stop_sig_term($envvars->{PIDDIR}); + $self->samba3_stop_sig_kill($envvars->{PIDDIR}); + + return 0; +} + +sub getlog_env($$) +{ + my ($self, $envvars) = @_; + + # TODO... + return ""; +} + +sub check_env($$) +{ + my ($self, $envvars) = @_; + + # TODO ... + return 1; +} + +sub setup_env($$$) +{ + my ($self, $envname, $path) = @_; + + if ($envname eq "dc") { + return $self->setup_dc("$path/dc"); + } else { + die("Samba4 can't provide environment '$envname'"); + } +} + +sub setup_dc($$) +{ + my ($self, $path) = @_; + + my $vars = $self->provision($path); + + $self->check_or_start($vars, ($ENV{NMBD_MAXTIME} or 2700), ($ENV{SMBD_MAXTIME} or 2700)); + + $self->wait_for_start($vars); + + return $vars; +} + +sub stop($) +{ + my ($self) = @_; +} + +sub samba3_stop_sig_term($$) { + my ($self, $piddir) = @_; + my $ret = 0; + kill("USR1", `cat $piddir/timelimit.nmbd.pid`) or \ + kill("ALRM", `cat $piddir/timelimit.nmbd.pid`) or $ret++; + + kill("USR1", `cat $piddir/timelimit.smbd.pid`) or \ + kill("ALRM", `cat $piddir/timelimit.smbd.pid`) or $ret++; + + return $ret; +} + +sub samba3_stop_sig_kill($$) { + my ($self, $piddir) = @_; + kill("ALRM", `cat $piddir/timelimit.nmbd.pid`); + kill("ALRM", `cat $piddir/timelimit.smbd.pid`); + return 0; +} + +sub check_or_start($$$$) { + my ($self, $env_vars, $nmbd_maxtime, $smbd_maxtime) = @_; + + unlink($env_vars->{NMBD_TEST_LOG}); + print "STARTING NMBD..."; + my $pid = fork(); + if ($pid == 0) { + open STDOUT, ">$env_vars->{NMBD_TEST_LOG}"; + open STDERR, '>&STDOUT'; + + $ENV{MAKE_TEST_BINARY} = $self->binpath("nmbd"); + exec($self->binpath("timelimit"), $nmbd_maxtime, $self->binpath("nmbd"), "-F", "-S", "--no-process-group", "-d0" ,"-s", $env_vars->{SERVERCONFFILE}) or die("Unable to start nmbd: $!"); + } + open(PID, ">$env_vars->{PIDDIR}/timelimit.nmbd.pid"); + print PID $pid; + close(PID); + print "DONE\n"; + + unlink($env_vars->{SMBD_TEST_LOG}); + print "STARTING SMBD..."; + $pid = fork(); + if ($pid == 0) { + open STDOUT, ">$env_vars->{SMBD_TEST_LOG}"; + open STDERR, '>&STDOUT'; + + $ENV{MAKE_TEST_BINARY} = $self->binpath("smbd"); + exec($self->binpath("timelimit"), $nmbd_maxtime, $self->binpath("smbd"), "-F", "-S", "--no-process-group", "-d0" ,"-s", $env_vars->{SERVERCONFFILE}) or die("Unable to start smbd: $!"); + } + open(PID, ">$env_vars->{PIDDIR}/timelimit.smbd.pid"); + print PID $pid; + close(PID); + print "DONE\n"; + + return 0; +} + +sub create_clientconf($$$) +{ + my ($self, $prefix, $domain) = @_; + + my $lockdir = "$prefix/locks"; + my $logdir = "$prefix/logs"; + my $piddir = "$prefix/pid"; + my $privatedir = "$prefix/private"; + my $scriptdir = "$RealBin/.."; + my $conffile = "$prefix/smb.conf"; + + my $torture_interfaces='127.0.0.6/8,127.0.0.7/8,127.0.0.8/8,127.0.0.9/8,127.0.0.10/8,127.0.0.11/8'; + open(CONF, ">$conffile"); + print CONF " +[global] + workgroup = $domain + + private dir = $privatedir + pid directory = $piddir + lock directory = $lockdir + log file = $logdir/log.\%m + log level = 0 + + name resolve order = bcast + + netbios name = TORTURE_6 + interfaces = $torture_interfaces + panic action = $scriptdir/gdb_backtrace \%d %\$(MAKE_TEST_BINARY) + + passdb backend = tdbsam + "; + close(CONF); +} + +sub provision($$) +{ + my ($self, $prefix) = @_; + + ## + ## setup the various environment variables we need + ## + + my %ret = (); + my $server = "localhost2"; + my $server_ip = "127.0.0.2"; + my $username = `PATH=/usr/ucb:$ENV{PATH} whoami`; + my $password = "test"; + + my $srcdir="$RealBin/.."; + my $scriptdir="$srcdir/selftest"; + my $prefix_abs = abs_path($prefix); + my $shrdir="$prefix_abs/tmp"; + my $libdir="$prefix_abs/lib"; + my $piddir="$prefix_abs/pid"; + my $conffile="$libdir/server.conf"; + my $privatedir="$prefix_abs/private"; + my $lockdir="$prefix_abs/lockdir"; + my $logdir="$prefix_abs/logs"; + my $domain = "SAMBA-TEST"; + + ## + ## create the test directory layout + ## + mkdir($prefix_abs, 0777); + print "CREATE TEST ENVIRONMENT IN '$prefix'..."; + system("rm -rf $prefix_abs/*"); + mkdir($_, 0777) foreach($privatedir,$libdir,$piddir,$lockdir,$logdir); + my $tmpdir = "$prefix_abs/tmp"; + mkdir($tmpdir, 0777); + chmod 0777, $tmpdir; + + open(CONF, ">$conffile") or die("Unable to open $conffile"); + print CONF " +[global] + workgroup = $domain + + private dir = $privatedir + pid directory = $piddir + lock directory = $lockdir + log file = $logdir/log.\%m + log level = 0 + + name resolve order = bcast + + netbios name = $server + interfaces = $server_ip/8 + bind interfaces only = yes + panic action = $scriptdir/gdb_backtrace %d %\$(MAKE_TEST_BINARY) + + passdb backend = tdbsam + + ; Necessary to add the build farm hacks + add user script = /bin/false + add machine script = /bin/false + + kernel oplocks = no + kernel change notify = no + + syslog = no + printing = bsd + printcap name = /dev/null + +[tmp] + path = $tmpdir + read only = no + smbd:sharedelay = 100000 + map hidden = yes + map system = yes + create mask = 755 +[hideunread] + copy = tmp + hide unreadable = yes +[hideunwrite] + copy = tmp + hide unwriteable files = yes +[print1] + copy = tmp + printable = yes + printing = test +[print2] + copy = print1 +[print3] + copy = print1 +[print4] + copy = print1 + "; + close(CONF); + + ## + ## create a test account + ## + + open(PWD, "|".$self->binpath("smbpasswd")." -c $conffile -L -s -a $username"); + print PWD "$password\n$password\n"; + close(PWD) or die("Unable to set password for test account"); + + print "DONE\n"; + + $ret{SERVER_IP} = $server_ip; + $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log"; + $ret{SMBD_TEST_LOG} = "$prefix/smbd_test.log"; + $ret{SERVERCONFFILE} = $conffile; + $ret{CONFIGURATION} ="-s $conffile"; + $ret{SERVER} = $server; + $ret{USERNAME} = $username; + $ret{DOMAIN} = $domain; + $ret{NETBIOSNAME} = $server; + $ret{PASSWORD} = $password; + $ret{PIDDIR} = $piddir; + return \%ret; +} + +sub wait_for_start($$) +{ + my ($self, $envvars) = @_; + + # give time for nbt server to register its names + print "delaying for nbt name registration\n"; + sleep(10); + # This will return quickly when things are up, but be slow if we need to wait for (eg) SSL init + system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} __SAMBA__"); + system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} __SAMBA__"); + system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U 127.255.255.255 __SAMBA__"); + system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} $envvars->{SERVER}"); + system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} $envvars->{SERVER}"); + # make sure smbd is also up set + print "wait for smbd\n"; + system($self->binpath("smbclient") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER_IP} -U% -p 139 | head -2"); + system($self->binpath("smbclient") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER_IP} -U% -p 139 | head -2"); + + print $self->getlog_env($envvars); +} + +1; diff --git a/source4/selftest/Samba4.pm b/source4/selftest/Samba4.pm new file mode 100644 index 0000000000..acf5ceef3e --- /dev/null +++ b/source4/selftest/Samba4.pm @@ -0,0 +1,829 @@ +#!/usr/bin/perl +# Bootstrap Samba and run a number of tests against it. +# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL, v3 or later. + +package Samba4; + +use strict; +use Cwd qw(abs_path); +use FindBin qw($RealBin); +use POSIX; + +sub new($$$$) { + my ($classname, $bindir, $ldap, $setupdir) = @_; + my $self = { + vars => {}, + ldap => $ldap, + bindir => $bindir, + setupdir => $setupdir + }; + bless $self; + return $self; +} + +sub openldap_start($$$) { + my ($slapd_conf, $uri, $logs) = @_; + my $oldpath = $ENV{PATH}; + $ENV{PATH} = "/usr/local/sbin:/usr/sbin:/sbin:$ENV{PATH}"; + system("slapd -d0 -f $slapd_conf -h $uri > $logs 2>&1 &"); + $ENV{PATH} = $oldpath; +} + +sub slapd_start($$) +{ + my $count = 0; + my ($self, $env_vars) = @_; + + my $uri = $env_vars->{LDAP_URI}; + + # running slapd in the background means it stays in the same process group, so it can be + # killed by timelimit + if ($self->{ldap} eq "fedora") { + system("$ENV{FEDORA_DS_PREFIX}/sbin/ns-slapd -D $env_vars->{FEDORA_DS_DIR} -d0 -i $env_vars->{FEDORA_DS_PIDFILE}> $env_vars->{LDAPDIR}/logs 2>&1 &"); + } elsif ($self->{ldap} eq "openldap") { + openldap_start($env_vars->{SLAPD_CONF}, $uri, "$env_vars->{LDAPDIR}/logs"); + } + while (system("$self->{bindir}/ldbsearch -H $uri -s base -b \"\" supportedLDAPVersion > /dev/null") != 0) { + $count++; + if ($count > 40) { + $self->slapd_stop($env_vars); + return 0; + } + sleep(1); + } + return 1; +} + +sub slapd_stop($$) +{ + my ($self, $envvars) = @_; + if ($self->{ldap} eq "fedora") { + system("$envvars->{LDAPDIR}/slapd-samba4/stop-slapd"); + } elsif ($self->{ldap} eq "openldap") { + open(IN, "<$envvars->{OPENLDAP_PIDFILE}") or + die("unable to open slapd pid file: $envvars->{OPENLDAP_PIDFILE}"); + kill 9, <IN>; + close(IN); + } + return 1; +} + +sub check_or_start($$$) +{ + my ($self, $env_vars, $max_time) = @_; + return 0 if ( -p $env_vars->{SMBD_TEST_FIFO}); + + unlink($env_vars->{SMBD_TEST_FIFO}); + POSIX::mkfifo($env_vars->{SMBD_TEST_FIFO}, 0700); + unlink($env_vars->{SMBD_TEST_LOG}); + + print "STARTING SMBD... "; + my $pid = fork(); + if ($pid == 0) { + open STDIN, $env_vars->{SMBD_TEST_FIFO}; + open STDOUT, ">$env_vars->{SMBD_TEST_LOG}"; + open STDERR, '>&STDOUT'; + + SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE}); + + my $valgrind = ""; + if (defined($ENV{SMBD_VALGRIND})) { + $valgrind = $ENV{SMBD_VALGRIND}; + } + + $ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG}; + + # Start slapd before smbd, but with the fifo on stdin + if (defined($self->{ldap})) { + $self->slapd_start($env_vars) or + die("couldn't start slapd (2nd time)"); + } + + my $optarg = ""; + if (defined($max_time)) { + $optarg = "--maximum-runtime=$max_time "; + } + my $ret = system("$valgrind $self->{bindir}/smbd $optarg $env_vars->{CONFIGURATION} -M single -i --leak-report-full"); + if ($? == -1) { + print "Unable to start smbd: $ret: $!\n"; + exit 1; + } + unlink($env_vars->{SMBD_TEST_FIFO}); + my $exit = $? >> 8; + if ( $ret == 0 ) { + print "smbd exits with status $exit\n"; + } elsif ( $ret & 127 ) { + print "smbd got signal ".($ret & 127)." and exits with $exit!\n"; + } else { + $ret = $? >> 8; + print "smbd failed with status $exit!\n"; + } + exit $exit; + } + print "DONE\n"; + + open(DATA, ">$env_vars->{SMBD_TEST_FIFO}"); + + return $pid; +} + +sub wait_for_start($$) +{ + my ($self, $testenv_vars) = @_; + # give time for nbt server to register its names + print "delaying for nbt name registration\n"; + sleep 2; + + # This will return quickly when things are up, but be slow if we + # need to wait for (eg) SSL init + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSALIAS}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSALIAS}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSALIAS}"); + system("bin/nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSALIAS}"); + + print $self->getlog_env($testenv_vars); +} + +sub write_ldb_file($$$) +{ + my ($self, $file, $ldif) = @_; + + open(LDIF, "|$self->{bindir}/ldbadd -H $file >/dev/null"); + print LDIF $ldif; + return close(LDIF); +} + +sub add_wins_config($$) +{ + my ($self, $privatedir) = @_; + + return $self->write_ldb_file("$privatedir/wins_config.ldb", " +dn: name=TORTURE_6,CN=PARTNERS +objectClass: wreplPartner +name: TORTURE_6 +address: 127.0.0.6 +pullInterval: 0 +pushChangeCount: 0 +type: 0x3 +"); +} + +sub mk_fedora($$$$$$) +{ + my ($self, $ldapdir, $basedn, $root, $password, $privatedir, $configuration) = @_; + + mkdir($ldapdir, 0777); + + my $fedora_ds_inf = "$ldapdir/fedorads.inf"; + my $fedora_ds_initial_ldif = "$ldapdir/fedorads-initial.ldif"; + + #Make the subdirectory be as fedora DS would expect + my $fedora_ds_dir = "$ldapdir/slapd-samba4"; + + my $pidfile = "$fedora_ds_dir/logs/slapd-samba4.pid"; + + open(CONF, ">$fedora_ds_inf"); + print CONF " +[General] +SuiteSpotUserID = $root +FullMachineName= localhost +ServerRoot= $ldapdir + +[slapd] +ldapifilepath=$ldapdir/ldapi +Suffix= $basedn +RootDN= cn=Manager,$basedn +RootDNPwd= $password +ServerIdentifier= samba4 +#InstallLdifFile=$fedora_ds_initial_ldif + +inst_dir= $fedora_ds_dir +config_dir= $fedora_ds_dir +schema_dir= $fedora_ds_dir/schema +lock_dir= $fedora_ds_dir/lock +log_dir= $fedora_ds_dir/logs +run_dir= $fedora_ds_dir/logs +db_dir= $fedora_ds_dir/db +bak_dir= $fedora_ds_dir/bak +tmp_dir= $fedora_ds_dir/tmp +ldif_dir= $fedora_ds_dir/ldif +cert_dir= $fedora_ds_dir + +start_server= 0 +"; + close(CONF); + + open(LDIF, ">$fedora_ds_initial_ldif"); + +my $dir = getcwd(); +chdir "$ENV{FEDORA_DS_PREFIX}/bin" || die; + if (system("perl $ENV{FEDORA_DS_PREFIX}/bin/ds_newinst.pl $fedora_ds_inf >&2") != 0) { + chdir $dir; + die("perl $ENV{FEDORA_DS_PREFIX}/bin/ds_newinst.pl $fedora_ds_inf FAILED: $?"); + } + chdir $dir || die; + foreach(<$fedora_ds_dir/schema/*>) { + unlink unless (/00core.*/); + } + + open(LDIF, ">>$fedora_ds_dir/dse.ldif"); + print LDIF "dn: cn=\"cn=Configuration,$basedn\",cn=mapping tree,cn=config +objectclass: top +objectclass: extensibleObject +objectclass: nsMappingTree +nsslapd-state: backend +nsslapd-backend: configData +cn: cn=Configuration,$basedn + +dn: cn=configData,cn=ldbm database,cn=plugins,cn=config +objectclass: extensibleObject +objectclass: nsBackendInstance +nsslapd-suffix: cn=Configuration,$basedn +cn: configData + +dn: cn=\"cn=Schema,cn=Configuration,$basedn\",cn=mapping tree,cn=config +objectclass: top +objectclass: extensibleObject +objectclass: nsMappingTree +nsslapd-state: backend +nsslapd-backend: schemaData +cn: cn=Schema,cn=Configuration,$basedn + +dn: cn=schemaData,cn=ldbm database,cn=plugins,cn=config +objectclass: extensibleObject +objectclass: nsBackendInstance +nsslapd-suffix: cn=Schema,cn=Configuration,$basedn +cn: schemaData + +dn: cn=bitwise,cn=plugins,cn=config +objectClass: top +objectClass: nsSlapdPlugin +objectClass: extensibleObject +cn: bitwise +nsslapd-pluginPath: $ENV{FEDORA_DS_PREFIX}/lib/fedora-ds/plugins/libbitwise-plugin.so +nsslapd-pluginInitfunc: bitwise_init +nsslapd-pluginType: matchingRule +nsslapd-pluginEnabled: on +nsslapd-pluginId: bitwise +nsslapd-pluginVersion: 1.1.0a3 +nsslapd-pluginVendor: Fedora Project +nsslapd-pluginDescription: Allow bitwise matching rules +"; + close(LDIF); + + system("$self->{bindir}/ad2oLschema $configuration -H $privatedir/sam.ldb --option=convert:target=fedora-ds -I $self->{setupdir}/schema-map-fedora-ds-1.0 -O $fedora_ds_dir/schema/99_ad.ldif >&2") == 0 or die("schema conversion for Fedora DS failed"); + + return ($fedora_ds_dir, $pidfile); +} + +sub write_openldap_dbconfig($) { + my ( $ldapdbdir ) = @_; + open(CONF, ">$ldapdbdir/DB_CONFIG"); + print CONF " +# + # Set the database in memory cache size. + # + set_cachesize 0 524288 0 + + + # + # Set database flags (this is a test environment, we don't need to fsync()). + # + set_flags DB_TXN_NOSYNC + + # + # Set log values. + # + set_lg_regionmax 104857 + set_lg_max 1048576 + set_lg_bsize 209715 + set_lg_dir $ldapdbdir/bdb-logs + + + # + # Set temporary file creation directory. + # + set_tmp_dir $ldapdbdir/tmp + "; + close(CONF); + + +} + +sub mk_openldap($$$$$$$$) +{ + my ($self, $ldapdir, $basedn, $password, $privatedir, $dnsname, $configuration, $provision_options) = @_; + + my $slapd_conf = "$ldapdir/slapd.conf"; + my $pidfile = "$ldapdir/slapd.pid"; + my $modconf = "$ldapdir/modules.conf"; + + mkdir($_, 0777) foreach ($ldapdir, "$ldapdir/db", "$ldapdir/db/user", "$ldapdir/db/config", "$ldapdir/db/schema", "$ldapdir/db/bdb-logs", + "$ldapdir/db/tmp"); + + open(CONF, ">$slapd_conf"); + print CONF " +loglevel 0 + +include $ldapdir/ad.schema + +pidfile $pidfile +argsfile $ldapdir/slapd.args +sasl-realm $dnsname +access to * by * write + +allow update_anon + +authz-regexp + uid=([^,]*),cn=$dnsname,cn=digest-md5,cn=auth + ldap:///$basedn??sub?(samAccountName=\$1) + +authz-regexp + uid=([^,]*),cn=([^,]*),cn=digest-md5,cn=auth + ldap:///$basedn??sub?(samAccountName=\$1) + +include $modconf + +defaultsearchbase \"$basedn\" + +backend bdb +database bdb +suffix \"cn=Schema,cn=Configuration,$basedn\" +directory $ldapdir/db/schema +index objectClass eq +index samAccountName eq +index name eq +index objectCategory eq +index lDAPDisplayName eq +index subClassOf eq + +database bdb +suffix \"cn=Configuration,$basedn\" +directory $ldapdir/db/config +index objectClass eq +index samAccountName eq +index name eq +index objectSid eq +index objectCategory eq +index nCName eq pres +index subClassOf eq +index dnsRoot eq +index nETBIOSName eq pres + +database bdb +suffix \"$basedn\" +rootdn \"cn=Manager,$basedn\" +rootpw $password +directory $ldapdir/db/user +index objectClass eq +index samAccountName eq +index name eq +index objectSid eq +index objectCategory eq +index member eq +index uidNumber eq +index gidNumber eq +index unixName eq +index privilege eq +index nCName eq pres +index lDAPDisplayName eq +index subClassOf eq +index dnsRoot eq +index nETBIOSName eq pres + +#syncprov is stable in OpenLDAP 2.3, and available in 2.2. +#We only need this for the contextCSN attribute anyway.... +overlay syncprov +syncprov-checkpoint 100 10 +syncprov-sessionlog 100 +"; + + close(CONF); + + write_openldap_dbconfig("$ldapdir/db/user"); + write_openldap_dbconfig("$ldapdir/db/config"); + write_openldap_dbconfig("$ldapdir/db/schema"); + + #This uses the provision we just did, to read out the schema + system("$self->{bindir}/ad2oLschema $configuration -H $privatedir/sam.ldb -I $self->{setupdir}/schema-map-openldap-2.3 -O $ldapdir/ad.schema >&2") == 0 or die("schema conversion for OpenLDAP failed"); + + #Now create an LDAP baseDN + system("$self->{bindir}/smbscript $self->{setupdir}/provision $provision_options --ldap-base >&2") == 0 or die("creating an OpenLDAP basedn failed"); + + my $oldpath = $ENV{PATH}; + $ENV{PATH} = "/usr/local/sbin:/usr/sbin:/sbin:$ENV{PATH}"; + + unlink($modconf); + open(CONF, ">$modconf"); close(CONF); + + if (system("slaptest -u -f $slapd_conf >&2") != 0) { + open(CONF, ">$modconf"); + # enable slapd modules + print CONF " +modulepath /usr/lib/ldap +moduleload back_bdb +moduleload syncprov +"; + close(CONF); + } + + system("slaptest -u -f $slapd_conf") == 0 or die("slaptest still fails after adding modules"); + system("slapadd -b $basedn -f $slapd_conf -l $privatedir/$dnsname.ldif >/dev/null") == 0 or die("slapadd failed"); + system("slapadd -b cn=Configuration,$basedn -f $slapd_conf -l $privatedir/$dnsname-config.ldif >/dev/null") == 0 or die("slapadd failed"); + system("slapadd -b cn=Schema,cn=Configuration,$basedn -f $slapd_conf -l $privatedir/$dnsname-schema.ldif >/dev/null") == 0 or die("slapadd failed"); + + system("slaptest -f $slapd_conf >/dev/null") == 0 or + die ("slaptest after database load failed"); + + $ENV{PATH} = $oldpath; + + return ($slapd_conf, $pidfile); +} + +sub provision($$$$$$) +{ + my ($self, $prefix, $server_role, $netbiosname, $netbiosalias, $swiface, $password) = @_; + + my $smbd_loglevel = 1; + my $username = "administrator"; + my $domain = "SAMBADOMAIN"; + my $realm = "SAMBA.EXAMPLE.COM"; + my $dnsname = "samba.example.com"; + my $basedn = "dc=samba,dc=example,dc=com"; + my $root = ($ENV{USER} or $ENV{LOGNAME} or `whoami`); + my $srcdir="$RealBin/.."; + -d $prefix or mkdir($prefix, 0777) or die("Unable to create $prefix"); + my $prefix_abs = abs_path($prefix); + my $tmpdir = "$prefix_abs/tmp"; + my $etcdir = "$prefix_abs/etc"; + my $piddir = "$prefix_abs/pid"; + my $conffile = "$etcdir/smb.conf"; + my $krb5_config = "$etcdir/krb5.conf"; + my $privatedir = "$prefix_abs/private"; + my $ncalrpcdir = "$prefix_abs/ncalrpc"; + my $lockdir = "$prefix_abs/lockdir"; + my $winbindd_socket_dir = "$prefix_abs/winbind_socket"; + + my $configuration = "--configfile=$conffile"; + my $ldapdir = "$prefix_abs/ldap"; + + my $tlsdir = "$privatedir/tls"; + + my $ifaceipv4 = "127.0.0.$swiface"; + my $interfaces = "$ifaceipv4/8"; + + (system("rm -rf $prefix/*") == 0) or die("Unable to clean up"); + mkdir($_, 0777) foreach ($privatedir, $etcdir, $piddir, $ncalrpcdir, $lockdir, + $tmpdir); + + open(CONFFILE, ">$conffile"); + print CONFFILE " +[global] + netbios name = $netbiosname + netbios aliases = $netbiosalias + workgroup = $domain + realm = $realm + private dir = $privatedir + pid directory = $piddir + ncalrpc dir = $ncalrpcdir + lock dir = $lockdir + setup directory = $self->{setupdir} + js include = $srcdir/scripting/libjs + winbindd socket directory = $winbindd_socket_dir + name resolve order = bcast + interfaces = $interfaces + tls dh params file = $tlsdir/dhparms.pem + panic action = $srcdir/script/gdb_backtrace \%PID% \%PROG% + wins support = yes + server role = $server_role + max xmit = 32K + server max protocol = SMB2 + notify:inotify = false + ldb:nosync = true + system:anonymous = true +#We don't want to pass our self-tests if the PAC code is wrong + gensec:require_pac = true + log level = $smbd_loglevel + +[tmp] + path = $tmpdir + read only = no + ntvfs handler = posix + posix:sharedelay = 100000 + posix:eadb = $lockdir/eadb.tdb + +[cifs] + read only = no + ntvfs handler = cifs + cifs:server = $netbiosname + cifs:share = tmp +#There is no username specified here, instead the client is expected +#to log in with kerberos, and smbd will used delegated credentials. + +[simple] + path = $tmpdir + read only = no + ntvfs handler = simple + +[cifsposixtestshare] + copy = simple + ntvfs handler = cifsposix +"; + close(CONFFILE); + + die ("Unable to create key blobs") if + (system("TLSDIR=$tlsdir $RealBin/mk-keyblobs.sh") != 0); + + open(KRB5CONF, ">$krb5_config"); + print KRB5CONF " +#Generated krb5.conf for $realm + +[libdefaults] + default_realm = $realm + dns_lookup_realm = false + dns_lookup_kdc = false + ticket_lifetime = 24h + forwardable = yes + +[realms] + $realm = { + kdc = 127.0.0.1:88 + admin_server = 127.0.0.1:88 + default_domain = $dnsname + } + $dnsname = { + kdc = 127.0.0.1:88 + admin_server = 127.0.0.1:88 + default_domain = $dnsname + } + $domain = { + kdc = 127.0.0.1:88 + admin_server = 127.0.0.1:88 + default_domain = $dnsname + } + +[appdefaults] + pkinit_anchors = FILE:$tlsdir/ca.pem + +[kdc] + enable-pkinit = true + pkinit_identity = FILE:$tlsdir/kdc.pem,$tlsdir/key.pem + pkinit_anchors = FILE:$tlsdir/ca.pem + +[domain_realm] + .$dnsname = $realm +"; + close(KRB5CONF); + +#Ensure the config file is valid before we start + if (system("$self->{bindir}/testparm $configuration -v --suppress-prompt >/dev/null 2>&1") != 0) { + system("$self->{bindir}/testparm $configuration >&2"); + die("Failed to create a valid smb.conf configuration!"); + } + + (system("($self->{bindir}/testparm $configuration -v --suppress-prompt --parameter-name=\"netbios name\" --section-name=global 2> /dev/null | grep -i ^$netbiosname ) >/dev/null 2>&1") == 0) or die("Failed to create a valid smb.conf configuration!"); + + my @provision_options = ($configuration); + push (@provision_options, "--host-name=$netbiosname"); + push (@provision_options, "--host-ip=$ifaceipv4"); + push (@provision_options, "--quiet"); + push (@provision_options, "--domain $domain"); + push (@provision_options, "--realm $realm"); + push (@provision_options, "--adminpass $password"); + push (@provision_options, "--krbtgtpass krbtgt$password"); + push (@provision_options, "--machinepass machine$password"); + push (@provision_options, "--root=$root"); + push (@provision_options, "--simple-bind-dn=cn=Manager,$basedn"); + push (@provision_options, "--password=$password"); + push (@provision_options, "--root=$root"); + + (system("$self->{bindir}/smbscript $self->{setupdir}/provision " . join(' ', @provision_options) . ">&2") == 0) or die("Unable to provision"); + + my $ldap_uri= "$ldapdir/ldapi"; + $ldap_uri =~ s|/|%2F|g; + $ldap_uri = "ldapi://$ldap_uri"; + + my $ret = { + KRB5_CONFIG => $krb5_config, + PIDDIR => $piddir, + SERVER => $netbiosname, + SERVER_IP => $ifaceipv4, + NETBIOSNAME => $netbiosname, + NETBIOSALIAS => $netbiosalias, + LDAP_URI => $ldap_uri, + DOMAIN => $domain, + USERNAME => $username, + REALM => $realm, + PASSWORD => $password, + LDAPDIR => $ldapdir, + WINBINDD_SOCKET_DIR => $winbindd_socket_dir, + NCALRPCDIR => $ncalrpcdir, + CONFIGURATION => $configuration, + SOCKET_WRAPPER_DEFAULT_IFACE => $swiface + }; + + if (defined($self->{ldap})) { + + if ($self->{ldap} eq "openldap") { + ($ret->{SLAPD_CONF}, $ret->{OPENLDAP_PIDFILE}) = $self->mk_openldap($ldapdir, $basedn, $password, $privatedir, $dnsname, $configuration, join(' ', @provision_options)) or die("Unable to create openldap directories"); + } elsif ($self->{ldap} eq "fedora") { + ($ret->{FEDORA_DS_DIR}, $ret->{FEDORA_DS_PIDFILE}) = $self->mk_fedora($ldapdir, $basedn, $root, $password, $privatedir, $configuration) or die("Unable to create fedora ds directories"); + push (@provision_options, "--ldap-module=nsuniqueid"); + } + + $self->slapd_start($ret) or + die("couldn't start slapd"); + + $ret->{PROVISION_OPTIONS} = join(' ', @provision_options); + + print "LDAP PROVISIONING..."; + $self->provision_ldap($ret); + + $self->slapd_stop($ret) or + die("couldn't stop slapd"); + } else { + $ret->{PROVISION_OPTIONS} = join(' ', @provision_options); + } + return $ret; +} + +sub provision_member($$$) +{ + my ($self, $prefix, $dcvars) = @_; + print "PROVISIONING MEMBER..."; + + my $ret = $self->provision($prefix, + "member server", + "localmember3", + "localmember", + 3, + "localmemberpass"); + + $ret or die("Unable to provision"); + + system("$self->{bindir}/net join $ret->{CONFIGURATION} $dcvars->{DOMAIN} member -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}") == 0 or die("Join failed"); + + $ret->{SMBD_TEST_FIFO} = "$prefix/smbd_test.fifo"; + $ret->{SMBD_TEST_LOG} = "$prefix/smbd_test.log"; + $ret->{SMBD_TEST_LOG_POS} = 0; + + $ret->{DC_SERVER} = $dcvars->{SERVER}; + $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP}; + $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME}; + $ret->{DC_NETBIOSALIAS} = $dcvars->{NETBIOSALIAS}; + $ret->{DC_USERNAME} = $dcvars->{USERNAME}; + $ret->{DC_PASSWORD} = $dcvars->{PASSWORD}; + + return $ret; +} + +sub provision_dc($$) +{ + my ($self, $prefix) = @_; + + print "PROVISIONING DC..."; + my $ret = $self->provision($prefix, + "domain controller", + "localdc1", + "localdc", + 1, + "localdcpass"); + + $self->add_wins_config("$prefix/private") or + die("Unable to add wins configuration"); + + $ret->{SMBD_TEST_FIFO} = "$prefix/smbd_test.fifo"; + $ret->{SMBD_TEST_LOG} = "$prefix/smbd_test.log"; + $ret->{SMBD_TEST_LOG_POS} = 0; + return $ret; +} + +sub provision_ldap($$) +{ + my ($self, $envvars) = @_; + my $provision_aci = ""; + + if ($self->{ldap} eq "fedora") { + #it is easier to base64 encode this than correctly escape it: + # (targetattr = "*") (version 3.0;acl "full access to all by all";allow (all)(userdn = "ldap:///anyone");) + $provision_aci = "--aci=aci:: KHRhcmdldGF0dHIgPSAiKiIpICh2ZXJzaW9uIDMuMDthY2wgImZ1bGwgYWNjZXNzIHRvIGFsbCBieSBhbGwiO2FsbG93IChhbGwpKHVzZXJkbiA9ICJsZGFwOi8vL2FueW9uZSIpOykK"; + } + + system("$self->{bindir}/smbscript $self->{setupdir}/provision $envvars->{PROVISION_OPTIONS} \"$provision_aci\" --ldap-backend=$envvars->{LDAP_URI}") and + die("LDAP PROVISIONING failed: $self->{bindir}/smbscript $self->{setupdir}/provision $envvars->{PROVISION_OPTIONS} \"$provision_aci\" --ldap-backend=$envvars->{LDAP_URI}"); +} + +sub teardown_env($$) +{ + my ($self, $envvars) = @_; + + close(DATA); + + sleep(2); + + my $failed = $? >> 8; + + if (-f "$envvars->{PIDDIR}/smbd.pid" ) { + open(IN, "<$envvars->{PIDDIR}/smbd.pid") or die("unable to open smbd pid file"); + kill 9, <IN>; + close(IN); + } + + $self->slapd_stop($envvars) if ($self->{ldap}); + + print $self->getlog_env($envvars); + + return $failed; +} + +sub getlog_env($$) +{ + my ($self, $envvars) = @_; + my $title = "SMBD LOG of: $envvars->{NETBIOSNAME}\n"; + my $out = $title; + + open(LOG, "<$envvars->{SMBD_TEST_LOG}"); + + seek(LOG, $envvars->{SMBD_TEST_LOG_POS}, SEEK_SET); + while (<LOG>) { + $out .= $_; + } + $envvars->{SMBD_TEST_LOG_POS} = tell(LOG); + close(LOG); + + return "" if $out eq $title; + + return $out; +} + +sub check_env($$) +{ + my ($self, $envvars) = @_; + + return 1 if (-p $envvars->{SMBD_TEST_FIFO}); + + print $self->getlog_env($envvars); + + return 0; +} + +sub setup_env($$$) +{ + my ($self, $envname, $path) = @_; + + if ($envname eq "dc") { + return $self->setup_dc("$path/dc"); + } elsif ($envname eq "member") { + if (not defined($self->{vars}->{dc})) { + $self->setup_dc("$path/dc"); + } + return $self->setup_member("$path/member", $self->{vars}->{dc}); + } else { + die("Samba4 can't provide environment '$envname'"); + } +} + +sub setup_member($$$$) +{ + my ($self, $path, $dc_vars) = @_; + + my $env = $self->provision_member($path, $dc_vars); + + $self->check_or_start($env, ($ENV{SMBD_MAXTIME} or 6500)); + + $self->wait_for_start($env); + + return $env; +} + +sub setup_dc($$) +{ + my ($self, $path) = @_; + + my $env = $self->provision_dc($path); + + $self->check_or_start($env, + ($ENV{SMBD_MAXTIME} or 6500)); + + $self->wait_for_start($env); + + $self->{vars}->{dc} = $env; + + return $env; +} + +sub stop($) +{ + my ($self) = @_; +} + +1; diff --git a/source4/selftest/SocketWrapper.pm b/source4/selftest/SocketWrapper.pm new file mode 100644 index 0000000000..e63605b8df --- /dev/null +++ b/source4/selftest/SocketWrapper.pm @@ -0,0 +1,66 @@ +#!/usr/bin/perl +# Bootstrap Samba and run a number of tests against it. +# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL, v3 or later. + +package SocketWrapper; + +use Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(setup_dir setup_pcap set_default_iface); + +use strict; +use FindBin qw($RealBin); + +sub setup_dir($$) +{ + my ($dir, $pcap) = @_; + my $pcap_dir = undef; + + if (defined($dir)) { + if ( -d $dir ) { + unlink <$dir/*>; + } else { + mkdir($dir, 0777); + } + + if ($pcap) { + $pcap_dir = $dir."/pcap"; + + if ( -d $pcap_dir ) { + unlink <$pcap_dir/*>; + } else { + mkdir($pcap_dir, 0777); + } + } + } + + if (defined($pcap_dir)) { + $ENV{SOCKET_WRAPPER_PCAP_DIR} = $pcap_dir; + } else { + delete $ENV{SOCKET_WRAPPER_PCAP_DIR}; + } + + if (defined($dir)) { + $ENV{SOCKET_WRAPPER_DIR} = $dir; + } else { + delete $ENV{SOCKET_WRAPPER_DIR}; + } + + return $dir; +} + +sub setup_pcap($) +{ + my ($pcap_file) = @_; + + $ENV{SOCKET_WRAPPER_PCAP_FILE} = $pcap_file; +} + +sub set_default_iface($) +{ + my ($i) = @_; + $ENV{SOCKET_WRAPPER_DEFAULT_IFACE} = $i; +} + +1; diff --git a/source4/selftest/TODO b/source4/selftest/TODO new file mode 100644 index 0000000000..42f90188ed --- /dev/null +++ b/source4/selftest/TODO @@ -0,0 +1,3 @@ +- warn about unexpected successes +- better way to detect that smbd has finished initialization +- move ldap-specific code into mktestdc.sh diff --git a/source4/selftest/Windows.pm b/source4/selftest/Windows.pm new file mode 100644 index 0000000000..d0c90d7f7b --- /dev/null +++ b/source4/selftest/Windows.pm @@ -0,0 +1,40 @@ +#!/usr/bin/perl +# Bootstrap Samba and run a number of tests against it. +# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL, v3 or later. + +package Windows; + +use strict; +use FindBin qw($RealBin); +use POSIX; + +sub new($) +{ + my ($classname) = @_; + my $self = { }; + bless $self; + return $self; +} + +sub provision($$$) +{ + my ($self, $environment, $prefix) = @_; + + die ("Windows tests will not run without root privileges.") + if (`whoami` ne "root"); + + die("Environment variable WINTESTCONF has not been defined.\n". + "Windows tests will not run unconfigured.") if (not defined($ENV{WINTESTCONF})); + + die ("$ENV{WINTESTCONF} could not be read.") if (! -r $ENV{WINTESTCONF}); + + $ENV{WINTEST_DIR}="$ENV{SRCDIR}/selftest/win"; +} + +sub setup_env($$) +{ + my ($self, $name) = @_; +} + +1; diff --git a/source4/selftest/mk-keyblobs.sh b/source4/selftest/mk-keyblobs.sh new file mode 100755 index 0000000000..7792e0a6d5 --- /dev/null +++ b/source4/selftest/mk-keyblobs.sh @@ -0,0 +1,156 @@ +#TLS and PKINIT crypto blobs +DHFILE=$TLSDIR/dhparms.pem +CAFILE=$TLSDIR/ca.pem +CERTFILE=$TLSDIR/cert.pem +REQKDC=$TLSDIR/req-kdc.der +KDCCERTFILE=$TLSDIR/kdc.pem +KEYFILE=$TLSDIR/key.pem +ADMINKEYFILE=$TLSDIR/adminkey.pem +REQADMIN=$TLSDIR/req-admin.der +ADMINKEYFILE=$TLSDIR/adminkey.pem +ADMINCERTFILE=$TLSDIR/admincert.pem + +mkdir -p $TLSDIR + +#This is specified here to avoid draining entropy on every run +cat >$DHFILE<<EOF +-----BEGIN DH PARAMETERS----- +MGYCYQC/eWD2xkb7uELmqLi+ygPMKyVcpHUo2yCluwnbPutEueuxrG/Cys8j8wLO +svCN/jYNyR2NszOmg7ZWcOC/4z/4pWDVPUZr8qrkhj5MRKJc52MncfaDglvEdJrv +YX70obsCAQI= +-----END DH PARAMETERS----- + +EOF + +#Likewise, we pregenerate the key material. This allows the +#other certificates to be pre-generated +cat >$KEYFILE<<EOF +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpc +ol3+S9/6I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H +6H+pPqVIRLOmrWImai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQAB +AoGAAqDLzFRR/BF1kpsiUfL4WFvTarCe9duhwj7ORc6fs785qAXuwUYAJ0Uvzmy6 +HqoGv3t3RfmeHDmjcpPHsbOKnsOQn2MgmthidQlPBMWtQMff5zdoYNUFiPS0XQBq +szNW4PRjaA9KkLQVTwnzdXGkBSkn/nGxkaVu7OR3vJOBoo0CQQDO4upypesnbe6p +9/xqfZ2uim8IwV1fLlFClV7WlCaER8tsQF4lEi0XSzRdXGUD/dilpY88Nb+xok/X +8Z8OvgAXAkEA+pcLsx1gN7kxnARxv54jdzQjC31uesJgMKQXjJ0h75aUZwTNHmZQ +vPxi6u62YiObrN5oivkixwFNncT9MxTxVQJBAMaWUm2SjlLe10UX4Zdm1MEB6OsC +kVoX37CGKO7YbtBzCfTzJGt5Mwc1DSLA2cYnGJqIfSFShptALlwedot0HikCQAJu +jNKEKnbf+TdGY8Q0SKvTebOW2Aeg80YFkaTvsXCdyXrmdQcifw4WdO9KucJiDhSz +Y9hVapz7ykEJtFtWjLECQQDIlfc63I5ZpXfg4/nN4IJXUW6AmPVOYIA5215itgki +cSlMYli1H9MEXH0pQMGv5Qyd0OYIx2DDg96mZ+aFvqSG +-----END RSA PRIVATE KEY----- + +EOF + +cat >$ADMINKEYFILE<<EOF +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQD0+OL7TQBj0RejbIH1+g5GeRaWaM9xF43uE5y7jUHEsi5owhZF +5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMFxB6esnXhl0Jpip1JkUMM +XLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xdl3JRlwIDAQAB +AoGAP8mjCP628Ebc2eACQzOWjgEvwYCPK4qPmYOf1zJkArzG2t5XAGJ5WGrENRuB +cm3XFh1lpmaADl982UdW3gul4gXUy6w4XjKK4vVfhyHj0kZ/LgaXUK9BAGhroJ2L +osIOUsaC6jdx9EwSRctwdlF3wWJ8NK0g28AkvIk+FlolW4ECQQD7w5ouCDnf58CN +u4nARx4xv5XJXekBvOomkCQAmuOsdOb6b9wn3mm2E3au9fueITjb3soMR31AF6O4 +eAY126rXAkEA+RgHzybzZEP8jCuznMqoN2fq/Vrs6+W3M8/G9mzGEMgLLpaf2Jiz +I9tLZ0+OFk9tkRaoCHPfUOCrVWJZ7Y53QQJBAMhoA6rw0WDyUcyApD5yXg6rusf4 +ASpo/tqDkqUIpoL464Qe1tjFqtBM3gSXuhs9xsz+o0bzATirmJ+WqxrkKTECQHt2 +OLCpKqwAspU7N+w32kaUADoRLisCEdrhWklbwpQgwsIVsCaoEOpt0CLloJRYTANE +yoZeAErTALjyZYZEPcECQQDlUi0N8DFxQ/lOwWyR3Hailft+mPqoPCa8QHlQZnlG ++cfgNl57YHMTZFwgUVFRdJNpjH/WdZ5QxDcIVli0q+Ko +-----END RSA PRIVATE KEY----- + +EOF + +#generated with +#hxtool issue-certificate --self-signed --issue-ca --ca-private-key=FILE:$KEYFILE \ +# --subject="CN=CA,$BASEDN" --certificate="FILE:$CAFILE" + +cat >$CAFILE<<EOF +-----BEGIN CERTIFICATE----- +MIIChTCCAe6gAwIBAgIUFZoF6jt0R+hQBdF7cWPy0tT3fGwwCwYJKoZIhvcNAQEFMFIxEzAR +BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy +LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDU1MzA5WhgPMjAwODAxMjQw +NTUzMDlaMFIxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl +MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpcol3+S9/6 +I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H6H+pPqVIRLOmrWIm +ai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABo1YwVDAOBgNVHQ8BAf8EBAMC +AqQwEgYDVR0lBAswCQYHKwYBBQIDBTAdBgNVHQ4EFgQUwtm596AMotmzRU7IVdgrUvozyjIw +DwYDVR0TBAgwBgEB/wIBADANBgkqhkiG9w0BAQUFAAOBgQBgzh5uLDmESGYv60iUdEfuk/T9 +VCpzb1z3VJVWt3uJoQYbcpR00SKeyMdlfTTLzO6tSPMmlk4hwqfvLkPzGCSObR4DRRYa0BtY +2laBVlg9X59bGpMUvpFQfpvxjvFWNJDL+377ELCVpLNdoR23I9TKXlalj0bY5Ks46CVIrm6W +EA== +-----END CERTIFICATE----- + +EOF + +#generated with GNUTLS internally in Samba. + +cat >$CERTFILE<<EOF +-----BEGIN CERTIFICATE----- +MIICYTCCAcygAwIBAgIE5M7SRDALBgkqhkiG9w0BAQUwZTEdMBsGA1UEChMUU2Ft +YmEgQWRtaW5pc3RyYXRpb24xNDAyBgNVBAsTK1NhbWJhIC0gdGVtcG9yYXJ5IGF1 +dG9nZW5lcmF0ZWQgY2VydGlmaWNhdGUxDjAMBgNVBAMTBVNhbWJhMB4XDTA2MDgw +NDA0MzY1MloXDTA4MDcwNDA0MzY1MlowZTEdMBsGA1UEChMUU2FtYmEgQWRtaW5p +c3RyYXRpb24xNDAyBgNVBAsTK1NhbWJhIC0gdGVtcG9yYXJ5IGF1dG9nZW5lcmF0 +ZWQgY2VydGlmaWNhdGUxDjAMBgNVBAMTBVNhbWJhMIGcMAsGCSqGSIb3DQEBAQOB +jAAwgYgCgYDKg6pAwCHUMA1DfHDmWhZfd+F0C+9Jxcqvpw9ii9En3E1uflpcol3+ +S9/6I/uaTmJHZre+DF3dTzb/UOZo0Zem8N+IzzkgoGkFafjXuT3BL5UPY2/H6H+p +PqVIRLOmrWImai359YyoKhFyo37Y6HPeU8QcZ+u2rS9geapIWfeuowIDAQABoyUw +IzAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAsGCSqGSIb3DQEB +BQOBgQAmkN6XxvDnoMkGcWLCTwzxGfNNSVcYr7TtL2aJh285Xw9zaxcm/SAZBFyG +LYOChvh6hPU7joMdDwGfbiLrBnMag+BtGlmPLWwp/Kt1wNmrRhduyTQFhN3PP6fz +nBr9vVny2FewB2gHmelaPS//tXdxivSXKz3NFqqXLDJjq7P8wA== +-----END CERTIFICATE----- + +EOF + +#KDC certificate +# hxtool request-create --subject="CN=krbtgt,cn=users,$basedn" --key=FILE:$KEYFILE $KDCREQ + +# hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE --type="pkinit-kdc" --pk-init-principal="krbtgt/$RELAM@$REALM" --req="$KDCREQ" --certificate="FILE:$KDCCERTFILE" + +cat >$KDCCERTFILE<<EOF +-----BEGIN CERTIFICATE----- +MIIDDDCCAnWgAwIBAgIUDEhjaOT1ZjHjHHEn+l5eYO05oK8wCwYJKoZIhvcNAQEFMFIxEzAR +BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy +LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDcwNzA4WhgPMjAwODAxMjQw +NzA3MDhaMGYxEzARBgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxl +MRUwEwYKCZImiZPyLGQBGQwFc2FtYmExDjAMBgNVBAMMBXVzZXJzMQ8wDQYDVQQDDAZrcmJ0 +Z3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMqDqkDAIdQwDUN8cOZaFl934XQL70nF +yq+nD2KL0SfcTW5+WlyiXf5L3/oj+5pOYkdmt74MXd1PNv9Q5mjRl6bw34jPOSCgaQVp+Ne5 +PcEvlQ9jb8fof6k+pUhEs6atYiZqLfn1jKgqEXKjftjoc95TxBxn67atL2B5qkhZ966jAgMB +AAGjgcgwgcUwDgYDVR0PAQH/BAQDAgWgMBIGA1UdJQQLMAkGBysGAQUCAwUwVAYDVR0RBE0w +S6BJBgYrBgEFAgKgPzA9oBMbEVNBTUJBLkVYQU1QTEUuQ09NoSYwJKADAgEBoR0wGxsGa3Ji +dGd0GxFTQU1CQS5FWEFNUExFLkNPTTAfBgNVHSMEGDAWgBTC2bn3oAyi2bNFTshV2CtS+jPK +MjAdBgNVHQ4EFgQUwtm596AMotmzRU7IVdgrUvozyjIwCQYDVR0TBAIwADANBgkqhkiG9w0B +AQUFAAOBgQCMSgLkIv9RobE0a95H2ECA+5YABBwKXIt4AyN/HpV7iJdRx7B9PE6vM+nboVKY +E7i7ECUc3bu6NgrLu7CKHelNclHWWMiZzSUwhkXyvG/LE9qtr/onNu9NfLt1OV+dwQwyLdEP +n63FxSmsKg3dfi3ryQI/DIKeisvipwDtLqOn9g== +-----END CERTIFICATE----- + +EOF + +#hxtool request-create --subject="CN=Administrator,cn=users,$basedn" --key=FILE:$ADMINKEYFILE $ADMINREQFILE +#hxtool issue-certificate --ca-certificate=FILE:$CAFILE,$KEYFILE --type="pkinit-client" --pk-init-principal="administrator@$REALM" --req="$ADMINREQFILE" --certificate="FILE:$ADMINCERTFILE" + +cat >$ADMINCERTFILE<<EOF +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgIUXyECoq4im33ByZDWZMGhtpvHYWEwCwYJKoZIhvcNAQEFMFIxEzAR +BgoJkiaJk/IsZAEZDANjb20xFzAVBgoJkiaJk/IsZAEZDAdleGFtcGxlMRUwEwYKCZImiZPy +LGQBGQwFc2FtYmExCzAJBgNVBAMMAkNBMCIYDzIwMDcwMTIzMDcyMzE2WhgPMjAwODAxMjQw +NzIzMTZaMCgxDjAMBgNVBAMMBXVzZXJzMRYwFAYDVQQDDA1BZG1pbmlzdHJhdG9yMIGfMA0G +CSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0+OL7TQBj0RejbIH1+g5GeRaWaM9xF43uE5y7jUHE +si5owhZF5iIoHZeeL6cpDF5y1BZRs0JlA1VqMry1jjKlzFYVEMMFxB6esnXhl0Jpip1JkUMM +XLOP1m/0dqayuHBWozj9f/cdyCJr0wJIX1Z8Pr+EjYRGPn/MF0xdl3JRlwIDAQABo4G8MIG5 +MA4GA1UdDwEB/wQEAwIFoDASBgNVHSUECzAJBgcrBgEFAgMEMEgGA1UdEQRBMD+gPQYGKwYB +BQICoDMwMaATGxFTQU1CQS5FWEFNUExFLkNPTaEaMBigAwIBAaERMA8bDWFkbWluaXN0cmF0 +b3IwHwYDVR0jBBgwFoAUwtm596AMotmzRU7IVdgrUvozyjIwHQYDVR0OBBYEFCDzVsvJ8IDz +wLYH8EONeUa5oVrGMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAbTCnaPTieVZPV3bH +UmAMbnF9+YN1mCbe2xZJ0xzve+Yw1XO82iv/9kZaZkcRkaQt2qcwsBK/aSPOgfqGx+mJ7hXQ +AGWvAJhnWi25PawNaRysCN8WC6+nWKR4d2O2m5rpj3T9kH5WE7QbG0bCu92dGaS29FvWDCP3 +q9pRtDOoAZc= +-----END CERTIFICATE----- + +EOF diff --git a/source4/selftest/selftest.pl b/source4/selftest/selftest.pl new file mode 100755 index 0000000000..104fc7d15f --- /dev/null +++ b/source4/selftest/selftest.pl @@ -0,0 +1,883 @@ +#!/usr/bin/perl +# Bootstrap Samba and run a number of tests against it. +# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> +# Published under the GNU GPL, v3 or later. + +=pod + +=head1 NAME + +selftest - Samba test runner + +=head1 SYNOPSIS + +selftest --help + +selftest [--srcdir=DIR] [--builddir=DIR] [--target=samba4|samba3|win] [--socket-wrapper] [--quick] [--one] [--prefix=prefix] [--immediate] [TESTS] + +=head1 DESCRIPTION + +A simple test runner. TESTS is a regular expression with tests to run. + +=head1 OPTIONS + +=over 4 + +=item I<--help> + +Show list of available options. + +=item I<--srcdir=DIR> + +Source directory. + +=item I<--builddir=DIR> + +Build directory. + +=item I<--prefix=DIR> + +Change directory to run tests in. Default is 'st'. + +=item I<--immediate> + +Show errors as soon as they happen rather than at the end of the test run. + +=item I<--target samba4|samba3|win> + +Specify test target against which to run. Default is 'samba4'. + +=item I<--quick> + +Run only a limited number of tests. Intended to run in about 30 seconds on +moderately recent systems. + +=item I<--socket-wrapper> + +Use socket wrapper library for communication with server. Only works +when the server is running locally. + +Will prevent TCP and UDP ports being opened on the local host but +(transparently) redirects these calls to use unix domain sockets. + +=item I<--expected-failures> + +Specify a file containing a list of tests that are expected to fail. Failures for +these tests will be counted as successes, successes will be counted as failures. + +The format for the file is, one entry per line: + +TESTSUITE-NAME/TEST-NAME + +=item I<--skip> + +Specify a file containing a list of tests that should be skipped. Possible candidates are +tests that segfault the server, flip or don't end. + +=item I<--one> + +Abort as soon as one test fails. + +=back + +=head1 ENVIRONMENT + +=over 4 + +=item I<SMBD_VALGRIND> + +=item I<TORTURE_MAXTIME> + +=item I<VALGRIND> + +=item I<TLS_ENABLED> + +=item I<srcdir> + +=back + +=head1 LICENSE + +selftest is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>. + +=head1 AUTHOR + +Jelmer Vernooij + +=cut + +use strict; + +use FindBin qw($RealBin $Script); +use File::Spec; +use Getopt::Long; +use POSIX; +use Cwd qw(abs_path); +use lib "$RealBin"; +use Samba3; +use Samba4; +use SocketWrapper; + +my $opt_help = 0; +my $opt_target = "samba4"; +my $opt_quick = 0; +my $opt_socket_wrapper = 0; +my $opt_socket_wrapper_pcap = undef; +my $opt_socket_wrapper_keep_pcap = undef; +my $opt_one = 0; +my $opt_immediate = 0; +my $opt_expected_failures = undef; +my $opt_skip = undef; +my $opt_verbose = 0; +my $opt_testenv = 0; +my $ldap = undef; +my $opt_analyse_cmd = undef; +my $opt_resetup_env = undef; +my $opt_bindir = undef; + +my $srcdir = "."; +my $builddir = "."; +my $prefix = "./st"; + +my $suitesfailed = []; +my $start = time(); +my @expected_failures = (); +my @skips = (); + +my $statistics = { + SUITES_FAIL => 0, + SUITES_OK => 0, + SUITES_SKIPPED => 0, + + TESTS_UNEXPECTED_OK => 0, + TESTS_EXPECTED_OK => 0, + TESTS_UNEXPECTED_FAIL => 0, + TESTS_EXPECTED_FAIL => 0, + TESTS_ERROR => 0 +}; + +sub expecting_failure($) +{ + my $fullname = shift; + + foreach (@expected_failures) { + return 1 if ($fullname =~ /$_/); + } + + return 0; +} + +sub skip($) +{ + my $fullname = shift; + + foreach (@skips) { + return 1 if ($fullname =~ /$_/); + } + + return 0; +} + +sub getlog_env($); + +my $test_output = {}; + +sub buildfarm_start_msg($) +{ + my ($state) = @_; + my $out = ""; + + $out .= "--==--==--==--==--==--==--==--==--==--==--\n"; + $out .= "Running test $state->{NAME} (level 0 stdout)\n"; + $out .= "--==--==--==--==--==--==--==--==--==--==--\n"; + $out .= scalar(localtime())."\n"; + $out .= "SELFTEST RUNTIME: " . ($state->{START} - $start) . "s\n"; + $out .= "NAME: $state->{NAME}\n"; + $out .= "CMD: $state->{CMD}\n"; + + $test_output->{$state->{NAME}} = ""; + + print $out; +} + +sub buildfarm_output_msg($$) +{ + my ($state, $output) = @_; + + $test_output->{$state->{NAME}} .= $output; +} + +sub buildfarm_end_msg($$$) +{ + my ($state, $expected_ret, $ret) = @_; + my $out = ""; + + $out .= "TEST RUNTIME: " . (time() - $state->{START}) . "s\n"; + + if ($ret == $expected_ret) { + $out .= "ALL OK\n"; + } else { + $out .= "ERROR: $ret"; + $out .= $test_output->{$state->{NAME}}; + } + + $out .= "PCAP FILE: $state->{PCAP_FILE}\n" if defined($state->{PCAP_FILE}); + + $out .= getlog_env($state->{ENVNAME}); + + $out .= "==========================================\n"; + if ($ret == $expected_ret) { + $out .= "TEST PASSED: $state->{NAME}\n"; + } else { + $out .= "TEST FAILED: $state->{NAME} (status $ret)\n"; + } + $out .= "==========================================\n"; + + print $out; +} + +my $buildfarm_msg_ops = { + start_msg => \&buildfarm_start_msg, + output_msg => \&buildfarm_output_msg, + end_msg => \&buildfarm_end_msg +}; + +sub plain_output_msg($$); + +sub plain_start_msg($) +{ + my ($state) = @_; + my $out = ""; + + $out .= "[$state->{INDEX}/$state->{TOTAL} in " . ($state->{START} - $start) . "s"; + $out .= ", ".($#$suitesfailed+1)." errors" if ($#$suitesfailed+1 > 0); + $out .= "] $state->{NAME}\n"; + + $test_output->{$state->{NAME}} = "" unless $opt_verbose; + + plain_output_msg($state, "CMD: $state->{CMD}\n"); + + print $out; +} + +sub plain_output_msg($$) +{ + my ($state, $output) = @_; + + if ($opt_verbose) { + print $output; + } else { + $test_output->{$state->{NAME}} .= $output; + } +} + +sub plain_end_msg($$$) +{ + my ($state, $expected_ret, $ret) = @_; + my $out = ""; + + if ($ret != $expected_ret) { + plain_output_msg($state, "ERROR: $ret\n"); + } + + if ($ret != $expected_ret and ($opt_immediate or $opt_one) and not $opt_verbose) { + $out .= $test_output->{$state->{NAME}}; + } + + if (not $opt_socket_wrapper_keep_pcap and defined($state->{PCAP_FILE})) { + $out .= "PCAP FILE: $state->{PCAP_FILE}\n"; + } + + $out .= getlog_env($state->{ENVNAME}); + + print $out; +} + +my $plain_msg_ops = { + start_msg => \&plain_start_msg, + output_msg => \&plain_output_msg, + end_msg => \&plain_end_msg +}; + +sub setup_pcap($) +{ + my ($state) = @_; + + return unless ($opt_socket_wrapper_pcap); + return unless defined($ENV{SOCKET_WRAPPER_PCAP_DIR}); + + my $fname = sprintf("t%03u_%s", $state->{INDEX}, $state->{NAME}); + $fname =~ s%[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\-]%_%g; + + $state->{PCAP_FILE} = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/$fname.pcap"; + + SocketWrapper::setup_pcap($state->{PCAP_FILE}); +} + +sub cleanup_pcap($$$) +{ + my ($state, $expected_ret, $ret) = @_; + + return unless ($opt_socket_wrapper_pcap); + return if ($opt_socket_wrapper_keep_pcap); + return unless ($expected_ret == $ret); + return unless defined($state->{PCAP_FILE}); + + unlink($state->{PCAP_FILE}); + $state->{PCAP_FILE} = undef; +} + +sub run_test($$$$$$) +{ + my ($envname, $name, $cmd, $i, $totalsuites, $msg_ops) = @_; + my $expected_ret = 1; + my $open_tests = {}; + my $msg_state = { + ENVNAME => $envname, + NAME => $name, + CMD => $cmd, + INDEX => $i, + TOTAL => $totalsuites, + START => time() + }; + + setup_pcap($msg_state); + + $msg_ops->{start_msg}->($msg_state); + + open(RESULT, "$cmd 2>&1|"); + while (<RESULT>) { + $msg_ops->{output_msg}->($msg_state, $_); + if (/^test: (.+)\n/) { + $open_tests->{$1} = 1; + } elsif (/^(success|failure|skip|error): (.*?)( \[)?\n/) { + my $result = $1; + if ($1 eq "success") { + delete $open_tests->{$2}; + if (expecting_failure("$name/$2")) { + $statistics->{TESTS_UNEXPECTED_OK}++; + } else { + $statistics->{TESTS_EXPECTED_OK}++; + } + } elsif ($1 eq "failure") { + delete $open_tests->{$2}; + if (expecting_failure("$name/$2")) { + $statistics->{TESTS_EXPECTED_FAIL}++; + $expected_ret = 0; + } else { + print "n:$name/$2l\n"; + $statistics->{TESTS_UNEXPECTED_FAIL}++; + } + } elsif ($1 eq "skip") { + delete $open_tests->{$2}; + } elsif ($1 eq "error") { + $statistics->{TESTS_ERROR}++; + delete $open_tests->{$2}; + } + } + } + foreach (keys %$open_tests) { + $msg_ops->{output_msg}->($msg_state, "$_ was started but never finished!\n"); + $statistics->{TESTS_ERROR}++; + } + my $ret = close(RESULT); + + cleanup_pcap($msg_state, $expected_ret, $ret); + + $msg_ops->{end_msg}->($msg_state, $expected_ret, $ret); + + if ($ret != $expected_ret) { + push(@$suitesfailed, $name); + $statistics->{SUITES_FAIL}++; + exit(1) if ($opt_one); + } else { + $statistics->{SUITES_OK}++; + } + + return ($ret == $expected_ret); +} + +sub ShowHelp() +{ + print "Samba test runner +Copyright (C) Jelmer Vernooij <jelmer\@samba.org> + +Usage: $Script [OPTIONS] PREFIX + +Generic options: + --help this help page + --target=samba4|samba3|win Samba version to target + +Paths: + --prefix=DIR prefix to run tests in [st] + --srcdir=DIR source directory [.] + --builddir=DIR output directory [.] + +Target Specific: + --socket-wrapper-pcap=DIR save traffic to pcap directories + --socket-wrapper-keep-pcap keep all pcap files, not just those for tests that + failed + --socket-wrapper enable socket wrapper + --expected-failures=FILE specify list of tests that is guaranteed to fail + +Samba4 Specific: + --ldap=openldap|fedora back smbd onto specified ldap server + +Samba3 Specific: + --bindir=PATH path to binaries + +Behaviour: + --quick run quick overall test + --one abort when the first test fails + --immediate print test output for failed tests during run + --verbose be verbose + --analyse-cmd CMD command to run after each test +"; + exit(0); +} + +my $result = GetOptions ( + 'help|h|?' => \$opt_help, + 'target=s' => \$opt_target, + 'prefix=s' => \$prefix, + 'socket-wrapper' => \$opt_socket_wrapper, + 'socket-wrapper-pcap' => \$opt_socket_wrapper_pcap, + 'socket-wrapper-keep-pcap' => \$opt_socket_wrapper_keep_pcap, + 'quick' => \$opt_quick, + 'one' => \$opt_one, + 'immediate' => \$opt_immediate, + 'expected-failures=s' => \$opt_expected_failures, + 'skip=s' => \$opt_skip, + 'srcdir=s' => \$srcdir, + 'builddir=s' => \$builddir, + 'verbose' => \$opt_verbose, + 'testenv' => \$opt_testenv, + 'ldap:s' => \$ldap, + 'analyse-cmd=s' => \$opt_analyse_cmd, + 'resetup-environment' => \$opt_resetup_env, + 'bindir:s' => \$opt_bindir, + ); + +exit(1) if (not $result); + +ShowHelp() if ($opt_help); + +my $tests = shift; + +# quick hack to disable rpc validation when using valgrind - its way too slow +unless (defined($ENV{VALGRIND})) { + $ENV{VALIDATE} = "validate"; + $ENV{MALLOC_CHECK_} = 2; +} + +my $old_pwd = "$RealBin/.."; + +# Backwards compatibility: +if (defined($ENV{TEST_LDAP}) and $ENV{TEST_LDAP} eq "yes") { + if (defined($ENV{FEDORA_DS_PREFIX})) { + $ldap = "fedora"; + } else { + $ldap = "openldap"; + } +} + +my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200); +if ($ldap) { + # LDAP is slow + $torture_maxtime *= 2; +} + +$prefix =~ s+//+/+; +$prefix =~ s+/./+/+; +$prefix =~ s+/$++; + +die("using an empty prefix isn't allowed") unless $prefix ne ""; + +#Ensure we have the test prefix around +mkdir($prefix, 0777) unless -d $prefix; + +my $prefix_abs = abs_path($prefix); +my $srcdir_abs = abs_path($srcdir); + +die("using an empty absolute prefix isn't allowed") unless $prefix_abs ne ""; +die("using '/' as absolute prefix isn't allowed") unless $prefix_abs ne "/"; + +$ENV{PREFIX} = $prefix; +$ENV{SRCDIR} = $srcdir; + +my $tls_enabled = not $opt_quick; +my $from_build_farm = (defined($ENV{RUN_FROM_BUILD_FARM}) and + ($ENV{RUN_FROM_BUILD_FARM} eq "yes")); + +$ENV{TLS_ENABLED} = ($tls_enabled?"yes":"no"); +$ENV{LD_LDB_MODULE_PATH} = "$old_pwd/bin/modules/ldb"; +$ENV{LD_SAMBA_MODULE_PATH} = "$old_pwd/bin/modules"; +if (defined($ENV{LD_LIBRARY_PATH})) { + $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared:$ENV{LD_LIBRARY_PATH}"; +} else { + $ENV{LD_LIBRARY_PATH} = "$old_pwd/bin/shared"; +} +$ENV{PKG_CONFIG_PATH} = "$old_pwd/bin/pkgconfig:$ENV{PKG_CONFIG_PATH}"; +$ENV{PATH} = "$old_pwd/bin:$ENV{PATH}"; + + +if ($opt_socket_wrapper_pcap) { + # Socket wrapper pcap implies socket wrapper + $opt_socket_wrapper = 1; +} + +my $socket_wrapper_dir; +if ($opt_socket_wrapper) { + $socket_wrapper_dir = SocketWrapper::setup_dir("$prefix/w", $opt_socket_wrapper_pcap); + print "SOCKET_WRAPPER_DIR=$socket_wrapper_dir\n"; +} else { + warn("Not using socket wrapper, but also not running as root. Will not be able to listen on proper ports") unless $< == 0; +} + +my $target; + +if ($opt_target eq "samba4") { + $target = new Samba4("$srcdir/bin", $ldap, "$srcdir/setup"); +} elsif ($opt_target eq "samba3") { + if ($opt_socket_wrapper and `smbd -b | grep SOCKET_WRAPPER` eq "") { + die("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting...."); + } + + $target = new Samba3($opt_bindir); +} elsif ($opt_target eq "win") { + die("Windows tests will not run with socket wrapper enabled.") + if ($opt_socket_wrapper); + $target = new Windows(); +} + +if (defined($opt_expected_failures)) { + open(KNOWN, "<$opt_expected_failures") or die("unable to read known failures file: $!"); + while (<KNOWN>) { + chomp; + s/([ \t]+)\#(.*)$//; + push (@expected_failures, $_); } + close(KNOWN); +} + +if (defined($opt_skip)) { + open(SKIP, "<$opt_skip") or die("unable to read skip file: $!"); + while (<SKIP>) { + chomp; + s/([ \t]+)\#(.*)$//; + push (@skips, $_); } + close(SKIP); +} + +my $interfaces = join(',', ("127.0.0.6/8", + "127.0.0.7/8", + "127.0.0.8/8", + "127.0.0.9/8", + "127.0.0.10/8", + "127.0.0.11/8")); + +my $conffile = "$prefix_abs/client/client.conf"; + +sub write_clientconf($$) +{ + my ($conffile, $vars) = @_; + + mkdir("$prefix/client", 0777) unless -d "$prefix/client"; + + if ( -d "$prefix/client/private" ) { + unlink <$prefix/client/private/*>; + } else { + mkdir("$prefix/client/private", 0777); + } + + open(CF, ">$conffile"); + print CF "[global]\n"; + if (defined($ENV{VALGRIND})) { + print CF "\ticonv:native = true\n"; + } else { + print CF "\ticonv:native = false\n"; + } + print CF "\tnetbios name = client\n"; + if (defined($vars->{DOMAIN})) { + print CF "\tworkgroup = $vars->{DOMAIN}\n"; + } + if (defined($vars->{REALM})) { + print CF "\trealm = $vars->{REALM}\n"; + } + if (defined($vars->{NCALRPCDIR})) { + print CF "\tncalrpc dir = $vars->{NCALRPCDIR}\n"; + } + if (defined($vars->{PIDDIR})) { + print CF "\tpid directory = $vars->{PIDDIR}\n"; + } + if (defined($vars->{WINBINDD_SOCKET_DIR})) { + print CF "\twinbindd socket directory = $vars->{WINBINDD_SOCKET_DIR}\n"; + } + print CF " + private dir = $prefix_abs/client/private + js include = $srcdir_abs/scripting/libjs + name resolve order = bcast + interfaces = $interfaces + panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\% + max xmit = 32K + notify:inotify = false + ldb:nosync = true + system:anonymous = true + torture:basedir = $prefix_abs/client +#We don't want to pass our self-tests if the PAC code is wrong + gensec:require_pac = true +"; + close(CF); +} + + +my @torture_options = (); +push (@torture_options, "--configfile=$conffile"); +# ensure any one smbtorture call doesn't run too long +push (@torture_options, "--maximum-runtime=$torture_maxtime"); +push (@torture_options, "--target=$opt_target"); +push (@torture_options, "--option=torture:progress=no") if ($from_build_farm); +push (@torture_options, "--format=subunit"); +push (@torture_options, "--option=torture:quick=yes") if ($opt_quick); + +$ENV{TORTURE_OPTIONS} = join(' ', @torture_options); +print "OPTIONS $ENV{TORTURE_OPTIONS}\n"; + +my @todo = (); + +my $testsdir = "$srcdir/selftest"; +$ENV{CONFIGURATION} = "--configfile=$conffile"; + + +if ($opt_quick) { + open(IN, "$testsdir/tests_quick.sh|"); +} else { + open(IN, "$testsdir/tests_all.sh|"); +} +while (<IN>) { + if ($_ eq "-- TEST --\n") { + my $name = <IN>; + $name =~ s/\n//g; + my $env = <IN>; + $env =~ s/\n//g; + my $cmdline = <IN>; + $cmdline =~ s/\n//g; + push (@todo, [$name, $env, $cmdline]) + if (not defined($tests) or $name =~ /$tests/); + } else { + print; + } +} +close(IN) or die("Error creating recipe"); + +my $suitestotal = $#todo + 1; +my $i = 0; +$| = 1; + +my %running_envs = (); + +my @exported_envvars = ( + # domain stuff + "DOMAIN", + "REALM", + + # domain controller stuff + "DC_SERVER", + "DC_SERVER_IP", + "DC_NETBIOSNAME", + "DC_NETBIOSALIAS", + + # server stuff + "SERVER", + "SERVER_IP", + "NETBIOSNAME", + "NETBIOSALIAS", + + # user stuff + "USERNAME", + "PASSWORD", + "DC_USERNAME", + "DC_PASSWORD", + + # misc stuff + "KRB5_CONFIG" +); + +sub setup_env($) +{ + my ($envname) = @_; + + my $testenv_vars; + if ($envname eq "none") { + $testenv_vars = {}; + } elsif (defined($running_envs{$envname})) { + $testenv_vars = $running_envs{$envname}; + if (not $target->check_env($testenv_vars)) { + $testenv_vars = undef; + } + } else { + $testenv_vars = $target->setup_env($envname, $prefix); + } + + return undef unless defined($testenv_vars); + + SocketWrapper::set_default_iface(6); + write_clientconf($conffile, $testenv_vars); + + foreach (@exported_envvars) { + if (defined($testenv_vars->{$_})) { + $ENV{$_} = $testenv_vars->{$_}; + } else { + delete $ENV{$_}; + } + } + + $running_envs{$envname} = $testenv_vars; + return $testenv_vars; +} + +sub exported_envvars_str($) +{ + my ($testenv_vars) = @_; + my $out = ""; + + foreach (@exported_envvars) { + next unless defined($testenv_vars->{$_}); + $out .= $_."=".$testenv_vars->{$_}."\n"; + } + + return $out; +} + +sub getlog_env($) +{ + my ($envname) = @_; + return "" if ($envname eq "none"); + return $target->getlog_env($running_envs{$envname}); +} + +sub check_env($) +{ + my ($envname) = @_; + return 1 if ($envname eq "none"); + return $target->check_env($running_envs{$envname}); +} + +sub teardown_env($) +{ + my ($envname) = @_; + return if ($envname eq "none"); + $target->teardown_env($running_envs{$envname}); + delete $running_envs{$envname}; +} + +my $msg_ops; +if ($from_build_farm) { + $msg_ops = $buildfarm_msg_ops; +} else { + $msg_ops = $plain_msg_ops; +} + +if ($opt_testenv) { + my $testenv_name = $ENV{SELFTEST_TESTENV}; + $testenv_name = "dc" unless defined($testenv_name); + + my $testenv_vars = setup_env($testenv_name); + + $ENV{PIDDIR} = $testenv_vars->{PIDDIR}; + + my $envvarstr = exported_envvars_str($testenv_vars); + + my $term = ($ENV{TERM} or "xterm"); + system("$term -e 'echo -e \" +Welcome to the Samba4 Test environment '$testenv_name' + +This matches the client environment used in make test +smbd is pid `cat \$PIDDIR/smbd.pid` + +Some useful environment variables: +TORTURE_OPTIONS=\$TORTURE_OPTIONS +CONFIGURATION=\$CONFIGURATION + +$envvarstr +\" && bash'"); + teardown_env($testenv_name); +} else { + foreach (@todo) { + $i++; + my $cmd = $$_[2]; + $cmd =~ s/([\(\)])/\\$1/g; + my $name = $$_[0]; + my $envname = $$_[1]; + + if (skip($name)) { + print "SKIPPED: $name\n"; + $statistics->{SUITES_SKIPPED}++; + next; + } + + my $envvars = setup_env($envname); + if (not defined($envvars)) { + push(@$suitesfailed, $name); + $statistics->{SUITES_FAIL}++; + $statistics->{TESTS_ERROR}++; + print "FAIL: $name (ENV[$envname] not available!)\n"; + next; + } + + run_test($envname, $name, $cmd, $i, $suitestotal, $msg_ops); + + if (defined($opt_analyse_cmd)) { + system("$opt_analyse_cmd \"$name\""); + } + + teardown_env($envname) if ($opt_resetup_env); + } +} + +print "\n"; + +teardown_env($_) foreach (keys %running_envs); + +$target->stop(); + +my $end = time(); +my $duration = ($end-$start); +my $numfailed = $#$suitesfailed+1; +if ($numfailed == 0) { + my $ok = $statistics->{TESTS_EXPECTED_OK} + + $statistics->{TESTS_EXPECTED_FAIL}; + print "ALL OK ($ok tests in $statistics->{SUITES_OK} testsuites)\n"; +} else { + unless ($from_build_farm) { + if (not $opt_immediate and not $opt_verbose) { + foreach (@$suitesfailed) { + print "===============================================================================\n"; + print "FAIL: $_\n"; + print $test_output->{$_}; + print "\n"; + } + } + + print "FAILED ($statistics->{TESTS_UNEXPECTED_FAIL} failures and $statistics->{TESTS_ERROR} errors in $statistics->{SUITES_FAIL} testsuites)\n"; + } +} +print "DURATION: $duration seconds\n"; + +my $failed = 0; + +# if there were any valgrind failures, show them +foreach (<$prefix/valgrind.log*>) { + next unless (-s $_); + system("grep DWARF2.CFI.reader $_ > /dev/null"); + if ($? >> 8 == 0) { + print "VALGRIND FAILURE\n"; + $failed++; + system("cat $_"); + } +} + +if ($from_build_farm) { + print "TEST STATUS: $numfailed\n"; +} + +exit $numfailed; diff --git a/source4/selftest/test_binding_string.sh b/source4/selftest/test_binding_string.sh new file mode 100755 index 0000000000..a8afc07ac1 --- /dev/null +++ b/source4/selftest/test_binding_string.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +incdir=`dirname $0` +. $incdir/test_functions.sh + +for I in "ncacn_np:\$SERVER" \ + "ncacn_ip_tcp:\$SERVER" \ + "ncacn_np:\$SERVER[rpcecho]" \ + "ncacn_np:\$SERVER[/pipe/rpcecho]" \ + "ncacn_np:\$SERVER[/pipe/rpcecho,sign,seal]" \ + "ncacn_np:\$SERVER[,sign]" \ + "ncacn_ip_tcp:\$SERVER[,sign]" \ + "ncalrpc:" \ + "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:\$SERVER" \ + "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:\$SERVER" +do + plantest "$I" dc bin/smbtorture $TORTURE_OPTIONS "$I" -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" --option=torture:quick=yes RPC-ECHO "$*" +done diff --git a/source4/selftest/test_blackbox.sh b/source4/selftest/test_blackbox.sh new file mode 100755 index 0000000000..6397918fff --- /dev/null +++ b/source4/selftest/test_blackbox.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# this runs tests that interact directly with the command-line tools rather than using the API + +if [ $# -lt 1 ]; then +cat <<EOF +Usage: test_blackbox.sh PREFIX [...] +EOF +exit 1; +fi + +PREFIX=$1 +shift 1 +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +plantest "blackbox.smbclient" dc $incdir/../../testprogs/blackbox/test_smbclient.sh "\$NETBIOSNAME" "\$USERNAME" "\$PASSWORD" "\$DOMAIN" "$PREFIX" "$ADDARGS" +plantest "blackbox.kinit" dc $incdir/../../testprogs/blackbox/test_kinit.sh "\$NETBIOSNAME" "\$USERNAME" "\$PASSWORD" "\$REALM" "$PREFIX" "$ADDARGS" + +plantest "blackbox.cifsdd" dc $incdir/../../testprogs/blackbox/test_cifsdd.sh "\$NETBIOSNAME" "\$USERNAME" "\$PASSWORD" "\$DOMAIN" "$ADDARGS" diff --git a/source4/selftest/test_cifs.sh b/source4/selftest/test_cifs.sh new file mode 100755 index 0000000000..2bf3c4a5b1 --- /dev/null +++ b/source4/selftest/test_cifs.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with the +# current posix ntvfs backend, via the ntvfs cifs proxy + +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +raw=`bin/smbtorture --list | grep "^RAW-" | xargs` +base=`bin/smbtorture --list | grep "^BASE-" | xargs` +tests="$base $raw $smb2" + +for t in $tests; do + if [ ! -z "$start" -a "$start" != $t ]; then + continue; + fi + start="" + plantest "ntvfs/cifs $t" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS //\$NETBIOSNAME/cifs -U"\$USERNAME"%"\$PASSWORD" $t +done diff --git a/source4/selftest/test_echo.sh b/source4/selftest/test_echo.sh new file mode 100755 index 0000000000..f09aeca4e5 --- /dev/null +++ b/source4/selftest/test_echo.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +incdir=`dirname $0` +. $incdir/test_functions.sh + +transports="ncacn_np ncacn_ip_tcp ncalrpc" + +for transport in $transports; do + for bindoptions in connect spnego spnego,sign spnego,seal $VALIDATE padcheck bigendian bigendian,seal; do + for ntlmoptions in \ + "--option=socket:testnonblock=True --option=torture:quick=yes"; do + name="RPC-ECHO on $transport with $bindoptions and $ntlmoptions" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" $ntlmoptions -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" RPC-ECHO "$*" + done + done +done + +for transport in $transports; do + for bindoptions in sign seal; do + for ntlmoptions in \ + "--option=ntlmssp_client:ntlm2=yes --option=torture:quick=yes" \ + "--option=ntlmssp_client:ntlm2=no --option=torture:quick=yes" \ + "--option=ntlmssp_client:ntlm2=yes --option=ntlmssp_client:128bit=no --option=torture:quick=yes" \ + "--option=ntlmssp_client:ntlm2=no --option=ntlmssp_client:128bit=no --option=torture:quick=yes" \ + "--option=ntlmssp_client:ntlm2=yes --option=ntlmssp_client:keyexchange=no --option=torture:quick=yes" \ + "--option=ntlmssp_client:ntlm2=no --option=ntlmssp_client:keyexchange=no --option=torture:quick=yes" \ + "--option=clientntlmv2auth=yes --option=ntlmssp_client:keyexchange=no --option=torture:quick=yes" \ + "--option=clientntlmv2auth=yes --option=ntlmssp_client:128bit=no --option=ntlmssp_client:keyexchange=yes --option=torture:quick=yes" \ + "--option=clientntlmv2auth=yes --option=ntlmssp_client:128bit=no --option=ntlmssp_client:keyexchange=no --option=torture:quick=yes" \ + ; do + name="RPC-ECHO on $transport with $bindoptions and $ntlmoptions" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" $ntlmoptions -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN RPC-ECHO "$*" + done + done +done + +name="RPC-ECHO on ncacn_np over smb2" +plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS ncacn_np:"\$SERVER[smb2]" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN RPC-ECHO "$*" diff --git a/source4/selftest/test_ejs.sh b/source4/selftest/test_ejs.sh new file mode 100755 index 0000000000..858602ce38 --- /dev/null +++ b/source4/selftest/test_ejs.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# test some simple EJS operations + +CONFIGURATION="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +SCRIPTDIR=../testprogs/ejs +DATADIR=../testdata + +PATH=bin:$PATH +export PATH + +plantest "base.js" dc "$SCRIPTDIR/base.js" $CONFIGURATION +plantest "samr.js" dc "$SCRIPTDIR/samr.js" $CONFIGURATION ncalrpc: -U\$USERNAME%\$PASSWORD +plantest "echo.js" dc "$SCRIPTDIR/echo.js" $CONFIGURATION ncalrpc: -U\$USERNAME%\$PASSWORD +plantest "ejsnet.js" dc "$SCRIPTDIR/ejsnet.js" $CONFIGURATION -U\$USERNAME%\$PASSWORD \$DOMAIN ejstestuser +plantest "ldb.js" none "$SCRIPTDIR/ldb.js" `pwd` $CONFIGURATION +plantest "samba3sam.js" none $SCRIPTDIR/samba3sam.js $CONFIGURATION `pwd` $DATADIR/samba3/ +plantest "winreg" dc scripting/bin/winreg $CONFIGURATION ncalrpc: 'HKLM' -U\$USERNAME%\$PASSWORD diff --git a/source4/selftest/test_functions.sh b/source4/selftest/test_functions.sh new file mode 100755 index 0000000000..6a7f8aba98 --- /dev/null +++ b/source4/selftest/test_functions.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +plantest() { + name=$1 + env=$2 + shift 2 + cmdline="$*" + echo "-- TEST --" + echo $name + echo $env + echo $cmdline +} diff --git a/source4/selftest/test_ldap.sh b/source4/selftest/test_ldap.sh new file mode 100755 index 0000000000..4a31451a01 --- /dev/null +++ b/source4/selftest/test_ldap.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# test some simple LDAP and CLDAP operations + +incdir=`dirname $0` +. $incdir/test_functions.sh + +p=ldap +for options in "" "--option=socket:testnonblock=true" "-U\$USERNAME%\$PASSWORD --option=socket:testnonblock=true" "-U\$USERNAME%\$PASSWORD"; do + plantest "TESTING PROTOCOL $p with options $options" dc ../testprogs/blackbox/test_ldb.sh $p \$SERVER_IP $options +done +# see if we support ldaps +if grep ENABLE_GNUTLS.1 include/config.h > /dev/null; then + p=ldaps + for options in "" "-U\$USERNAME%\$PASSWORD"; do + plantest "TESTING PROTOCOL $p with options $options" dc ../testprogs/blackbox/test_ldb.sh $p \$SERVER_IP $options + done +fi +for t in LDAP-CLDAP LDAP-BASIC LDAP-SCHEMA LDAP-UPTODATENESS +do + plantest "$t" dc bin/smbtorture $TORTURE_OPTIONS "-U\$USERNAME%\$PASSWORD" //\$SERVER_IP/_none_ $t +done + +# only do the ldb tests when not in quick mode - they are quite slow, and ldb +# is now pretty well tested by the rest of the quick tests anyway +test "$TORTURE_QUICK" = "yes" || { + LDBDIR=lib/ldb + export LDBDIR + plantest "ldb" none $LDBDIR/tests/test-tdb.sh +} + +SCRIPTDIR=../testprogs/ejs + +plantest "ejs ldap" dc $SCRIPTDIR/ldap.js $CONFIGURATION \$SERVER -U\$USERNAME%\$PASSWORD diff --git a/source4/selftest/test_local.sh b/source4/selftest/test_local.sh new file mode 100755 index 0000000000..e8bf10c901 --- /dev/null +++ b/source4/selftest/test_local.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +local_tests=`bin/smbtorture --list | grep "^LOCAL-" | xargs` + +if [ `uname` = "Linux" ]; then + # testing against the system iconv only makes sense for our 'reference' iconv + # behaviour + local_tests="$local_tests LOCAL-ICONV" +fi + +incdir=`dirname $0` +. $incdir/test_functions.sh + +# the local tests don't need smbd +SMBD_TEST_FIFO="" +export SMBD_TEST_FIFO + +for t in $local_tests; do + plantest "$t" none $VALGRIND bin/smbtorture $TORTURE_OPTIONS ncalrpc: $t "$*" +done + +plantest "tdb stress" none $VALGRIND bin/tdbtorture diff --git a/source4/selftest/test_member.sh b/source4/selftest/test_member.sh new file mode 100755 index 0000000000..b1bb0c7b09 --- /dev/null +++ b/source4/selftest/test_member.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +incdir=`dirname $0` +. $incdir/test_functions.sh + +plantest "RPC-ECHO against member server" member $VALGRIND bin/smbtorture $TORTURE_OPTIONS ncacn_np:"\$SERVER" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN RPC-ECHO "$*" diff --git a/source4/selftest/test_nbt.sh b/source4/selftest/test_nbt.sh new file mode 100755 index 0000000000..ceac810922 --- /dev/null +++ b/source4/selftest/test_nbt.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# test some NBT/WINS operations + +incdir=`dirname $0` +. $incdir/test_functions.sh + +SCRIPTDIR=../testprogs/ejs + +PATH=bin:$PATH +export PATH + +TEST_NBT_ENVNAME=$1 +if test x"$TEST_NBT_ENVNAME" = x"";then + TEST_NBT_ENVNAME="dc" +fi + +plantest "nmblookup -U \$SERVER_IP \$SERVER" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS -U \$SERVER_IP \$SERVER +plantest "nmblookup -U \$SERVER_IP \$NETBIOSNAME" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS -U \$SERVER_IP \$NETBIOSNAME +plantest "nmblookup -U \$SERVER_IP \$NETBIOSALIAS" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS -U \$SERVER_IP \$NETBIOSALIAS +plantest "nmblookup \$SERVER" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS \$SERVER +plantest "nmblookup \$NETBIOSNAME" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS \$NETBIOSNAME +plantest "nmblookup \$NETBIOSALIAS" $TEST_NBT_ENVNAME bin/nmblookup $TORTURE_OPTIONS \$NETBIOSALIAS + +NBT_TESTS=`bin/smbtorture --list | grep "^NBT-" | xargs` + +if test x"$TEST_NBT_ENVNAME" = x"dc";then + for f in $NBT_TESTS; do + plantest "$f:$TEST_NBT_ENVNAME" $TEST_NBT_ENVNAME bin/smbtorture $TORTURE_OPTIONS //\$SERVER/_none_ $f -U\$USERNAME%\$PASSWORD + done +fi diff --git a/source4/selftest/test_net.sh b/source4/selftest/test_net.sh new file mode 100755 index 0000000000..7973461f98 --- /dev/null +++ b/source4/selftest/test_net.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# add tests to this list as they start passing, so we test +# that they stay passing +ncacn_np_tests="NET-API-LOOKUP NET-API-LOOKUPHOST NET-API-LOOKUPPDC NET-API-RPCCONN-BIND NET-API-RPCCONN-SRV NET-API-RPCCONN-PDC NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES NET-API-CREATEUSER NET-API-DELETEUSER NET-API-DOMLIST" +ncalrpc_tests="NET-API-RPCCONN-SRV NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES NET-API-CREATEUSER NET-API-DELETEUSER NET-USERINFO NET-USERADD NET-USERDEL NET-USERMOD NET-API-LOOKUPNAME NET-API-USERINFO NET-API-USERLIST NET-API-DOMOPENLSA NET-API-DOMCLOSELSA NET-API-DOMOPENSAMR NET-API-DOMCLOSESAMR NET-API-DOMLIST" +ncacn_ip_tcp_tests="NET-API-LOOKUP NET-API-LOOKUPHOST NET-API-LOOKUPPDC NET-API-RPCCONN-SRV NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES NET-API-CREATEUSER NET-API-DELETEUSER NET-API-MODIFYUSER NET-API-DOMLIST" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +for bindoptions in seal,padcheck $VALIDATE bigendian; do + for transport in ncalrpc ncacn_np ncacn_ip_tcp; do + case $transport in + ncalrpc) tests=$ncalrpc_tests ;; + ncacn_np) tests=$ncacn_np_tests ;; + ncacn_ip_tcp) tests=$ncacn_ip_tcp_tests ;; + esac + for t in $tests; do + name="$t on $transport with $bindoptions" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER_IP[$bindoptions]" -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" $t "$*" + done + done +done diff --git a/source4/selftest/test_pidl.sh b/source4/selftest/test_pidl.sh new file mode 100755 index 0000000000..d143cd6b0a --- /dev/null +++ b/source4/selftest/test_pidl.sh @@ -0,0 +1,16 @@ +#!/bin/sh +if [ ! -n "$PERL" ] +then + PERL=perl +fi + +incdir=`dirname $0` +. $incdir/test_functions.sh + +if $PERL -e 'eval require Test::More;' > /dev/null 2>&1; then + for f in pidl/tests/*.pl; do + plantest "$f" none $PERL $f + done +else + echo "Skipping pidl tests - Test::More not installed" +fi diff --git a/source4/selftest/test_posix.sh b/source4/selftest/test_posix.sh new file mode 100755 index 0000000000..88040def88 --- /dev/null +++ b/source4/selftest/test_posix.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with the +# current posix ntvfs backend + +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +smb2=`bin/smbtorture --list | grep "^SMB2-" | xargs` +raw=`bin/smbtorture --list | grep "^RAW-" | xargs` +base=`bin/smbtorture --list | grep "^BASE-" | xargs` +tests="$base $raw $smb2" + +for t in $tests; do + if [ ! -z "$start" -a "$start" != $t ]; then + continue; + fi + start="" + plantest "$t" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS //\$SERVER/tmp -U"\$USERNAME"%"\$PASSWORD" $t +done diff --git a/source4/selftest/test_quick.sh b/source4/selftest/test_quick.sh new file mode 100755 index 0000000000..e2c14e42f2 --- /dev/null +++ b/source4/selftest/test_quick.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# run a quick set of filesystem tests + +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +tests="BASE-UNLINK BASE-ATTR BASE-DELETE" +tests="$tests BASE-TCON BASE-OPEN" +tests="$tests BASE-CHKPATH RAW-QFSINFO RAW-QFILEINFO RAW-SFILEINFO" +tests="$tests RAW-MKDIR RAW-SEEK RAW-OPEN RAW-WRITE" +tests="$tests RAW-UNLINK RAW-READ RAW-CLOSE RAW-IOCTL RAW-RENAME" +tests="$tests RAW-EAS RAW-STREAMS" + +for t in $tests; do + name="$t" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS //\$SERVER/tmp -U"\$USERNAME"%"\$PASSWORD" $t +done + +name=BASE-OPEN +plantest "ntvfs/cifs $name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS //\$NETBIOSNAME/cifs -U"\$USERNAME"%"\$PASSWORD" $name diff --git a/source4/selftest/test_rpc.sh b/source4/selftest/test_rpc.sh new file mode 100755 index 0000000000..724196bbfa --- /dev/null +++ b/source4/selftest/test_rpc.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# add tests to this list as they start passing, so we test +# that they stay passing +ncacn_np_tests="RPC-SPOOLSS RPC-SRVSVC RPC-UNIXINFO RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-ECHO RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-MGMT RPC-HANDLES RPC-WINREG RPC-WKSSVC RPC-SVCCTL RPC-EPMAPPER RPC-INITSHUTDOWN RPC-EVENTLOG RPC-ATSVC RPC-SAMSYNC" +ncalrpc_tests="RPC-MGMT RPC-UNIXINFO RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-ECHO RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-WINREG RPC-WKSSVC RPC-SVCCTL RPC-EPMAPPER RPC-EVENTLOG RPC-ATSVC RPC-INITSHUTDOWN" +ncacn_ip_tcp_tests="RPC-UNIXINFO RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-ECHO RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON RPC-MGMT RPC-HANDLES RPC-WINREG RPC-WKSSVC RPC-SVCCTL RPC-EPMAPPER RPC-ATSVC RPC-EVENTLOG RPC-DSSYNC" +slow_ncacn_np_tests="RPC-SAMLOGON RPC-SAMR RPC-SAMR-USERS RPC-SAMR-PASSWORDS RPC-COUNTCALLS" +slow_ncalrpc_tests="RPC-SAMR RPC-SAMR-PASSWORDS RPC-COUNTCALLS RPC-CRACKNAMES" +slow_ncacn_ip_tcp_tests="RPC-SAMR RPC-SAMR-PASSWORDS RPC-COUNTCALLS RPC-CRACKNAMES" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +for bindoptions in seal,padcheck $VALIDATE bigendian; do + for transport in ncalrpc ncacn_np ncacn_ip_tcp; do + case $transport in + ncalrpc) tests=$ncalrpc_tests ;; + ncacn_np) tests=$ncacn_np_tests ;; + ncacn_ip_tcp) tests=$ncacn_ip_tcp_tests ;; + esac + for t in $tests; do + name="$t on $transport with $bindoptions" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN $t "$*" + done + done +done + +for bindoptions in connect $VALIDATE ; do + for transport in ncalrpc ncacn_np ncacn_ip_tcp; do + case $transport in + ncalrpc) tests=$slow_ncalrpc_tests ;; + ncacn_np) tests=$slow_ncacn_np_tests ;; + ncacn_ip_tcp) tests=$slow_ncacn_ip_tcp_tests ;; + esac + for t in $tests; do + name="$t on $transport with $bindoptions" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN $t "$*" + done + done +done diff --git a/source4/selftest/test_rpc_quick.sh b/source4/selftest/test_rpc_quick.sh new file mode 100755 index 0000000000..8793e0b6e6 --- /dev/null +++ b/source4/selftest/test_rpc_quick.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# add tests to this list as they start passing, so we test +# that they stay passing +ncacn_np_tests="RPC-ALTERCONTEXT RPC-JOIN RPC-ECHO RPC-SCHANNEL RPC-NETLOGON RPC-UNIXINFO RPC-HANDLES" +ncacn_ip_tcp_tests="RPC-ALTERCONTEXT RPC-JOIN RPC-ECHO RPC-HANDLES" +ncalrpc_tests="RPC-ECHO" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +for bindoptions in seal,padcheck $VALIDATE bigendian; do + for transport in ncalrpc ncacn_np ncacn_ip_tcp; do + case $transport in + ncalrpc) tests=$ncalrpc_tests ;; + ncacn_np) tests=$ncacn_np_tests ;; + ncacn_ip_tcp) tests=$ncacn_ip_tcp_tests ;; + esac + for t in $tests; do + name="$t on $transport with $bindoptions" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN $t "$*" + done + done +done diff --git a/source4/selftest/test_s3upgrade.sh b/source4/selftest/test_s3upgrade.sh new file mode 100755 index 0000000000..1ed43cb8eb --- /dev/null +++ b/source4/selftest/test_s3upgrade.sh @@ -0,0 +1,22 @@ +#!/bin/sh +PREFIX=$1 + +if [ -z "$PREFIX" ] +then + echo "Usage: test_s3upgrade.sh <prefix>" + exit 1 +fi + +SCRIPTDIR=../testprogs/ejs +DATADIR=../testdata + +PATH=bin:$PATH +export PATH + +mkdir -p $PREFIX +rm -f $PREFIX/* + +. selftest/test_functions.sh + +plantest "parse samba3" none bin/smbscript ../testdata/samba3/verify $CONFIGURATION ../testdata/samba3 +#plantest "upgrade" none bin/smbscript setup/upgrade $CONFIGURATION --verify --targetdir=$PREFIX ../testdata/samba3 ../testdata/samba3/smb.conf diff --git a/source4/selftest/test_samba4.pl b/source4/selftest/test_samba4.pl new file mode 100755 index 0000000000..f2935be66b --- /dev/null +++ b/source4/selftest/test_samba4.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl + +use Test::More tests => 3; +use FindBin qw($RealBin); +use lib $RealBin; +use Samba4; + +my $s = new Samba4($RealBin."/../bin", undef, $RealBin."/../setup"); + +ok($s); + +is($RealBin."/../bin", $s->{bindir}); + +ok($s->write_ldb_file("tmpldb", " +dn: a=b +a: b +c: d +")); + +unlink("tmpldb"); diff --git a/source4/selftest/test_session_key.sh b/source4/selftest/test_session_key.sh new file mode 100755 index 0000000000..30d03431ba --- /dev/null +++ b/source4/selftest/test_session_key.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +incdir=`dirname $0` +. $incdir/test_functions.sh + +transport="ncacn_np" +for bindoptions in bigendian seal; do + for keyexchange in "yes" "no"; do + for ntlm2 in "yes" "no"; do + for lm_key in "yes" "no"; do + for ntlmoptions in \ + "-k no --option=usespnego=yes" \ + "-k no --option=usespnego=yes --option=ntlmssp_client:128bit=no" \ + "-k no --option=usespnego=yes --option=ntlmssp_client:56bit=yes" \ + "-k no --option=usespnego=yes --option=ntlmssp_client:56bit=no" \ + "-k no --option=usespnego=yes --option=ntlmssp_client:128bit=no --option=ntlmssp_client:56bit=yes" \ + "-k no --option=usespnego=yes --option=ntlmssp_client:128bit=no --option=ntlmssp_client:56bit=no" \ + "-k no --option=usespnego=yes --option=clientntlmv2auth=yes" \ + "-k no --option=usespnego=yes --option=clientntlmv2auth=yes --option=ntlmssp_client:128bit=no" \ + "-k no --option=usespnego=yes --option=clientntlmv2auth=yes --option=ntlmssp_client:128bit=no --option=ntlmssp_client:56bit=yes" \ + "-k no --option=usespnego=no --option=clientntlmv2auth=yes" \ + "-k no --option=gensec:spnego=no --option=clientntlmv2auth=yes" \ + "-k no --option=usespnego=no"; do + name="RPC-SECRETS on $transport with $bindoptions with NTLM2:$ntlm2 KEYEX:$keyexchange LM_KEY:$lm_key $ntlmoptions" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" --option=ntlmssp_client:keyexchange=$keyexchange --option=ntlmssp_client:ntlm2=$ntlm2 --option=ntlmssp_client:lm_key=$lm_key $ntlmoptions -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN --option=gensec:target_hostname=\$NETBIOSNAME RPC-SECRETS "$*" + done + done + done + done + name="RPC-SECRETS on $transport with $bindoptions with Kerberos" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" -k yes -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN "--option=gensec:target_hostname=\$NETBIOSNAME" RPC-SECRETS "$*" + name="RPC-SECRETS on $transport with $bindoptions with Kerberos - use target principal" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER[$bindoptions]" -k yes -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN "--option=clientusespnegoprincipal=yes" "--option=gensec:target_hostname=\$NETBIOSNAME" RPC-SECRETS "$*" +done +name="RPC-SECRETS on $transport with Kerberos - use Samba3 style login" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER" -k yes -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" "--option=gensec:fake_gssapi_krb5=yes" "--option=gensec:gssapi_krb5=no" "--option=gensec:target_hostname=\$NETBIOSNAME" RPC-SECRETS "$*" +name="RPC-SECRETS on $transport with Kerberos - use Samba3 style login, use target principal" + plantest "$name" dc bin/smbtorture $TORTURE_OPTIONS $transport:"\$SERVER" -k yes -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" "--option=clientusespnegoprincipal=yes" "--option=gensec:fake_gssapi_krb5=yes" "--option=gensec:gssapi_krb5=no" "--option=gensec:target_hostname=\$NETBIOSNAME" RPC-SECRETS "$*" diff --git a/source4/selftest/test_simple.sh b/source4/selftest/test_simple.sh new file mode 100755 index 0000000000..a4a672cd5b --- /dev/null +++ b/source4/selftest/test_simple.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# run a quick set of filesystem tests + +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +tests="BASE-RW1" + +for t in $tests; do + name="$t" + plantest "$name" dc $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS //\$SERVER/simple -U"\$USERNAME"%"\$PASSWORD" $t +done diff --git a/source4/selftest/test_swig.sh b/source4/selftest/test_swig.sh new file mode 100755 index 0000000000..9f5e7c0ebf --- /dev/null +++ b/source4/selftest/test_swig.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +if [ $# -ne 0 ]; then + cat <<EOF +Usage: test_swig.sh +EOF + exit 1; +fi + +incdir=`dirname $0` +. $incdir/test_functions.sh + +export PYTHONPATH=lib/tdb/swig:lib/ldb/swig:scripting/swig:$PYTHONPATH +export LD_LIBRARY_PATH=bin:$LD_LIBRARY_PATH + +echo Testing tdb wrappers +scripting/swig/torture/torture_tdb.py + +echo Testing ldb wrappers +scripting/swig/torture/torture_ldb.py diff --git a/source4/selftest/test_w2k3.sh b/source4/selftest/test_w2k3.sh new file mode 100755 index 0000000000..b262029892 --- /dev/null +++ b/source4/selftest/test_w2k3.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# tests that should pass against a w2k3 DC, as administrator + +# add tests to this list as they start passing, so we test +# that they stay passing +ncacn_np_tests="RPC-SCHANNEL RPC-DSSETUP RPC-EPMAPPER RPC-SAMR RPC-WKSSVC RPC-SRVSVC RPC-EVENTLOG RPC-NETLOGON RPC-LSA RPC-SAMLOGON RPC-SAMSYNC RPC-MULTIBIND RPC-WINREG" +ncacn_ip_tcp_tests="RPC-SCHANNEL RPC-EPMAPPER RPC-SAMR RPC-NETLOGON RPC-LSA RPC-SAMLOGON RPC-SAMSYNC RPC-MULTIBIND" + +if [ $# -lt 4 ]; then +cat <<EOF +Usage: test_w2k3.sh SERVER USERNAME PASSWORD DOMAIN REALM +EOF +exit 1; +fi + +server="$1" +username="$2" +password="$3" +domain="$4" +realm="$5" +shift 5 + +incdir=`dirname $0` +. $incdir/test_functions.sh + +OPTIONS="-U$username%$password -W $domain --option realm=$realm" + +name="RPC-SPOOLSS on ncacn_np" +testit "$name" rpc bin/smbtorture $TORTURE_OPTIONS ncacn_np:"$server" $OPTIONS RPC-SPOOLSS "$*" + +for bindoptions in padcheck connect sign seal ntlm,sign ntlm,seal $VALIDATE bigendian; do + for transport in ncacn_ip_tcp ncacn_np; do + case $transport in + ncacn_np) tests=$ncacn_np_tests ;; + ncacn_ip_tcp) tests=$ncacn_ip_tcp_tests ;; + esac + for t in $tests; do + name="$t on $transport with $bindoptions" + testit "$name" rpc bin/smbtorture $TORTURE_OPTIONS $transport:"$server[$bindoptions]" $OPTIONS $t "$*" + done + done +done + +name="RPC-DRSUAPI on ncacn_ip_tcp with seal" +testit "$name" rpc bin/smbtorture $TORTURE_OPTIONS ncacn_ip_tcp:"$server[seal]" $OPTIONS RPC-DRSUAPI "$*" +name="RPC-DRSUAPI on ncacn_ip_tcp with seal,bigendian" +testit "$name" rpc bin/smbtorture $TORTURE_OPTIONS ncacn_ip_tcp:"$server[seal,bigendian]" $OPTIONS RPC-DRSUAPI "$*" diff --git a/source4/selftest/test_w2k3_file.sh b/source4/selftest/test_w2k3_file.sh new file mode 100755 index 0000000000..f008d49128 --- /dev/null +++ b/source4/selftest/test_w2k3_file.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with win2003 + +if [ $# -lt 3 ]; then +cat <<EOF +Usage: test_w2k3_file.sh UNC USERNAME PASSWORD <first> <smbtorture args> +EOF +exit 1; +fi + +unc="$1" +username="$2" +password="$3" +start="$4" +shift 4 +ADDARGS="$*" + +incdir=`dirname $0` +. $incdir/test_functions.sh + +tests="BASE-FDPASS BASE-LOCK " +tests="$tests BASE-UNLINK BASE-ATTR" +tests="$tests BASE-DIR1 BASE-DIR2 BASE-VUID" +tests="$tests BASE-TCON BASE-TCONDEV BASE-RW1" +tests="$tests BASE-DENY3 BASE-XCOPY BASE-OPEN BASE-DENYDOS" +tests="$tests BASE-DELETE BASE-PROPERTIES BASE-MANGLE" +tests="$tests BASE-CHKPATH BASE-SECLEAK BASE-TRANS2" +tests="$tests BASE-NTDENY1 BASE-NTDENY2 BASE-RENAME BASE-OPENATTR" +tests="$tests RAW-QFILEINFO RAW-SFILEINFO-BUG RAW-SFILEINFO" +tests="$tests RAW-LOCK RAW-MKDIR RAW-SEEK RAW-CONTEXT RAW-MUX RAW-OPEN RAW-WRITE" +tests="$tests RAW-UNLINK RAW-READ RAW-CLOSE RAW-IOCTL RAW-CHKPATH RAW-RENAME" +tests="$tests RAW-EAS RAW-STREAMS RAW-OPLOCK RAW-NOTIFY BASE-DELAYWRITE" +# slowest tests last +tests="$tests BASE-DENY1 BASE-DENY2" + +# these tests are known to fail against windows +fail="RAW-SEARCH RAW-ACLS RAW-QFSINFO" + +echo "Skipping tests expected to fail: $fail" + +for t in $tests; do + if [ ! -z "$start" -a "$start" != $t ]; then + continue; + fi + start="" + name="$t" + testit "$name" smb $VALGRIND bin/smbtorture $TORTURE_OPTIONS $ADDARGS $unc -U"$username"%"$password" $t +done diff --git a/source4/selftest/test_win.sh b/source4/selftest/test_win.sh new file mode 100755 index 0000000000..4e5558c206 --- /dev/null +++ b/source4/selftest/test_win.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# A shell script to connect to a windows host over telnet, +# setup for a smbtorture test, +# run the test, +# and remove the previously configured directory and share. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +. selftest/test_functions.sh + +export SMBTORTURE_REMOTE_HOST=`perl -I$WINTEST_DIR $WINTEST_DIR/vm_get_ip.pl VM_CFG_PATH` +if [ -z $SMBTORTURE_REMOTE_HOST ]; then + # Restore snapshot to ensure VM is in a known state, then exit. + restore_snapshot "Test failed to get the IP address of the windows host." "$VM_CFG_PATH" + exit 1 +fi + +name="BASE against Windows 2003" +testit "$name" smb $WINTEST_DIR/wintest_base.sh $SMBTORTURE_REMOTE_HOST \ + $SMBTORTURE_USERNAME $SMBTORTURE_PASSWORD $SMBTORTURE_WORKGROUP + +name="RAW against Windows 2003" +testit "$name" smb $WINTEST_DIR/wintest_raw.sh $SMBTORTURE_REMOTE_HOST \ + $SMBTORTURE_USERNAME $SMBTORTURE_PASSWORD $SMBTORTURE_WORKGROUP + +name="RPC against Windows 2003" +testit "$name" smb $WINTEST_DIR/wintest_rpc.sh $SMBTORTURE_REMOTE_HOST \ + $SMBTORTURE_USERNAME $SMBTORTURE_PASSWORD $SMBTORTURE_WORKGROUP + +name="NET against Windows 2003" +testit "$name" smb $WINTEST_DIR/wintest_net.sh $SMBTORTURE_REMOTE_HOST \ + $SMBTORTURE_USERNAME $SMBTORTURE_PASSWORD $SMBTORTURE_WORKGROUP + +name="Windows 2003 against smbd" +testit "$name" smb $WINTEST_DIR/wintest_client.sh $SMBTORTURE_REMOTE_HOST + +dc_tests="RPC-DRSUAPI RPC-SPOOLSS ncacn_np ncacn_ip_tcp" +for name in $dc_tests; do + testit "$name against Windows 2003 DC" rpc $WINTEST_DIR/wintest_2k3_dc.sh \ + "$name" +done diff --git a/source4/selftest/tests_all.sh b/source4/selftest/tests_all.sh new file mode 100755 index 0000000000..7a1167e9ac --- /dev/null +++ b/source4/selftest/tests_all.sh @@ -0,0 +1,18 @@ +#!/bin/sh + $SRCDIR/selftest/test_ejs.sh $CONFIGURATION + $SRCDIR/selftest/test_ldap.sh + $SRCDIR/selftest/test_nbt.sh "dc" + $SRCDIR/selftest/test_rpc.sh + $SRCDIR/selftest/test_net.sh + $SRCDIR/selftest/test_session_key.sh + $SRCDIR/selftest/test_binding_string.sh + $SRCDIR/selftest/test_echo.sh + $SRCDIR/selftest/test_posix.sh + $SRCDIR/selftest/test_cifs.sh + $SRCDIR/selftest/test_local.sh + $SRCDIR/selftest/test_pidl.sh + $SRCDIR/selftest/test_blackbox.sh $PREFIX + $SRCDIR/selftest/test_simple.sh + $SRCDIR/selftest/test_s3upgrade.sh $PREFIX/upgrade + $SRCDIR/selftest/test_member.sh + $SRCDIR/selftest/test_nbt.sh "member" diff --git a/source4/selftest/tests_quick.sh b/source4/selftest/tests_quick.sh new file mode 100755 index 0000000000..bb3065b0a3 --- /dev/null +++ b/source4/selftest/tests_quick.sh @@ -0,0 +1,9 @@ +#!/bin/sh +TORTURE_QUICK="yes" +export TORTURE_QUICK + +$SRCDIR/selftest/test_ejs.sh $CONFIGURATION +$SRCDIR/selftest/test_ldap.sh +$SRCDIR/selftest/test_nbt.sh +$SRCDIR/selftest/test_quick.sh +$SRCDIR/selftest/test_rpc_quick.sh diff --git a/source4/selftest/tests_win.sh b/source4/selftest/tests_win.sh new file mode 100755 index 0000000000..19460eee0e --- /dev/null +++ b/source4/selftest/tests_win.sh @@ -0,0 +1,30 @@ +#!/bin/sh + + if [ `whoami` != "root" ]; then + echo "Windows tests will not run without root privileges." + exit 1 + fi + + if [ "$DO_SOCKET_WRAPPER" = SOCKET_WRAPPER ]; then + echo "Windows tests will not run with socket wrapper enabled." + exit 1 + fi + + if [ ! $WINTESTCONF ]; then + echo "Environment variable WINTESTCONF has not been defined." + echo "Windows tests will not run unconfigured." + exit 1 + fi + + if [ ! -r $WINTESTCONF ]; then + echo "$WINTESTCONF could not be read." + exit 1 + fi + + export WINTEST_DIR=$SRCDIR/selftest/win + export TMPDIR=$TMPDIR + export NETBIOSNAME=$NETBIOSNAME + + . $WINTESTCONF + + $SRCDIR/selftest/test_win.sh diff --git a/source4/selftest/tests_win2k3_dc.sh b/source4/selftest/tests_win2k3_dc.sh new file mode 100755 index 0000000000..290a4ef666 --- /dev/null +++ b/source4/selftest/tests_win2k3_dc.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +if [ ! $WINTESTCONF ]; then + echo "Environment variable WINTESTCONF has not been defined." + echo "Windows tests will not run unconfigured." + exit 1 +fi + +if [ ! -r $WINTESTCONF ]; then + echo "$WINTESTCONF could not be read." + exit 1 +fi + +. selftest/test_functions.sh + +export SRCDIR=$SRCDIR + +tests="RPC-DRSUAPI RPC-SPOOLSS ncacn_np ncacn_ip_tcp" + +for name in $tests; do + testit $name rpc $SRCDIR/selftest/win/wintest_2k3_dc.sh $name +done diff --git a/source4/selftest/win/README b/source4/selftest/win/README new file mode 100644 index 0000000000..fc934385c4 --- /dev/null +++ b/source4/selftest/win/README @@ -0,0 +1,121 @@ +This framework uses a VMware Server hosted Windows guest VM to test the +behaviour of Windows -> Samba and Samba -> Windows interactions. To setup a +Windows host for testing, vm_setup.tar.gz contain some scripts which create +an administrative user account, and enable and start the installed telnet +service on the Windows host. Optionally, the hostname and workgroup name can +also be set. vm_setup.tar.gz is currently located in the SOC/bnh branch of +Samba's SVN repository. + +PREREQUISITES + +To use these scripts, VMware Server needs to be running with a Windows guest +VM installed, IP addressed, and VMware tools needs to be installed and running +on the guest VM. The Windows OS I used to test with was Windows Server 2003, +but I think this should work with any version of Windows that has the +Microsoft telnet service installed. The VMware Server versions I used for +testing was 1.0.0 build-27828, and 1.0.0 build-28343. + +PLEASE NOTE: Due to problems with my original revert_snapshot() code, the initial +setup now requires that the VM configuration setting 'When Powering Off' is +manually set to 'Revert to snapshot' (snapshot.action="autoRevert" in the +guest's .vmx file). This should not be a permanent change, but the original +revert_snapshot() code I wrote no longer works and i'm not sure why. + +On the machine that these scripts are running on (this need not be the same +machine as the VMware host), the VMware perl scripting api needs to be +installed, as well as the vix-perl api. These come with the VMware Server +console package. + +After unzipping this file, the libraries are installed by extracting the +VMware-vix-e.x.p-<revision number>.tar.gz and +VMware-VmPerlAPI-e.x.p-<revision number>.tar.gz archives, and running the +vmware-install.pl scripts inside their respective directories. + +On Slackware 10.2, I encountered a problem in that when I tried to use the vix +api libraries, I would get the following error: + +SSLLoadSharedLibrary: Failed to load library /<client program directory>/libcrypto.so.0.9.7:/<client program directory>/libcrypto.so.0.9.7: cannot open a shared object file: No such file or directory. + +The fix found on the VMware knowledge base (search http://kb.vmware.com for +Doc ID: 1837104) states that it's a known problem with the scripting libraries, +and can be resolved by installing VMware Server on the host, which properly +sets up the SSL module loader. This is what I would suggest if you encounter +this, as it solved the problem for me (I don't have VMware Server actually +running on that host though). + +INSTALLATION + +To use these scripts, modify initial_setup.conf to match your environment. The +GUEST_HOSTNAME, GUEST_WORKGROUP, HOST_SERVER_NAME, HOST_SERVER_PORT, +HOST_USERNAME, and HOST_PASSWORD variables are optional, and are commented out +in this release. + +Running initial_setup.sh will: +* Get the IP address of the Windows guest VM. +* Take a snapshot of the pristine Windows guest. +* Copy the windows scripts from the windows-scripts directory on the unix host + to the directory on the Windows guest specified by the + GUEST_SCRIPT_PATH option. This path will be created on the guest if + it does not already exist. +* Execute win_setup.wsf on the Windows guest in order to create the + administrator account specified by GUEST_USERNAME and GUEST_PASSWORD, + enable and start the telnet service, and set the GUEST_HOSTNAME and + GUEST_WORKGROUP if configured. +* If these operations are successful so far, another snapshot is taken at this + point. This is the snapshot which is restored if the tests encounter + problems they are unable to recover from. + +These operations leave the Windows guest in a state such that it can be +remotely administered with telnet. Specifically, this will allow us to use +'make wintest' in Samba 4 to perform smbtorture tests against a Windows host, +and perform tests from a Windows client to a Samba server. + +INTEGRATING WITH THE BUILD FARM + +Follow the standard steps to add a host to the build farm. The major +difference is that we will need to run these tests as root. To run the +Windows tests in the build farm, a .fns file will need to be created for +your new host that exports a WINTESTCONF environment variable pointing to a +config file used by 'make wintest'. An example of this config file can be +found at source/selftest/win/test_win.conf in the Samba 4 source tree. + +I've also included the bnhtest.fns file that I'm using for my build farm host +below, as an example. It was modified from generic.fns. + +action_test_windows() { + do_make wintest + w_status=$? + echo "WINTEST STATUS: $w_status" + return $w_status; +} + +per_run_hook + +system=`uname` + +export WINTESTCONF="/home/build/win/test_win.conf" + +for compiler in gcc cc icc; do + + # arrgh, "which" gives no err code on solaris + path=`which $compiler` + if [ -x "$path" ]; then + + if $compiler -v 2>&1 | grep gcc.version > /dev/null; then + isgcc=1 + CFLAGS="-Wall" + export CFLAGS + else + CFLAGS="" + export CFLAGS + isgcc=0 + fi + if [ $compiler = gcc -o $isgcc = 0 ]; then + + # only attempt samba4 if we have perl + if which perl > /dev/null; then + test_tree samba4 source $compiler configure build install test_windows test + fi + fi + fi +done diff --git a/source4/selftest/win/VMHost.pm b/source4/selftest/win/VMHost.pm new file mode 100644 index 0000000000..359d8df315 --- /dev/null +++ b/source4/selftest/win/VMHost.pm @@ -0,0 +1,359 @@ +#!/usr/bin/perl -w + +# A perl object to provide a simple, unified method of handling some +# VMware Server VM management functions using the perl and VIX API's. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +# VMware Perl API +use VMware::VmPerl; +use VMware::VmPerl::VM; +use VMware::VmPerl::ConnectParams; + +# VMware C bindings +use VMware::Vix::Simple; +use VMware::Vix::API::Constants; + +# Create a class to abstract from the Vix and VMPerl APIs. +{ package VMHost; + my $perl_vm = VMware::VmPerl::VM::new(); + my $perl_vm_credentials; + my $vix_vm; + my $vix_vm_host; + + my $err_code = 0; + my $err_str = ""; + + my $hostname; + my $port; + my $username; + my $password; + my $vm_cfg_path; + my $guest_admin_username; + my $guest_admin_password; + + sub error { + my $old_err_code = $err_code; + my $old_err_str = $err_str; + $err_code = 0; + $err_str = ""; + return ($old_err_code, $old_err_str); + } + + # Power on the guest if it isn't already running. + # Returns 0 when the guest is already running, and + # if not, it waits until it is started. + sub start_guest { + my $vm_power_state = $perl_vm->get_execution_state(); + if (!defined($vm_power_state)) { + ($err_code, $err_str) = $perl_vm->get_last_error(); + return ($err_code); + } + if ($vm_power_state == VMware::VmPerl::VM_EXECUTION_STATE_OFF + || $vm_power_state == + VMware::VmPerl::VM_EXECUTION_STATE_SUSPENDED) + { + if (!$perl_vm->start()) { + ($err_code, $err_str) = + $perl_vm->get_last_error(); + return ($err_code); + } + while ($perl_vm->get_tools_last_active() == 0) { + sleep(60); + } + } + return ($err_code); + } + + sub host_connect { + # When called as a method, the first parameter passed is the + # name of the method. Called locally, this function will lose + # the first parameter. + shift @_; + ($hostname, $port, $username, $password, $vm_cfg_path, + $guest_admin_username, $guest_admin_password) = @_; + + # Connect to host using vmperl api. + $perl_vm_credentials = + VMware::VmPerl::ConnectParams::new($hostname, $port, + $username, $password); + if (!$perl_vm->connect($perl_vm_credentials, $vm_cfg_path)) { + ($err_code, $err_str) = $perl_vm->get_last_error(); + undef $perl_vm; + return ($err_code); + } + + # Connect to host using vix api. + ($err_code, $vix_vm_host) = + VMware::Vix::Simple::HostConnect( + VMware::Vix::Simple::VIX_API_VERSION, + VMware::Vix::Simple::VIX_SERVICEPROVIDER_VMWARE_SERVER, + $hostname, $port, $username, $password, + 0, VMware::Vix::Simple::VIX_INVALID_HANDLE); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = + VMware::Vix::Simple::GetErrorText($err_code); + undef $perl_vm; + undef $vix_vm; + undef $vix_vm_host; + return ($err_code); + } + + # Power on our guest os if it isn't already running. + $err_code = start_guest(); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Starting guest power after connect " . + "failed: " . $old_err_str; + undef $perl_vm; + undef $vix_vm; + undef $vix_vm_host; + return ($err_code); + } + + # Open VM. + ($err_code, $vix_vm) = + VMware::Vix::Simple::VMOpen($vix_vm_host, $vm_cfg_path); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = + VMware::Vix::Simple::GetErrorText($err_code); + undef $perl_vm; + undef $vix_vm; + undef $vix_vm_host; + return ($err_code); + } + + # Login to $vix_vm guest OS. + $err_code = VMware::Vix::Simple::VMLoginInGuest($vix_vm, + $guest_admin_username, $guest_admin_password, + 0); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = + VMware::Vix::Simple::GetErrorText($err_code); + undef $perl_vm; + undef $vix_vm; + undef $vix_vm_host; + return ($err_code); + } + return ($err_code); + } + + sub host_disconnect { + undef $perl_vm; + + $perl_vm = VMware::VmPerl::VM::new(); + if (!$perl_vm) { + $err_code = 1; + $err_str = "Error creating new VmPerl object"; + } + + undef $vix_vm; + VMware::Vix::Simple::HostDisconnect($vix_vm_host); + VMware::Vix::Simple::ReleaseHandle($vix_vm_host); + return ($err_code); + } + + sub host_reconnect { + $err_code = host_disconnect(); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Disconnecting from host failed: " . + $old_err_str; + return ($err_code); + } + + $err_code = host_connect(NULL, $hostname, $port, $username, + $password, $vm_cfg_path, $guest_admin_username, + $guest_admin_password); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Re-connecting to host failed: " . + $old_err_str; + return ($err_code); + } + return ($err_code); + } + + sub create_snapshot { + my $snapshot; + + ($err_code, $snapshot) = + VMware::Vix::Simple::VMCreateSnapshot($vix_vm, + "Snapshot", "Created by vm_setup.pl", 0, + VMware::Vix::Simple::VIX_INVALID_HANDLE); + + VMware::Vix::Simple::ReleaseHandle($snapshot); + + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = + VMware::Vix::Simple::GetErrorText($err_code); + return $err_code; + } + + $err_code = host_reconnect(); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Reconnecting to host after creating " . + "snapshot: " . $old_err_str; + return ($err_code); + } + return ($err_code); + } + + sub revert_snapshot { + # Because of problems with VMRevertToSnapshot(), we have to + # rely on the guest having set 'Revert to Snapshot' following + # a power-off event. + $err_code = VMware::Vix::Simple::VMPowerOff($vix_vm, 0); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = + VMware::Vix::Simple::GetErrorText($err_code); + return $err_code; + } + + # host_reconnect() will power-on a guest in a non-running state. + $err_code = host_reconnect(); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Reconnecting to host after reverting " . + "snapshot: " . $old_err_str; + return ($err_code); + } + return ($err_code); + } + + # $dest_path must exist. It doesn't get created. + sub copy_files_to_guest { + shift @_; + my (%files) = @_; + + my $src_file; + my $dest_file; + + foreach $src_file (keys(%files)) { + $dest_file = $files{$src_file}; + $err_code = + VMware::Vix::Simple::VMCopyFileFromHostToGuest( + $vix_vm, $src_file, $dest_file, 0, + VMware::Vix::Simple::VIX_INVALID_HANDLE); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = "Copying $src_file: " . + VMware::Vix::Simple::GetErrorText( + $err_code); + return $err_code; + } + } + return $err_code; + } + + sub copy_to_guest { + # Read parameters $src_path, $dest_path. + shift @_; + my ($src_path, $dest_dir) = @_; + + my $len = length($dest_dir); + my $idx = rindex($dest_dir, '\\'); + if ($idx != ($len - 1)) { + $err_code = -1; + $err_str = "Destination $dest_dir must be a " . + "directory path"; + return ($err_code); + } + + # Create the directory $dest_path on the guest VM filesystem. + my $cmd = "cmd.exe "; + my $cmd_args = "/C MKDIR " . $dest_dir; + $err_code = run_on_guest(NULL, $cmd, $cmd_args); + if ( $err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Creating directory $dest_dir on host: " . + $old_err_str; + return ($err_code); + } + + # If $src_filepath specifies a file, create it in $dest_path + # and keep the same name. + # If $src_path is a directory, create the files it contains in + # $dest_path, keeping the same names. + $len = length($src_path); + my %files; + $idx = rindex($src_path, '/'); + if ($idx == ($len - 1)) { + # $src_path is a directory. + if (!opendir (DIR_HANDLE, $src_path)) { + $err_code = -1; + $err_str = "Error opening directory $src_path"; + return $err_code; + } + + foreach $file (readdir DIR_HANDLE) { + my $src_file = $src_path . $file; + + if (!opendir(DIR_HANDLE2, $src_file)) { + # We aren't interested in subdirs. + my $dest_path = $dest_dir . $file; + $files{$src_file} = $dest_path; + } else { + closedir(DIR_HANDLE2); + } + } + } else { + # Strip if preceeding path from $src_path. + my $src_file = substr($src_path, ($idx + 1), $len); + my $dest_path = $dest_dir . $src_file; + + # Add $src_path => $dest_path to %files. + $files{$src_path} = $dest_path; + } + + $err_code = copy_files_to_guest(NULL, %files); + if ($err_code != 0) { + my $old_err_str = $err_str; + $err_str = "Copying files to host after " . + "populating %files: " . $old_err_str; + return ($err_code); + } + return ($err_code); + } + + sub run_on_guest { + # Read parameters $cmd, $cmd_args. + shift @_; + my ($cmd, $cmd_args) = @_; + + $err_code = VMware::Vix::Simple::VMRunProgramInGuest($vix_vm, + $cmd, $cmd_args, 0, + VMware::Vix::Simple::VIX_INVALID_HANDLE); + if ($err_code != VMware::Vix::Simple::VIX_OK) { + $err_str = VMware::Vix::Simple::GetErrorText( + $err_code); + return ($err_code); + } + + return ($err_code); + } + + sub get_guest_ip { + my $guest_ip = $perl_vm->get_guest_info('ip'); + + if (!defined($guest_ip)) { + ($err_code, $err_str) = $perl_vm->get_last_error(); + return NULL; + } + + if (!($guest_ip)) { + $err_code = 1; + $err_str = "Guest did not set the 'ip' variable"; + return NULL; + } + return $guest_ip; + } + + sub DESTROY { + host_disconnect(); + undef $perl_vm; + undef $vix_vm_host; + } +} + +return TRUE; diff --git a/source4/selftest/win/common.exp b/source4/selftest/win/common.exp new file mode 100644 index 0000000000..a7ba95d722 --- /dev/null +++ b/source4/selftest/win/common.exp @@ -0,0 +1,521 @@ +# A library of commonly used functions written in expect. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +# This function maps a drive letter to a share point. +proc map_share { remote_prompt share_drive sharepoint username domain password } { + set default_err_str "Unknown error in function map_share" + set err_str $default_err_str + + set cmd "net use $share_drive $sharepoint $password /USER:$username@$domain\r\n" + send $cmd + + expect { + "The command completed successfully." { + expect_prompt $remote_prompt + set err_str "OK" + } \ + "The local device name is already in use." { + expect_prompt $remote_prompt + set err_str "The device name $share_drive is already in use" + } \ + "The network name cannot be found." { + expect_prompt $remote_prompt + set err_str "Sharepoint $sharepoint could not be found" + } \ + timeout { + set err_str "Function map_share timed out while mapping $share_drive to $sharepoint" + } + } + return $err_str +} + +# This function unmaps a drive letter from a share point. +proc unmap_share { remote_prompt share_drive } { + set default_err_str "Unknown error in function unmap_share" + set err_str $default_err_str + + set cmd "net use $share_drive /DELETE\r\n" + send $cmd + + expect { + "was deleted successfully." { + expect_prompt $remote_prompt + set err_str "OK" + } \ + "NET HELPMSG 2250" { + expect_prompt $remote_prompt + set err_str "The network connection could not be found while unmapping $share_drive" + } \ + timeout { + set err_str "Function unmap_share timed out while unmapping $share_drive" + } + } + return $err_str +} + +# This function uses xcopy to copy a text file from one location on the +# remote windows host to another. +proc xcopy_file { remote_prompt in_filename out_filename xcopy_options } { + set default_err_str "Unknown error in function xcopy_file" + set err_str $default_err_str + + set cmd "xcopy $in_filename $out_filename $xcopy_options\r\n" + send $cmd + + expect { + "(F = file, D = directory)? " { + set cmd "F\r\n" + send $cmd + expect { + "1 File(s) copied\r\n\r\n" { + expect_prompt $remote_prompt + set err_str "OK" + } \ + "0 File(s) copied\r\n\r\n" { + expect_prompt $remote_prompt + set err_str $default_err_str + } \ + timeout { + set err_str "Function xcopy_file has timed out while copying $in_filename" + } + } + } \ + "1 File(s) copied\r\n\r\n" { + expect_prompt $remote_prompt + set err_str "OK" + } \ + "0 File(s) copied\r\n\r\n" { + expect_prompt $remote_prompt + set err_str $default_err_str + } \ + timeout { + set err_str "Function xcopy_file timed out while copying $in_filename" + } + } + return $err_str +} + +# This function creates a temporary file on the remote windows host. +# The file contents are populated by a recursive directory listing of +# the windows %HOMEDRIVE%. +proc create_tmp_file { remote_prompt filename } { + set default_err_str "Unknown error in function create_tmp_file" + set err_str $default_err_str + + set cmd "dir %HOMEDRIVE%\\ /S > $filename\r\n" + send $cmd + expect { + $remote_prompt { + set err_str "OK" + } \ + timeout { + set err_str "Function create_tmp_file timed out while creating $filename" + } + } + return $err_str +} + +# This function compares two files on the remote windows host. +proc compare_files { remote_prompt file1 file2 } { + set default_err_str "Unknown error in function compare_files" + set err_str $default_err_str + + set cmd "fc $file1 $file2\r\n" + send $cmd + expect { + "FC: no differences encountered\r\n\r\n\r\n" { + expect_prompt $remote_prompt + set err_str "OK" + } \ + "\*\*\*\*\* $file1" { + expect_prompt $remote_prompt + set err_str "Files $file1 and $file2 differ" + } \ + "\*\*\*\*\* $file2" { + expect_prompt $remote_prompt + set err_str "Files $file1 and $file2 differ" + } \ + timeout { + set err_str "Function compare_files timed out while comparing files $file1 and $file2" + } + } + return $err_str +} + +# This function deletes a file on the remote windows host. +proc delete_file { remote_prompt filename } { + set default_err_str "Unknown error in function delete_file" + set err_str $default_err_str + + set cmd "del $filename\r\n" + send $cmd + expect { + "Could Not" { + expect_prompt $remote_prompt + set err_str $default_err_str + } \ + $remote_prompt { + set err_str "OK" + } \ + timeout { + set err_str "Function delete_file timed oout while deleting $filename" + } + } + return $err_str +} + +# This function copies a text file over telnet from the local unix host +# to the remote windows host. +proc copy_file { remote_prompt in_filename out_filename } { + set default_err_str "Unknown error in function copy_file" + set err_str $default_err_str + + # The octal ASCII code for Control-Z is 032. + set CTRLZ \032 + + # Open local file and read contents. + set in_file [open $in_filename r] + set in_data [read $in_file] + + # Initiate copy on remote host. + set cmd "copy con $out_filename\r\n" + send $cmd + + # Separate $in_data into lines and send to remote host. + set out_data [split $in_data "\n"] + foreach out_line $out_data { + send $out_line + # We might as well do a unix -> windows line conversion. + send "\r\n" + # Are we overwriting an existing file? + # If so, exit so we can handle it. + expect { + "(Yes/No/All)" { + send "NO\r\n" + expect_prompt $remote_prompt + set err_str "File exists" + } \ + $out_line { + set err_str "OK" + } \ + timeout { + set err_str "Function copy_file timed out while copying $in_filename" + } + } + if { $err_str != "OK" } { + return $err_str + } else { + set err_str $default_err_str + } + } + + # ^Z\r to complete the transfer. + send $CTRLZ + send "\r" + expect { + "file(s) copied." { + set err_str [expect_prompt $remote_prompt] + } \ + $remote_prompt { + set err_str $default_err_str + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Function copy_file timed out while finishing copy of $in_filename" + } + } + return $err_str +} + +# This function waits for the command prompt and reports an error on +# timeout. +proc expect_prompt { remote_prompt } { + set default_err_str "Unknown error occurred while waiting for the command prompt" + set err_str $default_err_str + + expect { + $remote_prompt { + set err_str "OK" + } \ + timeout { + set err_str "Timeout occurred while waiting for the command prompt" + } + } + return $err_str +} + +# This function will create a telnet login shell to $remote_host as $username. +# If expected dialogue is not recieved, return with a specific error if one +# is recognized. Otherwise return a generic error indicating the function +# name. +proc telnet_login { remote_prompt remote_host username password } { + + set default_err_str "Unknown error in function telnet_login" + set err_str $default_err_str + + set cmd "telnet $remote_host\r" + send $cmd + expect { + "login: " { + set err_str "OK" + } \ + "Connection refused" { + set err_str "Connection refused" + } \ + "No route to host" { + set err_str "No route to host" + } \ + timeout { + set err_str "Function telnet_login timed out while waiting for the login prompt" + } + } + if { $err_str != "OK" } { + # Return because something unexpected happened. + return $err_str + } else { + # Reset err_str + set err_str $default_err_str + } + + set cmd "$username\r" + send $cmd + expect { + "password: " { + set err_str "OK" + } \ + timeout { + set err_str "Function telnet_login timed out while waiting for the password prompt" + } + } + if { $err_str != "OK" } { + return $err_str + } else { + set err_str $default_err_str + } + + set cmd "$password\r" + send $cmd + expect { + $remote_prompt { + set err_str "OK" + } \ + "Login Failed" { + set err_str "Telnet login failed" + } \ + timeout { + set err_str "Function telnet_login timed out while waiting for the command prompt" + } + } + return $err_str +} + +proc create_directory { remote_prompt sharepath } { + + set default_err_str "Unknown error in function create_directory" + set err_str $default_err_str + + set cmd "mkdir $sharepath\r\n" + send $cmd + expect { + "already exists" { + expect_prompt $remote_prompt + set err_str "Directory already exists" + } \ + $remote_prompt { + set err_str "OK" + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached starting create_directory." + } + } + return $err_str +} + +proc delete_directory { remote_prompt sharepath } { + + set default_err_str "Unknown error in function delete_directory" + set err_str $default_err_str + + set cmd "rmdir /S /Q $sharepath\r\n" + send $cmd + expect { + "Access is denied." { + expect_prompt $remote_prompt + set err_str "Directory access is denied" + } \ + $remote_prompt { + set err_str "OK" + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached in delete_directory" + } + } + return $err_str +} + +proc create_share { remote_prompt username sharepath sharename } { + + set default_err_str "Unknown error in function create_share" + set err_str $default_err_str + + set cmd "net share $sharename=$sharepath /GRANT:$username,FULL\r\n" + send $cmd + expect { + "was shared successfully." { + set err_str [expect_prompt $remote_prompt] + } \ + "NET HELPMSG 2118." { + expect_prompt $remote_prompt + set err_str "The name has already been shared" + } \ + $remote_prompt { + set err_str $default_err_str + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached in create_share" + } + } + return $err_str +} + +proc delete_share { remote_prompt sharename } { + + set default_err_str "Unknown error in function delete_share" + set err_str $default_err_str + + set cmd "net share $sharename /DELETE\r\n" + send $cmd + expect { + "was deleted successfully." { + set err_str [expect_prompt $remote_prompt] + } \ + "does not exist." { + expect_prompt $remote_prompt + set err_str "The share does not exist" + } \ + $remote_prompt { + set err_str $default_err_str + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached in delete_share" + } + } + return $err_str +} + +proc delete_hosts_entry { remote_prompt hosts_file_path backup_hosts_filename } { + + set default_err_str "Unknown error in function delete_hosts_entry" + set err_str $default_err_str + + set cmd "cd $hosts_file_path\r\n" + send $cmd + expect { + "." { + expect_prompt $remote_prompt + set err_str $default_err_str + } \ + $remote_prompt { + set err_str "OK" + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached in delete_hosts_entry" + } + } + if { $err_str != "OK" } { + return $err_str + } else { + set err_str $default_err_str + } + + set cmd "move /Y $backup_hosts_filename hosts\r\n" + send $cmd + expect { + "1 file(s) moved." { + set err_str [expect_prompt $remote_prompt] + } \ + "cannot find the file specified." { + expect_prompt $remote_prompt + set err_str "File not found" + } \ + $remote_prompt { + set err_str $default_err_str + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Function delete_hosts_entry timed out while renaming $backup_hosts_filename" + } + } + return $err_str +} + +proc create_hosts_entry { remote_prompt hosts_file_path hostname ip \ + backup_hosts_filename } { + + set default_err_str "Unknown error in function create_hosts_entry" + set err_str $default_err_str + + set cmd "cd $hosts_file_path\r\n" + send $cmd + expect { + "." { + expect_prompt $remote_prompt + set err_str $default_err_str + } \ + $remote_prompt { + set err_str "OK" + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Timeout reached in create_hosts_entry" + } + } + if { $err_str != "OK" } { + return $err_str + } else { + set err_str $default_err_str + } + + set cmd "copy /Y hosts $backup_hosts_filename\r\n" + send $cmd + expect { + "1 file(s) copied." { + set err_str [expect_prompt $remote_prompt] + } \ + "cannot find the file specified." { + expect_prompt $remote_prompt + set err_str "File not found." + } \ + $remote_prompt { + set err_str $default_err_str + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Function create_hosts_entry timed out while copying hosts file" + } + } + if { $err_str != "OK" } { + return $err_str + } else { + set err_str $default_err_str + } + + set cmd "echo $ip $hostname #smbtorture host. >> hosts\r\n" + send $cmd + expect { + $remote_prompt { + set err_str "OK" + } \ + timeout { + expect_prompt $remote_prompt + set err_str "Function create_hosts timed out while updating hosts file" + } + } + return $err_str +} diff --git a/source4/selftest/win/test_win.conf b/source4/selftest/win/test_win.conf new file mode 100644 index 0000000000..ed52be999e --- /dev/null +++ b/source4/selftest/win/test_win.conf @@ -0,0 +1,83 @@ + +# perl needs to know to look in $WINTEST_DIR for VMHost.pm. +export PERLLIB=$WINTEST_DIR + +# Command prompt that we are expecting on the windows host. +export SMBTORTURE_REMOTE_PROMPT=">" + +## +## The variables in this section apply to the 'make wintest_dc' set of tests. +## + +# A username and password with admin rights to the DC we're testing against. +export WIN2K3_DC_USERNAME="tortureuser" +export WIN2K3_DC_PASSWORD="torturepass" + +# The domain and realm that the DC is configured for. +export WIN2K3_DC_DOMAIN="WINTESTDC" +export WIN2K3_DC_REALM="wintest.dc" + +# The path to the DC vmware image config file, local to the vmware server. +export WIN2K3_DC_VM_CFG_PATH="/var/lib/vmware/Virtual Machines/Windows Server 2003 DC BuildFarm/Windows 2003 DC BuildFarm.vmx" + +## +## The parameters in this section apply to the 'make wintest' set of tests. +## + +# The username and password we will be testing with. +# This user will need admin rights on the remote windows host. +export SMBTORTURE_USERNAME="tortureuser" +export SMBTORTURE_PASSWORD="torturepass" + +# The name of the workgroup we will be using on the remote windows host. +export SMBTORTURE_WORKGROUP="SMBTEST" + +# The name of and path to the windows share we'll be testing against. +export SMBTORTURE_REMOTE_SHARE_NAME="smbtorture_share" +export SMBTORTURE_REMOTE_SHARE_PATH="%HOMEDRIVE%\smbtorture_shared_dir" + +# Default timeout for the expect scripts to wait for a response from the remote. +export SMBTORTURE_EXPECT_TIMEOUT=30 + +# Path to the local smbtorture binary. +export SMBTORTURE_BIN_PATH="bin/smbtorture" + +# Local system hostname and ip address we'll be adding to the remote's +# hosts file. +export SMBTORTURE_LOCAL_HOSTNAME=$NETBIOSNAME +export SMBTORTURE_LOCAL_IP="192.168.100.12" + +# Filename of the windows hosts' unedited hosts file. +export REMOTE_BACKUP_HOSTS_FILENAME="hosts.smbtorture" +export REMOTE_HOSTS_FILE_PATH="%SYSTEMROOT%\\system32\\drivers\\etc" + +# These coincide with the parameters mktestsetup.sh uses to setup smbd. +export SMBTORTURE_LOCAL_USERNAME="administrator" +export SMBTORTURE_LOCAL_PASSWORD="penguin" +export SMBTORTURE_LOCAL_DOMAIN="SAMBADOMAIN" + +# This is the name of the samba share the windows vm will connect to. +export SMBTORTURE_LOCAL_SHARE_NAME="TMP" + +# This is the drive letter which will be used to mount a share on the windows vm. +export SMBTORTURE_REMOTE_DRIVE_LETTER="X:" + +# This is the name of the file which will be created on the windows vm +# and used for samba server tests. +export SMBTORTURE_TMP_FILENAME="smbtorture.tmp" + +# The path to the vmware image config file local to the vmware server. +export VM_CFG_PATH="/var/lib/vmware/Virtual Machines/Win2k3-BuildFarm/Win2k3-BuildFarm.vmx" + +# In order to copy files and execute programs on the guest vm, +# we need administrator-level credentials to log in with. +export GUEST_ADMIN_USERNAME="administrator" +export GUEST_ADMIN_PASSWORD="adminpass" + +# These parameters are optional. If not specified, the script tries to access +# a local vmware server as the executing user. +# logged-in user running the script are used. +export HOST_SERVER_NAME="vmhost" +export HOST_SERVER_PORT=902 +export HOST_USERNAME="vmuser" +export HOST_PASSWORD="vmpass" diff --git a/source4/selftest/win/vm_get_ip.pl b/source4/selftest/win/vm_get_ip.pl new file mode 100644 index 0000000000..9286786155 --- /dev/null +++ b/source4/selftest/win/vm_get_ip.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w + +# A perl script to connect to a VMware server and get the IP address of a VM. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +use VMHost; + +sub check_error { + my $vm = VMHost; + my $custom_err_str = ""; + ($vm, $custom_err_str) = @_; + + my ($err_code, $err_str) = $vm->error; + if ($err_code != 0) { + undef $vm; + die $custom_err_str . "Returned $err_code: $err_str.\n"; + } +} + +# Read in parameters from environment. +my $vm_cfg_path = $ENV{"$ARGV[0]"}; +my $host_server_name = $ENV{'HOST_SERVER_NAME'}; +my $host_server_port = $ENV{'HOST_SERVER_PORT'}; +if (!defined($host_server_port)) { + $host_server_port = 902; +} + +my $host_username = $ENV{'HOST_USERNAME'}; +my $host_password = $ENV{'HOST_PASSWORD'}; +my $guest_admin_username = $ENV{'GUEST_ADMIN_USERNAME'}; +my $guest_admin_password = $ENV{'GUEST_ADMIN_PASSWORD'}; + +my $vm = VMHost; + +$vm->host_connect($host_server_name, $host_server_port, $host_username, + $host_password, $vm_cfg_path, $guest_admin_username, + $guest_admin_password); +check_error($vm, "Error in \$vm->host_connect().\n"); + +my $guest_ip = $vm->get_guest_ip(); +check_error($vm, "Error in \$vm->get_guest_ip().\n"); + +print $guest_ip; + +undef $vm; + +exit 0; diff --git a/source4/selftest/win/vm_load_snapshot.pl b/source4/selftest/win/vm_load_snapshot.pl new file mode 100644 index 0000000000..e8ba9b39cf --- /dev/null +++ b/source4/selftest/win/vm_load_snapshot.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +# A perl script to connect to a VMware server and revert a VM snapshot. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +use VMHost; + +sub check_error { +my $vm = VMHost; + my $custom_err_str = ""; + ($vm, $custom_err_str) = @_; + + my ($err_code, $err_str) = $vm->error; + if ($err_code != 0) { + undef $vm; + die $custom_err_str . "Returned $err_code: $err_str.\n"; + } +} + +# Read in parameters from environment. +my $vm_cfg_path = $ENV{'VM_CFG_PATH'}; +my $host_server_name = $ENV{'HOST_SERVER_NAME'}; +my $host_server_port = $ENV{'HOST_SERVER_PORT'}; +if (!defined($host_server_port)) { + $host_server_port = 902; +} + +my $host_username = $ENV{'HOST_USERNAME'}; +my $host_password = $ENV{'HOST_PASSWORD'}; +my $guest_admin_username = $ENV{'GUEST_ADMIN_USERNAME'}; +my $guest_admin_password = $ENV{'GUEST_ADMIN_PASSWORD'}; + +my $vm = VMHost; + +$vm->host_connect($host_server_name, $host_server_port, $host_username, + $host_password, $vm_cfg_path, $guest_admin_username, + $guest_admin_password); +check_error($vm, "Error in \$vm->host_connect().\n"); + +$vm->revert_snapshot(); +check_error($vm, "Error in \$vm->revert_snapshot().\n"); + +undef $vm; + +exit 0; diff --git a/source4/selftest/win/wintest_2k3_dc.sh b/source4/selftest/win/wintest_2k3_dc.sh new file mode 100755 index 0000000000..ed964a274a --- /dev/null +++ b/source4/selftest/win/wintest_2k3_dc.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then +cat <<EOF +Usage: wintest_2k3_dc.sh TESTGROUP +EOF +exit 1; +fi + +TESTGROUP=$1 + +if [ -z $WINTEST_DIR ]; then + echo "Environment variable WINTEST_DIR not found." + exit 1; +fi + +# This variable is defined in the per-hosts .fns file for build-farm hosts that run windows tests. +if [ -z $WINTESTCONF ]; then + echo "Please point environment variable WINTESTCONF to your test_win.conf file." + exit 1; +fi + +. $WINTESTCONF +. $WINTEST_DIR/wintest_functions.sh + +export WIN2K3_DC_REMOTE_HOST=`perl -I$WINTEST_DIR $WINTEST_DIR/vm_get_ip.pl WIN2K3_DC_VM_CFG_PATH` + +if [ -z $WIN2K3_DC_REMOTE_HOST ]; then + # Restore snapshot to ensure VM is in a known state, then exit. + restore_snapshot "Test failed to get the IP address of the windows 2003 DC." "$WIN2K3_DC_VM_CFG_PATH" + exit 1; +fi + +server=$WIN2K3_DC_REMOTE_HOST +username=$WIN2K3_DC_USERNAME +password=$WIN2K3_DC_PASSWORD +domain=$WIN2K3_DC_DOMAIN +realm=$WIN2K3_DC_REALM + +OPTIONS="-U$username%$password -W $domain --option realm=$realm" + +all_errs=0 + +on_error() { + name=$1 + + all_errs=`expr $all_errs + 1` + restore_snapshot "$name test failed." "$WIN2K3_DC_VM_CFG_PATH" +} + +drsuapi_tests() { + + name="RPC-DRSUAPI on ncacn_ip_tcp with seal" + bin/smbtorture \ + ncacn_ip_tcp:$server[seal] $OPTIONS \ + RPC-DRSUAPI || on_error "$name" + + name="RPC-DRSUAPI on ncacn_ip_tcp with seal,bigendian" + bin/smbtorture \ + ncacn_ip_tcp:$server[seal,bigendian] $OPTIONS \ + RPC-DRSUAPI || on_error "$name" +} + +spoolss_tests() { + + name="RPC-SPOOLSS on ncacn_np" + bin/smbtorture \ + ncacn_np:$server $OPTIONS \ + RPC-SPOOLSS || on_error "$name" +} + +ncacn_ip_tcp_tests() { + bindopt=$1 + transport="ncacn_ip_tcp" + tests="RPC-SCHANNEL RPC-EPMAPPER RPC-SAMR RPC-NETLOGON RPC-LSA RPC-SAMLOGON RPC-SAMSYNC RPC-MULTIBIND" + + for bindoptions in $bindopt; do + for t in $tests; do + name="$t on $transport with $bindoptions" + bin/smbtorture $TORTURE_OPTIONS \ + $transport:$server[$bindoptions] \ + $OPTIONS $t || on_error "$name" + done + done +} + +ncacn_np_tests() { + bindopt=$1 + transport="ncacn_np" + tests="RPC-SCHANNEL RPC-DSSETUP RPC-EPMAPPER RPC-SAMR RPC-WKSSVC RPC-SRVSVC RPC-EVENTLOG RPC-NETLOGON RPC-LSA RPC-SAMLOGON RPC-SAMSYNC RPC-MULTIBIND RPC-WINREG" + + for bindoptions in $bindopt; do + for t in $tests; do + name="$t on $transport with $bindoptions" + bin/smbtorture $TORTURE_OPTIONS \ + $transport:$server[$bindoptions] \ + $OPTIONS $t || on_error "$name" + done + done +} + +bindoptions="padcheck connect sign seal ntlm,sign ntml,seal $VALIDATE bigendian" + +case $TESTGROUP in + RPC-DRSUAPI) drsuapi_tests ;; + RPC-SPOOLSS) spoolss_tests ;; + ncacn_ip_tcp) ncacn_ip_tcp_tests $bindoptions ;; + ncacn_np) ncacn_np_tests $bindoptions ;; + *) echo "$TESTGROUP is not a known set of tests." + exit 1; + ;; +esac + +exit $all_errs diff --git a/source4/selftest/win/wintest_base.sh b/source4/selftest/win/wintest_base.sh new file mode 100755 index 0000000000..b78da4f7c9 --- /dev/null +++ b/source4/selftest/win/wintest_base.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +. selftest/test_functions.sh + +. selftest/win/wintest_functions.sh + +# This variable is defined in the per-hosts .fns file. +. $WINTESTCONF + +if [ $# -lt 4 ]; then +cat <<EOF +Usage: test_net.sh SERVER USERNAME PASSWORD DOMAIN +EOF +exit 1; +fi + +server="$1" +username="$2" +password="$3" +domain="$4" +shift 4 + +export SMBTORTURE_REMOTE_HOST=$server + +base_tests="BASE-UNLINK BASE-ATTR BASE-DELETE BASE-TCON BASE-OPEN BASE-CHKPATH" + +all_errs=0 +err=0 + +on_error() { + errstr=$1 + + all_errs=`expr $all_errs + 1` + restore_snapshot $errstr "$VM_CFG_PATH" +} + +for t in $base_tests; do + test_name="$t / WINDOWS SERVER" + echo -e "\n$test_name SETUP PHASE" + + setup_share_test + + if [ $err_rtn -ne 0 ]; then + # If test setup fails, load VM snapshot and skip test. + on_error "\n$test_name setup failed, skipping test." + else + echo -e "\n$test_name setup completed successfully." + + $SMBTORTURE_BIN_PATH -U $username%$password \ + -W $domain //$server/$SMBTORTURE_REMOTE_SHARE_NAME \ + $t || err=1 + if [ $err -ne 0 ]; then + on_error "\n$test_name failed." + else + echo -e "\n$test_name CLEANUP PHASE" + remove_share_test + if [ $err_rtn -ne 0 ]; then + # If cleanup fails, restore VM snapshot. + on_error "\n$test_name removal failed." + else + echo -e "\n$test_name removal completed successfully." + fi + fi + fi +done + +exit $all_errs diff --git a/source4/selftest/win/wintest_client.exp b/source4/selftest/win/wintest_client.exp new file mode 100644 index 0000000000..5b45eb2bb0 --- /dev/null +++ b/source4/selftest/win/wintest_client.exp @@ -0,0 +1,95 @@ +# An expect script to create a temporary file, map a share, copy the file to the share, +# and compare the contents of the two files. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +proc run_test { remote_prompt tmp_filename share_drive host_drive buildhost_ip buildhost_share username domain password } { + + # Create the temp file on the windows host and connect to the samba share. + set host_tmpfile "$host_drive\\$tmp_filename" + set err_str [create_tmp_file $remote_prompt $host_tmpfile] + if { $err_str != "OK" } { + return $err_str + } + + set buildhost_sharepoint "\\\\$buildhost_ip\\$buildhost_share" + set err_str [map_share $remote_prompt $share_drive $buildhost_sharepoint $username $domain $password] + if { $err_str != "OK" } { + return $err_str + } + + # Copy the temp file to the share and compare its contents with the original. + set share_tmpfile "$share_drive\\$tmp_filename" + set xcopy_options "" + set err_str [xcopy_file $remote_prompt $host_tmpfile $share_tmpfile $xcopy_options] + if { $err_str != "OK" } { + return $err_str + } + + set err_str [compare_files $remote_prompt $host_tmpfile $share_tmpfile] + if { $err_str != "OK" } { + return $err_str + } + + # Remove files and unmap share. + set err_str [delete_file $remote_prompt $share_tmpfile] + if { $err_str != "OK" } { + return $err_str + } + set err_str [delete_file $remote_prompt $host_tmpfile] + if { $err_str != "OK" } { + return $err_str + } + + set err_str [unmap_share $remote_prompt $share_drive] + if {$err_str != "OK" } { + return $err_str + } + + return $err_str +} + +# Read parameters. +set remote_prompt $env(SMBTORTURE_REMOTE_PROMPT) +set remote_host $env(SMBTORTURE_REMOTE_HOST) +set username $env(SMBTORTURE_USERNAME) +set password $env(SMBTORTURE_PASSWORD) +set timeout $env(SMBTORTURE_EXPECT_TIMEOUT) + +set tmp_filename $env(SMBTORTURE_TMP_FILENAME) + +set share_drive $env(SMBTORTURE_REMOTE_DRIVE_LETTER) +set host_drive "%HOMEDRIVE%" + +set buildhost_ip $env(SMBTORTURE_LOCAL_IP) +set buildhost_share $env(SMBTORTURE_LOCAL_SHARE_NAME) +set buildhost_username $env(SMBTORTURE_LOCAL_USERNAME) +set buildhost_domain $env(SMBTORTURE_LOCAL_DOMAIN) +set buildhost_password $env(SMBTORTURE_LOCAL_PASSWORD) + +set err_val [spawn $env(SHELL)] +if {$err_val == 0} { + puts stderr "Expect failed while spawning a shell process." + exit $err_val +} + +set err_str [telnet_login $remote_prompt $remote_host $username $password] +if {$err_str != "OK"} { + puts stderr "\nFunction telnet_login failed during Samba server testing." + puts stderr "Error was: $err_str." + exit 1 +} + +set err_str [run_test $remote_prompt $tmp_filename $share_drive $host_drive $buildhost_ip $buildhost_share $buildhost_username $buildhost_domain $buildhost_password] +if {$err_str != "OK"} { + puts stderr "\nFunction run_test failed during Samba server testing." + puts stderr "Error was: $err_str." + + # Log off from the telnet server. + send "exit\r\n" + exit 1 +} + +# Log off from the telnet server. +send "exit\r\n" +exit 0 diff --git a/source4/selftest/win/wintest_client.sh b/source4/selftest/win/wintest_client.sh new file mode 100755 index 0000000000..6b76ae36f7 --- /dev/null +++ b/source4/selftest/win/wintest_client.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +. selftest/test_functions.sh + +. selftest/win/wintest_functions.sh + +# This variable is defined in the per-hosts .fns file. +. $WINTESTCONF + +export SMBTORTURE_REMOTE_HOST=$1 + +test_name="WINDOWS CLIENT / SAMBA SERVER SHARE" + +cat $WINTEST_DIR/common.exp > $TMPDIR/client_test.exp +cat $WINTEST_DIR/wintest_client.exp >> $TMPDIR/client_test.exp + +expect $TMPDIR/client_test.exp || all_errs=`expr $all_errs + 1` + +if [ $all_errs > 0 ]; then + # Restore snapshot to ensure VM is in a known state. + restore_snapshot "\n$test_name failed." "$VM_CFG_PATH" +fi + +rm -f $TMPDIR/client_test.exp + +exit $all_errs diff --git a/source4/selftest/win/wintest_functions.sh b/source4/selftest/win/wintest_functions.sh new file mode 100755 index 0000000000..3c0a1dccac --- /dev/null +++ b/source4/selftest/win/wintest_functions.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# Setup the windows environment. +# This was the best way I could figure out including library files +# for the moment. +# I was finding that "cat common.exp wintest_setup.exp | expect -f -" +# fails to run, but exits with 0 status something like 1% of the time. + +setup_share_test() +{ + echo -e "\nSetting up windows environment." + cat $WINTEST_DIR/common.exp > $TMPDIR/setup.exp + cat $WINTEST_DIR/wintest_setup.exp >> $TMPDIR/setup.exp + expect $TMPDIR/setup.exp + err_rtn=$? + rm -f $TMPDIR/setup.exp +} + +# Clean up the windows environment after the test has run or failed. +remove_share_test() +{ + echo -e "\nCleaning up windows environment." + cat $WINTEST_DIR/common.exp > $TMPDIR/remove.exp + cat $WINTEST_DIR/wintest_remove.exp >> $TMPDIR/remove.exp + expect $TMPDIR/remove.exp + err_rtn=$? + rm -f $TMPDIR/remove.exp +} + +restore_snapshot() +{ + err_str=$1 + VMX_PATH=$2 + + # Display the error that caused us to restore the snapshot. + echo -e $err_str + + if [ -z $HOST_SERVER_NAME ]; then + # The vmware server is running locally. + vmrun revertToSnapshot "$VMX_PATH" + err_rtn=$? + else + vmrun -h $HOST_SERVER_NAME -P $HOST_SERVER_PORT \ + -u $HOST_USERNAME -p $HOST_PASSWORD \ + revertToSnapshot "$VMX_PATH" + err_rtn=$? + fi + + if [ $err_rtn -eq 0 ]; then + echo "Snapshot restored." + else + echo "Error $err_rtn restoring snapshot!" + fi +} diff --git a/source4/selftest/win/wintest_net.sh b/source4/selftest/win/wintest_net.sh new file mode 100755 index 0000000000..88cec1f3a7 --- /dev/null +++ b/source4/selftest/win/wintest_net.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +. selftest/test_functions.sh + +. selftest/win/wintest_functions.sh + +# This variable is defined in the per-hosts .fns file. +. $WINTESTCONF + +if [ $# -lt 4 ]; then +cat <<EOF +Usage: test_net.sh SERVER USERNAME PASSWORD DOMAIN +EOF +exit 1; +fi + +server="$1" +username="$2" +password="$3" +domain="$4" +shift 4 + +ncacn_np_tests="NET-API-LOOKUP NET-API-LOOKUPHOST NET-API-RPCCONN-BIND NET-API-RPCCONN-SRV NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES" +#These tests fail on ncacn_np: NET-API-LOOKUPPDC NET-API-CREATEUSER NET-API-DELETEUSER + +ncalrpc_tests="NET-API-RPCCONN-SRV NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES" +#These tests fail on ncalrpc: NET-API-CREATEUSER NET-API-DELETEUSER + +ncacn_ip_tcp_tests="NET-API-LOOKUP NET-API-LOOKUPHOST NET-API-RPCCONN-SRV NET-API-RPCCONN-DC NET-API-RPCCONN-DCINFO NET-API-LISTSHARES" +#These tests fail on ncacn_ip_tcp: NET-API-LOOKUPPDC NET-API-CREATEUSER NET-API-DELETEUSER + +bind_options="seal,padcheck bigendian" + +test_type="ncalrpc ncacn_np ncacn_ip_tcp" + +all_errs=0 + +on_error() { + errstr=$1 + + all_errs=`expr $all_errs + 1` + restore_snapshot "$errstr" "$VM_CFG_PATH" +} + +for o in $bind_options; do + for transport in $test_type; do + case $transport in + ncalrpc) net_test=$ncalrpc_tests ;; + ncacn_np) net_test=$ncacn_np_tests ;; + ncacn_ip_tcp) net_test=$ncacn_ip_tcp_tests ;; + esac + + for t in $net_test; do + test_name="$t on $transport with $o" + $SMBTORTURE_BIN_PATH -U $username%$password \ + -W $domain $transport:$server[$o] \ + $t || on_error "\n$test_name failed." + done + done +done + +exit $all_errs diff --git a/source4/selftest/win/wintest_raw.sh b/source4/selftest/win/wintest_raw.sh new file mode 100755 index 0000000000..541e19829a --- /dev/null +++ b/source4/selftest/win/wintest_raw.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +. selftest/test_functions.sh + +. selftest/win/wintest_functions.sh + +# This variable is defined in the per-hosts .fns file. +. $WINTESTCONF + +if [ $# -lt 4 ]; then +cat <<EOF +Usage: test_net.sh SERVER USERNAME PASSWORD DOMAIN +EOF +exit 1; +fi + +server="$1" +username="$2" +password="$3" +domain="$4" +shift 4 + +export SMBTORTURE_REMOTE_HOST=$server + +raw_tests="RAW-QFILEINFO RAW-SFILEINFO RAW-MKDIR RAW-SEEK RAW-OPEN RAW-WRITE RAW-UNLINK RAW-READ RAW-CLOSE RAW-IOCTL RAW-RENAME RAW-EAS RAW-STREAMS" +# This test fails: RAW-QFSINFO + +all_errs=0 +err=0 + +on_error() { + errstr=$1 + all_errs=`expr $all_errs + 1` + + restore_snapshot "$errstr" "$VM_CFG_PATH" +} + +for t in $raw_tests; do + test_name="$t / WINDOWS SERVER" + echo -e "\n$test_name SETUP PHASE" + + setup_share_test + + if [ $err_rtn -ne 0 ]; then + # If test setup fails, load VM snapshot and skip test. + on_error "\n$test_name setup failed, skipping test." + else + echo -e "\n$test_name setup completed successfully." + + $SMBTORTURE_BIN_PATH -U $username%$password -W $domain \ + //$server/$SMBTORTURE_REMOTE_SHARE_NAME \ + $t || err=1 + if [ $err -ne 0 ]; then + on_error "\n$test_name failed." + else + echo -e "\n$test_name CLEANUP PHASE" + remove_share_test + if [ $err_rtn -ne 0 ]; then + # If cleanup fails, restore VM snapshot. + on_error "\n$test_name removal failed." + else + echo -e "\n$test_name removal completed successfully." + fi + fi + fi +done + +exit $all_errs diff --git a/source4/selftest/win/wintest_remove.exp b/source4/selftest/win/wintest_remove.exp new file mode 100644 index 0000000000..a361db2958 --- /dev/null +++ b/source4/selftest/win/wintest_remove.exp @@ -0,0 +1,71 @@ +# An expect script to remove a directory and share which was +# previously setup for an smbtorture test. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +proc remove_test { remote_prompt sharepath sharename hosts_file_path \ + backup_hosts_filename } { + + set err_str [delete_share $remote_prompt $sharename] + if { $err_str != "OK" } { + puts stderr "Error in function delete_share: $err_str." + puts stderr "Function remove_test will continue." + } + + set err_str [delete_directory $remote_prompt $sharepath] + if { $err_str != "OK" } { + puts stderr "Error in function delete_directory: $err_str." + puts stderr "Function remove_test will continue." + } + + # Overwrite the current hosts file with the backup we made during setup. + set err_str [delete_hosts_entry $remote_prompt $hosts_file_path \ + $backup_hosts_filename] + if { $err_str != "OK" } { + puts stderr "Error in function delete_hosts_entry: $err_str." + puts stderr "Function remove_test will continue." + } + return $err_str +} + +# read parameters +set remote_host $env(SMBTORTURE_REMOTE_HOST) +set remote_prompt $env(SMBTORTURE_REMOTE_PROMPT) + +set username $env(SMBTORTURE_USERNAME) +set password $env(SMBTORTURE_PASSWORD) + +set timeout $env(SMBTORTURE_EXPECT_TIMEOUT) + +set sharepath $env(SMBTORTURE_REMOTE_SHARE_PATH) +set sharename $env(SMBTORTURE_REMOTE_SHARE_NAME) + +set backup_hosts_filename $env(REMOTE_BACKUP_HOSTS_FILENAME) +set hosts_file_path $env(REMOTE_HOSTS_FILE_PATH) + +set err_val [spawn $env(SHELL)] +if {$err_val == 0} { + puts stderr "Expect failed while spawning a shell process." + exit $err_val +} + +set err_str [telnet_login $remote_prompt $remote_host $username $password] +if {$err_str != "OK"} { + puts stderr "\nFunction telnet_login failed during cleanup." + puts stderr "Error was: $err_str." + exit 1 +} + +set err_str [remove_test $remote_prompt $sharepath $sharename \ + $hosts_file_path $backup_hosts_filename] +if {$err_str != "OK"} { + puts stderr "\nFunction remove_test failed." + puts stderr "Error was: $err_str." + # Log off from the telnet server. + send "exit\r\n" + exit 1 +} + +# Log off from the telnet server. +send "exit\r\n" +exit 0 diff --git a/source4/selftest/win/wintest_rpc.sh b/source4/selftest/win/wintest_rpc.sh new file mode 100755 index 0000000000..d0a0783c2e --- /dev/null +++ b/source4/selftest/win/wintest_rpc.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +. selftest/test_functions.sh + +. selftest/win/wintest_functions.sh + +# This variable is defined in the per-hosts .fns file. +. $WINTESTCONF + +if [ $# -lt 4 ]; then +cat <<EOF +Usage: test_rpc.sh SERVER USERNAME PASSWORD DOMAIN +EOF +exit 1; +fi + +server="$1" +username="$2" +password="$3" +domain="$4" +shift 4 + +ncacn_np_tests="RPC-SRVSVC RPC-UNIXINFO RPC-ECHO RPC-DSSETUP RPC-ALTERCONTEXT RPC-MULTIBIND" +# These tests fail on ncacn_np: RPC-SPOOLSS RPC-SCHANNEL RPC-JOIN RPC-LSA +# RPC-NETLOGON + +ncalrpc_tests="RPC-UNIXINFO RPC-ECHO" +# These tests fail on ncalrpc: RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-DSSETUP +# RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON + +ncacn_ip_tcp_tests="RPC-UNIXINFO RPC-ECHO" +# These tests fail on ncacn_ip_tcp: RPC-SCHANNEL RPC-JOIN RPC-LSA RPC-DSSETUP +# RPC-ALTERCONTEXT RPC-MULTIBIND RPC-NETLOGON + +bind_options="seal,padcheck bigendian" + +test_type="ncalrpc ncacn_np ncacn_ip_tcp" + +all_errs=0 + +on_error() { + errstr=$1 + all_errs=`expr $all_errs + 1` + + restore_snapshot "$errstr" "$VM_CFG_PATH" +} + +for o in $bind_options; do + for transport in $test_type; do + case $transport in + ncalrpc) rpc_test=$ncalrpc_tests ;; + ncacn_np) rpc_test=$ncacn_np_tests ;; + ncacn_ip_tcp) rpc_test=$ncacn_ip_tcp_tests ;; + esac + + for t in $rpc_test; do + test_name="$t on $transport with $o" + + $SMBTORTURE_BIN_PATH -U $username%$password \ + -W $domain $transport:$server[$o] \ + $t || on_error "\n$test_name failed." + done + done +done + +exit $all_errs diff --git a/source4/selftest/win/wintest_setup.exp b/source4/selftest/win/wintest_setup.exp new file mode 100644 index 0000000000..1dcbabb488 --- /dev/null +++ b/source4/selftest/win/wintest_setup.exp @@ -0,0 +1,104 @@ +# An expect script to setup a directory and share for an smbtorture test. +# Copyright Brad Henry <brad@samba.org> 2006 +# Released under the GNU GPL v2 or later. + +proc setup_test { remote_prompt sharepath sharename username local_hostname \ + local_ip hosts_file_path backup_hosts_filename } { + + # If creating the directory fails, remove, then + # re-create the directory. + set err_str [create_directory $remote_prompt $sharepath] + if { $err_str != "OK" } { + if { $err_str != "Directory already exists" } { + puts stderr "\nUnexpected error occured in setup_test.\n" + puts stderr "Function create_directory returned $err_str." + } else { + puts stdout "\nDirectory $sharepath exists." + } + puts stdout "Re-creating directory $sharepath." + + set err_str [delete_directory $remote_prompt $sharepath] + if { $err_str != "OK" } { + return $err_str + } + set err_str [create_directory $remote_prompt $sharepath] + if { $err_str != "OK" } { + return $err_str + } + } + + # If creating the share fails, remove, then + # re-create the share. + set err_str [create_share $remote_prompt $username $sharepath \ + $sharename] + if { $err_str != "OK" } { + if { $err_str != "The name has already been shared" } { + puts stderr "\nUnexpected error occured in setup_test." + puts stderr "Function create_share returned $err_str." + } else { + puts stdout "\nShare $sharename exists." + } + puts stdout "Re-creating share $sharename." + + set err_str [delete_share $remote_prompt $sharename] + if { $err_str != "OK" } { + return $err_str + } + set err_str [create_share $remote_prompt $username $sharepath \ + $sharename] + if { $err_str != "OK" } { + return $err_str + } + } + + # Add a hosts file entry on the windows machine for the smbtorture host. + set err_str [create_hosts_entry $remote_prompt $hosts_file_path \ + $local_hostname $local_ip $backup_hosts_filename] + return $err_str +} + +# Read parameters. +set remote_host $env(SMBTORTURE_REMOTE_HOST) +set remote_prompt $env(SMBTORTURE_REMOTE_PROMPT) + +set username $env(SMBTORTURE_USERNAME) +set password $env(SMBTORTURE_PASSWORD) + +set timeout $env(SMBTORTURE_EXPECT_TIMEOUT) + +set sharepath $env(SMBTORTURE_REMOTE_SHARE_PATH) +set sharename $env(SMBTORTURE_REMOTE_SHARE_NAME) + +set local_hostname $env(SMBTORTURE_LOCAL_HOSTNAME) +set local_ip $env(SMBTORTURE_LOCAL_IP) + +set backup_hosts_filename $env(REMOTE_BACKUP_HOSTS_FILENAME) +set hosts_file_path $env(REMOTE_HOSTS_FILE_PATH) + +set err_val [spawn $env(SHELL)] +if {$err_val == 0} { + puts stderr "Expect failed while spawning a shell process." + exit $err_val +} + +set err_str [telnet_login $remote_prompt $remote_host $username $password] +if {$err_str != "OK"} { + puts stderr "\nFunction telnet_login failed during setup." + puts stderr "Error was: $err_str." + exit 1 +} + +set err_str [setup_test $remote_prompt $sharepath $sharename $username \ + $local_hostname $local_ip $hosts_file_path \ + $backup_hosts_filename] +if {$err_str != "OK"} { + puts stderr "\nFunction setup_test failed during setup." + puts stderr "Error was: $err_str." + # Log off from the telnet server. + send "exit\r\n" + exit 1 +} + +# Log off from the telnet server. +send "exit\r\n" +exit 0 |