diff options
Diffstat (limited to '')
156 files changed, 19300 insertions, 0 deletions
diff --git a/source3/script/tests/dlopen.sh b/source3/script/tests/dlopen.sh new file mode 100755 index 0000000..a1299b2 --- /dev/null +++ b/source3/script/tests/dlopen.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# +# Copyright (C) Nalin Dahyabhai <nalin@redhat.com> 2003 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +tempdir=$(mktemp -d /tmp/dlopenXXXXXX) +test -n "$tempdir" || exit 1 +cat >>$tempdir/dlopen.c <<_EOF +#include <dlfcn.h> +#include <stdio.h> +#include <limits.h> +#include <sys/stat.h> +/* Simple program to see if dlopen() would succeed. */ +int main(int argc, char **argv) +{ + int i; + struct stat st; + char buf[PATH_MAX]; + for (i = 1; i < argc; i++) { + if (dlopen(argv[i], RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"%s\" succeeded.\n", + argv[i]); + } else { + snprintf(buf, sizeof(buf), "./%s", argv[i]); + if ((stat(buf, &st) == 0) && dlopen(buf, RTLD_NOW)) { + fprintf(stdout, "dlopen() of \"./%s\" " + "succeeded.\n", argv[i]); + } else { + fprintf(stdout, "dlopen() of \"%s\" failed: " + "%s\n", argv[i], dlerror()); + return 1; + } + } + } + return 0; +} +_EOF + +for arg in "$@"; do + case "$arg" in + "") ;; + + -I* | -D* | -f* | -m* | -g* | -O* | -W*) + cflags="$cflags $arg" + ;; + -l* | -L*) + ldflags="$ldflags $arg" + ;; + /*) + modules="$modules $arg" + ;; + *) + modules="$modules $arg" + ;; + esac +done + +${CC:-gcc} $RPM_OPT_FLAGS $CFLAGS -o $tempdir/dlopen $cflags $tempdir/dlopen.c $ldflags + +retval=0 +for module in $modules; do + case "$module" in + "") ;; + + /*) + $tempdir/dlopen "$module" + retval=$? + ;; + *) + $tempdir/dlopen ./"$module" + retval=$? + ;; + esac +done + +rm -f $tempdir/dlopen $tempdir/dlopen.c +rmdir $tempdir +exit $retval diff --git a/source3/script/tests/fake_snap.pl b/source3/script/tests/fake_snap.pl new file mode 100755 index 0000000..d88307e --- /dev/null +++ b/source3/script/tests/fake_snap.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl -w + +use strict; + +use File::Path qw(rmtree); +use POSIX (); + +sub _untaint_path +{ + my ($path) = @_; + + if ($path =~ /^(.*)$/) { + return $1; + } + die "bad path"; +} + +sub _create_snapshot +{ + my ($base_path) = _untaint_path(shift); + my $time_str = POSIX::strftime("%Y.%m.%d-%H.%M.%S" , localtime()); + my $snap_path = $base_path . "/.snapshots/\@GMT-" . $time_str; + my $ret; + + delete @ENV{'BASH_ENV'}; + + $ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH + POSIX::mkdir($base_path . "/.snapshots", 0755); + + # add trailing slash to src path to ensure that only contents is copied + $ret = system("rsync", "-a", "--exclude=.snapshots/", "${base_path}/", + $snap_path); + if ($ret != 0) { + print STDERR "rsync failed with $ret\n"; + } else { + print "$snap_path\n"; + } + + return $ret; +} + +sub _delete_snapshot +{ + my $base_path = _untaint_path(shift); + my $snap_path = _untaint_path(shift); + + # we're doing a recursive delete, so do some sanity checks + if ((index($snap_path, $base_path) != 0) || (index($snap_path, ".snapshots") == -1)) { + print STDERR "invalid snap_path: $snap_path\n"; + return -1; + } + + $ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH + rmtree($snap_path, {error => \my $err}); + if (@$err) { + for my $diag (@$err) { + my ($file, $message) = %$diag; + if ($file eq '') { + print STDERR "rmtree error: $message\n"; + } else { + print STDERR "rmtree error $file: $message\n"; + } + } + return -1; + } + + return 0; +} + +my $ret; +my $num_args = $#ARGV + 1; +my $cmd = shift; + +if (($num_args == 2) && ($cmd eq "--check")) { + $ret = 0; +} elsif (($num_args == 2) && ($cmd eq "--create")) { + $ret = _create_snapshot($ARGV[0]); +} elsif (($num_args == 3) && ($cmd eq "--delete")) { + $ret = _delete_snapshot($ARGV[0], $ARGV[1]); +} else { + print STDERR "invalid script argument\n"; + $ret = -1; +} + +exit $ret; diff --git a/source3/script/tests/full_audit_segfault/run.sh b/source3/script/tests/full_audit_segfault/run.sh new file mode 100755 index 0000000..a2ba43f --- /dev/null +++ b/source3/script/tests/full_audit_segfault/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh +if [ $# -lt 1 ]; then + cat <<EOF +Usage: run.sh VFSTEST +EOF + exit 1 +fi + +TALLOC_FILL_FREE=0 +export TALLOC_FILL_FREE + +TESTBASE="$(dirname $0)" +VFSTEST="$VALGRIND $1" +shift 1 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +testit "vfstest" "$VFSTEST" -f "$TESTBASE/vfstest.cmd" "$ADDARGS" || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/full_audit_segfault/vfstest.cmd b/source3/script/tests/full_audit_segfault/vfstest.cmd new file mode 100644 index 0000000..84e93e2 --- /dev/null +++ b/source3/script/tests/full_audit_segfault/vfstest.cmd @@ -0,0 +1,3 @@ +load full_audit +connect +create_file . diff --git a/source3/script/tests/getset_quota.py b/source3/script/tests/getset_quota.py new file mode 100755 index 0000000..39d7024 --- /dev/null +++ b/source3/script/tests/getset_quota.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Tests for smbcquotas +# Copyright (C) Noel Power 2017 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import sys +import traceback +import logging +import os + +USER_QUOTAS = 1 +USER_DEFAULT_QUOTAS = 2 +GROUP_QUOTAS = 3 +GROUP_DEFAULT_QUOTAS = 4 + +#Quota model + +class Quota: + def __init__(self): + self.flags = 0 + self.quotatype = USER_DEFAULT_QUOTAS + self.uid = 0 + self.usedblocks = 0 + self.softlimit = 0 + self.hardlimit = 0 + self.hardlimit = 0 + self.usedinodes = 0 + self.slimitinodes = 0 + self.hlimitinodes = 0 + +def quota_to_str(item): + result = str(item.flags) + " " + str(item.usedblocks) + " " + str(item.softlimit) + " " + str(item.hardlimit) + " " + str(item.usedinodes) + " " + str(item.slimitinodes) + " " + str(item.hlimitinodes) + return result + +def quota_to_db_str(item): + result = item.uid + " " + str(item.usedblocks) + " " + str(item.softlimit) + " " + str(item.hardlimit) + " " + str(item.usedinodes) + " " + str(item.slimitinodes) + " " + str(item.hlimitinodes) + return result + +def load_quotas(input_file): + fileContents = open(input_file,"r") + lineno = 0 + quotas = [] + for line in fileContents: + if line.strip().startswith("#"): + continue + content = line.strip().split() + quota = Quota() + if len(content) < 7: + logging.debug("ignoring line %d, doesn't have enough fields\n"%lineno) + else: + quota.flags = 2 + quota.uid = content[0] + quota.usedblocks = content[1] + quota.softlimit = content[2] + quota.hardlimit = content[3] + quota.usedinodes = content[4] + quota.slimitinodes = content[5] + quota.hlimitinodes = content[6] + quotas.append(quota) + + fileContents.close() + return quotas + +def set_quotas(quota_list, output_file): + filecontents = open(output_file,"w+") + if filecontents == None: + return False + lines = "" + for quota in quota_list: + next_line = quota_to_db_str(quota) + if next_line: + lines = lines + next_line + "\n" + filecontents.write(lines) + filecontents.close() + return True + +def get_quotas(uid, quota_list): + logging.debug("in get_quotas\n") + for quota in quota_list: + if quota.uid == uid: + return quota + return None + +def main(): + logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG) + logging.debug("system args passed are %s\n"% str(sys.argv)) + quota_file_dir = os.path.dirname(sys.argv[0]) + quota_file_db = os.path.join(quota_file_dir,"quotas.db") + logging.debug("quota db is located %s\n", quota_file_db) + quota_list = load_quotas(quota_file_db) + logging.debug("quotas loaded have %s entries\n", len(quota_list)) + result = None + if len(sys.argv) == 4: + # Get Quota + directory = sys.argv[1] + if sys.argv[2] == "1": + query_type = USER_QUOTAS + elif sys.argv[2] == "2": + query_type = USER_DEFAULT_QUOTAS + elif sys.argv[2] == "3": + query_type = GROUP_QUOTAS + elif sys.argv[2] == "4": + query_type = GROUP_DEFAULT_QUOTAS + uid = sys.argv[3] + quota = get_quotas(uid, quota_list) + if quota is None: + logging.debug("no result for uid %s"%uid) + else: + result = quota_to_str(quota) + logging.debug("got result for uid %s\n"%uid) + if result is None: + result = "0 0 0 0 0 0 0" + logging.debug("for uid %s returning quotas %s\n"%(uid,result)) + print("%s"%result) + elif len(sys.argv) > 8: + # Set Quota + quota = Quota() + directory = sys.argv[1] + quota.query_type = sys.argv[2] + quota.uid = sys.argv[3] + quota.flags = sys.argv[4] + quota.softlimit = sys.argv[5] + quota.hardlimit = sys.argv[6] + quota.slimitinodes = sys.argv[7] + quota.hlimitinodes = sys.argv[8] + found = get_quotas(quota.uid, quota_list) + if found: + found.query_type = quota.query_type + found.uid = quota.uid + found.flags = quota.flags + found.softlimit = quota.softlimit + found.hardlimit = quota.hardlimit + found.slimitinodes = quota.slimitinodes + found.hlimitinodes = quota.hlimitinodes + else: + quota_list.append(quota) + if set_quotas(quota_list,quota_file_db): + print ("%s\n"%quota_to_str(quota_list[-1])) + return +if __name__ == '__main__': + main() diff --git a/source3/script/tests/printing/modprinter.pl b/source3/script/tests/printing/modprinter.pl new file mode 100755 index 0000000..28817db --- /dev/null +++ b/source3/script/tests/printing/modprinter.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w + +use strict; + +use Getopt::Long; +use Cwd qw(abs_path); + +my $opt_help = 0; +my $opt_smb_conf = undef; +my $opt_add = 0; +my $opt_delete = 0; + +my $result = GetOptions( + 'help|h|?' => \$opt_help, + 'smb_conf|s=s' => \$opt_smb_conf, + 'add|a' => \$opt_add, + 'delete|d' => \$opt_delete +); + +sub usage($;$) +{ + my ($ret, $msg) = @_; + + print $msg."\n\n" if defined($msg); + + print "usage: + + --help|-h|-? Show this help. + + --smb_conf|-s <path> Path of the 'smb.conf' file. + + --add|-a 'add' a printer. + --delete|-d 'delete' a printer. + + printer_name share_name port_name driver_name location XX remote_machine +"; + exit($ret); +} + +usage(1) if (not $result); + +usage(0) if ($opt_help); + +if (!$opt_add && !$opt_delete) { + usage(1, "invalid: neither --add|-a nor --delete|-d set"); +} + +if (!$opt_smb_conf) { + usage(1, "invalid: no smb.conf file set"); +} + +my @argv = @ARGV; + +my $printer_name = shift(@argv); +my $share_name = shift(@argv); +my $port_name = shift(@argv); +my $driver_name = shift(@argv); +my $location = shift(@argv); +my $win9x_driver_location = shift(@argv); +my $remote_machine = shift(@argv); + +if (!defined($share_name) || length($share_name) == 0) { + $share_name = $printer_name; +} + +if (!defined($share_name)) { + die "share name not defined"; +} + +my $smb_conf_file = $opt_smb_conf; +if ($smb_conf_file =~ /^(.*)$/) { + $smb_conf_file = $1; # untaint file name +} else { + die "Invalid file name $smb_conf_file"; +} + +my $tmp = $smb_conf_file.$$; + +my $section = undef; +my $within_section = 0; +my $found_section = 0; + +open(CONFIGFILE_NEW, "+>$tmp") || die "Unable top open conf file $tmp"; + +open (CONFIGFILE, "+<$smb_conf_file") || die "Unable to open config file $smb_conf_file"; +while (<CONFIGFILE>) { + my $line = $_; + chomp($_); + $_ =~ s/^\s*//; + $_ =~ s/\s*$//; + if (($_ =~ /^#/) || ($_ =~ /^;/)) { + print CONFIGFILE_NEW $line; + next; + } + if ($_ =~ /^\[.*\]$/) { + $_ = substr($_, 1, length($_)-2); + if (length($_)) { + $section = $_; + } else { + die "invalid section found"; + } + if ($section eq $share_name) { + $found_section = 1; + if ($opt_add) { + exit 0; +# die("share $share_name already exists\n"); + } + if ($opt_delete) { + $within_section = 1; + next; + } + } else { + print CONFIGFILE_NEW $line; + $within_section = 0; + } + next; + } else { + if ($within_section == 1) { + next; + } + print CONFIGFILE_NEW $line; + } +} +if ($opt_add) { + print CONFIGFILE_NEW "[$share_name]\n\tprintable = yes\n\tpath = /tmp\n"; +} +close (CONFIGFILE); +close (CONFIGFILE_NEW); + +if ($opt_delete && ($found_section == 0)) { + die "share $share_name not found"; +} + +delete @ENV{"BASH_ENV"}; + +$ENV{'PATH'} = '/bin:/usr/bin'; # untaint PATH +system("cp", "$tmp", "$smb_conf_file"); +unlink $tmp; + +exit 0; diff --git a/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh b/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh new file mode 100755 index 0000000..c25b49a --- /dev/null +++ b/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +logfile="${SELFTEST_TMPDIR}/${USER}_printing_var_exp.log" + +rm -f "$logfile" + +for i in $(seq 1 $#); do + eval echo "arg $i: \$$i" >>"$logfile" +done diff --git a/source3/script/tests/smbspool_argv_wrapper.c b/source3/script/tests/smbspool_argv_wrapper.c new file mode 100644 index 0000000..6f84f3b --- /dev/null +++ b/source3/script/tests/smbspool_argv_wrapper.c @@ -0,0 +1,72 @@ +/* + Wrapper for smbspool to test Device URI in argv[0] + + Copyright (C) Bryan Mason 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +/* + * Before calling a backend like smbspool, CUPS will set argv[0] to + * the Device URI. This program wraps a program like smbspool and + * sets argv[0] to the device URI before exec()ing the actual backend + * program. + */ + +int main(int argc, char *argv[], char *envp[]) +{ + char **new_argv; + char *exec_path; + int a; + int rv; +/* + * Expected parameters: + * + * smbspool_argv_wrapper smbspool uri job user title copies opts file(s) + * argv[0] 1 2 3 4 5 6 7 8 + * + */ + /* Allocate memory for the new arguments (exit on failure). */ + new_argv = calloc(argc, sizeof(char *)); + if (new_argv == 0) { + exit(ENOMEM); + } + + /* Save the path to the smbspool executable */ + exec_path = argv[1]; + + /* + * Shift the rest of the args so smbspool is called with: + * + * uri job user title copies opts file(s) + * argv[0] 1 2 3 4 5 6 + */ + + for (a = 2; a < argc; a++) { + new_argv[a-2] = argv[a]; + } + + /* Execute smbspool with new arguments */ + rv = execve(exec_path, new_argv, envp); + if (rv == -1) { + exit(errno); + } + + /* Avoid compiler error/warning */ + return 0; +} diff --git a/source3/script/tests/stream-depot/run.sh b/source3/script/tests/stream-depot/run.sh new file mode 100755 index 0000000..bcc85b6 --- /dev/null +++ b/source3/script/tests/stream-depot/run.sh @@ -0,0 +1,36 @@ +#!/bin/sh +if [ $# -lt 2 ]; then + cat <<EOF +Usage: run.sh VFSTEST PREFIX +EOF + exit 1 +fi + +TESTBASE=$(dirname $0) +VFSTEST=$1 +PREFIX=$2 +shift 2 +ADDARGS="$*" + +VFSTEST_PREFIX=vfstest +VFSTEST_TMPDIR=$(mktemp -d ${PREFIX}/${VFSTEST_PREFIX}_XXXXXX) + +incdir=$(dirname $0)/../../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $VFSTEST_TMPDIR || exit 1 + +testit "vfstest" $VFSTEST -f $TESTBASE/vfstest.cmd $ADDARGS || failed=$(expr $failed + 1) +testname=".streams check" +subunit_start_test $testname +NUM=$(find .streams | wc -l) +if [ $NUM -ne 3 ]; then + echo "streams_depot left ${NUM} in .streams, expected 3" | subunit_fail_test $testname + failed=$(expr $failed + 1) +else + subunit_pass_test $testname +fi + +exit $failed diff --git a/source3/script/tests/stream-depot/vfstest.cmd b/source3/script/tests/stream-depot/vfstest.cmd new file mode 100644 index 0000000..1400546 --- /dev/null +++ b/source3/script/tests/stream-depot/vfstest.cmd @@ -0,0 +1,5 @@ +connect +mkdir x +open x:y RC 0770 +unlink x:y +rmdir x diff --git a/source3/script/tests/test_acl_xattr.sh b/source3/script/tests/test_acl_xattr.sh new file mode 100755 index 0000000..d0eec66 --- /dev/null +++ b/source3/script/tests/test_acl_xattr.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +# this tests acl_xattr config parameter "ignore system acl" + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVER USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +PREFIX="$4" +SMBCLIENT="$5" +SMBCACLS="$6" +shift 6 +ADDARGS="$*" +SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}" +SMBCACLS="$VALGRIND ${SMBCACLS} ${ADDARGS}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +setup_remote_file() +{ + local share=$1 + local fname="$share.$$" + local local_fname=$PREFIX/$fname + touch $local_fname + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "rm $fname" + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "ls" | grep "$fname" && exit 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put $fname" || exit 1 +} + +smbcacls_x() +{ + local share=$1 + local fname="$share.$$" + + # skip with SMB1 + echo "$ADDARGS" | grep mNT1 && exit 0 + + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD "$fname" -x || exit 1 + mxac=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD "$fname" -x | awk '/Maximum access/ {print $3}') + + echo "mxac: $mxac" + if test "$mxac" != "0x1f01ff"; then + exit 1 + fi +} + +nt_affects_posix() +{ + local share=$1 + local expected=$2 + local b4 + local af + local fname="$share.$$" + b4=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "ACL:$SERVER\force_user:ALLOWED/0x0/READ" 2>/dev/null || exit 1 + af=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "before: $b4" + echo "after: $af" + echo "${b4}" | grep -q "^# owner:" || exit 1 + echo "${af}" | grep -q "^# owner:" || exit 1 + if test "$expected" = "true"; then + test "$b4" != "$af" + else + test "$b4" = "$af" + fi +} + +nt_affects_chown() +{ + local share=$1 + local b4_expected + local af_expected + local b4_actual + local af_actual + local fname="$share.$$" + + echo -n "determining uid of $USERNAME..." + b4_expected=$(getent passwd $USERNAME) || exit 1 + b4_expected=$(echo "$b4_expected" | awk -F: '{print $3}') + echo "$b4_expected" + + echo -n "determining uid of force_user..." + af_expected=$(getent passwd force_user) || exit 1 + af_expected=$(echo "$af_expected" | awk -F: '{print $3}') + echo "$af_expected" + + #basic sanity... + test "$b4_expected != $af_expected" || exit 1 + + b4_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${b4_actual}" | grep -q "^# owner:" || exit 1 + b4_actual=$(echo "$b4_actual" | sed -rn 's/^# owner: (.*)/\1/p') + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "ACL:$SERVER\force_user:ALLOWED/0x0/FULL" || exit 1 + $SMBCACLS //$SERVER/$share $fname -U force_user%$PASSWORD -C force_user 2>/dev/null || exit 1 + af_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${af_actual}" | grep -q "^# owner:" || exit 1 + af_actual=$(echo "$af_actual" | sed -rn 's/^# owner: (.*)/\1/p') + echo "before: $b4_actual" + echo "after: $af_actual" + test "$b4_expected" = "$b4_actual" && test "$af_expected" = "$af_actual" +} + +nt_affects_chgrp() +{ + local share=$1 + local b4_expected + local af_expected + local b4_actual + local af_actual + local fname="$share.$$" + + echo -n "determining gid of domusers..." + b4_expected=$(getent group domusers) || exit 1 + b4_expected=$(echo "$b4_expected" | awk -F: '{print $3}') + echo "$b4_expected" + + echo -n "determining gid of domadmins..." + af_expected=$(getent group domadmins) || exit 1 + af_expected=$(echo "$af_expected" | awk -F: '{print $3}') + echo "$af_expected" + + #basic sanity... + test "$b4_expected" != "$af_expected" || exit 1 + + b4_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${b4_actual}" | grep -q "^# group:" || exit 1 + b4_actual=$(echo "$b4_actual" | sed -rn 's/^# group: (.*)/\1/p') + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -G domadmins 2>/dev/null || exit 1 + af_actual=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null) || exit 1 + echo "${af_actual}" | grep -q "^# group:" || exit 1 + af_actual=$(echo "$af_actual" | sed -rn 's/^# group: (.*)/\1/p') + echo "before: $b4_actual" + echo "after: $af_actual" + test "$af_expected" != "$b4_actual" && test "$af_expected" = "$af_actual" +} + +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "smbcacls -x" smbcacls_x tmp +testit "nt_affects_posix tmp" nt_affects_posix tmp "true" +testit "nt_affects_posix ign_sysacls" nt_affects_posix ign_sysacls "false" +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "nt_affects_chown tmp" nt_affects_chown tmp +testit "nt_affects_chown ign_sysacls" nt_affects_chown ign_sysacls +testit "setup remote file tmp" setup_remote_file tmp +testit "setup remote file ign_sysacls" setup_remote_file ign_sysacls +testit "nt_affects_chgrp tmp" nt_affects_chgrp tmp +testit "nt_affects_chgrp ign_sysacls" nt_affects_chgrp ign_sysacls diff --git a/source3/script/tests/test_aio_outstanding.sh b/source3/script/tests/test_aio_outstanding.sh new file mode 100755 index 0000000..a497181 --- /dev/null +++ b/source3/script/tests/test_aio_outstanding.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# +# Test terminating an smbclient connection with outstanding +# aio requests. +# +# Note this is designed to be run against +# the aio_delay_inject share which is preconfigured +# with 2 second delays on pread/pwrite. + +if [ $# -lt 4 ]; then + echo Usage: test_aio_outstanding.sh \ + SERVERCONFFILE SMBCLIENT IP aio_delay_inject_sharename + exit 1 +fi + +CONF=$1 +SMBCLIENT=$2 +SERVER=$3 +SHARE=$4 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +# +# Note if we already have any panics in the smbd log. +# +panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG) + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +# Create a large-ish testfile +rm aio_outstanding_testfile +head -c 20MB /dev/zero >aio_outstanding_testfile + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +# consume the smbclient startup messages +head -n 1 <&101 + +# Ensure we're putting a fresh file. +echo "del aio_outstanding_testfile" >&100 +echo "put aio_outstanding_testfile" >&100 + +sleep 2 + +# Terminate the smbclient write to the aio_delay_inject share whilst +# we have outstanding writes. +kill $CLIENT_PID + +sleep 1 + +# Ensure the panic count didn't change. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14301 +# + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +# Rerun smbclient to remove the testfile on the server. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr aio_outstanding_testfile +mkfifo smbclient-stdin smbclient-stdout + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout & + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout + +echo "del aio_outstanding_testfile" >&100 +echo "exit" >&100 + +sleep 2 + +rm -f smbclient-stdin smbclient-stdout aio_outstanding_testfile + +testit "check_panic" test $panic_count_0 -eq $panic_count_1 || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_async_req.sh b/source3/script/tests/test_async_req.sh new file mode 100755 index 0000000..27b4680 --- /dev/null +++ b/source3/script/tests/test_async_req.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +SOCKET_WRAPPER_IPV4_NETWORK="127.0.0.0" +export SOCKET_WRAPPER_IPV4_NETWORK + +testit "async_connect_send" $VALGRIND $BINDIR/async_connect_send_test || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_bad_auditnames.sh b/source3/script/tests/test_bad_auditnames.sh new file mode 100755 index 0000000..69ddf14 --- /dev/null +++ b/source3/script/tests/test_bad_auditnames.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# this tests a full audit share with bad VFS +# names will not allow connection. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15098 + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: $0 SERVER SHARE USERNAME PASSWORD SMBCLIENT +EOF + exit 1 +fi + +SERVER="$1" +SHARE="$2" +USERNAME="$3" +PASSWORD="$4" +SMBCLIENT="$5" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir/subunit.sh" + +can_connect() +{ + $SMBCLIENT //"$SERVER"/"$SHARE" -U"$USERNAME"%"$PASSWORD" -c "ls" | grep "tree connect failed: NT_STATUS_UNSUCCESSFUL" >/dev/null 2>&1 +} + +testit "Cannot connect to share $SHARE" can_connect || failed=$((failed + 1)) diff --git a/source3/script/tests/test_bug15435_widelink_dfs.sh b/source3/script/tests/test_bug15435_widelink_dfs.sh new file mode 100755 index 0000000..f0705ca --- /dev/null +++ b/source3/script/tests/test_bug15435_widelink_dfs.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# regression test for dfs access with wide links enabled on dfs share + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_bug15435_widelink_dfs.sh SERVER SERVER_IP USERNAME PASSWORD SMBCLIENT CONFIGURATION <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +CONFIGURATION="$6" +shift 6 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +# TEST +test_smbclient "smbclient as $DOMAIN\\$USERNAME" 'ls' "//$SERVER/msdfs-share-wl" -U$DOMAIN\\$USERNAME%$PASSWORD $ADDARGS -c 'cd msdfs-src1' || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_chdir_cache.sh b/source3/script/tests/test_chdir_cache.sh new file mode 100755 index 0000000..29f54d1 --- /dev/null +++ b/source3/script/tests/test_chdir_cache.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# +# Ensure we get a chdir_current_service error if CHDIR fails with EACCESS +# for an SMB2 request. +# +# BUG:https://bugzilla.samba.org/show_bug.cgi?id=14682 +# +# Copyright (C) 2021 Jeremy Allison + +if [ $# -lt 5 ]; then + echo Usage: test_chdir_cache.sh \ + --configfile=SERVERCONFFILE SMBCLIENT SMBCONTROL SERVER SHARE PREFIX TESTENV + exit 1 +fi + +CONF=$1 +shift 1 +SMBCLIENT=$1 +shift 1 +SMBCONTROL=$1 +shift 1 +SERVER=$1 +shift 1 +SHARE=$1 +shift 1 +PREFIX=${1} +shift 1 +TESTENV=${1} +shift 1 + +PREFIX_ABS="$(readlink -f "${PREFIX}")" + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +conf_dir=$(dirname ${SERVERCONFFILE}) + +error_inject_conf=${conf_dir}/error_inject.conf +rm -f ${error_inject_conf} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +log_file="${PREFIX_ABS}/${TESTENV}/smbd_test.log" +# Add support for "SMBD_DONT_LOG_STDOUT=1" +if [ -r "${PREFIX_ABS}/${TESTENV}/logs/log.smbd" ]; then + log_file="${PREFIX_ABS}/${TESTENV}/logs/log.smbd" +fi + +# Count the number of chdir_current_service: vfs_ChDir.*failed: Permission denied +# errors that are already in the log (should be zero). +num_errs=$(grep "chdir_current_service: vfs_ChDir.*failed: Permission denied" ${log_file} | wc -l) + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +# consume the smbclient startup messages +head -n 1 <&101 + +# Do an 'ls' as ${USER} to make sure we've done a CHDIR into +# the share directory. +echo "ls" >&100 + +# consume the smbclient output +head -n 4 <&101 + +# Now change user to user2, and connect to the share. +# This should leave us in the same share directory. +echo "logon user2 ${PASSWORD}" >&100 +echo "tcon ${SHARE}" >&100 + +# consume the smbclient output +head -n 4 <&101 + +# Ensure any chdir will give EACCESS. +echo "error_inject:chdir = EACCES" >${error_inject_conf} +testit "reload config 1" \ + "${SMBCONTROL}" "${CONF}" smbd reload-config || + failed=$((failed + 1)) + +sleep 1 + +# Do an 'ls' as user2. Changing users should have +# deleted the CHDIR cache, so we should now see +# a chdir_current_service: vfs_ChDir.*failed: Permission denied +# error message in the log. +echo 'ls' >&100 + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +# Remove the chdir inject. +rm -f ${error_inject_conf} +testit "reload config 2" \ + "${SMBCONTROL}" "${CONF}" smbd reload-config || + failed=$((failed + 1)) + +# Now look for chdir_current_service: vfs_ChDir.*failed: Permission denied +# in the smb log. There should be one more than before. + +num_errs1=$(grep "chdir_current_service: vfs_ChDir.*failed: Permission denied" ${log_file} | wc -l) + +testit "Verify we got at least one chdir error" \ + test $num_errs1 -gt $num_errs || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_close_denied_share.sh b/source3/script/tests/test_close_denied_share.sh new file mode 100755 index 0000000..2e6e285 --- /dev/null +++ b/source3/script/tests/test_close_denied_share.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Test smbcontrol close-denied-share command. +# +# Copyright (C) 2020 Volker Lendecke + +if [ $# -lt 6 ]; then + echo Usage: test_close_denied_share.sh \ + SERVERCONFFILE SHARESEC SMBCLIENT SMBCONTROL IP SHARE + exit 1 +fi + +CONF=$1 +SHARESEC=$2 +SMBCLIENT=$3 +SMBCONTROL=$4 +SERVER=$5 +SHARE=$6 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout +mkfifo smbclient-stdin smbclient-stdout + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout + +# consume the smbclient startup message + +head -n 1 <&101 + +testit "smbcontrol" ${SMBCONTROL} ${CONF} smbd close-denied-share ${SHARE} || + failed=$(expr $failed + 1) +sleep 1 + +echo dir >&100 + +COUNT=$(head -n 2 <&101 | + grep NT_STATUS_NETWORK_NAME_DELETED | + wc -l) +testit "Verify close-denied-share did not kill valid client" \ + test $COUNT -eq 0 || failed=$(expr $failed + 1) + +testit "Deny access" ${SHARESEC} ${CONF} --replace S-1-1-0:DENIED/0x0/FULL \ + ${SHARE} || failed=$(expr $failed + 1) + +testit "smbcontrol" ${SMBCONTROL} ${CONF} smbd close-denied-share ${SHARE} || + failed=$(expr $failed + 1) +sleep 1 + +echo dir >&100 + +COUNT=$(head -n 2 <&101 | + grep NT_STATUS_NETWORK_NAME_DELETED | + wc -l) +testit "Verify close-denied-share did kill now-invalid client" \ + test $COUNT -eq 1 || failed=$(expr $failed + 1) + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout + +testit "Allow access" ${SHARESEC} ${CONF} --replace S-1-1-0:ALLOWED/0x0/FULL \ + ${SHARE} || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_deadtime.sh b/source3/script/tests/test_deadtime.sh new file mode 100755 index 0000000..3d6368e --- /dev/null +++ b/source3/script/tests/test_deadtime.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Test deadtime parameter +# + +if [ $# -lt 1 ]; then + echo Usage: test_deadtime.sh IP + exit 1 +fi + +server=$1 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +smbclient="$BINDIR/smbclient" +smbcontrol="$BINDIR/smbcontrol" + +global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf + +echo "deadtime = 1" >$global_inject_conf +$smbcontrol smbd reload-config + +cd $SELFTEST_TMPDIR || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +export CLI_FORCE_INTERACTIVE=1 +export SAMBA_DEPRECATED_SUPPRESS=1 + +# This gets inherited by smbclient and is required to smbclient doesn't get +# killed by an unhandled SIGPIPE when writing an SMB2 KEEPALIVE packet to the +# connection fd that was already closed by the server. +trap "" SIGPIPE + +$smbclient //$server/tmp -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +client_pid=$! + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +# consume the smbclient startup message +head -n 1 <&101 + +sleep 70 + +err=$(head -n 1 <&102) +echo "err: $err" + +kill $client_pid + +echo "$err" | grep NT_STATUS_CONNECTION_DISCONNECTED +testit "deadtime" test $? -eq 0 || failed=$(expr $failed + 1) + +echo "" >$global_inject_conf +$smbcontrol smbd reload-config + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testok $0 $failed diff --git a/source3/script/tests/test_delete_stream.sh b/source3/script/tests/test_delete_stream.sh new file mode 100755 index 0000000..43d591e --- /dev/null +++ b/source3/script/tests/test_delete_stream.sh @@ -0,0 +1,123 @@ +#!/bin/sh +# +# this verifies that deleting a stream uses the correct ACL +# when using vfs_acl_xattr. +# + +if [ $# -lt 9 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +PREFIX="$5" +SMBCLIENT="$6" +SMBCACLS="$7" +NET="$8" +SHARE="$9" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +SMBCACLS="$VALGRIND ${SMBCACLS}" +NET="$VALGRIND ${NET}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + + +setup_testfile() +{ + touch $PREFIX/file + echo stream > $PREFIX/stream + + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "mkdir dir" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put file dir/file" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put stream dir/file:stream" || return 1 + + rm $PREFIX/file + rm $PREFIX/stream + + # + # Add full control ACE to the file and an ACL without "DELETE" on the + # parent directory + # + + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x1bf" dir || return 1 + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -a "ACL:Everyone:ALLOWED/0x0/0x101ff" dir/file || return 1 +} + +remove_testfile() +{ + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x101ff" dir/file || return 1 + $SMBCACLS //$SERVER/$SHARE -U $USERNAME%$PASSWORD -S "ACL:Everyone:ALLOWED/0x0/0x101ff" dir || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "rm dir/file" || return 1 + $SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "rmdir dir" || return 1 +} + +set_win_owner() +{ + local owner=$1 + + $SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD -C "$owner" || return 1 +} + +delete_stream() +{ + # + # Setup a file with a stream where we're not the owner and + # have delete rights. Bug 15126 would trigger a fallback to + # "acl_xattr:default acl style" because fetching the stored + # ACL would fail. The stored ACL allows deleting the stream + # but the synthesized default ACL does not, so the deletion + # of the stream should work, but it fails if we have the bug. + # + + # Now try deleting the stream + out=$($SMBCLIENT //$SERVER/$SHARE -U $USERNAME%$PASSWORD -c "wdel 0x20 dir/file:stream") || return 1 + + # + # Bail out in case we get any sort of NT_STATUS_* error, should be + # NT_STATUS_ACCESS_DENIED, but let's not slip through any other error. + # + echo "$out" | grep NT_STATUS_ && return 1 + + return 0 +} + +win_owner_is() +{ + local expected_owner=$1 + local actual_owner + + $SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD + actual_owner=$($SMBCACLS //$SERVER/$SHARE dir/file -U $USERNAME%$PASSWORD | sed -rn 's/^OWNER:(.*)/\1/p') + echo "actual_owner = $actual_owner" + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of dir/file is $actual_owner', expected $expected_owner" + return 1 + fi + return 0 +} + +# Create a testfile +testit "create testfile" setup_testfile $SHARE || exit 1 + +# Grant SeRestorePrivilege to the user so we can change the owner +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || exit 1 + +# We have SeRestorePrivilege, so both give and take ownership must succeed +testit "give owner with SeRestorePrivilege" set_win_owner "$SERVER\user1" || exit 1 +testit "verify owner" win_owner_is "$SERVER/user1" || exit 1 + +# Now try to remove the stream on the testfile +testit "delete stream" delete_stream $SHARE afile || exit 1 + +# Remove testfile +testit "remove testfile" remove_testfile $SHARE || exit 1 + +# Revoke SeRestorePrivilege, give ownership must fail now with NT_STATUS_INVALID_OWNER +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || exit 1 + +exit 0 diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh new file mode 100755 index 0000000..08f257f --- /dev/null +++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh @@ -0,0 +1,182 @@ +#!/bin/sh +# +# Check smbclient can (or cannot) delete a directory containing dangling symlinks. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +USERNAME=${3} +PASSWORD=${4} +SHAREPATH=${5} +SMBCLIENT=${6} +shift 6 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +rmdir_path="$SHAREPATH/dir" + +# +# Using the share "[delete_veto_files_only]" we CAN delete +# a directory containing only a dangling symlink. +# +test_dangle_symlink_delete_veto_rmdir() +{ + local dangle_symlink_path="$rmdir_path/bad_link" + local tmpfile=$PREFIX/smbclient.in.$$ + + # Create rmdir directory. + mkdir -p "$rmdir_path" + # Create dangling symlink underneath. + ln -s "nowhere-foo" "$dangle_symlink_path" + + cat >"$tmpfile" <<EOF +cd dir +ls +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share delete_veto_files_only - $ret" + echo "$out" + return 1 + fi + + # We should NOT see the dangling symlink file. + echo "$out" | grep bad_link + ret=$? + if [ $ret -eq 0 ]; then + echo "Saw dangling symlink bad_link in share delete_veto_files_only" + echo "$out" + return 1 + fi + + # Try and remove the directory, should succeed. + cat >"$tmpfile" <<EOF +rd dir +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share delete_veto_files_only - $ret" + echo "$out" + return 1 + fi + + # We should get no NT_STATUS_ errors. + echo "$out" | grep NT_STATUS_ + ret=$? + if [ $ret -eq 0 ]; then + echo "Got error NT_STATUS_ in share delete_veto_files_only" + echo "$out" + return 1 + fi + + return 0 +} + +# +# Using the share "[veto_files_nodelete]" we CANNOT delete +# a directory containing only a dangling symlink. +# +test_dangle_symlink_veto_files_nodelete() +{ + local dangle_symlink_path="$rmdir_path/bad_link" + local tmpfile=$PREFIX/smbclient.in.$$ + + # Create rmdir directory. + mkdir -p "$rmdir_path" + # Create dangling symlink underneath. + ln -s "nowhere-foo" "$dangle_symlink_path" + + cat >"$tmpfile" <<EOF +cd dir +ls +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_nodelete - $ret" + echo "$out" + return 1 + fi + + # We should NOT see the dangling symlink file. + echo "$out" | grep bad_link + ret=$? + if [ $ret -eq 0 ]; then + echo "Saw dangling symlink bad_link in share veto_files_nodelete" + echo "$out" + return 1 + fi + + # Try and remove the directory, should fail with DIRECTORY_NOT_EMPTY. + cat >"$tmpfile" <<EOF +rd dir +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_nodelete - $ret" + echo "$out" + return 1 + fi + + # We should get NT_STATUS_DIRECTORY_NOT_EMPTY errors. + echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY + ret=$? + if [ $ret -ne 0 ]; then + echo "Should get NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete" + echo "$out" + return 1 + fi + + return 0 +} + +testit "rmdir can delete directory containing dangling symlink" \ + test_dangle_symlink_delete_veto_rmdir || failed=$(expr "$failed" + 1) + +rm -rf "$rmdir_path" + +testit "rmdir cannot delete directory delete_veto_files_no containing dangling symlink" \ + test_dangle_symlink_veto_files_nodelete || failed=$(expr "$failed" + 1) + +rm -rf "$rmdir_path" +exit "$failed" diff --git a/source3/script/tests/test_dfree_command.sh b/source3/script/tests/test_dfree_command.sh new file mode 100755 index 0000000..3ebb50c --- /dev/null +++ b/source3/script/tests/test_dfree_command.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# +# Blackbox test for 'dfree command' and smbclient "l" +# command disk free printout. +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_dfree_command.sh SERVER DOMAIN USERNAME PASSWORD PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER=$1 +DOMAIN=$2 +USERNAME=$3 +PASSWORD=$4 +PREFIX=$5 +smbclient=$6 +protocol=$7 + +shift 7 +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +test_smbclient_dfree() +{ + name="$1" + share="$2" + cmd="$3" + expected="$4" + shift + shift + shift + subunit_start_test "$name" + output=$($VALGRIND $smbclient //$SERVER/$share -c "$cmd" "$@" 2>&1) + status=$? + if [ x$status = x0 ]; then + received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +if [ $protocol = "SMB3" ]; then + test_smbclient_dfree "Test dfree command share root SMB3" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + test_smbclient_dfree "Test dfree command subdir1 SMB3" dfree "cd subdir1; l" "8000 1024. 80" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + test_smbclient_dfree "Test dfree command subdir2 SMB3" dfree "cd subdir2; l" "32000 1024. 320" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +elif [ $protocol = "NT1" ]; then + test_smbclient_dfree "Test dfree command share root NT1" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + #SMB1 queries disk usage stat on the share's root, regardless of working directory + test_smbclient_dfree "Test dfree command subdir1 NT1" dfree "cd subdir1; l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + +else + echo "unsupported protocol $protocol" | subunit_fail_test "Test dfree command" + failed=$(expr $failed + 1) +fi +exit $failed diff --git a/source3/script/tests/test_dfree_quota.sh b/source3/script/tests/test_dfree_quota.sh new file mode 100755 index 0000000..9151016 --- /dev/null +++ b/source3/script/tests/test_dfree_quota.sh @@ -0,0 +1,296 @@ +#!/bin/sh +# +# Blackbox test for disk-free, quota, and their interaction +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_dfree_quota.sh SERVER DOMAIN USERNAME PASSWORD LOCAL_PATH SMBCLIENT SMBCQUOTAS SMBCACLS +EOF + exit 1 +fi + +SERVER=$1 +DOMAIN=$2 +USERNAME=$3 +PASSWORD=$4 +ENVDIR=$(dirname $5) +WORKDIR=$5/dfree +smbclient=$6 +smbcquotas=$7 +smbcacls=$8 +protocol=$9 +shift 9 +failed=0 + +CONFFILE=$ENVDIR/lib/dfq.conf + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +sighup_smbd() +{ + kill -HUP -$(cat $ENVDIR/pid/smbd.pid) +} + +conf_lines() +{ + local uid + local gid + uid=$(id -u $USERNAME) + gid=$(id -g $USERNAME) + uid1=$(id -u user1) + uid2=$(id -u user2) + cat <<ABC +conf1:df:block size = 512:disk free = 10:disk size = 20 +conf2:df:block size = 1024:disk free = 10:disk size = 20 +conf3:df:block size = 4096:disk free = 750:disk size = 281474976710656 +confq1:u$uid:block size = 4096:hard limit = 750:soft limit = 1000:cur blocks = 10 +confdfq1:df:block size = 4096:disk free = 10:disk size = 20 +confdfq1:u$uid:block size = 4096:hard limit = 750:soft limit = 1000:cur blocks = 10 +confdfq2:df:block size = 4096:disk free = 10:disk size = 20 +confdfq2:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 37 +confdfq3:df:block size = 4096:disk free = 10:disk size = 80 +confdfq3:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 0 +confdfq4:df:block size = 4096:disk free = 10:disk size = 80 +confdfq4:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 37 +slimit:df:block size = 4096:disk free = 10:disk size = 80 +slimit:u$uid:block size = 4096:hard limit = 44:soft limit = 40:cur blocks = 42 +hlimit:df:block size = 4096:disk free = 10:disk size = 80 +hlimit:u$uid:block size = 4096:hard limit = 44:soft limit = 0:cur blocks = 45 +islimit:df:block size = 4096:disk free = 10:disk size = 80 +islimit:u$uid:block size = 4096:hard limit = 44:soft limit = 40:cur blocks = 37:inode soft limit = 30:inode hard limit = 35:cur inodes = 32 +ihlimit:df:block size = 4096:disk free = 10:disk size = 80 +ihlimit:u$uid:block size = 4096:hard limit = 44:soft limit = 40:cur blocks = 37:inode soft limit = 0:inode hard limit = 35:cur inodes = 36 +trygrp1:df:block size = 4096:disk free = 10:disk size = 80 +trygrp1:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 41:err = 1 +trygrp1:g$gid:block size = 4096:hard limit = 60:soft limit = 60:cur blocks = 55 +trygrp2:df:block size = 4096:disk free = 10:disk size = 80 +trygrp2:u$uid:block size = 4096:hard limit = 0:soft limit = 0:cur blocks = 41 +trygrp2:g$gid:block size = 4096:hard limit = 60:soft limit = 60:cur blocks = 56 +blksize:df:block size = 512:disk free = 614400:disk size = 614400 +blksize:u$uid:block size = 1024:hard limit = 512000:soft limit = 0:cur blocks = 0 +notenforce:df:block size = 4096:disk free = 10:disk size = 80 +notenforce:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 37 +notenforce:udflt:block size = 4096:qflags = 0 +nfs:df:block size = 4096:disk free = 10:disk size = 80 +nfs:u$uid:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 37 +nfs:udflt:nosys = 1 +confdfqp:df:block size = 4096:disk free = 10:disk size = 80 +confdfqp:u$uid1:block size = 4096:hard limit = 40:soft limit = 40:cur blocks = 36 +confdfqp:u$uid2:block size = 4096:hard limit = 41:soft limit = 41:cur blocks = 36 +sgid:stat:sgid = 98765 +sgid:u$uid:block size = 4096:hard limit = 0:soft limit = 0:cur blocks = 80 +sgid:g98765:block size = 4096:hard limit = 50:soft limit = 50:cur blocks = 40 +ABC +} + +setup_1_conf() +{ + conf_name="$1" + subdir="$2" + absdir=$(readlink -f $WORKDIR/$subdir) + conf_lines | sed -rn "s/^$conf_name:(.*)/\1/p" | tr ":" "\n" | + awk -F '=' -v atdir=$absdir 'NF==1 {section=$1} NF==2 {sub(/\s*$/, "", $1); printf "\tfake_dfq:%s/%s/%s =%s\n", section, $1, atdir, $2}' +} + +setup_conf() +{ + rm $CONFFILE + touch $CONFFILE + + until [ -z "$1" ]; do + setup_1_conf $1 $2 >>$CONFFILE + shift + shift + done + sighup_smbd + #let it load... + sleep .5 +} + +test_smbclient_dfree() +{ + name="$1" + share="$2" + dir="$3" + confs="$4" + expected="$5" + shift + shift + shift + shift + subunit_start_test "$name" + setup_conf $confs + output=$($VALGRIND $smbclient //$SERVER/$share -c "cd $dir; l" "$@" 2>&1) + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +# Issue two queries to different directories in one session to test +# caching effects +test_smbclient_dfree_2() +{ + name="$1" + share="$2" + dir1="$3" + dir2="$4" + confs="$5" + expected="$6" + subunit_start_test "$name" + setup_conf $confs + output=$($VALGRIND $smbclient //$SERVER/$share \ + -c "cd $dir1; du; cd ..; cd $dir2 ; du" "$@" 2>&1) + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | + awk '/blocks of size/ {print $1, $5, $6}' | + tr '\n' ' ') + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +test_smbcquotas() +{ + name="$1" + conf="$2" + user="$3" + expected="$4" + proto="$5" + shift + shift + shift + shift + shift + subunit_start_test "$name" + setup_conf "$conf" "." + if [ "$proto" = "smb2" ]; then + mproto="-m SMB2" + else + mproto="-m SMB1" + fi + + output=$($VALGRIND $smbcquotas $mproto //$SERVER/dfq "$@" 2>/dev/null | tr '\\' '/') + status=$? + if [ "$status" = "0" ]; then + received=$(echo "$output" | awk "/$SERVER\\/$user/ {printf \"%s%s%s\", \$3, \$4, \$5}") + if [ "$expected" = "$received" ]; then + subunit_pass_test "$name" + return 0 + else + echo "$output" | subunit_fail_test "$name" + return 1 + fi + else + echo "$output" | subunit_fail_test "$name" + return $status + fi +} + +if [ $protocol != "SMB3" ] && [ $protocol != "NT1" ]; then + echo "unsupported protocol $protocol" | subunit_fail_test "Test dfree quota" + failed=$(expr $failed + 1) +fi + +if [ $protocol = "NT1" ]; then + setup_conf + #basic quota test (SMB1 only) + test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" "smb1" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=$(expr $failed + 1) + exit $failed +fi + +#basic disk-free tests +test_smbclient_dfree "Test dfree share root SMB3 no quota" dfq "." "conf1 ." "10 1024. 5" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree subdir SMB3 no quota" dfq "subdir1" "conf1 . conf2 subdir1" "20 1024. 10" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test large disk" dfq "." "conf3 ." "1125899906842624 1024. 3000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#basic quota test (SMB2 only) +test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" "smb2" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB2 || failed=$(expr $failed + 1) + +# Test dfree cache through queries in two different directories +test_smbclient_dfree_2 "Test dfree cache" dfq_cache "." "subdir1" \ + "conf1 . conf2 subdir1" "10 1024. 5 20 1024. 10 " \ + -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || + failed=$(expr $failed + 1) + +#quota limit > disk size, remaining quota > disk free +test_smbclient_dfree "Test dfree share root df vs quota case 1" dfq "." "confdfq1 ." "80 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit > disk size, remaining quota < disk free +test_smbclient_dfree "Test dfree share root df vs quota case 2" dfq "." "confdfq2 ." "80 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit < disk size, remaining quota > disk free +test_smbclient_dfree "Test dfree share root df vs quota case 3" dfq "." "confdfq3 ." "160 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +#quota limit < disk size, remaining quota < disk free +test_smbclient_dfree "Test dfree share root df vs quota case 4" dfq "." "confdfq4 ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree subdir df vs quota case 4" dfq "subdir1" "confdfq4 subdir1" "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#quota-->disk free special cases +test_smbclient_dfree "Test quota->dfree soft limit" dfq "subdir1" "slimit subdir1" "168 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree hard limit" dfq "subdir1" "hlimit subdir1" "180 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree inode soft limit" dfq "subdir1" "islimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree inode hard limit" dfq "subdir1" "ihlimit subdir1" "148 1024. 0" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree err try group" dfq "subdir1" "trygrp1 subdir1" "240 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test quota->dfree no-quota try group" dfq "subdir1" "trygrp2 subdir1" "240 1024. 16" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +# sgid on directory +test_smbclient_dfree "Test quota on sgid directory" dfq "subdir1" \ + "sgid subdir1" "200 1024. 40" -U$USERNAME%$PASSWORD \ + --option=clientmaxprotocol=SMB3 || + failed=$(expr $failed + 1) + +#block size different in quota and df systems +test_smbclient_dfree "Test quota->dfree different block size" dfq "subdir1" "blksize subdir1" "307200 1024. 307200" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#quota configured but not enforced +test_smbclient_dfree "Test dfree share root quota not enforced" dfq "." "notenforce ." "320 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#FS quota not implemented (NFS case) +test_smbclient_dfree "Test dfree share root FS quota not implemented" dfq "." "nfs ." "160 1024. 12" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +#test for dfree when owner is inherited +#setup two folders with different owners +rm -rf $WORKDIR/subdir3/* +for d in / subdir3; do + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d >/dev/null 2>&1 + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user1:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=$(expr $failed + 1) + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -D "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d >/dev/null 2>&1 + $VALGRIND $smbcacls -U$USERNAME%$PASSWORD -a "ACL:$SERVER\user2:ALLOWED/0x0/FULL" //$SERVER/dfq $d || failed=$(expr $failed + 1) +done + +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user1" -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 >/dev/null 2>&1 || failed=$(expr $failed + 1) +$VALGRIND $smbclient //$SERVER/dfq -c "cd subdir3; mkdir user2" -Uuser2%$PASSWORD --option=clientmaxprotocol=SMB3 >/dev/null 2>&1 || failed=$(expr $failed + 1) +#test quotas +test_smbclient_dfree "Test dfree without inherit owner - user1 at user1" \ + dfq "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree without inherit owner - user1 at user2" \ + dfq "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree with inherit owner - user1 at user1" \ + dfq_owner "subdir3/user1" "confdfqp subdir3/user1 confdfqp subdir3/user2" "160 1024. 16" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) +test_smbclient_dfree "Test dfree with inherit owner - user1 at user2" \ + dfq_owner "subdir3/user2" "confdfqp subdir3/user1 confdfqp subdir3/user2" "164 1024. 20" \ + -Uuser1%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=$(expr $failed + 1) + +setup_conf +exit $failed diff --git a/source3/script/tests/test_dropbox.sh b/source3/script/tests/test_dropbox.sh new file mode 100755 index 0000000..a920c27 --- /dev/null +++ b/source3/script/tests/test_dropbox.sh @@ -0,0 +1,88 @@ +#!/bin/sh +# +# Blackbox test for valid users. +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: $0 SERVER DOMAIN USERNAME PASSWORD PREFIX TARGET_ENV SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +DOMAIN=${2} +USERNAME=${3} +PASSWORD=${4} +PREFIX=${5} +TARGET_ENV=${6} +SMBCLIENT=${7} +shift 7 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Test listing a share with valid users succeeds +test_dropbox() +{ + local filename="wurst.$$" + local filename_path="$PREFIX/$filename" + local dropbox_path="$PREFIX/$TARGET_ENV/share/$1/dirmode733" + + local tmpfile=$PREFIX/smbclient.in.$$ + + echo "wurstbar" >$filename_path + + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename dirmode733\\$filename +quit +EOF + + # Create dropbox directory and set permissions + mkdir -p $dropbox_path + chmod 0333 $dropbox_path + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/$1 -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + # Reset dropbox permissions + chmod 0755 $dropbox_path + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "Failed accessing share $ret" + echo "$out" + + return 1 + fi + rm -f $filename_path + + dropped_file="$dropbox_path/$filename" + if [ ! -r "$dropped_file" ]; then + echo "Failed to drop file $filename" + echo "$out" + return 1 + fi + + content=$(cat $dropped_file) + if [ "$content" != "wurstbar" ]; then + echo "Invalid file content: $content" + echo "$out" + return 1 + fi + + return 0 +} + +testit "dropbox dirmode 0733" \ + test_dropbox dropbox || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_durable_handle_reconnect.sh b/source3/script/tests/test_durable_handle_reconnect.sh new file mode 100755 index 0000000..0ab3297 --- /dev/null +++ b/source3/script/tests/test_durable_handle_reconnect.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Test Durable Handle reconnect with injected delay in the disconnect. +# +# Copyright (C) 2018 Ralph Boehme + +. $(dirname $0)/../../../testprogs/blackbox/subunit.sh +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +delay_inject_conf=$(dirname $SMB_CONF_PATH)/delay_inject.conf + +echo 'delay_inject:fntimes = 5000' >$delay_inject_conf + +testit "durable_v2_delay.durable_v2_reconnect_delay" $VALGRIND \ + $BINDIR/smbtorture //$SERVER_IP/delay_inject \ + -U$USERNAME%$PASSWORD \ + smb2.durable-v2-delay.durable_v2_reconnect_delay || + failed=$(expr $failed + 1) + +SMBD_LOG_FILES="$SMBD_TEST_LOG" +if [ $SMBD_DONT_LOG_STDOUT -eq 1 ]; then + _SMBD_LOG_FILE=$(dirname $SMBD_TEST_LOG)/logs/log.smbd + SMBD_LOG_FILES="$SMBD_LOG_FILES $_SMBD_LOG_FILE" +fi + +testit "durable_v2_delay.durable_v2_reconnect_delay_msec" $VALGRIND \ + $BINDIR/smbtorture //$SERVER_IP/durable \ + -U$USERNAME%$PASSWORD \ + smb2.durable-v2-delay.durable_v2_reconnect_delay_msec || + failed=$(expr $failed + 1) + +rm $delay_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_failure.sh b/source3/script/tests/test_failure.sh new file mode 100755 index 0000000..7a2c9ae --- /dev/null +++ b/source3/script/tests/test_failure.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Blackbox test that should fail one of three subtests. +# +# Copyright (C) 2011 Michael Adam <obnox@samba.org> + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_failure() +{ + false +} + +test_success() +{ + true +} + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testit "failure" \ + test_failure || + failed=$(expr $failed + 1) + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_fakedircreatetimes.sh b/source3/script/tests/test_fakedircreatetimes.sh new file mode 100755 index 0000000..4ce2bcf --- /dev/null +++ b/source3/script/tests/test_fakedircreatetimes.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_fakedircreatetimes.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT ADDARGS +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 7 +ADDARGS="$*" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" + + +test_fakedircreatetimes() +{ + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/recycle -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + cmd="LC_ALL=C TZ=UTC CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/fakedircreatetimes -I$SERVER_IP $ADDARGS -c 'allinfo \\'" + eval echo "$cmd" + out=$(eval "$cmd") + + ret=$? + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed recycle smbclient run with error %s\n" "$ret" + return 1 + fi + + echo "$out" | grep -q "create_time:.*1979 UTC" && { + return 0 + } + + echo "ERROR: create_time does not match 1979 UTC:" + echo "$out" + return 1 +} + + +testit "fakedircreatetimes" \ + test_fakedircreatetimes || + failed=$((failed + 1)) + + +testok "$0" "$failed" diff --git a/source3/script/tests/test_fifo.sh b/source3/script/tests/test_fifo.sh new file mode 100755 index 0000000..199b0b4 --- /dev/null +++ b/source3/script/tests/test_fifo.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# Check smbclient can list a directory containing a fifo. +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: $0 SERVER DOMAIN USERNAME PASSWORD PREFIX TARGET_ENV SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +DOMAIN=${2} +USERNAME=${3} +PASSWORD=${4} +PREFIX=${5} +TARGET_ENV=${6} +SMBCLIENT=${7} +shift 7 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Test that listing a share with a directory containing a fifo succeeds. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14816 +# +test_fifo() +{ + local fifo_dir_path="$PREFIX/$TARGET_ENV/share/fifodir" + local fifo_path="$fifo_dir_path/fifo_name" + + local tmpfile=$PREFIX/smbclient.in.$$ + + cat >$tmpfile <<EOF +cd fifodir +ls +quit +EOF + + # Create fifo directory. + mkdir -p $fifo_dir_path + # Create fifo underneath. + mkfifo $fifo_path + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/$1 -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + # Remove fifo and containing dir. + rm $fifo_path + rmdir $fifo_dir_path + rm -f $tmpfile + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share containing dir with fifo $ret" + echo "$out" + return 1 + fi + + # Check for smbclient timeout (server hung). + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + # Client was disconnected as server timed out. + echo "$out" + return 1 + fi + + return 0 +} + +testit "list directory containing a fifo" \ + test_fifo tmp || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_force_close_share.sh b/source3/script/tests/test_force_close_share.sh new file mode 100755 index 0000000..c9f943a --- /dev/null +++ b/source3/script/tests/test_force_close_share.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# +# Test smbcontrol close-share command. +# +# Copyright (C) 2020 Volker Lendecke +# Copyright (C) 2020 Jeremy Allison +# +# Note this is designed to be run against +# the aio_delay_inject share which is preconfigured +# with 2 second delays on pread/pwrite. + +if [ $# -lt 6 ]; then + echo Usage: $0 SERVERCONFFILE SMBCLIENT SMBCONTROL IP aio_delay_inject_sharename PREFIX + exit 1 +fi + +CONFIGURATION=$1 +smbclient=$2 +SMBCONTROL=$3 +SERVER=$4 +SHARE=$5 +PREFIX=$6 +shift 6 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +mkdir -p $PREFIX/private + +FIFO_STDIN="$PREFIX/smbclient-stdin" +FIFO_STDOUT="$PREFIX/smbclient-stdout" +FIFO_STDERR="$PREFIX/smbclient-stderr" +TESTFILE="$PREFIX/testfile" + +rm -f $FIFO_STDIN $FIFO_STDOUT $FIFO_STDERR $TESTFILE 2>/dev/null + +# Create the smbclient communication pipes. +mkfifo $FIFO_STDIN $FIFO_STDOUT $FIFO_STDERR +if [ $? -ne 0 ]; then + echo "Failed to create fifos" + exit 1 +fi + +# Create a large-ish testfile +head -c 100MB /dev/zero >$TESTFILE + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${smbclient} //${SERVER}/${SHARE} ${CONFIGURATION} -U${USER}%${PASSWORD} \ + <$FIFO_STDIN >$FIFO_STDOUT 2>$FIFO_STDERR & +CLIENT_PID=$! + +count=0 +while [ 1 ]; do + if [ $count -ge 20 ]; then + echo "Failed to start smbclient" + exit 1 + fi + kill -0 $CLIENT_PID + if [ $? -eq 0 ]; then + break + fi + sleep 0.5 + count=$((count + 1)) +done + +exec 100>$FIFO_STDIN 101<$FIFO_STDOUT 102<$FIFO_STDERR + +# consume the smbclient startup messages +head -n 1 <&101 + +# Ensure we're putting a fresh file. +echo "lcd $(dirname $TESTFILE)" >&100 +echo "del testfile" >&100 +echo "put testfile" >&100 + +sleep 0.2 + +# Close the aio_delay_inject share whilst we have outstanding writes. + +testit "smbcontrol" ${SMBCONTROL} ${CONFIGURATION} smbd close-share ${SHARE} || + failed=$(expr $failed + 1) + +sleep 0.5 + +# If we get one or more NT_STATUS_NETWORK_NAME_DELETED +# or NT_STATUS_INVALID_HANDLE on stderr from the writes we +# know the server stayed up and didn't crash when the +# close-share removed the share. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14301 +# +COUNT=$(head -n 2 <&102 | + grep -e NT_STATUS_NETWORK_NAME_DELETED -e NT_STATUS_INVALID_HANDLE | + wc -l) + +testit "Verify close-share did cancel the file put" \ + test $COUNT -ge 1 || failed=$(expr $failed + 1) + +kill ${CLIENT_PID} + +# Remove the testfile from the server +test_smbclient "remove_testfile" \ + 'del testfile; quit' //${SERVER}/${SHARE} -U${USER}%${PASSWORD} || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_force_create_mode.sh b/source3/script/tests/test_force_create_mode.sh new file mode 100755 index 0000000..289f219 --- /dev/null +++ b/source3/script/tests/test_force_create_mode.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Blackbox test for 'force create mode' +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: $0 SERVER DOMAIN USERNAME PASSWORD PREFIX TARGET_ENV SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +DOMAIN=${2} +USERNAME=${3} +PASSWORD=${4} +PREFIX=${5} +TARGET_ENV=${6} +SMBCLIENT=${7} +shift 7 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_force_create_mode() +{ + local filename="wurst.$$" + local filename_path="$PREFIX/$filename" + + local tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + echo wurstbar >$filename_path + + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/$1 $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "Failed to connect - error: $ret" + return 1 + fi + rm -f $filename_path + + share_filename="$PREFIX/$TARGET_ENV/share/$filename" + file_perms=$(stat --format=%a $share_filename) + if [ "$file_perms" != "664" ]; then + echo "Invalid file permissions: $file_perms" + return 1 + fi + + rm -f $share_filename + + return 0 +} + +testit "test_mode=0664" \ + test_force_create_mode create_mode_664 || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_force_group_change.sh b/source3/script/tests/test_force_group_change.sh new file mode 100755 index 0000000..bf82903 --- /dev/null +++ b/source3/script/tests/test_force_group_change.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Copyright (c) Jeremy Allison <jra@samba.org> +# License: GPLv3 +# Regression test for BUG:https://bugzilla.samba.org/show_bug.cgi?id=13690 + +if [ $# -lt 6 ]; then + echo "Usage: test_force_group_change.sh SERVER USERNAME PASSWORD LOCAL_PATH SMBCLIENT SMBCONTROL" + exit 1 +fi + +SERVER="${1}" +USERNAME="${2}" +PASSWORD="${3}" +LOCAL_PATH="${4}" +SMBCLIENT="${5}" +SMBCONTROL="${6}" +shift 6 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_force_group_change() +{ + # + # A SMB_CONF variable passed in here is the client smb.conf. + # We need to convert to the server.conf file from + # the LOCAL_PATH variable. + # + SERVER_CONFIG=$(dirname $LOCAL_PATH)/lib/server.conf + SERVER_CONFIG_SAVE=${SERVER_CONFIG}.bak + SERVER_CONFIG_NEW=${SERVER_CONFIG}.new + cp $SERVER_CONFIG $SERVER_CONFIG_SAVE + + sed -e 's/#\tforce group = everyone/\tforce group = everyone/' <${SERVER_CONFIG} >${SERVER_CONFIG_NEW} + + tmpfile=$PREFIX/smbclient_force_group_change_commands + cat >$tmpfile <<EOF +ls +!cp ${SERVER_CONFIG_NEW} ${SERVER_CONFIG} +!${SMBCONTROL} --configfile=${SERVER_CONFIG} all reload-config +ls +!cp ${SERVER_CONFIG_SAVE} ${SERVER_CONFIG} +!${SMBCONTROL} --configfile=${SERVER_CONFIG} all reload-config +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/force_group_test $CONFIGURATION < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + rm -f $SERVER_CONFIG_SAVE + rm -f $SERVER_CONFIG_NEW + + echo "$out" | grep 'NT_STATUS_CONNECTION_DISCONNECTED' + ret=$? + if [ $ret -eq 0 ]; then + # Client was disconnected as server crashed. + echo "$out" + return 1 + fi + + return 0 +} + +testit "test force group change" \ + test_force_group_change || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_force_user_unlink.sh b/source3/script/tests/test_force_user_unlink.sh new file mode 100755 index 0000000..c67b28f --- /dev/null +++ b/source3/script/tests/test_force_user_unlink.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# Test unlink on share with "force user" +# +# Copyright (C) 2021 Ralph Boehme + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +smbclient="$BINDIR/smbclient" +error_inject_conf=$(dirname ${SMB_CONF_PATH})/error_inject.conf +failed=0 + +test_forced_user_can_delete() +{ + out=$($smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "rm dir/file") + if [ $? -ne 0 ]; then + echo $out + return 1 + fi + tmp=$(echo $out | grep NT_STATUS_) + if [ $? -eq 0 ]; then + return 1 + fi + return 0 +} + +echo "error_inject:unlinkat = EACCES" >${error_inject_conf} + +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "mkdir dir" || failed=$(expr $failed + 1) +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "put WHATSNEW.txt dir/file" || failed=$(expr $failed + 1) + +testit "test_forced_user_can_delete" test_forced_user_can_delete || failed=$(expr $failed + 1) + +rm ${error_inject_conf} + +# Clean up after ourselves. +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "del dir/file; rmdir dir" + +testok $0 $failed diff --git a/source3/script/tests/test_forceuser_validusers.sh b/source3/script/tests/test_forceuser_validusers.sh new file mode 100755 index 0000000..11c1a5b --- /dev/null +++ b/source3/script/tests/test_forceuser_validusers.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# +# Blackbox test for share with force user settings +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_forceuser_validusers.sh SERVER DOMAIN USERNAME PASSWORD LOCAL_PATH SMBCLIENT <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +DOMAIN="$2" +USERNAME="force_user" +PASSWORD="$4" +LOCAL_PATH="$5" +SMBCLIENT="$6" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 +ADDARGS="$*" +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +cd $SELFTEST_TMPDIR || exit 1 + +run_cmd_nooutput() +{ + CMD="$1" + + out=$(eval ${CMD} >TESTOUT 2>&1) + if [ $? != 0 ]; then + cat TESTOUT + rm -f TESTOUT + echo "command failed" + false + return + fi + + rm -f TESTOUT + true + return +} + +test_force_user_valid_users() +{ + SMB_SHARE="force_user_valid_users" + run_cmd_nooutput "${SMBCLIENT} //${SERVER}/${SMB_SHARE} -U$USERNAME%$PASSWORD -c 'ls'" +} + +# Test +testit "force user not works when combined with valid users" \ + test_force_user_valid_users || failed=$(expr $failed + 1) + +# Cleanup + +# Results +testok $0 $failed diff --git a/source3/script/tests/test_fruit_resource_stream.sh b/source3/script/tests/test_fruit_resource_stream.sh new file mode 100755 index 0000000..7e99ea3 --- /dev/null +++ b/source3/script/tests/test_fruit_resource_stream.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# this tests copying a file and then deleting it +# to a share using fruit:resource = stream +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15099 + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVER SHARE USERNAME PASSWORD LOCAL_PATH SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SHARE="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +SMBCLIENT="${6}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir/subunit.sh" + +failed=0 + +put_then_delete_file() +{ + $SMBCLIENT //"$SERVER"/"$SHARE" -U"$USERNAME"%"$PASSWORD" -c "lcd $LOCAL_PATH; put src dst; rm dst" >/dev/null 2>&1 +} + +rm -f "$LOCAL_PATH/src" +rm -f "$LOCAL_PATH/dst" +touch "$LOCAL_PATH/src" + +testit "resource_stream" put_then_delete_file || failed=$((failed + 1)) + +rm -f "$LOCAL_PATH/src" +rm -f "$LOCAL_PATH/dst" + +testok "$0" "$failed" diff --git a/source3/script/tests/test_give_owner.sh b/source3/script/tests/test_give_owner.sh new file mode 100755 index 0000000..9d00918 --- /dev/null +++ b/source3/script/tests/test_give_owner.sh @@ -0,0 +1,147 @@ +#!/bin/sh +# +# this verifies that SEC_STD_WRITE_OWNER only effectively grants take-ownership +# permissions but NOT give-ownership. +# + +if [ $# -lt 9 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +PREFIX="$5" +SMBCLIENT="$6" +SMBCACLS="$7" +NET="$8" +SHARE="$9" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +SMBCACLS="$VALGRIND ${SMBCACLS}" +NET="$VALGRIND ${NET}" +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +setup_testfile() +{ + local share=$1 + local fname=$2 + touch $PREFIX/$fname + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "rm $fname" + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "ls" | grep "$fname" && return 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "lcd $PREFIX; put $fname" || return 1 +} + +remove_testfile() +{ + local share=$1 + local fname=$2 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "rm $fname" +} + +set_win_owner() +{ + local share=$1 + local fname=$2 + local owner=$3 + echo "$SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C '$owner'" + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C "$owner" || return 1 +} + +win_owner_is() +{ + local share=$1 + local fname=$2 + local expected_owner=$3 + local actual_owner + + echo "$SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD" + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD + actual_owner=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD | sed -rn 's/^OWNER:(.*)/\1/p') + echo "actual_owner = $actual_owner" + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of $share/$fname is [$actual_owner] expected [$expected_owner]" + return 1 + fi + return 0 +} + +add_ace() +{ + local share=$1 + local fname=$2 + local ace=$3 + + local_ace=$(printf '%s' "$ace" | sed 's|\\|/|') + + # avoid duplicate + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD) + if [ $? -ne 0 ]; then + echo "get acl failed" + echo "$out" + return 1 + fi + echo "Original ACL" + echo $out + echo "$out" | grep "$local_ace" && return 0 + + # add it + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -a "$ace" + if [ $? -ne 0 ]; then + echo "add acl failed" + return 1 + fi + + # check it's there + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD) + if [ $? -ne 0 ]; then + echo "get new acl failed" + echo "$out" + return 1 + fi + echo "New ACL" + echo $out + echo "Checking if new ACL has \"$local_ace\"" + echo "$out" | grep "$local_ace" || return 1 + echo "ok" +} + +chown_give_fails() +{ + local share=$1 + local fname=$2 + local user=$3 + local expected_error=$4 + + # this must fail + out=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C "$user") && return 1 + # it failed, now check it returned the expected error code + echo "$out" | grep $expected_error || return 1 +} + +# Create a testfile +testit "create testfile" setup_testfile $SHARE afile || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/$USERNAME" || failed=$(expr $failed + 1) + +# Grant SeRestorePrivilege to the user and full rights on the file +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) +testit "grant full rights" add_ace $SHARE afile "ACL:$SERVER\\$USERNAME:ALLOWED/0x0/FULL" || failed=$(expr $failed + 1) + +# We have SeRestorePrivilege, so both give and take ownership must succeed +testit "give owner with SeRestorePrivilege" set_win_owner $SHARE afile "$SERVER\user1" || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/user1" || failed=$(expr $failed + 1) +testit "take owner" set_win_owner $SHARE afile "$SERVER\\$USERNAME" || failed=$(expr $failed + 1) +testit "verify owner" win_owner_is $SHARE afile "$SERVER/$USERNAME" || failed=$(expr $failed + 1) + +# Revoke SeRestorePrivilege, give ownership must fail now with NT_STATUS_INVALID_OWNER +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) +testit "give owner without SeRestorePrivilege" chown_give_fails $SHARE afile "$SERVER\user1" NT_STATUS_INVALID_OWNER || failed=$(expr $failed + 1) + +testit "delete testfile" remove_testfile $SHARE afile || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_groupmap.sh b/source3/script/tests/test_groupmap.sh new file mode 100755 index 0000000..a1e9a08 --- /dev/null +++ b/source3/script/tests/test_groupmap.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# test groupmap code tridge@samba.org September 2006 +# note that this needs root access to add unix groups, +# so this cannot be run on the build farm + +testone() +{ + echo $* + $VALGRIND bin/net groupmap $* +} + +tstart() +{ + TBASE=$(date '+%s') +} + +treport() +{ + TNOW=$(date '+%s') + echo "Took $(expr $TNOW - $TBASE) seconds" + TBASE=$TNOW +} + +rm -f $PREFIX_ABS/var/locks/group_mapping.?db + +NLOCAL=12 +NGROUP=11 +NBUILTIN=10 +DOMSID=$(bin/net getlocalsid | awk '{print $6}') +FORSID="S-1-2-3-4-5" + +echo "DOMSID $DOMSID" +echo "FORSID $FORSID" + +tstart +echo "Creating unix groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + gid=$(expr 30000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + gid=$(expr 40000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + gid=$(expr 50000 + $i) + groupdel $unixgroup 2>/dev/null + groupadd -g $gid $unixgroup || exit 1 +done +date + +treport + +echo "Creating local groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + ntgroup=ntlgrp$i + rid=$(expr 10000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=local || exit 1 +done + +echo "trying a duplicate add" +testone add rid=10001 unixgroup=testlocal1 ntgroup=foo type=local && exit 1 + +treport + +echo "Creating domain groups" +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + ntgroup=ntgrp$i + rid=$(expr 20000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=domain || exit 1 +done + +treport + +echo "Creating builtin groups" +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + ntgroup=ntbgrp$i + rid=$(expr 30000 + $i) + testone add rid=$rid unixgroup=$unixgroup ntgroup=$ntgroup type=builtin || exit 1 +done + +treport + +echo "Adding domain groups to local groups" +for i in $(seq 1 1 $NLOCAL); do + for j in $(seq 1 1 $i); do + + lrid=$(expr 10000 + $i) + drid=$(expr 20000 + $j) + + testone addmem $DOMSID-$lrid $DOMSID-$drid || exit 1 + (testone listmem $DOMSID-$lrid | sort -r) || exit 1 + done +done + +echo "trying a duplicate addmem" +testone addmem $DOMSID-10001 $DOMSID-20001 && exit 1 + +echo "Adding foreign SIDs to local groups" +for i in $(seq 1 1 $NLOCAL); do + for j in $(seq 1 1 $i); do + + lrid=$(expr 10000 + $i) + frid=$(expr 70000 + $j) + + testone addmem $DOMSID-$lrid $FORSID-$frid || exit 1 + (testone listmem $DOMSID-$lrid | sort -r) || exit 1 + done +done + +echo "trying a duplicate foreign addmem" +testone addmem $DOMSID-10001 $FORSID-70001 && exit 1 + +treport + +echo "Listing local group memberships of domain groups" +for i in $(seq 1 1 $NGROUP); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +echo "Trying memberships on bogus sid" +testone memberships $DOMSID-999999 || exit 1 + +treport + +testone list | sort + +echo "Deleting some domain groups" +for i in $(seq 2 2 $NGROUP); do + drid=$(expr 20000 + $i) + testone delete sid=$DOMSID-$drid || exit 1 +done + +echo "Trying duplicate domain group delete" +testone delete sid=$DOMSID-20002 && exit 1 + +treport + +echo "Deleting some local groups" +for i in $(seq 2 4 $NLOCAL); do + lrid=$(expr 10000 + $i) + testone delete sid=$DOMSID-$lrid || exit 1 +done + +echo "Trying duplicate local group delete" +testone delete sid=$DOMSID-10002 && exit 1 + +treport + +echo "Modifying some domain groups" +for i in $(seq 3 2 $NGROUP); do + drid=$(expr 20000 + $i) + testone modify sid=$DOMSID-$drid comment="newcomment-$i" type=domain || exit 1 +done + +treport + +testone list | sort + +echo "Listing local group memberships" +for i in $(seq 1 1 $NLOCAL); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +treport + +echo "Removing some domain groups from local groups" +for i in $(seq 1 2 $NLOCAL); do + for j in $(seq 1 3 $i); do + + lrid=$(expr 10000 + $i) + drid=$(expr 20000 + $j) + + testone delmem $DOMSID-$lrid $DOMSID-$drid || exit 1 + done +done + +echo "Trying duplicate delmem" +testone delmem $DOMSID-10001 $DOMSID-20001 && exit 1 + +treport + +echo "Listing local group memberships" +for i in $(seq 1 1 $NLOCAL); do + rid=$(expr 20000 + $i) + (testone memberships $DOMSID-$rid | sort -r) || exit 1 +done + +treport + +echo "Deleting unix groups" +for i in $(seq 1 1 $NLOCAL); do + unixgroup=testlocal$i + groupdel $unixgroup 2>/dev/null +done +for i in $(seq 1 1 $NGROUP); do + unixgroup=testgrp$i + groupdel $unixgroup 2>/dev/null +done +for i in $(seq 1 1 $NBUILTIN); do + unixgroup=testb$i + groupdel $unixgroup 2>/dev/null +done + +treport + +echo "ALL DONE" diff --git a/source3/script/tests/test_guest_auth.sh b/source3/script/tests/test_guest_auth.sh new file mode 100755 index 0000000..fc18114 --- /dev/null +++ b/source3/script/tests/test_guest_auth.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# Test guest authentication +# +# Copyright (C) 2019 Ralph Boehme +# + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: $0 SERVER SMBCLIENT SMBCONTROL NET CONFIGURATION +EOF + exit 1 +fi + +SERVER=$1 +SMBCLIENT=$2 +SMBCONTROL=$3 +NET=$4 +CONFIGURATION=$5 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 +SIDS="" + +prepare_empty_builtin_guests() +{ + TMP=$($NET $CONFIGURATION groupmap listmem S-1-5-32-546 2>&1) + bg_exists=$? + if [ $bg_exists != 0 ]; then + printf "Group map for BUILTIN\\Guests must exist for test\n" + return 1 + fi + + SIDS=$($NET $CONFIGURATION groupmap listmem S-1-5-32-546) + if [ $? != 0 ]; then + printf "$NET $CONFIGURATION groupmap listmem S-1-5-32-546 failed. Returned:\n" + printf "$SIDS\n" + return 1 + fi + printf "Got S-1-5-32-546 members:\n$SIDS\n" + + if [ "$SIDS" != "" ]; then + for SID in $SIDS; do + printf "Deleting member $SID from S-1-5-32-546\n" + $NET $CONFIGURATION groupmap delmem S-1-5-32-546 $SID || return 1 + done + fi + + return 0 +} + +add_local_guest_to_builtin_guests() +{ + if [ "$SIDS" != "" ]; then + for SID in $SIDS; do + printf "Adding $SID as member to S-1-5-32-546\n" + $NET $CONFIGURATION groupmap addmem S-1-5-32-546 $SID || return 1 + done + fi +} + +test_smbclient() +{ + $SMBCLIENT -U foo%bar //$SERVER/tmpguest -c exit + if [ $? != 0 ]; then + printf "smbclient failed\n" + return 1 + fi + return 0 +} + +testit "smbclient_guest_at_startup" \ + test_smbclient || + failed=$(expr $failed + 1) + +printf "Prepare BUILTIN\\Guests group mapping without members\n" + +prepare_empty_builtin_guests || { + printf "Setting up BUILTIN\\Guests without members failed\n" + exit 1 +} + +$SMBCONTROL $CONFIGURATION smbd reload-config || { + printf "Reloading parent smbd guest info failed\n" + exit 1 +} + +testit "smbclient_guest_auth_without_members" \ + test_smbclient || + failed=$(expr $failed + 1) + +# restore config +add_local_guest_to_builtin_guests + +$SMBCONTROL $CONFIGURATION smbd reload-config || { + printf "Reloading parent smbd guest info failed\n" + exit 1 +} + +testit "smbclient_works_after_restored_setup" \ + test_smbclient || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_homes.sh b/source3/script/tests/test_homes.sh new file mode 100755 index 0000000..be8e9b2 --- /dev/null +++ b/source3/script/tests/test_homes.sh @@ -0,0 +1,136 @@ +#!/bin/sh + +# Copyright (c) Andreas Schneider <asn@samba.org> +# License: GPLv3 + +if [ $# -lt 7 ]; then + echo "Usage: test_homes.sh SERVER USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT CONFIGURATION" + exit 1 +fi + +SERVER="${1}" +USERNAME="${2}" +PASSWORD="${3}" +LOCAL_PATH="${4}" +PREFIX="${5}" +SMBCLIENT="${6}" +CONFIGURATION="${7}" +shift 7 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_gooduser_home() +{ + tmpfile=$PREFIX/smbclient_homes_gooduser_commands + cat >$tmpfile <<EOF +ls +quit +EOF + + USERNAME=gooduser + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/$USERNAME $CONFIGURATION < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed to connect error $ret" + return 1 + fi + + echo "$out" | grep 'Try "help" to get a list of possible commands.' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo 'failed - should get: Try "help" to get a list of possible commands.' + return 1 + fi + + return 0 +} + +test_eviluser_home() +{ + tmpfile=$PREFIX/smbclient_homes_eviluser_commands + cat >$tmpfile <<EOF +ls +quit +EOF + + USERNAME=eviluser + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/$USERNAME $CONFIGURATION < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 1 ]; then + echo "$out" + echo "The server should reject connecting ret=$ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS_BAD_NETWORK_NAME' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo 'failed - should get: NT_STATUS_BAD_NETWORK_NAME.' + return 1 + fi + + return 0 +} + +test_slashuser_home() +{ + tmpfile=$PREFIX/smbclient_homes_slashuser_commands + cat >$tmpfile <<EOF +ls +quit +EOF + + USERNAME=slashuser + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/$USERNAME $CONFIGURATION < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 1 ]; then + echo "$out" + echo "The server should reject connecting ret=$ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS_BAD_NETWORK_NAME' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo 'failed - should get: NT_STATUS_BAD_NETWORK_NAME.' + return 1 + fi + + return 0 +} + +testit "test gooduser home" \ + test_gooduser_home || + failed=$(expr $failed + 1) + +testit "test eviluser home reject" \ + test_eviluser_home || + failed=$(expr $failed + 1) + +testit "test slashuser home reject" \ + test_slashuser_home || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_inherit_owner.sh b/source3/script/tests/test_inherit_owner.sh new file mode 100755 index 0000000..aa61671 --- /dev/null +++ b/source3/script/tests/test_inherit_owner.sh @@ -0,0 +1,170 @@ +#!/bin/sh + +# this tests "inherit owner" config parameter +# currently needs to run in SMB1 mode, because it uses UNIX +# extensions to fetch the UNIX owner of a file. + +if [ $# -lt 10 ]; then + cat <<EOF +Usage: $0 SERVER USERNAME PASSWORD PREFIX SMBCLIENT SMBCACLS NET SHARE INH_WIN INH_UNIX <additional args> +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +PREFIX="$4" +SMBCLIENT="$5" +SMBCACLS="$6" +NET="$7" +SHARE="$8" +INH_WIN="$9" +INH_UNIX="${10}" +shift 10 +ADDARGS="$*" +SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}" +SMBCACLS="$VALGRIND ${SMBCACLS} ${ADDARGS}" +NET="$VALGRIND ${NET}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +create_file() +{ + local share=$1 + local fname=$2 + local rem_dirname=$(dirname $fname) + local bname=$(basename $fname) + touch $PREFIX/$bname + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rm $bname" 2>/dev/null + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; allinfo $bname" 2>/dev/null | grep "NT_STATUS_OBJECT_NAME_NOT_FOUND" || exit 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "lcd $PREFIX; cd $rem_dirname; put $bname" 2>/dev/null || exit 1 +} + +create_dir() +{ + local share=$1 + local dname=$2 + local rem_dirname=$(dirname $dname) + local bname=$(basename $dname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rmdir $bname" 2>/dev/null + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; allinfo $bname" 2>/dev/null | grep "NT_STATUS_OBJECT_NAME_NOT_FOUND" || exit 1 + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; mkdir $bname" 2>/dev/null || exit 1 +} + +cleanup_file() +{ + local share=$1 + local fname=$2 + local rem_dirname=$(dirname $fname) + local bname=$(basename $fname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rm $bname" 2>/dev/null || exit 1 +} + +cleanup_dir() +{ + local share=$1 + local dname=$2 + local rem_dirname=$(dirname $dname) + local bname=$(basename $dname) + $SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "cd $rem_dirname; rmdir $bname" 2>/dev/null || exit 1 +} + +set_win_owner() +{ + local share=$1 + local fname=$2 + local owner=$3 + $SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD -C $owner 2>/dev/null || exit 1 +} + +unix_owner_id_is() +{ + local share=$1 + local fname=$2 + local expected_id=$3 + local actual_id + actual_id=$($SMBCLIENT //$SERVER/$share -U $USERNAME%$PASSWORD -c "posix; getfacl $fname" 2>/dev/null | sed -rn 's/^# owner: (.*)/\1/p') + if ! test "x$actual_id" = "x$expected_id"; then + echo "Actual uid of $share/$fname is [$actual_id] expected [$expected_id]" + exit 1 + fi +} + +get_unix_id() +{ + local user=$1 + local ent + ent=$(getent passwd $user) || exit 1 + echo "$ent" | awk -F: '{print $3}' +} + +win_owner_is() +{ + local share=$1 + local fname=$2 + local expected_owner=$3 + local actual_owner + actual_owner=$($SMBCACLS //$SERVER/$share $fname -U $USERNAME%$PASSWORD 2>/dev/null | sed -rn 's/^OWNER:(.*)/\1/p') + if ! test "x$actual_owner" = "x$expected_owner"; then + echo "Actual owner of $share/$fname is [$actual_owner] expected [$expected_owner]" + exit 1 + fi +} + +default_uid=$(get_unix_id $USERNAME) +alt_uid=$(get_unix_id force_user) + +if [ "$INH_WIN" = "0" ] && [ "$INH_UNIX" = "0" ]; then + #default - file owned by creator, change-owner modifies both + WIN_OWNER_AFTER_CREATE="$SERVER/$USERNAME" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id $USERNAME) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id smbget_user) + TEST_LABEL="default" +elif [ "$INH_WIN" = "1" ] && [ "$INH_UNIX" = "1" ]; then + #inherit owner=windows and unix - file owned by parent + #owner, change-owner modifies both + WIN_OWNER_AFTER_CREATE="$SERVER/force_user" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id force_user) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id smbget_user) + TEST_LABEL="both" +elif [ "$INH_WIN" = "0" ] && [ "$INH_UNIX" = "1" ]; then + #inherit owner=unix only - windows owner is creator, + #unix owner inherited, upon change-owner only windows + #owner is changed + WIN_OWNER_AFTER_CREATE="$SERVER/$USERNAME" + UNIX_OWNER_AFTER_CREATE=$(get_unix_id force_user) + WIN_OWNER_AFTER_CHOWN="$SERVER/smbget_user" + UNIX_OWNER_AFTER_CHOWN=$(get_unix_id force_user) + TEST_LABEL="unix" +else + echo "Unknown combination INH_WIN=$INH_WIN INH_UNIX=$INH_UNIX" + exit 1 +fi + +# SETUP +testit "$TEST_LABEL - setup root dir" create_dir tmp tmp.$$ +testit "grant SeRestorePrivilege" $NET rpc rights grant $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER || exit 1 +testit "$TEST_LABEL - assign default ACL" $SMBCACLS //$SERVER/tmp tmp.$$ -U $USERNAME%$PASSWORD -S "REVISION:1,OWNER:$SERVER\force_user,GROUP:$SERVER\domusers,ACL:Everyone:ALLOWED/0x3/FULL" 2>/dev/null +# END SETUP + +testit "$TEST_LABEL - create subdir under root" create_dir $SHARE tmp.$$/subdir +testit "$TEST_LABEL - verify subdir win owner" win_owner_is $SHARE tmp.$$/subdir "$WIN_OWNER_AFTER_CREATE" +testit "$TEST_LABEL - verify subdir unix owner" unix_owner_id_is $SHARE tmp.$$/subdir $UNIX_OWNER_AFTER_CREATE +testit "$TEST_LABEL - create file under root" create_file $SHARE tmp.$$/afile +testit "$TEST_LABEL - verify file win owner" win_owner_is $SHARE tmp.$$/afile "$WIN_OWNER_AFTER_CREATE" +testit "$TEST_LABEL - verify file unix owner" unix_owner_id_is $SHARE tmp.$$/afile $UNIX_OWNER_AFTER_CREATE +testit "$TEST_LABEL - change dir owner" set_win_owner $SHARE tmp.$$/subdir "$SERVER\smbget_user" +testit "$TEST_LABEL - verify subdir win owner after change" win_owner_is $SHARE tmp.$$/subdir "$WIN_OWNER_AFTER_CHOWN" +testit "$TEST_LABEL - verify subdir unix owner after change" unix_owner_id_is $SHARE tmp.$$/subdir $UNIX_OWNER_AFTER_CHOWN +testit "$TEST_LABEL - change file owner" set_win_owner $SHARE tmp.$$/afile "$SERVER\smbget_user" +testit "$TEST_LABEL - verify file win owner after change" win_owner_is $SHARE tmp.$$/afile "$WIN_OWNER_AFTER_CHOWN" +testit "$TEST_LABEL - verify file unix owner after change" unix_owner_id_is $SHARE tmp.$$/afile $UNIX_OWNER_AFTER_CHOWN +testit "$TEST_LABEL - cleanup subdir" cleanup_dir $SHARE tmp.$$/subdir +testit "$TEST_LABEL - cleanup file" cleanup_file $SHARE tmp.$$/afile +testit "$TEST_LABEL - cleanup root" cleanup_dir $SHARE tmp.$$ + +testit "revoke SeRestorePrivilege" $NET rpc rights revoke $USERNAME SeRestorePrivilege -U $USERNAME%$PASSWORD -I $SERVER || exit 1 diff --git a/source3/script/tests/test_large_acl.sh b/source3/script/tests/test_large_acl.sh new file mode 100755 index 0000000..4e98c2e --- /dev/null +++ b/source3/script/tests/test_large_acl.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# +# Blackbox test for fetching a large ACL +# + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: $0 SERVER USERNAME PASSWORD SMBCLIENT SMBCACLS PARAMS +EOF + exit 1 +fi + +SERVER=${1} +USERNAME=${2} +PASSWORD=${3} +SMBCLIENT=${4} +SMBCACLS=${5} +shift 5 +ADDARGS="$*" +SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}" +SMBCACLS="$VALGRIND ${SMBCACLS} ${ADDARGS}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +cd $SELFTEST_TMPDIR || exit 1 + +# build a file to work with +build_files() +{ + touch large_acl + $SMBCLIENT //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD -c 'put large_acl' >/dev/null 2>&1 + rm -rf large_acl >/dev/null +} + +cleanup() +{ + $SMBCLIENT //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD -c 'rm large_acl' >/dev/null 2>&1 +} + +build_files + +test_large_acl() +{ + #An ACL with 200 entries, ~7K + new_acl=$(seq 1001 1200 | sed -r -e '1 i\D:(A;;FA;;;WD)' -e 's/(.*)/(A;;FA;;;S-1-5-21-11111111-22222222-33333333-\1)/' | tr -d '\n') + $SMBCACLS //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD --sddl -S $new_acl large_acl + actual_acl=$($SMBCACLS //$SERVER/acl_xattr_ign_sysacl_windows -U $USERNAME%$PASSWORD --sddl --numeric large_acl 2>/dev/null | sed -rn 's/.*(D:.*)/\1/p' | tr -d '\n') + if [ ! "$new_acl" = "$actual_acl" ]; then + echo -e "expected:\n$new_acl\nactual:\n$actual_acl\n" + return 1 + fi +} + +failed=0 + +testit "able to retrieve a large ACL if VFS supports it" test_large_acl || failed=$(expr $failed + 1) + +cleanup + +exit $failed diff --git a/source3/script/tests/test_libwbclient_threads.sh b/source3/script/tests/test_libwbclient_threads.sh new file mode 100755 index 0000000..4f7ac12 --- /dev/null +++ b/source3/script/tests/test_libwbclient_threads.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: test_libwbclient_threads.sh DOMAIN USERNAME +EOF + exit 1 +fi + +DOMAIN="$1" +USERNAME="$2" +shift 2 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "libwbclient-threads" "$BINDIR/stress-nss-libwbclient" "$DOMAIN/$USERNAME" diff --git a/source3/script/tests/test_list_nt4_trust.sh b/source3/script/tests/test_list_nt4_trust.sh new file mode 100755 index 0000000..03ee7fc --- /dev/null +++ b/source3/script/tests/test_list_nt4_trust.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +wbinfo="$BINDIR/wbinfo" +smbclient="$BINDIR/smbclient" + +test_trust_wbinfo_m() { + i=0 + # Give the server some time to list trusted domains + while [ $i -lt 10 ] ; do + $wbinfo -m --verbose | grep "SAMBA-TEST" && return 0 + sleep 2 + i=$((i + 1)) + done + return 1 +} + +testit "nt4trust_wbinfo_m" test_trust_wbinfo_m || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_local_s3.sh b/source3/script/tests/test_local_s3.sh new file mode 100755 index 0000000..9de542a --- /dev/null +++ b/source3/script/tests/test_local_s3.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 + +if [ $# != 0 ]; then + cat <<EOF +Usage: test_local_s3.sh +EOF + exit 1 +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +if test -x $BINDIR/talloctort; then + testit "talloctort" $VALGRIND $BINDIR/talloctort || + failed=$(expr $failed + 1) +else + echo "Skipping talloctort" +fi + +testit "replace_testsuite" $VALGRIND $BINDIR/replace_testsuite || + failed=$(expr $failed + 1) + +if test -x $BINDIR/tdbtorture; then + testit "tdbtorture" $VALGRIND $BINDIR/tdbtorture || + failed=$(expr $failed + 1) +else + echo "Skipping tdbtorture" +fi + +testit "smbconftort" $VALGRIND $BINDIR/smbconftort $CONFIGURATION || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_cache_samlogon.sh b/source3/script/tests/test_net_cache_samlogon.sh new file mode 100755 index 0000000..671806a --- /dev/null +++ b/source3/script/tests/test_net_cache_samlogon.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# +# Test 'net cache samlogon' command. +# + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: $0 SERVER SHARE USER PASS +EOF + exit 1 +fi + +SERVER=$1 +SHARE=$2 +USER=$3 +PASS=$4 +smbclient=$BINDIR/smbclient + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +# Ensure the samlogon cache is primed +test_smbclient "Prime samlogon cache" 'exit' //$SERVER/$SHARE -U$USER%$PASS || failed=$(expr $failed + 1) + +# Ensure list works and remember the sid and name of the first entry +testit "net cache samlogon list" $BINDIR/net cache samlogon list || failed=$(expr $failed + 1) +usersid=$($BINDIR/net cache samlogon list | awk '/^S-/ { print $1 ; exit }') +username=$($BINDIR/net cache samlogon list | awk '/^S-/ { print $2 ; exit }') + +# Test the show command with the sid from the previous list command +testit "net cache samlogon show $usersid" $BINDIR/net cache samlogon show $usersid || failed=$(expr $failed + 1) +tmp=$($BINDIR/net cache samlogon show $usersid | awk '/^Name:/ {print $2}') +testit "net cache samlogon show SID name matches name from list command" test x"$tmp" = x"$username" || failed=$(expr $failed + 1) + +testit "net cache samlogon ndrdump $usersid" $BINDIR/net cache samlogon ndrdump $usersid || failed=$(expr $failed + 1) +tmp=$($BINDIR/net cache samlogon ndrdump $usersid | head -n 1 | grep "netr_SamInfo3: struct netr_SamInfo3") +retval=$? +testit "net cache samlogon ndrdump returns netr_SamInfo3 structure" test $retval -eq 0 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_conf.sh b/source3/script/tests/test_net_conf.sh new file mode 100755 index 0000000..7a70a9b --- /dev/null +++ b/source3/script/tests/test_net_conf.sh @@ -0,0 +1,1042 @@ +#!/bin/sh +# +# Blackbox test for net [rpc] conf. +# +# Copyright (C) 2011 Vicentiu Ciorbaru <cvicentiu@gmail.com> + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_net_conf.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION [rpc] +EOF + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" +RPC="$5" + +LOGDIR_PREFIX="conf_test" + +# remove old logs: +for OLDDIR in $(find ${PREFIX} -type d -name "${LOGDIR_PREFIX}_*"); do + echo "removing old directory ${OLDDIR}" + rm -rf ${OLDDIR} +done + +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" +DIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX) +LOG=$DIR/log + +if test "x${RPC}" = "xrpc"; then + NETCMD="${NET} -U${USERNAME}%${PASSWORD} -I ${SERVER_IP} rpc" +else + NETCMD="${NET}" +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +log_print() +{ + RC=$? + echo "CMD: $*" >>$LOG + echo "RC: $RC" >>$LOG + return $RC + # echo -n . +} + +test_conf_addshare() +{ + echo '\nTesting conf addshare' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #create a lot of shares + for i in $(seq 1 100); do + if [ $(($i % 2)) -eq 0 ]; then + $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" + else + $NETCMD conf addshare share$i /tmp "writeable=n" "guest_ok=y" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share$i /tmp "writeable=n" "guest_ok=y" \ + "test comment" + fi + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + done + + $NETCMD conf listshares >$DIR/listshares_out + log_print $NETCMD conf listshares + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + for i in $(seq 1 100); do + grep "share$i" $DIR/listshares_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + done + + #check the integrity of the shares + #if it fails, it can also point to an error in showshare + for i in $(seq 1 100); do + $NETCMD conf showshare share$i >$DIR/showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "path" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + + if [ $(($i % 2)) -eq 0 ]; then + grep "read only *= *no" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + else + grep "read only *= *yes" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + fi + + if [ $(($i % 2)) -eq 0 ]; then + grep "guest ok *= *no" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + else + grep "guest ok *= *yes" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + fi + + grep "comment *= *test comment" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not set correctly" | tee -a $LOG + return 1 + fi + done + + echo '\nTaking a conf snapshot for later use' >>$LOG + $NETCMD conf list >$DIR/conf_import_in + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } +} + +test_conf_addshare_existing() +{ + #try adding an already existing share + echo '\nAdding an already existing share' >>$LOG + $NETCMD conf addshare share1 /tmp "writeable=n" "guest_ok=y" \ + "test comment" >>$DIR/addshare_exp \ + 2>>$DIR/addshare_exp + log_print $NETCMD conf addshare share1 /tmp "writeable=n" "guest_ok=y" \ + "test comment" + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z $(cat $DIR/addshare_exp) && { + echo "ERROR: addshare output does not match" >>$LOG + return 1 + } + + return 0 +} + +test_conf_addshare_usage() +{ + #check to see if command prints usage + echo '\nChecking usage' >>$LOG + $NETCMD conf addshare >$DIR/addshare_usage_exp + log_print $NETCMD conf addshare + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf addshare" $DIR/addshare_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delshare() +{ + echo '\nTesting conf delshare' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf delshare share1 + log_print $NETCMD conf delshare share1 + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf listshares >$DIR/listshares_out + log_print $NETCMD conf listshares + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "share1$" $DIR/listshares_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delshare did not delete 'share1'" | tee -a $LOG + return 1 + fi +} + +test_conf_delshare_empty() +{ + echo '\nAttempting to delete non_existing share' + $NETCMD conf delshare share1 + log_print $NETCMD conf delshare share1 + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + +} + +test_conf_delshare_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf delshare >$DIR/delshare_usage_exp + log_print $NETCMD conf delshare + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delshare" $DIR/delshare_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_showshare_case() +{ + echo '\nChecking case in net conf shareshare' >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + for share in UPPERCASE lowercase; do + + log_print $NETCMD conf addshare $share /tmp + $NETCMD conf addshare $share /tmp \ + >>$DIR/case_addshare_exp \ + 2>>$DIR/case_addshare_exp + + # Lookup share in different case, check that output has + # share name in correct case. + switch_case=$(echo $share | tr 'A-Za-z' 'a-zA-Z') + log_print $NETCMD conf showshare $switch_case + $NETCMD conf showshare $switch_case >$DIR/showshare_out + test "x$?" = "x0" || { + echo 'ERROR: net conf showshare failed.' | tee -a $LOG + return 1 + } + + grep "\[$share\]" $DIR/showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: share not found" | tee -a $LOG + return 1 + fi + done + +} + +test_conf_drop() +{ + + echo '\nTesting conf drop' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #check to see if listing the configuration yields a blank file + $NETCMD conf list 1>>$DIR/list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z "$(cat $DIR/list_out)" || { + echo "ERROR: Expected list output did not match" | tee -a $LOG + return 1 + } +} + +test_conf_drop_empty() +{ + #Drop an empty config, see if conf drop fails + echo '\nAttempting to drop an empty configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #check to see if listing the configuration yields a blank file + $NETCMD conf list 1>>$DIR/list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + test -z "$(cat $DIR/list_out)" || { + echo ERROR:Expected list output did not match >>$LOG + return 1 + } +} + +test_conf_drop_usage() +{ + #check to see if command prints usage + echo '\nChecking usage' >>$LOG + $NETCMD conf drop extra_arg >$DIR/drop_usage_exp + log_print $NETCMD conf drop extra_arg + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "$RPC *conf drop" $DIR/drop_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm() +{ + echo '\nTesting conf setparm' >>$LOG + echo ------------------------- >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "path" /tmp/test_path + log_print $NETCMD conf setparm share1 "path" /tmp/test_path + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *yes" $DIR/setparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi + + grep "path *= */tmp/test_path" $DIR/setparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm_existing() +{ + + echo '\nSetting already existing param with the same value' + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setparm share1 "read only" yes + log_print $NETCMD conf setparm share1 "read only" yes + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_existing_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *yes" $DIR/setparm_existing_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi + + $NETCMD conf setparm share1 "read only" no + log_print $NETCMD conf setparm share1 "read only" no + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/setparm_existing_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "read only *= *no" $DIR/setparm_existing_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm did not set correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_setparm_forbidden() +{ + FORBIDDEN_PARAMS="state directory +lock directory +lock dir +config backend +include" + + echo '\nTrying to set forbidden parameters' >>$LOG + + echo '\nDropping existing configuration' >>$LOG + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + OLD_IFS="$IFS" + IFS=' +' + for PARAM in $FORBIDDEN_PARAMS; do + IFS="$OLD_IFS" + echo "Trying to set parameter '$PARAM'" | tee -a $LOG + $NETCMD conf setparm global "$PARAM" "value" >$DIR/setparm_forbidden_out 2>&1 + log_print $NETCMD conf setparm global \""$PARAM"\" "value" + test "x$?" = "x0" && { + echo "ERROR: setting forbidden parameter '$PARAM' succeeded" | tee -a $LOG + return 1 + } + + echo "output of net command: " | tee -a $LOG + cat $DIR/setparm_forbidden_out | tee -a $LOG + + SEARCH="Parameter '$PARAM' not allowed in registry." + grep "$SEARCH" $DIR/setparm_forbidden_out >/dev/null 2>>$LOG + test "x$?" = "x0" || { + echo "ERROR: expected '$SEARCH'" | tee -a $LOG + return 1 + } + done + + IFS="$OLD_IFS" + return 0 +} + +test_conf_setparm_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf setparm >$DIR/setparm_usage_exp + log_print $NETCMD conf setparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "$RPC *conf setparm" $DIR/setparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delparm_delete_existing() +{ + echo '\nTesting conf delparm' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf addshare share1 /tmp "writeable=y" "guest_ok=n" \ + "test comment" + log_print $NETCMD conf addshare share$i /tmp "writeable=y" "guest_ok=n" \ + "test comment" + + $NETCMD conf delparm share1 "path" + log_print $NETCMD conf delparm share1 "path" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf showshare share1 >$DIR/delparm_showshare_out + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + #test to see what delparm did delete and how + grep "read only *= *no" $DIR/delparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: delparm did not delete correctly" | tee -a $LOG + return 1 + fi + + grep "path *= */tmp" $DIR/delparm_showshare_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delparm did not delete correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_delparm_delete_non_existing() +{ + echo '\nDelete non existing share' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf delparm share1 "path" + log_print $NETCMD conf delparm share1 "path" + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } +} + +test_conf_delparm_usage() +{ + + echo '\nChecking usage' >>$LOG + $NETCMD conf delparm >$DIR/delparm_usage_exp + log_print $NETCMD conf delparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delparm" $DIR/delparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: delparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi + +} + +test_conf_getparm() +{ + + echo '\nTesting conf getparm' >>$LOG + echo ------------------------- >>$LOG + echo -n '\n' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + $NETCMD conf addshare share1 /tmp/path_test "writeable=n" "guest_ok=n" \ + "test comment" + log_print $NETCMD conf addshare share$i /tmp/path_test "writeable=n" "guest_ok=n" \ + "test comment" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 "read only" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "read only" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 "read only" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "read only" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + echo yes >$DIR/getparm_exp + diff -q $DIR/getparm_out $DIR/getparm_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm did not print correctly" | tee -a $LOG + return 1 + fi + + $NETCMD conf getparm share1 "path" >$DIR/getparm_out + log_print $NETCMD conf getparm share1 "path" + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + echo /tmp/path_test >$DIR/getparm_exp + diff -q $DIR/getparm_out $DIR/getparm_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm did not print correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_getparm_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf getparm >$DIR/getparm_usage_exp + log_print $NETCMD conf getparm + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf getparm" $DIR/getparm_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getparm no/wrong usage message printed" | tee -a $LOG + return 1 + fi + +} + +test_conf_getparm_non_existing() +{ + echo '\nTesting getparm non existing' >>$LOG + $NETCMD conf getparm fictional_share fictional_param + log_print $NETCMD conf getparm fictional_share fictional_param + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + $NETCMD conf getparm share1 fictional_param + log_print $NETCMD conf getparm share1 fictional_param + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } +} + +test_conf_setincludes() +{ + echo '\nTesting conf setincludes' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf addshare tmp_share /tmp + log_print $NETCMD conf addshare tmp_share /tmp + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf setincludes tmp_share /tmp/include1 /tmp/include2 /tmp/include3 + log_print $NETCMD conf setincludes tmp_share /tmp/include1 /tmp/include2 /tmp/include3 + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/setincludes_list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include *= */tmp/include1$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include2$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include3$" $DIR/setincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: setincludes did not set correctly" | tee -a $LOG + return 1 + fi + +} + +test_conf_setincludes_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf setincludes >$DIR/setincludes_usage_exp + log_print $NETCMD conf setincludes + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf setincludes" $DIR/setincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_getincludes() +{ + $NETCMD conf getincludes tmp_share >$DIR/getincludes_out + log_print $NETCMD conf getincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include *= */tmp/include1$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi + + grep "include *= */tmp/include2$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi + grep "include *= */tmp/include3$" $DIR/getincludes_out >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: getincludes did not print correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_getincludes_usage() +{ + $NETCMD conf getincludes >$DIR/getincludes_usage_exp + log_print $NETCMD conf getincludes + + grep "$RPC *conf getincludes" $DIR/getincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_delincludes() +{ + echo '\nTesting conf delincludes' >>$LOG + echo ------------------------- >>$LOG + + $NETCMD conf delincludes tmp_share + log_print $NETCMD conf delincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/delincludes_list_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + grep "include" $DIR/delincludes_list_out >/dev/null 2>>$LOG + if [ "$?" = "0" ]; then + echo "ERROR: delincludes did not delete correctly" | tee -a $LOG + return 1 + fi +} + +test_conf_delincludes_empty() +{ + $NETCMD conf delincludes tmp_share + log_print $NETCMD conf delincludes tmp_share + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf delincludes fictional_share + log_print $NETCMD conf delincludes fictional_share + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + return 0 +} + +test_conf_delincludes_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf delincludes >$DIR/delincludes_usage_exp + log_print $NETCMD conf delincludes + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf delincludes" $DIR/delincludes_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +test_conf_import() +{ + echo '\nTesting conf import' >>$LOG + echo ------------------------- >>$LOG + echo '\nDropping existing configuration' >>$LOG + + $NETCMD conf drop + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf import $DIR/conf_import_in + log_print $NETCMD conf drop + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + $NETCMD conf list >$DIR/conf_import_out + log_print $NETCMD conf list + test "x$?" = "x0" || { + echo 'ERROR: RC does not match, expected: 0' | tee -a $LOG + return 1 + } + + diff -q $DIR/conf_import_in $DIR/conf_import_out >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: import failed" | tee -a $LOG + return 1 + fi +} + +test_conf_import_usage() +{ + echo '\nChecking usage' >>$LOG + $NETCMD conf import >$DIR/import_usage_exp + log_print $NETCMD conf import + test "x$?" = "x255" || { + echo 'ERROR: RC does not match, expected: 255' | tee -a $LOG + return 1 + } + + grep "$RPC *conf import" $DIR/import_usage_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf import no/wrong usage message printed" | tee -a $LOG + return 1 + fi +} + +CONF_FILES=$SERVERCONFFILE + +testit "conf_drop" \ + test_conf_drop || + failed=$(expr $failed + 1) + +testit "conf_drop_empty" \ + test_conf_drop_empty || + failed=$(expr $failed + 1) + +testit "conf_drop_usage" \ + test_conf_drop_usage || + failed=$(expr $failed + 1) + +testit "conf_addshare" \ + test_conf_addshare || + failed=$(expr $failed + 1) + +testit "conf_addshare_existing" \ + test_conf_addshare_existing || + failed=$(expr $failed + 1) + +testit "conf_addshare_usage" \ + test_conf_addshare_usage || + failed=$(expr $failed + 1) + +testit "conf_delshare" \ + test_conf_delshare || + failed=$(expr $failed + 1) + +testit "conf_delshare_empty" \ + test_conf_delshare_empty || + failed=$(expr $failed + 1) + +testit "conf_delshare_usage" \ + test_conf_delshare_usage || + failed=$(expr $failed + 1) + +testit "test_conf_showshare_case" \ + test_conf_showshare_case || + failed=$(expr $failed + 1) + +testit "conf_setparm" \ + test_conf_setparm || + failed=$(expr $failed + 1) + +testit "conf_setparm_existing" \ + test_conf_setparm_existing || + failed=$(expr $failed + 1) + +testit "conf_setparm_forbidden" \ + test_conf_setparm_forbidden || + failed=$(expr $failed + 1) + +testit "conf_setparm_usage" \ + test_conf_setparm_usage || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_existing" \ + test_conf_delparm_delete_existing || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_non_existing" \ + test_conf_delparm_delete_non_existing || + failed=$(expr $failed + 1) + +testit "conf_delparm_delete_usage" \ + test_conf_delparm_usage || + failed=$(expr $failed + 1) + +testit "conf_getparm" \ + test_conf_getparm || + failed=$(expr $failed + 1) + +testit "conf_getparm_usage" \ + test_conf_getparm_usage || + failed=$(expr $failed + 1) + +testit "conf_setincludes" \ + test_conf_setincludes || + failed=$(expr $failed + 1) + +testit "conf_setincludes_usage" \ + test_conf_setincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_getincludes" \ + test_conf_getincludes || + failed=$(expr $failed + 1) + +testit "conf_getincludes_usage" \ + test_conf_getincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_delincludes" \ + test_conf_delincludes || + failed=$(expr $failed + 1) + +testit "conf_delincludes_empty" \ + test_conf_delincludes_usage || + failed=$(expr $failed + 1) + +testit "conf_delincludes_usage" \ + test_conf_delincludes_empty || + failed=$(expr $failed + 1) + +testit "conf_import" \ + test_conf_import || + failed=$(expr $failed + 1) + +testit "conf_import_usage" \ + test_conf_import_usage || + failed=$(expr $failed + 1) + +if [ $failed -eq 0 ]; then + rm -r $DIR +fi + +testok $0 $failed diff --git a/source3/script/tests/test_net_cred_change.sh b/source3/script/tests/test_net_cred_change.sh new file mode 100755 index 0000000..7b01673 --- /dev/null +++ b/source3/script/tests/test_net_cred_change.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_net_cred_change.sh CONFIGURATION +EOF + exit 1 +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "1: change machine secret" $VALGRIND $BINDIR/wbinfo --change-secret || failed=$(expr $failed + 1) +testit "1: validate secret" $VALGRIND $BINDIR/net rpc testjoin "$@" || failed=$(expr $failed + 1) +testit "2: change machine secret" $VALGRIND $BINDIR/wbinfo --change-secret || failed=$(expr $failed + 1) +testit "2: validate secret" $VALGRIND $BINDIR/net rpc testjoin "$@" || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_cred_change_at.sh b/source3/script/tests/test_net_cred_change_at.sh new file mode 100755 index 0000000..47434bc --- /dev/null +++ b/source3/script/tests/test_net_cred_change_at.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: test_net_cred_change_at.sh CONFIGURATION +EOF + exit 1 +fi + +incdir=$(dirname "$0")/../../../testprogs/blackbox +# shellcheck source=/dev/null +. "$incdir/subunit.sh" + +test_change_machine_secret_at() { + local DC_SERVER + local REPL_TARGET + + out=$("$BINDIR/wbinfo" --dc-info SAMBADOMAIN) || return 1 + echo "$out" + echo "$out" | grep localdc && DC_SERVER=localvampiredc && REPL_TARGET=localdc + echo "$out" | grep localvampiredc && DC_SERVER=localdc && REPL_TARGET=localvampiredc + if [ -z $DC_SERVER ] ; then return 1 ; fi + + $VALGRIND "$BINDIR/wbinfo" --change-secret-at=$DC_SERVER || return 1 + + # Force replication + $VALGRIND "$BINDIR/samba-tool" drs replicate -U Administrator%locDCpass1 $REPL_TARGET $DC_SERVER DC=samba,DC=example,DC=com +} + +testit "change machine secret at" test_change_machine_secret_at || failed=$(("$failed" + 1)) +testit "validate secret" $VALGRIND "$BINDIR/net rpc testjoin" "$@" || failed=$(("$failed" + 1)) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_net_dom_join_fail_dc.sh b/source3/script/tests/test_net_dom_join_fail_dc.sh new file mode 100755 index 0000000..4367492 --- /dev/null +++ b/source3/script/tests/test_net_dom_join_fail_dc.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_net_dom_join_fail_dc.sh USERNAME PASSWORD DOMAIN PREFIX +EOF + exit 1 +fi + +DC_USERNAME="$1" +DC_PASSWORD="$2" +DOMAIN="$3" +PREFIX="$4" +shift 4 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +mkdir -p $PREFIX/private +testit_expect_failure "net_dom_join_fail_dc" $VALGRIND $BINDIR/net dom join domain=$DOMAIN account=$USERNAME password=$PASSWORD --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_lookup.sh b/source3/script/tests/test_net_lookup.sh new file mode 100755 index 0000000..ee18333 --- /dev/null +++ b/source3/script/tests/test_net_lookup.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +if [ $# != 6 ]; then + echo "Usage: $0 SERVER USERNAME PASSWORD NET SAMBA-TOOL DNS-ZONE" + exit 1 +fi + +SERVER="$1" +shift 1 +USERNAME="$1" +shift 1 +PASSWORD="$1" +shift 1 +NET="$1" +shift 1 +SAMBATOOL="$1" +shift 1 +DNSZONE="$1" +shift 1 + +SITE="mysite" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +$SAMBATOOL dns add "$SERVER" -U "$USERNAME"%"$PASSWORD" \ + _msdcs."$DNSZONE" _ldap._tcp."$SITE"._sites.dc \ + SRV "mydc.$DNSZONE 389 100 100" +$SAMBATOOL dns add "$SERVER" -U "$USERNAME"%"$PASSWORD" \ + "$DNSZONE" mydc \ + A "1.2.3.4" + +# global lookup +testit_grep global 10.53.57.30:389 $NET lookup ldap "$DNSZONE" || + failed=$(expr $failed + 1) + +# correct site-aware lookup +testit_grep site-aware 1.2.3.4:389 $NET lookup ldap "$DNSZONE" "$SITE" || + failed=$(expr $failed + 1) + +# lookup with nonexisting site -- global fallback +testit_grep global 10.53.57.30:389 $NET lookup ldap "$DNSZONE" nosite || + failed=$(expr $failed + 1) + +$SAMBATOOL dns delete "$SERVER" -U "$USERNAME"%"$PASSWORD" \ + "$DNSZONE" mydc \ + A "1.2.3.4" +$SAMBATOOL dns delete "$SERVER" -U "$USERNAME"%"$PASSWORD" \ + _msdcs."$DNSZONE" _ldap._tcp."$SITE"._sites.dc \ + SRV "mydc.$DNSZONE 389 100 100" + +testok $0 $failed diff --git a/source3/script/tests/test_net_machine_account.sh b/source3/script/tests/test_net_machine_account.sh new file mode 100755 index 0000000..ad1d099 --- /dev/null +++ b/source3/script/tests/test_net_machine_account.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Reproducer for https://bugzilla.samba.org/show_bug.cgi?id=14908 + +if [ $# -lt 2 ]; then + echo "Usage: $0 NET CONFFILE SERVER_IP" + exit 1 +fi + +NET="$1" +shift +CONFFILE="$1" +shift +SERVER_IP="$1" +shift + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +net_ads_user() { + _out=$(UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 \ + ${VALGRIND} "${NET}" rpc user \ + --configfile="${CONFFILE}" -S "${SERVER_IP}" -P) + _ret=$? + + echo "${_out}" + + return ${_ret} +} + +testit "net_ads_user" net_ads_user || failed=$((failed + 1)) + +testok $0 $failed diff --git a/source3/script/tests/test_net_misc.sh b/source3/script/tests/test_net_misc.sh new file mode 100755 index 0000000..3c2c01f --- /dev/null +++ b/source3/script/tests/test_net_misc.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# various tests for the "net" command + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_net_misc.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION +EOF + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" + +# optional protocol, default to NT1 +if [ $# -gt 4 ]; then + PROTOCOL="$5" +else + PROTOCOL="NT1" +fi + +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" +NETTIME="${NET} --option=clientmaxprotocol=${PROTOCOL} time" +NETLOOKUP="${NET} --option=clientmaxprotocol=${PROTOCOL} lookup" +NETSHARE="${NET} -U${USERNAME}%${PASSWORD} --option=clientmaxprotocol=${PROTOCOL} -S ${SERVER} share" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_time() +{ + PARAM="$1" + + ${NETTIME} -S ${SERVER} ${PARAM} +} + +test_lookup() +{ + PARAM="$1" + + ${NETLOOKUP} ${PARAM} +} + +test_share() +{ + PARAM="$1" + + ${NETSHARE} ${PARAM} +} + +testit "get the time" \ + test_time || + failed=$(expr $failed + 1) + +testit "get the system time" \ + test_time system || + failed=$(expr $failed + 1) + +testit "get the time zone" \ + test_time zone || + failed=$(expr $failed + 1) + +testit "lookup the PDC" \ + test_lookup pdc || + failed=$(expr $failed + 1) + +testit "lookup the master browser" \ + test_lookup master || + failed=$(expr $failed + 1) + +# This test attempts to lookup shares +testit "lookup share list" \ + test_share list || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry.sh b/source3/script/tests/test_net_registry.sh new file mode 100755 index 0000000..155533e --- /dev/null +++ b/source3/script/tests/test_net_registry.sh @@ -0,0 +1,411 @@ +#!/bin/sh +# +# Blackbox tests for the "net registry" and "net rpc registry" commands. +# +# Copyright (C) 2010-2011 Michael Adam <obnox@samba.org> +# Copyright (C) 2010 Gregor Beck <gbeck@sernet.de> +# +# rpc tests are chose by specifying "rpc" as commandline parameter. + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_net_registry.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION RPC +EOF + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" +RPC="$5" + +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" + +if test "x${RPC}" = "xrpc"; then + NETREG="${NET} -U${USERNAME}%${PASSWORD} -I ${SERVER_IP} rpc registry" +else + NETREG="${NET} registry" +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_enumerate() +{ + KEY="$1" + + ${NETREG} enumerate ${KEY} +} + +test_getsd() +{ + KEY="$1" + + ${NETREG} getsd ${KEY} +} + +test_enumerate_nonexisting() +{ + KEY="$1" + ${NETREG} enumerate ${KEY} + + if test "x$?" = "x0"; then + echo "ERROR: enumerate succeeded with key '${KEY}'" + false + else + true + fi +} + +test_enumerate_no_key() +{ + ${NETREG} enumerate + if test "x$?" = "x0"; then + echo "ERROR: enumerate succeeded without any key specified" + false + else + true + fi +} + +test_create_existing() +{ + KEY="HKLM" + EXPECTED="createkey opened existing ${KEY}" + + OUTPUT=$(${NETREG} createkey ${KEY}) + if test "x$?" = "x0"; then + if test "$OUTPUT" = "$EXPECTED"; then + true + else + echo "got '$OUTPUT', expected '$EXPECTED'" + false + fi + else + printf "%s\n" "$OUTPUT" + false + fi +} + +test_createkey() +{ + KEY="$1" + BASEKEY=$(dirname $KEY) + SUBKEY=$(basename $KEY) + + OUTPUT=$(${NETREG} createkey ${KEY}) + if test "x$?" != "x0"; then + echo "ERROR: createkey ${KEY} failed" + echo "output:" + printf "%s\n" "$OUTPUT" + false + return + fi + + # check enumerate of basekey lists new key: + OUTPUT=$(${NETREG} enumerate ${BASEKEY}) + if test "x$?" != "x0"; then + echo "ERROR: failed to enumerate key '${BASEKEY}'" + echo "output:" + printf "%s\n" "$OUTPUT" + false + return + fi + + EXPECTED="Keyname = ${SUBKEY}" + printf "%s\n" "$OUTPUT" | grep '^Keyname' | grep ${SUBKEY} + if test "x$?" != "x0"; then + echo "ERROR: did not find expected '$EXPECTED' in output" + echo "output:" + printf "%s\n" "$OUTPUT" + false + fi + + # check enumerate of new key works: + ${NETREG} enumerate ${KEY} +} + +test_deletekey() +{ + KEY="$1" + BASEKEY=$(dirname ${KEY}) + SUBKEY=$(basename ${KEY}) + + OUTPUT=$(test_createkey "${KEY}") + if test "x$?" != "x0"; then + printf "%s\n" "${OUTPUT}" + false + return + fi + + OUTPUT=$(${NETREG} deletekey ${KEY}) + if test "x$?" != "x0"; then + printf "%s\n" "${OUTPUT}" + false + return + fi + + # check enumerate of basekey does not show key anymore: + OUTPUT=$(${NETREG} enumerate ${BASEKEY}) + if test "x$?" != "x0"; then + printf "%s\n" "$OUTPUT" + false + return + fi + + UNEXPECTED="Keyname = ${SUBKEY}" + printf "%s\n" "$OUTPUT" | grep '^Keyname' | grep ${SUBKEY} + if test "x$?" = "x0"; then + echo "ERROR: found '$UNEXPECTED' after delete in output" + echo "output:" + printf "%s\n" "$OUTPUT" + false + fi + + # check enumerate of key itself does not work anymore: + ${NETREG} enumerate ${KEY} + if test "x$?" = "x0"; then + echo "ERROR: 'enumerate ${KEY}' works after 'deletekey ${KEY}'" + false + else + true + fi +} + +test_deletekey_nonexisting() +{ + KEY="$1" + + OUTPUT=$(test_deletekey "${KEY}") + if test "x$?" != "x0"; then + printf "%s\n" "${OUTPUT}" + false + return + fi + + ${NETREG} deletekey "${KEY}" + if test "x$?" = "x0"; then + echo "ERROR: delete after delete succeeded for key '${KEY}'" + false + fi +} + +test_createkey_with_subkey() +{ + KEY="$1" + KEY2=$(dirname ${KEY}) + SUBKEYNAME2=$(basename ${KEY}) + BASENAME=$(dirname ${KEY2}) + SUBKEYNAME1=$(basename ${KEY2}) + + OUTPUT=$(${NETREG} createkey ${KEY}) + if test "x$?" != "x0"; then + echo "ERROR: createkey ${KEY} failed" + printf "%s\n" "${OUTPUT}" + false + return + fi + + # check we can enumerate to level key + OUTPUT=$(${NETREG} enumerate ${KEY}) + if test "x$?" != "x0"; then + echo "ERROR: failed to enumerate '${KEY}' after creation" + printf "%s\n" "${OUTPUT}" + false + return + fi + + # clear: + ${NETREG} deletekey ${KEY} && ${NETREG} deletekey ${KEY2} +} + +test_deletekey_with_subkey() +{ + KEY="$1" + KEY2=$(dirname ${KEY}) + + OUTPUT=$(${NETREG} createkey ${KEY}) + if test "x$?" != "x0"; then + printf "%s\n" "${OUTPUT}" + false + return + fi + + OUTPUT=$(${NETREG} deletekey ${KEY2}) + + if test "x$?" = "x0"; then + echo "ERROR: delete of key with subkey succeeded" + echo "output:" + printf "%s\n" "$OUTPUT" + false + return + fi + + ${NETREG} deletekey ${KEY} && ${NETREG} deletekey ${KEY2} +} + +test_setvalue() +{ + KEY="$1" + VALNAME="${2#_}" + VALTYPE="$3" + VALVALUE="$4" + + OUTPUT=$(test_createkey ${KEY}) + if test "x$?" != "x0"; then + printf "%s\n" "${OUTPUT}" + false + return + fi + + OUTPUT=$(${NETREG} setvalue ${KEY} "${VALNAME}" ${VALTYPE} ${VALVALUE}) + if test "x$?" != "x0"; then + echo "ERROR: failed to set value testval in key ${KEY}" + printf "%s\n" "${OUTPUT}" + false + return + fi + + OUTPUT=$(${NETREG} getvalueraw ${KEY} "${VALNAME}") + if test "x$?" != "x0"; then + echo "ERROR: failure calling getvalueraw for key ${KEY}" + echo output: + printf "%s\n" "${OUTPUT}" + false + return + fi + + if test "x${OUTPUT}" != "x${VALVALUE}"; then + echo "ERROR: failure retrieving value ${VALNAME} for key ${KEY}" + printf "expected: %s\ngot: %s\n" "${VALVALUE}" "${OUTPUT}" + false + return + fi + +} + +test_deletevalue() +{ + KEY="$1" + VALNAME="${2#_}" + + ${NETREG} deletevalue ${KEY} "${VALNAME}" +} + +test_deletevalue_nonexisting() +{ + KEY="$1" + VALNAME="${2#_}" + + ${NETREG} deletevalue ${KEY} "${VALNAME}" + if test "x$?" = "x0"; then + echo "ERROR: succeeded deleting value ${VALNAME}" + false + else + true + fi +} + +test_setvalue_twice() +{ + KEY="$1" + VALNAME="${2#_}" + VALTYPE1="$3" + VALVALUE1="$4" + VALTYPE2="$5" + VALVALUE2="$6" + + OUTPUT=$(test_setvalue ${KEY} _"${VALNAME}" ${VALTYPE1} ${VALVALUE1}) + if test "x$?" != "x0"; then + echo "ERROR: first setvalue call failed" + printf "%s\n" "$OUTPUT" + false + return + fi + + ${NETREG} setvalue ${KEY} "${VALNAME}" ${VALTYPE2} ${VALVALUE2} +} + +testit "enumerate HKLM" \ + test_enumerate HKLM || + failed=$(expr $failed + 1) + +testit "enumerate nonexisting hive" \ + test_enumerate_nonexisting XYZ || + failed=$(expr $failed + 1) + +testit "enumerate without key" \ + test_enumerate_no_key || + failed=$(expr $failed + 1) + +# skip getsd test for registry currently: it fails +if test "x${RPC}" != "xrpc"; then + testit "getsd HKLM" \ + test_getsd HKLM || + failed=$(expr $failed + 1) +fi + +testit "create existing HKLM" \ + test_create_existing || + failed=$(expr $failed + 1) + +testit "create key" \ + test_createkey HKLM/testkey || + failed=$(expr $failed + 1) + +testit "delete key" \ + test_deletekey HKLM/testkey || + failed=$(expr $failed + 1) + +testit "delete^2 key" \ + test_deletekey_nonexisting HKLM/testkey || + failed=$(expr $failed + 1) + +testit "enumerate nonexisting key" \ + test_enumerate_nonexisting HKLM/testkey || + failed=$(expr $failed + 1) + +testit "create key with subkey" \ + test_createkey_with_subkey HKLM/testkey/subkey || + failed=$(expr $failed + 1) + +testit "delete key with subkey" \ + test_deletekey_with_subkey HKLM/testkey/subkey || + failed=$(expr $failed + 1) + +testit "set value" \ + test_setvalue HKLM/testkey _testval sz moin || + failed=$(expr $failed + 1) + +testit "delete value" \ + test_deletevalue HKLM/testkey _testval || + failed=$(expr $failed + 1) + +testit "delete nonexisting value" \ + test_deletevalue_nonexisting HKLM/testkey _testval || + failed=$(expr $failed + 1) + +testit "set value to different type" \ + test_setvalue_twice HKLM/testkey testval sz moin dword 42 || + failed=$(expr $failed + 1) + +testit "set default value" \ + test_setvalue HKLM/testkey _"" sz 42 || + failed=$(expr $failed + 1) + +testit "delete default value" \ + test_deletevalue HKLM/testkey _"" || + failed=$(expr $failed + 1) + +testit "delete nonexisting default value" \ + test_deletevalue_nonexisting HKLM/testkey _"" || + failed=$(expr $failed + 1) + +testit "delete key with value" \ + test_deletekey HKLM/testkey || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry_check.sh b/source3/script/tests/test_net_registry_check.sh new file mode 100755 index 0000000..cb0ca17 --- /dev/null +++ b/source3/script/tests/test_net_registry_check.sh @@ -0,0 +1,145 @@ +#!/bin/sh +# +# Blackbox tests for the "net registry check" command. +# +# Copyright (C) 2011 Björn Baumbach <bb@sernet.de> + +if [ $# -lt 5 ]; then + echo "Usage: test_net_registry_check.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION DBWRAP_TOOL" + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" +DBWRAP_TOOL="$5 --persistent" + +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" + +NETREG="${NET} registry" +REGORIG="$(grep 'state directory = ' $SERVERCONFFILE | sed 's/[^=]*=//')/registry.tdb" +REG=$REGORIG.wip + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# run registry check and filter allowed errors +regcheck() +{ + ALLOWEDERR="Check database:|INFO: version =" + ERRSTR=$(${NETREG} check $REG "$@" 2>&1 | egrep -v "$ALLOWEDERR") +} + +# try to repair registry +regrepair() +{ + regcheck -a +} + +# check if $ERRSTR contains expected error +checkerr() +{ + EXPERR=$1 + + ERRCNT=$(echo "$ERRSTR" | grep "$EXPERR" | wc -l) + return $ERRCNT +} + +regchecknrepair() +{ + EXPERR="$1" + EXPERRCNT="$2" + + regcheck + checkerr "$EXPERR" + test "$?" -eq "$ERRCNT" || { + echo "Expected $EXPERRCNT of error $EXPERR. Received $ERRCNT" + return 1 + } + + regrepair + regcheck + test "x$ERRSTR" = "x" || { + echo "Error: Can't repair database" + return 1 + } +} + +test_simple() +( + ERRSTR="" + cp $REGORIG $REG + + regcheck + test "x$ERRSTR" = "x" || { + echo $ERRSTR + return 1 + } +) + +test_damage() +{ + diff $REGORIG $REG +} + +test_duplicate() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM/SOFTWARE' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Duplicate subkeylist" 1 +) + +test_slashes() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM/SOFTWARE' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Unnormal key:" 1 +) + +test_uppercase() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM\Software' hex '02000000534F4654574152450053595354454D00' + + regchecknrepair "Unnormal key:" 1 +) + +test_strangeletters() +( + ERRSTR="" + $DBWRAP_TOOL $REG store 'HKLM\SOFTWARE' hex '02000000534F4654574FABFABFABFAB354454D00' + + regchecknrepair "Conversion error: Incomplete multibyte sequence" 1 +) + +testit "simple" \ + test_simple || + failed=$(expr $failed + 1) + +testit "damages_registry" \ + test_damage || + failed=$(expr $failed + 1) + +testit "duplicate" \ + test_duplicate || + failed=$(expr $failed + 1) + +testit "slashes" \ + test_slashes || + failed=$(expr $failed + 1) + +testit "uppercase" \ + test_uppercase || + failed=$(expr $failed + 1) + +#Can't repair this atm +#testit "strangeletters" \ +# test_strangeletters || \ +# failed=`expr $failed + 1` + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry_import.sh b/source3/script/tests/test_net_registry_import.sh new file mode 100755 index 0000000..cca566f --- /dev/null +++ b/source3/script/tests/test_net_registry_import.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_net_registry_import.sh SERVER LOCAL_PATH USERNAME PASSWORD +EOF + exit 1 +fi + +SERVER="$1" +LOCAL_PATH="$2" +USERNAME="$3" +PASSWORD="$4" +shift 4 +ADDARGS="$@" + +failed=0 + +samba_net="$BINDIR/net" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +test_net_registry_import() +{ + + # + # Expect: + # Found Byte Order Mark for : UTF-16LE + # + cmd='$VALGRIND $samba_net rpc registry import $LOCAL_PATH/case3b45ccc3b.dat -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS' + + eval echo "$cmd" + out=$(eval $cmd 2>&1) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'Found Byte Order Mark for : UTF-16LE' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/case3b45ccc3b.dat failed - should get 'Found Byte Order Mark for : UTF-16LE'" + false + return + fi + + # + # Expect: + # reg_parse_fd: smb_iconv error in file at line 0: <bf><77><d4><41> + # + cmd='$VALGRIND $samba_net rpc registry import $LOCAL_PATH/casecbe8c2427.dat -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS' + + eval echo "$cmd" + out=$(eval $cmd 2>&1) + ret=$? + + if [ $? != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'reg_parse_fd: smb_iconv error in file at line 0: <bf><77><d4><41>' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/case3b45ccc3b.dat failed - should get 'reg_parse_fd: smb_iconv error in file at line 0: <bf><77><d4><41>'" + false + return + fi + + # + # For test3.dat, the parse of the first part of the file is successful, + # but fails on upload as we're writing to an unwriteable registry. + # Expect: + # setval ProductType failed: WERR_REGISTRY_IO_FAILED + # reg_parse_fd: reg_parse_line line 21 fail -2 + # This counts as a success test as the file is parsed, but + # the upload failed. + # + cmd='$VALGRIND $samba_net rpc registry import $LOCAL_PATH/regtest3.dat -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS' + + eval echo "$cmd" + out=$(eval $cmd 2>&1) + ret=$? + + if [ $? != 0 ]; then + echo "$out" + echo "command failed with output $ret" + false + return + fi + + echo "$out" | grep 'setval ProductType failed: WERR_REGISTRY_IO_FAILED' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/regtest3.dat failed - should get 'setval ProductType failed: WERR_REGISTRY_IO_FAILED'" + false + return + fi + + echo "$out" | grep 'reg_parse_fd: reg_parse_line 20 fail -2' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "$samba_net rpc registry import $LOCAL_PATH/regtest3.dat failed - should get 'reg_parse_fd: reg_parse_line 20 fail -2'" + false + return + fi + + true + return +} + +########################################################### +# Check net rpc registry import doesn't crash +########################################################### + +rm -f $LOCAL_PATH/case3b45ccc3b.dat +rm -f $LOCAL_PATH/casecbe8c2427.dat +rm -f $LOCAL_PATH/regtest3.dat + +# Create test cases + +base64 -d <<'EOF' | gunzip -c >$LOCAL_PATH/case3b45ccc3b.dat +H4sIAODLjlwCA/v/L5whkyGPIYUhn6GcoZhBgSGIIZUhHShWzFDCUMRQCRRxBcpmAnn5QL4CQxhQ +vggomwnk5wH5pgx6DAZAyMvABcbRDB4M3kA9kQzxDD4M/gzODI5AOp7BF0g7A+U8GfyAsjEMwUAV +wQwhQLYvkOfMUPqRUvDw4yAHnz6OgsELgGlYh8EYCHXA6RnENmLIgbJNGZLh4jEMvEWRee8eXl8u +//f8N9vK5cVVXP9v2rB+/qYw+3xko5Su8jSiLZ0zwJ4GAO4s/cYABAAA +EOF + +base64 -d <<'EOF' | gunzip -c >$LOCAL_PATH/casecbe8c2427.dat +H4sIALjPjlwCA2NwZfBliGFwZihlKALCVIY8hhIgLx9MFwHpHIZgoGgJUA2ILmIoY8hkSAayioEi +OQyJQHW5YLIcqLaIIRsoXgLklwBVgcyIYSgA8oqAOBdsCsiEYoZYBl4GLgYlsG2JDElAc1KB6kCm +ZYLtTWWoAJIgncVACDE5BajeFkjCeFYMBijQEIuZxUCcDPZZJkNJ3f7yK45/V3S8epR2I14uf+4W +ee+dz0RXshv4SHxzff2XJYbx0pWaEs+ul5XKF9hlFIu4RG73Lf3rOXHW3NxpuvVnE9Xk7zxv2p3I +tlLtWjY/i1HIGhdpLy/Gub9nH5jLd/rqdYfv2uumzgq7PIldPY3Labru/65Q/nLJh1oBk/0tT2v2 +eUdbzFg0NfPmamFH421aJxMPhnr7X+y0iRdSX+ex+IJ0Yaf0ahV5440Wj7cbK/jkbSjcNdvpR+WN +/5Knnn8PjvvD9O/Ws4pXUqG3lbdFrf1846zzcTOFW8yhB3QNZRP6TjOsu1rDvIaHZVfMyYd1Mhev +ik/a5m36Y85+y63pPmtXb8nOU5Zd0qK0yVJK8a27WqKHSOKaS7wpwULu1TsM94bVGD3xviR0u1Il +rFHoxeUrm2+6Ke4x2SGitD912ZGfLcmG0xiyIn+bmx0+s+dbXuT8xfl+CgL168yNzYxCgsviz/46 +b7746Wnh8zXZHDof6/yDyxdf31JkzN5YVP4kf/vkvrS1ioauYemc3RIt7znZQvpOy7XO8VU5+KeP +VXKPXrzr+nMv/v5wkpA7v2TukgqHZ4e6i+Zsjfny6vHdg7+mLFjg/th4m55ppH75HYcLjEa/U4/w +SeXMTuVXablo/fmJnlPA6T12usz8nBGVKbVzTNqrTJ6d/+Y0y2bGc5MlzgnymUVq/9/PyZ2QxZvR +4WyR810zd32X5ncJRd/y7VNCd746G/jTTFLTJfHx86dVtlkL02zeCJeYsmkdrXVhtpl7Y5OOyJcD +DJXA9JPJkA5MT8YMOuA0psNgBExRMLYZgwkSOxnM1kdiG6CQkNTpD0zXGeBc4AJMx7nQFF8MTttA +8f8VDBoM5gya4NRNtgN0zczNjM1MDCwMLcwMTCwtLYxNjLE4wK5pwpebAAJ05DUABAAA +EOF + +base64 -d <<'EOF' >$LOCAL_PATH/regtest3.dat +UkVHRURJVDQKCltIS0VZX0xPQ0FMX01BQ0hJTkVdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNPRlRX +QVJFXQoKW0hLRVlfTE9DQUxfTUFDSElORVxTT0ZUV0FSRVxNaWNyb3NvZnRdCgpbSEtFWV9MT0NB +TF9NQUNISU5FXFNPRlRXQVJFXE1pY3Jvc29mdFxXaW5kb3dzIE5UXQoKW0hLRVlfTE9DQUxfTUFD +SElORVxTT0ZUV0FSRVxNaWNyb3NvZnRcV2luZG93cyBOVFxDdXJyZW50VmVyc2lvbl0KIkN1cnJl +bnRWZXJzaW9uIj0iNi4xIgoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1dCgpbSEtFWV9MT0NB +TF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29udHJvbFNldF0KCltIS0VZX0xPQ0FMX01BQ0hJTkVc +U1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XENvbnRyb2xdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNZ +U1RFTVxDdXJyZW50Q29udHJvbFNldFxDb250cm9sXFByb2R1Y3RPcHRpb25zXQoiUHJvZHVjdFR5 +cGUiPSJMYW5tYW5OVCIKCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9s +U2V0XENvbnRyb2xcUHJpbnRdCgpbSEtFWV9MT0NBTF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29u +dHJvbFNldFxDb250cm9sXFRlcm1pbmFsIFNlcnZlcl0KCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lT +VEVNXQoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRdCgpbSEtF +WV9MT0NBTF9NQUNISU5FXFNZU1RFTVxDdXJyZW50Q29udHJvbFNldFxTZXJ2aWNlc10KCltIS0VZ +X0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XFNlcnZpY2VzXE5ldGxvZ29u +XQoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRcU2VydmljZXNc +TmV0bG9nb25cUGFyYW1ldGVyc10KIlJlZnVzZVBhc3N3b3JkQ2hhbmdlIj1kd29yZDowMDAwMDAw +MAoKW0hLRVlfTE9DQUxfTUFDSElORVxTWVNURU1cQ3VycmVudENvbnRyb2xTZXRcU2VydmljZXNc +QWxlcnRlcl0KCltIS0VZX0xPQ0FMX01BQ0hJTkVcU1lTVEVNXEN1cnJlbnRDb250cm9sU2V0XA== +EOF + +testit "Test net rpc registry import" \ + test_net_registry_import || + failed=$(expr $failed + 1) + +# Clean up test cases. +rm -f $LOCAL_PATH/case3b45ccc3b.dat +rm -f $LOCAL_PATH/casecbe8c2427.dat +rm -f $LOCAL_PATH/regtest3.dat + +testok $0 $failed diff --git a/source3/script/tests/test_net_registry_roundtrip.sh b/source3/script/tests/test_net_registry_roundtrip.sh new file mode 100755 index 0000000..e1974c2 --- /dev/null +++ b/source3/script/tests/test_net_registry_roundtrip.sh @@ -0,0 +1,158 @@ +#!/bin/sh +# +# Blackbox test for net conf/registry roundtrips. +# +# Copyright (C) 2010 Gregor Beck <gbeck@sernet.de> +# Copyright (C) 2011 Michael Adam <obnox@samba.org> + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_net_registry_roundtrip.sh SCRIPTDIR SERVERCONFFILE NET CONFIGURATION RPC +EOF + exit 1 +fi + +SCRIPTDIR="$1" +SERVERCONFFILE="$2" +NET="$3" +CONFIGURATION="$4" +RPC="$5" + +NET="$VALGRIND ${NET} $CONFIGURATION" + +if test "x${RPC}" = "xrpc"; then + NETCMD="${NET} -U${USERNAME}%${PASSWORD} -I ${SERVER_IP} rpc" +else + NETCMD="${NET}" +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# +# List of parameters to skip when importing configuration files: +# They are forbidden in the registry and would lead import to fail. +# +SED_INVALID_PARAMS="{ +s/state directory/;&/g +s/lock directory/;&/g +s/lock dir/;&/g +s/config backend/;&/g +s/include/;&/g +}" + +REGPATH="HKLM\Software\Samba" + +conf_roundtrip_step() +{ + echo "CMD: $*" >>$LOG + "$@" 2>>$LOG + RC=$? + echo "RC: $RC" >>$LOG + test "x$RC" = "x0" || { + echo "ERROR: $* failed (RC=$RC)" | tee -a $LOG + } + return $RC + # echo -n . +} + +LOGDIR_PREFIX="conf_roundtrip" + +conf_roundtrip() +( + DIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX) + LOG=$DIR/log + + echo conf_roundtrip $1 >$LOG + + sed -e "$SED_INVALID_PARAMS" $1 >$DIR/conf_in + + conf_roundtrip_step $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + test -z "$($NETCMD conf list)" 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf drop failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD conf import $DIR/conf_in + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf list >$DIR/conf_exp + test "x$?" = "x0" || { + return 1 + } + + grep "\[global\]" $DIR/conf_exp >/dev/null 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf import => conf export failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD -d10 registry export $REGPATH $DIR/conf_exp.reg + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf drop + test "x$?" = "x0" || { + return 1 + } + + test -z "$($NETCMD conf list)" 2>>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: conf drop failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD registry import $DIR/conf_exp.reg + test "x$?" = "x0" || { + return 1 + } + + conf_roundtrip_step $NETCMD conf list >$DIR/conf_out + test "x$?" = "x0" || { + return 1 + } + + diff -q $DIR/conf_out $DIR/conf_exp >>$LOG + if [ "$?" = "1" ]; then + echo "ERROR: registry import => conf export failed" | tee -a $LOG + return 1 + fi + + conf_roundtrip_step $NETCMD registry export $REGPATH $DIR/conf_out.reg + test "x$?" = "x0" || { + return 1 + } + + diff -q $DIR/conf_out.reg $DIR/conf_exp.reg >>$LOG + if [ "$?" = "1" ]; then + echo "Error: registry import => registry export failed" | tee -a $LOG + return 1 + fi + rm -r $DIR +) + +CONF_FILES=$SERVERCONFFILE + +# remove old logs: +for OLDDIR in $(find ${PREFIX} -type d -name "${LOGDIR_PREFIX}_*"); do + echo "removing old directory ${OLDDIR}" + rm -rf ${OLDDIR} +done + +for conf_file in $CONF_FILES; do + testit "conf_roundtrip $conf_file" \ + conf_roundtrip $conf_file || + failed=$(expr $failed + 1) +done + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_join.sh b/source3/script/tests/test_net_rpc_join.sh new file mode 100755 index 0000000..319d044 --- /dev/null +++ b/source3/script/tests/test_net_rpc_join.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_net_rpc_join.sh USERNAME PASSWORD SERVER PREFIX +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +PREFIX="$4" +shift 4 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +mkdir -p $PREFIX/private +testit "net_rpc_join" $VALGRIND $BINDIR/net rpc join -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private -U$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_changetrustpw" $VALGRIND $BINDIR/net rpc changetrustpw -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin2" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_join_creds.sh b/source3/script/tests/test_net_rpc_join_creds.sh new file mode 100755 index 0000000..24376ef --- /dev/null +++ b/source3/script/tests/test_net_rpc_join_creds.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_net_rpc_join_creds.sh DOMAIN USERNAME PASSWORD SERVER PREFIX +EOF + exit 1 +fi + +DOMAIN="$1" +USERNAME="$2" +PASSWORD="$3" +SERVER="$4" +PREFIX="$5" +shift 5 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +mkdir -p $PREFIX/private +# Test using a credentials file. +credsfile=$PREFIX/creds.$$ +printf '%s\n' "username=$USERNAME" "password=$PASSWORD" "domain=$DOMAIN" >"$credsfile" +testit "net_rpc_join_creds" $VALGRIND $BINDIR/net rpc join -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private -A"$credsfile" $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin_creds" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_changetrustpw_creds" $VALGRIND $BINDIR/net rpc changetrustpw -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin2_creds" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER --option=netbiosname=netrpcjointest --option=domainlogons=yes --option=privatedir=$PREFIX/private $ADDARGS || failed=$(expr $failed + 1) +rm -f $credsfile + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_oldjoin.sh b/source3/script/tests/test_net_rpc_oldjoin.sh new file mode 100755 index 0000000..d650ead --- /dev/null +++ b/source3/script/tests/test_net_rpc_oldjoin.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_net_rpc_oldjoin.sh SERVER PREFIX SMB_CONF_PATH +EOF + exit 1 +fi + +SERVER="$1" +PREFIX="$2" +SMB_CONF_PATH="$3" +shift 3 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +maccount="OLDJOINTEST" +privatedir="$PREFIX/private" + +OPTIONS="--configfile $SMB_CONF_PATH --option=netbiosname=$maccount --option=security=domain --option=domainlogons=no --option=privatedir=$privatedir" + +test_smbpasswd() +{ + account=$1 + + echo "set password with smbpasswd" + + cmd='UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $VALGRIND $BINDIR/smbpasswd -L -c $SMB_CONF_PATH -a -m "$account"' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to change user password $user" + return 1 + fi +} + +testit "mkdir -p $privatedir" mkdir -p $privatedir || failed=$(expr $failed + 1) +testit "smbpasswd -a -m" \ + test_smbpasswd $maccount || + failed=$(expr $failed + 1) +testit "net_rpc_oldjoin" $VALGRIND $BINDIR/net rpc oldjoin -S $SERVER $OPTIONS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin1" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER $OPTIONS || failed=$(expr $failed + 1) +testit "net_rpc_changetrustpw" $VALGRIND $BINDIR/net rpc changetrustpw -S $SERVER $OPTIONS || failed=$(expr $failed + 1) +testit "net_rpc_testjoin2" $VALGRIND $BINDIR/net rpc testjoin -S $SERVER $OPTIONS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_share_allowedusers.sh b/source3/script/tests/test_net_rpc_share_allowedusers.sh new file mode 100755 index 0000000..3365813 --- /dev/null +++ b/source3/script/tests/test_net_rpc_share_allowedusers.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_net_rpc_share_allowedusers.sh SERVER USERNAME PASSWORD PREFIX +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +PREFIX="$4" +shift 4 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +mkdir -p $PREFIX/private +net=$BINDIR/net +# Check for the SID for group "Everyone" as a basic test things are working. +testit_grep "net_usersidlist" '^ S-1-1-0$' $VALGRIND $net usersidlist $ADDARGS || failed=$(expr $failed + 1) +# Check "print$" share is listed by default. +testit_grep "net_rpc_share_allowedusers" '^print\$$' $net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +# Check "print$" share is listed if we ask for it. +testit_grep "net_rpc_share_allowedusers" '^print\$$' $net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS - 'print$' || failed=$(expr $failed + 1) +# Check user "user1" is allowed to read share "tmp". +testit_grep "net_rpc_share_allowedusers" '^ user1$' $net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +# +# Subtle extra test for bug https://bugzilla.samba.org/show_bug.cgi?id=13992 +# +# '^ user1$' must appear MORE THAN ONCE, as it can read more than one +# share. The previous test found user1, but only once as the bug only +# allows reading the security descriptor for one share, and we were +# unlucky that the first share security descriptor returned allows +# user1 to read from it. +# +subunit_start_test "net_rpc_share_allowedusers" +multi_userout=$($net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS) +num_matches=$(echo "$multi_userout" | grep -c '^ user1$') +if [ "$num_matches" -gt "1" ]; then + subunit_pass_test "net_rpc_share_allowedusers" +else + echo "net_rpc_share_allowedusers only found $num_matches shares readable by user1. Should be greater than one.\n" + failed=$(expr $failed + 1) + echo "$multi_userout" | subunit_fail_test "net_rpc_share_allowedusers" +fi + +testok $0 $failed diff --git a/source3/script/tests/test_net_tdb.sh b/source3/script/tests/test_net_tdb.sh new file mode 100755 index 0000000..abc8786 --- /dev/null +++ b/source3/script/tests/test_net_tdb.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# +# Test 'net tdb' command. +# +# Verify that the command returns the correct information in the +# expected format. The 'dump' option is tested, but the output is not +# checked, since the internal data structure could change in the +# future. +# +# Copyright (C) 2017 Christof Schmitt + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: $0 SMBCLIENT SERVER SHARE USER PASS CONFIGURATION LOCALPATH LOCKDIR +EOF + exit 1 +fi + +SMBCLIENT=$1 +SERVER=$2 +SHARE=$3 +USER=$4 +PASS=$5 +CONFIGURATION=$6 +LOCALPATH=$7 +LOCKDIR=$8 + +FILENAME=net_tdb_testfile + +samba_tdbtool=tdbtool +if test -x $BINDIR/tdbtool; then + samba_tdbtool=$BINDIR/tdbtool +fi + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +touch $LOCALPATH/$FILENAME + +printf "open %s\n"'!sleep 10'"\n" ${FILENAME} | + $SMBCLIENT //$SERVER/$SHARE -U$USER%$PASS & +SMBCLIENTPID=$! + +# Give smbclient a chance to open the file +sleep 1 + +testit "Looking for record key of open file" \ + $samba_tdbtool $LOCKDIR/locking.tdb hexkeys || + failed=$(expr $failed + 1) + +# The assumption here is that only one file is open, so only one +# record can exist in the database. + +# Output of 'tdbtool hexkeys' is in this format: +#[000] 01 FD 00 00 00 00 00 00 56 02 5C 00 00 00 00 00 ....... V.\.... +#[010] 00 00 00 00 00 00 00 00 ....... +# Select only the hex data, remove space and join every thing together +key=0x$($samba_tdbtool $LOCKDIR/locking.tdb hexkeys | + grep '\[' | cut -c 7-56 | sed -e 's/ //g' | tr -d '\n') + +testit "Looking for open file in locking.tdb" \ + $BINDIR/net $CONFIGURATION tdb locking $key || + failed=$(expr $failed + 1) +out=$($BINDIR/net $CONFIGURATION tdb locking $key) + +out=$($BINDIR/net $CONFIGURATION tdb locking $key | + grep 'Share path: ' | sed -e 's/Share path: \+//') +testit "Verify pathname in output" \ + test "$out" = "$LOCALPATH" || + failed=$(expr $failed + 1) + +out=$($BINDIR/net $CONFIGURATION tdb locking $key | + grep 'Name:' | sed -e 's/Name: \+//') +testit "Verify filename in output" \ + test "$out" = "$FILENAME" || + failed=$(expr $failed + 1) + +out=$($BINDIR/net $CONFIGURATION tdb locking $key | + grep 'Number of share modes:' | + sed -e 's/Number of share modes: \+//') +testit "Verify number of share modes in output" \ + test "$out" = "1" || + failed=$(expr $failed + 1) + +testit "Complete record dump" \ + $BINDIR/net $CONFIGURATION tdb locking $key dump || + failed=$(expr $failed + 1) + +$BINDIR/net $CONFIGURATION tdb locking $key dump | grep -q $FILENAME +RC=$? +testit "Verify filename in dump output" \ + test $RC = 0 || + failed=$(expr $failed + 1) +$BINDIR/net $CONFIGURATION tdb locking $key dump | grep -q $LOCALPATH +RC=$? +testit "Verify share path in dump output" \ + test $RC = 0 || + failed=$(expr $failed + 1) + +kill $SMBCLIENTPID + +testok $0 $failed diff --git a/source3/script/tests/test_net_usershare.sh b/source3/script/tests/test_net_usershare.sh new file mode 100755 index 0000000..bf6334d --- /dev/null +++ b/source3/script/tests/test_net_usershare.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_net_usershare.sh SERVER SERVER_IP DOMAIN USERNAME PASSWORD SMBCLIENT <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +shift 5 +ADDARGS="$@" + +failed=0 + +samba_bindir="$BINDIR" +samba_net="$samba_bindir/net" +samba_smbcontrol="$samba_bindir/smbcontrol" + +samba_share_dir="$LOCAL_PATH" +samba_usershare_dir="$samba_share_dir/usershares" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +test_smbclient() +{ + name="$1" + share="$2" + cmd="$3" + shift 3 + echo "test: $name" + $VALGRIND $smbclient $CONFIGURATION //$SERVER/$share -c "$cmd" "$@" + status=$? + if [ x$status = x0 ]; then + echo "success: $name" + else + echo "failure: $name" + fi + return $status +} + +test_net_usershare() +{ + name="$1" + cmd="$2" + shift + shift + echo "test: $name" + $VALGRIND $samba_net usershare "$cmd" "$@" + status=$? + if [ x$status = x0 ]; then + echo "success: $name" + else + echo "failure: $name" + fi + return $status +} + +########################################################### +# Check if we can add and delete a usershare +########################################################### + +samba_usershare_name="test_usershare_1" +samba_usershare_path="$samba_usershare_dir/$samba_usershare_name" + +testit "create usershare dir for $samba_usershare_name" mkdir --mode=0755 --verbose $samba_usershare_path || failed=$(expr $failed + 1) + +test_net_usershare "net usershare add $samba_usershare_name" "add" "$samba_usershare_name" "$samba_usershare_path" "$samba_usershare_name" + +test_net_usershare "net usershare info $samba_usershare_name" "info" "$samba_usershare_name" + +test_smbclient "smbclient to $samba_usershare_name" "$samba_usershare_name" 'ls' -U$USERNAME%$PASSWORD || failed=$(expr $failed + 1) + +# CLEANUP +test_net_usershare "net usershare delete $samba_usershare_name" "delete" "$samba_usershare_name" +testit "remove usershare dir for $samba_usershare_name" rm -rf $samba_usershare_path || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_netfileenum.sh b/source3/script/tests/test_netfileenum.sh new file mode 100755 index 0000000..d343555 --- /dev/null +++ b/source3/script/tests/test_netfileenum.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# +# Test rpcclient netfileenum +# +# Copyright (C) 2020 Volker Lendecke + +if [ $# -lt 5 ]; then + echo Usage: $0 \ + SMBCLIENT RPCCLIENT NET SERVER SHARE + exit 1 +fi + +SMBCLIENT="$1" +shift 1 +RPCCLIENT="$1" +shift 1 +NET="$1" +shift 1 +SERVER="$1" +shift 1 +SHARE="$1" +shift 1 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +# consume the smbclient startup messages +head -n 1 <&101 + +FILE=x64 + +printf "open %s\\n" "$FILE" >&100 + +sleep 1 + +testit "Create builtin\\administrators group" \ + "${NET}" groupmap add \ + sid=S-1-5-32-544 unixgroup="${USER}"-group type=builtin || + failed=$((failed + 1)) +testit "Add ${USER} to builtin\\administrators" \ + "${NET}" groupmap addmem S-1-5-32-544 \ + $("${NET}" lookup name "${USER}" | cut -d' ' -f1) || + failed=$((failed + 1)) + +"${RPCCLIENT}" "${SERVER}" -U"${USER}"%"${PASSWORD}" -c netfileenum | + grep "$FILE"\$ +RC=$? +testit "netfileenum" test $RC = 0 || failed=$((failed + 1)) + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testit "Remove ${USER} from builtin\\administrators" \ + "${NET}" groupmap delmem S-1-5-32-544 \ + $("${NET}" lookup name "${USER}" | cut -d' ' -f1) || + failed=$((failed + 1)) +testit "Remove builtin\\administrators group" \ + "${NET}" groupmap delete \ + sid=S-1-5-32-544 || + failed=$((failed + 1)) + +testok $0 $failed diff --git a/source3/script/tests/test_nt4_trust.sh b/source3/script/tests/test_nt4_trust.sh new file mode 100755 index 0000000..b3d6ca6 --- /dev/null +++ b/source3/script/tests/test_nt4_trust.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +wbinfo="$BINDIR/wbinfo" +smbclient="$BINDIR/smbclient" + +test_trust_wbinfo_m() { + i=0 + # Give the server some time to list trusted domains + while [ $i -lt 10 ] ; do + $wbinfo -m | grep SAMBA-TEST && return 0 + sleep 2 + i=$((i + 1)) + done + return 1 +} + +test_trust_smbclient() { + $smbclient //$NT4_TRUST_SERVER_IP/tmp -U "$DOMAIN/$DOMAIN_USER%$DOMAIN_USER_PASSWORD" -c quit || return 1 + return 0 +} + +testit "nt4trust_wbinfo_m" test_trust_wbinfo_m || failed=$(expr $failed + 1) +testit "nt4trust_smbclient" test_trust_smbclient || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_offline.sh b/source3/script/tests/test_offline.sh new file mode 100755 index 0000000..5e06b1f --- /dev/null +++ b/source3/script/tests/test_offline.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Blackbox test for the offline VFS module. +# +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_offline SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +USERNAME=${4} +PASSWORD=${5} +WORKDIR=${6} +SMBCLIENT=${7} +shift 7 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +touch $WORKDIR/foo + +failed=0 + +attribs=$($SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/offline" -I $SERVER_IP -c "allinfo foo" | sed -n 's/^attributes:.*(\([^)]*\)).*/\1/p') +testit "file has offline attribute" test "x$attribs" = "x1000" || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_old_dirlisting.sh b/source3/script/tests/test_old_dirlisting.sh new file mode 100755 index 0000000..f50a474 --- /dev/null +++ b/source3/script/tests/test_old_dirlisting.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# This tests listing directories using the SMBSearch call family + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: $0 TIMELIMIT SMBCLIENT +EOF + exit 1 +fi + +TIMELIMIT="$1" +shift +SMBCLIENT="$VALGRIND $1" +shift + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +# Make sure we don't loop 100% CPU. A normal dir listing should return +# in less than 3 seconds. At the point of this commit smbclient -c dir +# | wc returns 43 lines, so checking for 100 lines should be well +# enough. + +count=$($TIMELIMIT 3 $SMBCLIENT //"$SERVER_IP"/tmpguest -m LANMAN1 -U% \ + -c dir | wc -l) + +testit "listing shares with LANMAN1" test ${count} -le 100 || + failed=$((failed + 1)) diff --git a/source3/script/tests/test_open_eintr.sh b/source3/script/tests/test_open_eintr.sh new file mode 100755 index 0000000..b40b14d --- /dev/null +++ b/source3/script/tests/test_open_eintr.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Test smbd handling when open returns EINTR +# +# Copyright (C) 2020 Volker Lendecke + +if [ $# -lt 5 ]; then + echo Usage: test_open_eintr.sh \ + --configfile=SERVERCONFFILE SMBCLIENT SMBCONTROL SERVER SHARE + exit 1 +fi + +CONF=$1 +shift 1 +SMBCLIENT=$1 +shift 1 +SMBCONTROL=$1 +shift 1 +SERVER=$1 +shift 1 +SHARE=$1 +shift 1 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +error_inject_conf=$(dirname ${SERVERCONFFILE})/error_inject.conf +>${error_inject_conf} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +sleep 1 + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +# consume the smbclient startup messages +head -n 1 <&101 + +echo "error_inject:openat = EINTR" >${error_inject_conf} +${SMBCONTROL} ${CONF} 0 reload-config + +sleep 1 +>${error_inject_conf} + +echo 'get badnames/blank.txt -' >&100 + +sleep 1 + +>${error_inject_conf} +${SMBCONTROL} ${CONF} 0 reload-config + +head -n 1 <&102 | grep 'getting file' >/dev/null +GREP_RET=$? + +kill ${CLIENT_PID} +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testit "Verify that we could get the file" \ + test $GREP_RET -eq 0 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_preserve_case.sh b/source3/script/tests/test_preserve_case.sh new file mode 100755 index 0000000..c9ca79a --- /dev/null +++ b/source3/script/tests/test_preserve_case.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Blackbox test for share with preserve case options +# +# https://bugzilla.samba.org/show_bug.cgi?id=10650 + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_preserve_case.sh SERVER DOMAIN USERNAME PASSWORD PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER=$1 +DOMAIN=$2 +USERNAME=$3 +PASSWORD=$4 +PREFIX=$5 +smbclient=$6 +if [ $# -gt 6 ]; then + PROTOCOL_LIST=$7 + shift 7 +else + PROTOCOL_LIST="NT1 SMB2 SMB3" + shift 6 +fi +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +cd $SELFTEST_TMPDIR || exit 1 + +test_smbclient() +{ + name="$1" + share="$2" + cmd="$3" + shift + shift + subunit_start_test "$name" + output=$($VALGRIND $smbclient //$SERVER/$share -c "$cmd" "$@" 2>&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +SHARE="lowercase" + +for PROTOCOL in $PROTOCOL_LIST; do + test_smbclient "Test lowercase ls 1 ($PROTOCOL)" $SHARE "ls 1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get 1 ($PROTOCOL)" $SHARE "get 1 LOCAL_1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_1 + + test_smbclient "Test lowercase ls A ($PROTOCOL)" $SHARE "ls A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get A ($PROTOCOL)" $SHARE "get A LOCAL_A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_A + + test_smbclient "Test lowercase ls z ($PROTOCOL)" $SHARE "ls z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get z ($PROTOCOL)" $SHARE "get z LOCAL_Z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_Z +done + +SHARE="lowercase-30000" + +for PROTOCOL in $PROTOCOL_LIST; do + test_smbclient "Test lowercase ls 25839 ($PROTOCOL)" $SHARE "ls 25839" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + + test_smbclient "Test lowercase ls 1 ($PROTOCOL)" $SHARE "ls 1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get 1 ($PROTOCOL)" $SHARE "get 1 LOCAL_1" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_1 + + test_smbclient "Test lowercase ls A ($PROTOCOL)" $SHARE "ls A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get A ($PROTOCOL)" $SHARE "get A LOCAL_A" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_A + + test_smbclient "Test lowercase ls z ($PROTOCOL)" $SHARE "ls z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + test_smbclient "Test lowercase get z ($PROTOCOL)" $SHARE "get z LOCAL_Z" -U$USERNAME%$PASSWORD -m$PROTOCOL || failed=$(expr $failed + 1) + rm -f LOCAL_Z +done + +exit $failed diff --git a/source3/script/tests/test_printing_var_exp.sh b/source3/script/tests/test_printing_var_exp.sh new file mode 100755 index 0000000..5729344 --- /dev/null +++ b/source3/script/tests/test_printing_var_exp.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_printing_var_exp.sh SERVER SERVER_IP DOMAIN USERNAME PASSWORD +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +DOMAIN="$3" +USERNAME="$4" +PASSWORD="$5" +shift 5 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +smbclient="$BINDIR/smbclient" +rpcclient="$BINDIR/rpcclient" + +test_var_expansion() +{ + logfile="${SELFTEST_TMPDIR}/${USER}_printing_var_exp.log" + + $smbclient -U $DOMAIN/$USERNAME%$PASSWORD \ + //$SERVER_IP/print_var_exp \ + -c "print $SRCDIR/testdata/printing/example.ps" + if [ $? -ne 0 ]; then + rm -f "$logfile" + return 1 + fi + cat "$logfile" + + grep "Windows user: $USERNAME" "$logfile" + if [ $? -ne 0 ]; then + rm -f "$logfile" + return 1 + fi + grep "UNIX user: $USERNAME" "$logfile" + if [ $? -ne 0 ]; then + rm -f "$logfile" + return 1 + fi + grep "Domain: $DOMAIN" "$logfile" + if [ $? -ne 0 ]; then + rm -f "$logfile" + return 1 + fi + + rm -f "$logfile" + return 0 +} + +test_empty_queue() +{ + # Try several times until the bgqd daemon updates the print queue status + tries="3" + for i in $(seq 1 $tries); do + echo "Try $i" + JOBS=$($rpcclient ncacn_np:$SERVER_IP \ + -U $DOMAIN/$USERNAME%$PASSWORD \ + -c "enumjobs print_var_exp 2") + if [ $? -ne 0 ]; then + return 1 + fi + if [[ -z $JOBS ]]; then + return 0 + fi + if [[ $i -gt $tries ]]; then + echo "Print queue not empty after $tries seconds:" + echo $JOBS + echo "Queue must be empty before leaving this test or" \ + "following ones may fail." + return 1 + fi + sleep 1 + done + return 0 +} + +testit "Test variable expansion for '%U', '%u' and '%D'" \ + test_var_expansion || + failed=$(expr $failed + 1) + +testit "Test queue is empty" \ + test_empty_queue || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_pthreadpool.sh b/source3/script/tests/test_pthreadpool.sh new file mode 100755 index 0000000..b3d24f7 --- /dev/null +++ b/source3/script/tests/test_pthreadpool.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +if [ ! -x $BINDIR/pthreadpooltest ]; then + # Some machines don't have /bin/true, simulate it + cat >$BINDIR/pthreadpooltest <<EOF +#!/bin/sh +exit 0 +EOF + chmod +x $BINDIR/pthreadpooltest +fi + +failed=0 + +testit "pthreadpool" $VALGRIND $BINDIR/pthreadpooltest || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_recycle.sh b/source3/script/tests/test_recycle.sh new file mode 100755 index 0000000..8c9291f --- /dev/null +++ b/source3/script/tests/test_recycle.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_recycle.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT ADDARGS +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 7 +ADDARGS="$*" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f testfile1 + rm -f testfile2.tmp + rm -rf .trash + ) +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + + +test_recycle() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + echo " +put $tmpfile testfile1 +put $tmpfile testfile2.tmp +del testfile1 +del testfile2.tmp +quit +" > $tmpfile + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/recycle -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed recycle smbclient run with error %s\n" "$ret" + return 1 + fi + + test -e "$share_test_dir/.trash/testfile1" || { + printf ".trash/testfile1 expected to exist but does NOT exist\n" + return 1 + } + test -e "$share_test_dir/.trash/testfile2.tmp" && { + printf ".trash/testfile2.tmp not expected to exist but DOES exist\n" + return 1 + } + perm_want=755 + perm_is=`stat -c '%a' "$share_test_dir/.trash/"` + test "$perm_is" = "$perm_want" || { + printf ".trash/ permission should be $perm_want but is $perm_is\n" + return 1 + } + return 0 +} + + +testit "recycle" \ + test_recycle || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_registry_share.sh b/source3/script/tests/test_registry_share.sh new file mode 100755 index 0000000..22e9f73 --- /dev/null +++ b/source3/script/tests/test_registry_share.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# Blackbox tests for registry shares +# + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_registry_share.sh SERVER USERNAME PASSWORD +EOF + exit 1 +fi + +SERVER=$1 +USERNAME=$2 +PASSWORD=$3 +shift 3 +failed=0 + +samba_bindir="$BINDIR" +samba_srcdir="$SRCDIR" +smbclient="$samba_bindir/smbclient" +rpcclient="$samba_bindir/rpcclient" + +. $samba_srcdir/testprogs/blackbox/subunit.sh +. $samba_srcdir/testprogs/blackbox/common_test_fns.inc + +test_smbclient \ + "Test access to registry share [${USERNAME}]" \ + "ls" "//${SERVER}/registry_share" "-U$USERNAME%$PASSWORD" || + failed=$((failed + 1)) + +testit_grep_count \ + "Test for share enum with registry share" \ + "netname: registry_share" \ + 1 \ + ${rpcclient} "ncacn_np:${SERVER}" "-U$USERNAME%$PASSWORD" \ + -c netshareenum || + failed=$((failed + 1)) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_registry_upgrade.sh b/source3/script/tests/test_registry_upgrade.sh new file mode 100755 index 0000000..ac4a9db --- /dev/null +++ b/source3/script/tests/test_registry_upgrade.sh @@ -0,0 +1,192 @@ +#!/bin/sh +# +# Test for registry upgrades. +# +# Copyright (C) 2011 Björn Baumbach <bb@sernet.de> + +if [ $# -lt 2 ]; then + echo "Usage: test_registry_upgrade.sh NET DBWRAP_TOOL" + exit 1 +fi + +SCRIPT_DIR=$(dirname $0) +BASE_DIR="${SCRIPT_DIR}/../../.." + +NET="$1" +DBWRAP_TOOL="$2 --persistent" +DATADIR="${BASE_DIR}/testdata/samba3" +WORKSPACE="${SELFTEST_TMPDIR}/registry_upgrade" +CONFIG_FILE="${WORKSPACE}/smb.conf" +CONFIGURATION="--configfile=${CONFIG_FILE}" + +NETCMD="$NET $CONFIGURATION" + +incdir="${BASE_DIR}/testprogs/blackbox" +. $incdir/subunit.sh + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +REGPATH="HKLM\Software\Samba" + +LOGDIR_PREFIX="registry_upgrade" + +registry_check() +( + CHECKNO="$1" + CHECKDIFF="$2" + REGVER="" + ALLOWEDERR="INFO: version =|Check database:|overwrite registry format version 0 with 1|no INFO/version found" + + test "x$CHECKNO" = "x0" && { + REGVER="--reg-version=1" + } + + echo "Registry check $CHECKNO" | tee -a $LOG + CHECK="$($NETCMD registry check $REGVER 2>&1)" + RC=$? + + ERRORSTR="$(echo "$CHECK" | grep -vE $ALLOWEDERR)" + test "x$RC" = "x0" || { + echo "upgrade check $CHECKNO failed:" | tee -a $LOG + return 1 + } + + test "x$ERRORSTR" = "x" || { + echo "upgrade check $CHECKNO failed:" | tee -a $LOG + echo "reason: $CHECK" | tee -a $LOG + return 1 + } + + test "x$CHECKDIFF" = "xcheckdiff" && { + $NETCMD registry export 'HKLM' $WORKSPACE/export_${CHECKNO}.reg >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry export HKLM' failed" | tee -a $LOG + } + + diff -q $WORKSPACE/export_0.reg $WORKSPACE/export_${CHECKNO}.reg >>$LOG + test "x$?" = "x0" || { + echo "Error: $WORKSPACE/export_0.reg differs from $WORKSPACE/export_${CHECKNO}.reg" | tee -a $LOG + return 1 + } + } + + return 0 +) + +registry_upgrade() +{ + echo registry_upgrade $1 | tee -a $LOG + + (cat $DATADIR/registry.tdb >$WORKSPACE/registry.tdb) >>$LOG 2>&1 + + REGISTRY="${WORKSPACE}/registry.tdb" + + test -e $REGISTRY || { + echo "Error: Database file not available" | tee -a $LOG + return 1 + } + + # create config file + echo '[global]' >${CONFIG_FILE} + echo " state directory = ${WORKSPACE}" >>${CONFIG_FILE} + echo " private directory = ${WORKSPACE}" >>${CONFIG_FILE} + echo " lock directory = ${WORKSPACE}" >>${CONFIG_FILE} + + # set database INFO/version to 1 + #$DBWRAP_TOOL $REGISTRY store 'INFO/version' uint32 1 + #test "x$?" = "x0" || { + # echo "Error: Can not set INFO/version" >> $LOG + # return 1 + #} + + # check original registry.tdb + echo "$REGISTRY" | tee -a $LOG + registry_check 0 + test "x$?" = "x0" || { + echo "Error: initial 'registry_check 0' failed" | tee -a $LOG + return 1 + } + + # trigger upgrade + echo "$NETCMD registry enumerate $REGPATH" >>$LOG + $NETCMD registry enumerate $REGPATH >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database + registry_check 1 + test "x$?" = "x0" || { + echo "Error: 'registry_check 1' after upgrade failed" | tee -a $LOG + return 1 + } + + # export database for diffs + $NETCMD registry export 'HKLM' $WORKSPACE/export_0.reg | tee -a $LOG + test "x$?" = "x0" || { + echo "Error 'net registry export' failed" | tee -a $LOG + return 1 + } + + # remove version string + $DBWRAP_TOOL $REGISTRY delete INFO/version | tee -a $LOG + test "x$?" = "x0" || { + echo "Error: Can not remove INFO/version key from registry" | tee -a $LOG + return 1 + } + + # trigger upgrade on upgraded database + echo "$NETCMD registry enumerate $REGPATH" >>$LOG + $NETCMD registry enumerate $REGPATH >>$LOG 2>&1 + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database again + registry_check 2 checkdiff + test "x$?" = "x0" || { + echo "Error: 'registry_check 2' after upgrade failed" | tee -a $LOG + return 1 + } + + # set database INFO/version to version 2 + $DBWRAP_TOOL $REGISTRY store 'INFO/version' uint32 2 + test "x$?" = "x0" || { + echo "Error: Can not set INFO/version" | tee -a $LOG + return 1 + } + + # trigger upgrade + $NETCMD registry enumerate $REGPATH >>$LOG + test "x$?" = "x0" || { + echo "Error: 'net registry enumerate $REGPATH' failed" | tee -a $LOG + return 1 + } + + # check upgraded database again + registry_check 3 checkdiff + test "x$?" = "x0" || { + echo "Error: 'registry_check 3' after upgrade failed" | tee -a $LOG + return 1 + } +} + +# remove old workspace +rm -rf $WORKSPACE + +mkdir $WORKSPACE + +DIR=$(mktemp -d ${WORKSPACE}/${LOGDIR_PREFIX}_XXXXXX) +LOG=$DIR/log + +testit "registry_upgrade" registry_upgrade || failed=$(expr $failed + 1) + +if [ $failed -eq 0 ]; then + rm -rf $WORKSPACE +fi + +testok $0 $failed diff --git a/source3/script/tests/test_resolvconf.sh b/source3/script/tests/test_resolvconf.sh new file mode 100755 index 0000000..6cf189c --- /dev/null +++ b/source3/script/tests/test_resolvconf.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +if [ ! -x $BINDIR/resolvconftest ]; then + # Some machines don't have /bin/true, simulate it + cat >$BINDIR/resolvconftest <<EOF +#!/bin/sh +exit 0 +EOF + chmod +x $BINDIR/resolvconftest +fi + +failed=0 + +testit "resolvconf" $VALGRIND $BINDIR/resolvconftest || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rofs.sh b/source3/script/tests/test_rofs.sh new file mode 100755 index 0000000..72901e5 --- /dev/null +++ b/source3/script/tests/test_rofs.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Test smbd handling EROFS when creating a file +# Copyright (C) 2023 Volker Lendecke + +if [ $# -ne 4 ]; then + echo Usage: $0 SERVERCONFFILE SMBCLIENT SERVER SHARE + exit 1 +fi + +CONF=$1 +shift 1 +SMBCLIENT=$1 +shift 1 +SERVER=$1 +shift 1 +SHARE=$1 +shift 1 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +error_inject_conf=$(dirname ${SERVERCONFFILE})/error_inject.conf +echo "error_inject:openat_create = EROFS" >${error_inject_conf} + +failed=0 + +out=$(${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} -U${USER}%${PASSWORD} \ + -c "put VERSION") +testit_grep "Expect MEDIA_WRITE_PROTECTED" NT_STATUS_MEDIA_WRITE_PROTECTED \ + echo "$out" || failed=$(expr $failed + 1) + +>${error_inject_conf} + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient.sh b/source3/script/tests/test_rpcclient.sh new file mode 100755 index 0000000..4260963 --- /dev/null +++ b/source3/script/tests/test_rpcclient.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_rpcclient.sh ccache binding <rpcclient commands> +EOF + exit 1 +fi + +KRB5CCNAME=$1 +shift 1 +export KRB5CCNAME +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "rpcclient" $VALGRIND $BINDIR/rpcclient $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient_dfs.sh b/source3/script/tests/test_rpcclient_dfs.sh new file mode 100755 index 0000000..0ae9e50 --- /dev/null +++ b/source3/script/tests/test_rpcclient_dfs.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Copyright (c) 2022 Pavel Filipenský <pfilipen@redhat.com> +# +# Blackbox tests for the rpcclient DFS commands + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_rpcclient_dfs.sh USERNAME PASSWORD SERVER RPCCLIENT +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +RPCCLIENT="$4" + +RPCCLIENTCMD="${VALGRIND} ${RPCCLIENT} ${SERVER} -U${USERNAME}%${PASSWORD}" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "${incdir}"/subunit.sh + +failed=0 + +${RPCCLIENTCMD} -c "dfsversion" +RC=$? +testit "dfsversion" test ${RC} -eq 0 || failed=$((failed + 1)) + +${RPCCLIENTCMD} -c "dfsenum 5" +RC=$? +testit "dfsenum" test ${RC} -eq 0 || failed=$((failed + 1)) + +# This test fails: _dfs_EnumEx() is not implemented on samba RPC server side +${RPCCLIENTCMD} -c "dfsenumex 5" +RC=$? +testit "dfsenumex" test ${RC} -eq 0 || failed=$((failed + 1)) + +# Every backslash is reduced twice, so we need to enter it 4 times. +# Rpc server then gets: '\\server\share\path' +${RPCCLIENTCMD} -c "dfsgetinfo \\\\\\\\${SERVER}\\\\msdfs-share\\\\msdfs-src1 ${SERVER} msdfs-src1" +RC=$? +testit "dfsgetinfo" test ${RC} -eq 0 || failed=$((failed + 1)) + +testok "$0" "${failed}" diff --git a/source3/script/tests/test_rpcclient_lookup.sh b/source3/script/tests/test_rpcclient_lookup.sh new file mode 100755 index 0000000..cc49838 --- /dev/null +++ b/source3/script/tests/test_rpcclient_lookup.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Blackbox tests for the rpcclient LSA lookup commands +# +# Copyright (C) 2020 Christof Schmitt + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_rpcclient_lookup.sh USERNAME PASSWORD SERVER RPCCLIENT +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +RPCCLIENT="$4" + +RPCCLIENTCMD="$RPCCLIENT $SERVER -U$USERNAME%$PASSWORD" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +$RPCCLIENTCMD -c "lookupsids S-1-1-0" +RC=$? +testit "lookupsids" test $RC -eq 0 || failed=$(expr $failed + 1) + +$RPCCLIENTCMD -c "lookupsids_level 1 S-1-1-0" +RC=$? +testit "lookupsids_level" test $RC -eq 0 || failed=$(expr $failed + 1) + +$RPCCLIENTCMD -c "lookupnames Everyone" +RC=$? +testit "lookupnames" test $RC -eq 0 || failed=$(expr $failed + 1) + +$RPCCLIENTCMD -c "lookupnames_level 1 Everyone" +RC=$? +testit "lookupnames_level" test $RC -eq 0 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient_netsessenum.sh b/source3/script/tests/test_rpcclient_netsessenum.sh new file mode 100755 index 0000000..1d04543 --- /dev/null +++ b/source3/script/tests/test_rpcclient_netsessenum.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Blackbox tests for the rpcclient srvsvc commands +# +# Copyright (C) 2018 Christof Schmitt + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 DOMAIN ADMIN_USER ADMIN_PASSWORD SERVER RPCCLIENT SMBTORTURE3 SHARE +EOF + exit 1 +fi + +DOMAIN="$1" +ADMIN_USER="$2" +ADMIN_PASSWORD="$3" +SERVER="$4" +RPCCLIENT="$5" +SMBTORTURE3="$6" +SHARE="$7" + +USERPASS="-U$DOMAIN/$ADMIN_USER%$ADMIN_PASSWORD" +RPCCLIENTCMD="$RPCCLIENT $SERVER $USERPASS" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# +# Verify initial number of sessions. +# +$RPCCLIENTCMD -c NetSessEnum | grep Received +RC=$? +testit "netsessenum" test $RC = 0 || failed=$(expr $failed + 1) + +OUT=$($RPCCLIENTCMD -c NetSessEnum | grep Received) +test "$OUT" = "Received 1 entries." +RC=$? +testit "count1" test $RC -eq 0 || failed=$(expr $failed + 1) + +# +# Inject smbd crash +# +$SMBTORTURE3 //"$SERVER"/"$SHARE" "$USERPASS" CLEANUP1 + +# +# Verify number of sessions after crash +# +OUT=$($RPCCLIENTCMD -c NetSessEnum | grep Received) +test "$OUT" = "Received 1 entries." +RC=$? +testit "count2" test $RC -eq 0 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient_pw_nt_hash.sh b/source3/script/tests/test_rpcclient_pw_nt_hash.sh new file mode 100755 index 0000000..c1e3660 --- /dev/null +++ b/source3/script/tests/test_rpcclient_pw_nt_hash.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# Blackbox tests for the rpcclient --pw-nt-hash option +# + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_rpcclient_pw_nt_hash.sh USERNAME PASSWORD SERVER RPCCLIENT +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +RPCCLIENT="$4" + +HASH=$(echo -n $PASSWORD | $PYTHON -c 'import sys, binascii, samba, samba.crypto; sys.stdout.buffer.write(binascii.hexlify(samba.crypto.md4_hash_blob(sys.stdin.buffer.read(1000).decode().encode("UTF-16LE"))))') + +RPCCLIENTCMD="$RPCCLIENT $SERVER --pw-nt-hash -U$USERNAME%$HASH -c queryuser" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "rpcclient --pw-nt-hash" $RPCCLIENTCMD || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclient_samlogon.sh b/source3/script/tests/test_rpcclient_samlogon.sh new file mode 100755 index 0000000..ff73be5 --- /dev/null +++ b/source3/script/tests/test_rpcclient_samlogon.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_rpcclient_samlogon.sh USERNAME PASSWORD binding <rpcclient commands> +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +shift 2 +ADDARGS="$@" + +rpcclient_samlogon_schannel_seal() +{ + $VALGRIND $BINDIR/rpcclient -U% -c "schannel;samlogon '$USERNAME' '$PASSWORD';samlogon '$USERNAME' '$PASSWORD'" "$@" +} + +rpcclient_samlogon_schannel_sign() +{ + $VALGRIND $BINDIR/rpcclient -U% -c "schannelsign;samlogon '$USERNAME' '$PASSWORD';samlogon '$USERNAME' '$PASSWORD'" "$@" +} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "rpcclient dsenumdomtrusts" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "dsenumdomtrusts" || failed=$(expr $failed + 1) +testit "rpcclient getdcsitecoverage" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "getdcsitecoverage" || failed=$(expr $failed + 1) +testit "rpcclient samlogon schannel seal" rpcclient_samlogon_schannel_seal $ADDARGS || failed=$(expr $failed +1) +testit "rpcclient samlogon schannel sign" rpcclient_samlogon_schannel_sign $ADDARGS || failed=$(expr $failed +1) + +testok $0 $failed diff --git a/source3/script/tests/test_rpcclientsrvsvc.sh b/source3/script/tests/test_rpcclientsrvsvc.sh new file mode 100755 index 0000000..fdade1a --- /dev/null +++ b/source3/script/tests/test_rpcclientsrvsvc.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# +# Blackbox tests for the rpcclient srvsvc commands +# +# Copyright (C) 2015 Christof Schmitt + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_rpcclientsrvsvc.sh USERNAME PASSWORD SERVER RPCCLIENT SHARE1 +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +RPCCLIENT="$4" +SHARE1="$5" + +RPCCLIENTCMD="$RPCCLIENT $SERVER -U$USERNAME%$PASSWORD" + +SHARENAME=SRVSVCTEST +MAX_USERS=5 +COMMENT="share for RPC SRVSVC testing" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Query path from existing share + +$RPCCLIENTCMD -c "netsharegetinfo $SHARE1" +RC=$? +testit "getinfo on S$SHARE1" test $RC = 0 || failed=$(expr $failed + 1) + +SHAREPATH=$($RPCCLIENTCMD -c "netsharegetinfo '$SHARE1'" | + grep path: | sed -e 's/.*path:\t//') +testit "verifying $SHARE1 path" test -n "$SHAREPATH" || + failed=$(expr $failed + 1) + +# Add a new share + +$RPCCLIENTCMD -c "netshareadd '$SHAREPATH' '$SHARENAME' '$MAX_USERS' '$COMMENT'" +RC=$? +testit "netshareadd" test $RC = 0 || failed=$(expr $failed + 1) + +# Verify comment for new share + +COMMENT_RET=$($RPCCLIENTCMD -c "netsharegetinfo '$SHARENAME'" | + grep remark: | sed -e 's/.*remark:\t//') + +test "$COMMENT" = "$COMMENT_RET" +RC=$? +testit "verifying comment" test $RC -eq 0 || failed=$(expr $failed + 1) + +# Verify share path for new share + +SHAREPATH_RET=$($RPCCLIENTCMD -c "netsharegetinfo '$SHARENAME'" | + grep path: | sed -e 's/.*path:\t//') +test "$SHAREPATH" = "$SHAREPATH_RET" +RC=$? +testit "verifying share path" test $RC -eq 0 || failed=$(expr $failed + 1) + +# Set CSC policy + +$RPCCLIENTCMD -c "netsharesetdfsflags '$SHARENAME' 0x30" +RC=$? +testit "set csc policy" test $RC -eq 0 || failed=$(expr $failed + 1) + +# Query CSC policy + +CSC_CACHING_RET=$($RPCCLIENTCMD -c "netsharegetinfo '$SHARENAME' 1005" | + grep 'csc caching' | sed -e 's/.*csc caching: //') +testit "verifying csc policy" test $CSC_CACHING_RET -eq 3 || + failed=$(expr $failed + 1) + +# Delete share + +$RPCCLIENTCMD -c "netsharedel '$SHARENAME'" +RC=$? +testit "deleting share" test $RC -eq 0 || failed=$(expr $failed + 1) + +# Verify that query to deleted share fails + +$RPCCLIENTCMD -c "netsharegetinfo '$SHARENAME' 1005" +RC=$? +testit "querying deleted share" test $RC -eq 1 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_sacl_set_get.sh b/source3/script/tests/test_sacl_set_get.sh new file mode 100755 index 0000000..1c78ab2 --- /dev/null +++ b/source3/script/tests/test_sacl_set_get.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Runs the smbtorture3 SMB2-SACL test +# that requires SeSecurityPrivilege +# against Samba. +# + +if [ $# -lt 7 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SMBTORTURE3 NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBTORTURE3="$5" +NET="$6" +SHARE="$7" + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +sacl_set_get() +{ + out=$($SMBTORTURE3 //$SERVER_IP/$SHARE -U $USERNAME%$PASSWORD SMB2-SACL) + if [ $? -ne 0 ]; then + echo "SMB2-SACL failed" + echo "$out" + return 1 + fi +} + +# Grant SeSecurityPrivilege to the user +testit "grant SeSecurityPrivilege" $NET rpc rights grant $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +# Run the tests. +testit "SACL set_get" sacl_set_get || failed=$(expr $failed + 1) + +# Revoke SeSecurityPrivilege +testit "revoke SeSecurityPrivilege" $NET rpc rights revoke $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_server_addresses.sh b/source3/script/tests/test_server_addresses.sh new file mode 100755 index 0000000..891c2f2 --- /dev/null +++ b/source3/script/tests/test_server_addresses.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Blackbox test for the server addresses parameter +# + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +testit_grep_count \ + "[only_ipv6] invisible over ipv4" "netname: only_ipv6" 0 \ + bin/rpcclient "$SERVER_IP" -U% -c netshareenumall || + failed=$(expr "$failed" + 1) + +testit_grep_count \ + "[only_ipv6] visible over ipv6" "netname: only_ipv6" 1 \ + bin/rpcclient "$SERVER_IPV6" -U% -c netshareenumall || + failed=$(expr "$failed" + 1) + +testit_expect_failure_grep \ + "[only_ipv6] inaccessible over ipv4" \ + "tree connect failed: NT_STATUS_BAD_NETWORK_NAME" \ + bin/smbclient //"$SERVER_IP"/only_ipv6 -U% -c quit || + failed=$(expr "$failed" + 1) + +testit \ + "[only_ipv6] accessible over ipv6" \ + bin/smbclient //"$SERVER_IPV6"/only_ipv6 -U% -c quit || + failed=$(expr "$failed" + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh new file mode 100755 index 0000000..dd6699f --- /dev/null +++ b/source3/script/tests/test_shadow_copy.sh @@ -0,0 +1,458 @@ +#!/usr/bin/env bash +# +# Blackbox test for shadow_copy2 VFS. +# + +if [ $# -lt 7 ]; then +cat <<EOF +Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT PARAMS +EOF +exit 1; +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +USERNAME=${4} +PASSWORD=${5} +WORKDIR=${6} +SMBCLIENT=${7} +shift 7 +ADDARGS="$*" +SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}" + +incdir=`dirname $0`/../../../testprogs/blackbox +. $incdir/subunit.sh + +SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30' +SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30' +SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30' +SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30' +SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30' +SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30' +SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30' +SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30' +SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30' +SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30' +SNAPSHOTS[10]='@GMT-2010-11-11' +SNAPSHOTS[11]='@GMT-2011.11.11-11.40.30' +SNAPSHOTS[12]='snap@GMT-2012.11.11-11.40.30' +SNAPSHOTS[13]='@GMT-2013.11.11-11_40_33-snap' +SNAPSHOTS[14]='@GMT-2014.11.11-11.40.30' +SNAPSHOTS[15]='daily@GMT-2015.11.11-11.40.30' +SNAPSHOTS[16]='snap_GMT-2016.11.11-11.40.30' +SNAPSHOTS[17]='sysp_GMT-2017.11.11-11.40.30' +SNAPSHOTS[18]='monthly@GMT-2018.11.11-11.40.30' +SNAPSHOTS[19]='straps_GMT-2019.11.11-11.40.33' + +# build a hierarchy of files, symlinks, and directories +build_files() +{ + local rootdir + local prefix + local version + local destdir + local content + rootdir=$1 + prefix=$2 + version=$3 + content=$4 + if [ -n "$prefix" ] ; then + destdir=$rootdir/$prefix + else + destdir=$rootdir + fi + + mkdir -p $destdir + if [ "$version" = "latest" ] ; then + #non-snapshot files + # for non-snapshot version, create legit files + # so that wide-link checks focus on snapshot files + echo "$content" > $destdir/foo + mkdir -p $destdir/bar + echo "$content" > $destdir/bar/baz + echo "$content" > $destdir/bar/lfoo + echo "$content" > $destdir/bar/letcpasswd + echo "$content" > $destdir/bar/loutside + elif [ "$version" = "fullsnap" ] ; then + #snapshot files + echo "$content" > $destdir/foo + mkdir -p $destdir/bar + echo "$content" > $destdir/bar/baz + ln -fs ../foo $destdir/bar/lfoo + ln -fs /etc/passwd $destdir/bar/letcpasswd + ln -fs ../../outside $destdir/bar/loutside + echo "$content" > `dirname $destdir`/outside + else #subshare snapshot - at bar + echo "$content" > $destdir/baz + ln -fs ../foo $destdir/lfoo + ln -fs /etc/passwd $destdir/letcpasswd + ln -fs ../../outside $destdir/loutside + echo "$content" > `dirname $destdir`/../outside + fi + +} + +# build a snapshots directory +build_snapshots() +{ + local where #where to build snapshots + local prefix #prefix from snapshot dir to share root + local start #timestamp index of first snapshot + local end #timestamp index of last snapshot + local sub #creat a snapshot of subtree of share + local snapdir + local snapname + local i + local version + + where=$1 + prefix=$2 + start=$3 + end=$4 + sub=$5 + + snapdir=$where/.snapshots + mkdir -p $snapdir + + version="fullsnap" + if [ "$sub" = "1" ] ; then + version="subsnap" + prefix="" + + # a valid link target for an inner symlink - + # the link is not broken yet should be blocked + # by wide link checks + touch $snapdir/foo + fi + + for i in `seq $start $end` ; do + snapname=${SNAPSHOTS[$i]} + mkdir $snapdir/$snapname + build_files $snapdir/$snapname "$prefix" $version "$snapname" + done +} + +# Test listing previous versions of a file +test_count_versions() +{ + local share + local path + local expected_count + local skip_content + local versions + local tstamps + local tstamp + local content + local is_dir + + share=$1 + path=$2 + expected_count=$3 + skip_content=$4 + versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l` + if [ "$versions" != "$expected_count" ] ; then + echo "expected $expected_count versions of $path, got $versions" + return 1 + fi + + is_dir=0 + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^attributes:.*D" && is_dir=1 + if [ $is_dir = 1 ] ; then + skip_content=1 + fi + + #readable snapshots + tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | awk '/^@GMT-/ {snapshot=$1} /^create_time:/ {printf "%s\n", snapshot}'` + for tstamp in $tstamps ; do + if [ $is_dir = 0 ] ; + then + if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then + echo "Failed getting \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + else + if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then + echo "Failed listing \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + fi + + #also check the content, but not for wide links + if [ "x$skip_content" != "x1" ] ; then + content=`cat $WORKDIR/foo` + if [ "$content" != "$tstamp" ] ; then + echo "incorrect content of \\\\$SERVER\\$share\\$tstamp\\$path expected [$tstamp] got [$content]" + return 1 + fi + fi + done + + #non-readable snapshots + tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | \ + awk '/^@GMT-/ {if (snapshot!=""){printf "%s\n", snapshot} ; snapshot=$1} /^create_time:/ {snapshot=""} END {if (snapshot!=""){printf "%s\n", snapshot}}'` + for tstamp in $tstamps ; do + if [ $is_dir = 0 ] ; + then + if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then + echo "Unexpected success getting \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + else + if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then + echo "Unexpected success listing \\\\$SERVER\\$share\\$tstamp\\$path" + return 1 + fi + fi + done +} + +# Test fetching a previous version of a file +test_fetch_snap_file() +{ + local share + local path + local snapidx + + share=$1 + path=$2 + snapidx=$3 + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo" +} + +# Test fetching a previous version of a file +test_fetch_snap_dir() +{ + local share + local path + local snapidx + + share=$1 + path=$2 + snapidx=$3 + + # This first command is not strictly needed, but it causes the snapshots to + # appear in a network trace which helps debugging... + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "allinfo $path" + + $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \ + -c "ls ${SNAPSHOTS[$snapidx]}/$path/*" +} + +test_shadow_copy_fixed() +{ + local share #share to contact + local where #where to place snapshots + local prefix #prefix to files inside snapshot + local msg + local allow_wl + local ncopies_allowd + local ncopies_blocked + + share=$1 + where=$2 + prefix=$3 + msg=$4 + allow_wl=$5 + + ncopies_allowed=4 + ncopies_blocked=1 + if [ -n "$allow_wl" ] ; then + ncopies_blocked=4 + fi + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" 0 2 + + testit "$msg - regular file" \ + test_count_versions $share foo $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - regular file in subdir" \ + test_count_versions $share bar/baz $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - regular file in case insensitive subdir" \ + test_count_versions $share bar/bAz $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - local symlink" \ + test_count_versions $share bar/lfoo $ncopies_allowed || \ + failed=`expr $failed + 1` + + testit "$msg - abs symlink outside" \ + test_count_versions $share bar/letcpasswd $ncopies_blocked 1 || \ + failed=`expr $failed + 1` + + testit "$msg - rel symlink outside" \ + test_count_versions $share bar/loutside $ncopies_blocked 1 || \ + failed=`expr $failed + 1` + + testit "$msg - list directory" \ + test_count_versions $share bar $ncopies_allowed || \ + failed=`expr $failed + 1` +} + +test_shadow_copy_everywhere() +{ + local share #share to contact + + share=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots "$WORKDIR/mount" "base/share" 0 0 + build_snapshots "$WORKDIR/mount/base" "share" 1 2 + build_snapshots "$WORKDIR/mount/base/share" "" 3 5 + build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1 + + testit "snapshots in each dir - regular file" \ + test_count_versions $share foo 4 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - regular file in subdir" \ + test_count_versions $share bar/baz 5 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - local symlink (but outside snapshot)" \ + test_count_versions $share bar/lfoo 1 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - abs symlink outside" \ + test_count_versions $share bar/letcpasswd 1 || \ + failed=`expr $failed + 1` + + testit "snapshots in each dir - rel symlink outside" \ + test_count_versions $share bar/loutside 1 || \ + failed=`expr $failed + 1` + + #the previous versions of the file bar/lfoo points to are outside its + #snapshot, and are not reachable. However, but previous versions + #taken at different, non-overlapping times higher up the + #hierarchy are still reachable. + testit "fetch a previous version of a regular file" \ + test_fetch_snap_file $share "bar/baz" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical parent path" \ + test_fetch_snap_file $share "BAR/baz" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical basepath" \ + test_fetch_snap_file $share "bar/BAZ" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a regular file via non-canonical path" \ + test_fetch_snap_file $share "BAR/BAZ" 6 || \ + failed=`expr $failed + 1` + + testit_expect_failure "fetch a (non-existent) previous version of a symlink" \ + test_fetch_snap_file $share "bar/lfoo" 6 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (1)" \ + test_fetch_snap_file $share "bar/lfoo" 0 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (2)" \ + test_fetch_snap_file $share "bar/lfoo" 1 || \ + failed=`expr $failed + 1` + + testit "fetch a previous version of a symlink via browsing (3)" \ + test_fetch_snap_file $share "bar/lfoo" 3 || \ + failed=`expr $failed + 1` + + testit "list a previous version directory" \ + test_fetch_snap_dir $share "bar" 6 || \ + failed=`expr $failed + 1` +} + +test_shadow_copy_format() +{ + local share #share to contact + local where #where to place snapshots + local prefix #prefix to files inside snapshot + local ncopies_allowd + local msg + + share=$1 + where=$2 + prefix=$3 + ncopies_allowed=$4 + msg=$5 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" 10 19 + + testit "$msg - regular file" \ + test_count_versions $share foo $ncopies_allowed 1 || \ + failed=`expr $failed + 1` +} + +# Test fetching a file where there's no current version of it +test_missing_basedir() +{ + local share + local where + local prefix + local snapidx + + share=$1 + where=$2 + prefix=$3 + snapidx=$4 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots $WORKDIR/$where "$prefix" "$snapidx" "$snapidx" + + (cd "$WORKDIR/$where"/share; mv bar _bar) + + testit "fetch a file without a latest version" \ + test_fetch_snap_file "$share" "bar/baz" "$snapidx" || \ + failed=`expr $failed + 1` + + (cd "$WORKDIR/$where"/share; mv _bar bar) +} + +#build "latest" files +build_files $WORKDIR/mount base/share "latest" "latest" + +failed=0 + +# a test with wide links allowed - also to verify that what's later +# being blocked is a result of server security measures and not +# a testing artifact. +test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1 + +# tests for a fixed snapshot location +test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume" +test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume" +test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point" +test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside" +test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume" +test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside" +test_shadow_copy_fixed shadow8 . share "logical snapshot layout" + +# tests for snapshot everywhere - one snapshot location +test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots" +test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots" +test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots" + +# a test for snapshots everywhere - multiple snapshot locations +test_shadow_copy_everywhere shadow7 + +# tests for testing snapshot selection via shadow:format +test_shadow_copy_format shadow_fmt0 mount/base share 3 "basic shadow:format test" +test_shadow_copy_format shadow_fmt1 mount/base share 2 "shadow:format with only date" +test_shadow_copy_format shadow_fmt2 mount/base share 2 "shadow:format with some prefix" +test_shadow_copy_format shadow_fmt3 mount/base share 2 "shadow:format with modified format" +test_shadow_copy_format shadow_fmt4 mount/base share 3 "shadow:format with snapprefix" +test_shadow_copy_format shadow_fmt5 mount/base share 6 "shadow:format with delimiter" +test_missing_basedir shadow3 "mount/base" "share" 6 + +exit $failed diff --git a/source3/script/tests/test_shadow_copy_torture.sh b/source3/script/tests/test_shadow_copy_torture.sh new file mode 100755 index 0000000..3a6ba91 --- /dev/null +++ b/source3/script/tests/test_shadow_copy_torture.sh @@ -0,0 +1,227 @@ +#!/usr/bin/env bash +# +# Blackbox test for shadow_copy2 VFS. +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBTORTURE SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +USERNAME=${4} +PASSWORD=${5} +WORKDIR=${6} +SMBTORTURE="$VALGRIND ${7}" +SMBCLIENT="$VALGRIND ${8}" +shift 7 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +SNAPSHOT="@GMT-2015.10.31-19.40.30" + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +# build a hierarchy of files, symlinks, and directories +build_files() +{ + local destdir + destdir=$1 + + echo "$content" >$destdir/foo + + mkdir -p $WORKDIR/subdir/ + touch $WORKDIR/subdir/hardlink +} + +# build a snapshots directory +build_snapshots() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + mkdir -p $snapdir/$SNAPSHOT + + build_files $snapdir/$SNAPSHOT + + mkdir -p $snapdir/$SNAPSHOT/subdir + ln "$WORKDIR"/subdir/hardlink "$snapdir"/$SNAPSHOT/subdir/hardlink +} + +build_stream_on_snapshot() +{ + file=$WORKDIR/.snapshots/$SNAPSHOT/foo + + setfattr -n 'user.DosStream.bar:$DATA' -v baz $file || return 1 +} + +test_shadow_copy_write() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "writing to shadow copy of a file" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_file=foo" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.write || + failed=$(expr $failed + 1) +} + +test_shadow_copy_stream() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + build_stream_on_snapshot || { + subunit_start_test msg + subunit_skip_test msg <<EOF +test_shadow_copy_stream needs an fs with xattrs +EOF + return 0 + } + + testit "reading stream of a shadow copy of a file" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_file=foo" \ + --option="torture:twrp_stream=bar" \ + --option="torture:twrp_stream_size=3" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.stream || + failed=$(expr $failed + 1) +} + +test_shadow_copy_openroot() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "opening shadow copy root of share" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.openroot || + failed=$(expr $failed + 1) +} + +test_shadow_copy_fix_inodes() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "open $SNAPSHOT/subdir/hardlink") || failed=$(expr $failed + 1) + echo $out + echo $out | grep "hardlink: for read/write fnum 1" || return 1 +} + +build_hiddenfile() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + touch $WORKDIR/hiddenfile + + # Create a file with hidden attribute + $SMBCLIENT -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "put $WORKDIR/hiddenfile hiddenfile; setmode hiddenfile +h" + # ...and move it to the snapshot directory + mv $WORKDIR/hiddenfile $snapdir/$SNAPSHOT/ +} + +test_hiddenfile() +{ + build_hiddenfile + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "allinfo $SNAPSHOT/hiddenfile") || return 1 + echo $out + echo $out | grep "attributes: HA (22)" || return 1 + + out=$($SMBCLIENT \ + -U $USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + -c "ls $SNAPSHOT/hiddenfile") || return 1 + echo $out + echo $out | grep "hiddenfile[[:blank:]]*AH" || return 1 + + return 0 +} + +test_shadow_copy_listdir_fix_inodes() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "$msg" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + smb2.twrp.listdir || + failed=$(expr $failed + 1) +} + +build_files $WORKDIR + +# test open for writing and write behaviour of snapshoted files +test_shadow_copy_write "write behaviour of snapshoted files" + +test_shadow_copy_stream "reading stream of snapshotted file" + +test_shadow_copy_openroot "opening root of shadow copy share" + +testit "fix inodes with hardlink" test_shadow_copy_fix_inodes || failed=$(expr $failed + 1) + +testit "Test reading DOS attribute" test_hiddenfile || failed=$(expr $failed + 1) + +test_shadow_copy_listdir_fix_inodes "fix inodes when listing directory" + +exit $failed diff --git a/source3/script/tests/test_shareenum.sh b/source3/script/tests/test_shareenum.sh new file mode 100755 index 0000000..0334243 --- /dev/null +++ b/source3/script/tests/test_shareenum.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# this tests share enumeration with "access based share enum" + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: $0 SERVER USERNAME PASSWORD RPCCLIENT +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +RPCCLIENT="$4" +RPCCLIENT="$VALGRIND ${RPCCLIENT}" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +user_see_share() +{ + local user=$1 + local share=$2 + $RPCCLIENT //$SERVER -U$user%$PASSWORD -c "netshareenumall" | grep $share >/dev/null 2>&1 +} + +testit "$USERNAME sees tmp" user_see_share $USERNAME tmp +testit "$USERNAME sees valid-users-tmp" user_see_share $USERNAME valid-users-tmp +testit "force_user sees tmp" user_see_share force_user tmp +testit_expect_failure "force_user does not see valid-users-tmp" user_see_share force_user valid-users-tmp diff --git a/source3/script/tests/test_sharesec.sh b/source3/script/tests/test_sharesec.sh new file mode 100755 index 0000000..a083a56 --- /dev/null +++ b/source3/script/tests/test_sharesec.sh @@ -0,0 +1,140 @@ +#!/bin/sh +# +# Test sharesec command. +# +# Verify that changing and querying the security descriptor works. Also +# ensure that the output format for ACL entries does not change. +# +# The test uses well-known SIDs to not require looking up names and SIDs +# +# Copyright (C) 2015, 2019 Christof Schmitt + +if [ $# -lt 4 ]; then + echo Usage: test_sharesec.sh SERVERCONFFILE SHARESEC NET SHARE + exit 1 +fi + +CONF=$1 +SHARESEC=$2 +NET=$3 +SHARE=$4 + +CMD="$SHARESEC $CONF $SHARE" +NET_CMD="$NET $CONF" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +testit "Set new ACL" $CMD --replace S-1-1-0:ALLOWED/0x0/READ || + failed=$(expr $failed + 1) +testit "Query new ACL" $CMD --view || failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify new ACL count" test $COUNT -eq 1 || failed=$(expr $failed + 1) +ACL=$($CMD --view | grep ACL: | sed -e 's/^ACL://') +testit "Verify new ACL" test $ACL = S-1-1-0:ALLOWED/0x0/READ + +OWNER=$($CMD --view | grep OWNER:) +testit "Verify empty OWNER" test "$OWNER" = "OWNER:" || + failed=$(expr $failed + 1) +GROUP=$($CMD --view | grep GROUP:) +testit "Verify empty GROUP" test "$GROUP" = "GROUP:" || + failed=$(expr $failed + 1) +CONTROL=$($CMD --view | grep CONTROL: | sed -e 's/^CONTROL://') +testit "Verify control flags" test "$CONTROL" = "SR|DP" || + failed=$(expr $failed + 1) + +testit "Add second ACL entry" $CMD --add S-1-5-32-544:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) +testit "Query ACL with two entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with two entries" test $COUNT -eq 2 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-544 | sed -e 's/^ACL://') +testit "Verify second ACL entry" test $ACL = S-1-5-32-544:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Modify ACL entry" $CMD --modify S-1-5-32-544:ALLOWED/0x0/CHANGE || + failed=$(expr $failed + 1) +testit "Verify ACL with two entries after modify" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with two entries after modify" test $COUNT -eq 2 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-544 | sed -e 's/^ACL://') +testit "Verify modified entry" test $ACL = S-1-5-32-544:ALLOWED/0x0/CHANGE || + failed=$(expr $failed + 1) + +testit "Add deny ACL entry" $CMD --add S-1-5-32-545:DENIED/0x0/CHANGE || + failed=$(expr $failed + 1) +testit "Query ACL with three entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with three entries" test $COUNT -eq 3 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-545 | sed -e 's/^ACL://') +testit "Verify DENIED ACL entry" test $ACL = S-1-5-32-545:DENIED/0x0/CHANGE || + failed=$(expr $failed + 1) + +testit "Add special ACL entry" $CMD --add S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) +testit "Query ACL with four entries" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count with four entries" test $COUNT -eq 4 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep S-1-5-32-546 | sed -e 's/^ACL://') +testit "Verify special entry" test $ACL = S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) + +testit "Remove ACL entry" $CMD --remove S-1-5-32-546:ALLOWED/0x0/RWXDP || + failed=$(expr $failed + 1) +testit "Query ACL with three entries after removal" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify ACL count after removal" test $COUNT -eq 3 || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-546)" +testit "Verify removal" test -e "$ACL" || failed=$(expr $failed + 1) + +testit "Set ACL as hex value" $CMD --add S-1-5-32-547:0x1/0x0/0x001F01FF || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-547 | sed -e 's/^ACL://')" +testit "Verify numerically set entry" \ + test "$ACL" = S-1-5-32-547:DENIED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Set ACL as dec value" $CMD --add S-1-5-32-548:1/0/0x001F01FF || + failed=$(expr $failed + 1) +ACL="$($CMD --view | grep S-1-5-32-548 | sed -e 's/^ACL://')" +testit "Verify numerically set entry" \ + test "$ACL" = S-1-5-32-548:DENIED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Set back to default ACL " $CMD --replace S-1-1-0:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) +testit "Query standard ACL" $CMD --view || + failed=$(expr $failed + 1) +COUNT=$($CMD --view | grep ACL: | sed -e 's/^ACL://' | wc -l) +testit "Verify standard ACL count" test $COUNT -eq 1 || + failed=$(expr $failed + 1) +ACL=$($CMD --view | grep ACL: | sed -e 's/^ACL://') +testit "Verify standard ACL" test $ACL = S-1-1-0:ALLOWED/0x0/FULL || + failed=$(expr $failed + 1) + +testit "Create new share" $NET_CMD conf addshare tmp_share /tmp || + failed=$(expr $failed + 1) +testit "Change ACL" $SHARESEC $CONF --replace S-1-1-0:DENIED/0x0/FULL tmp_share || + failed=$(expr $failed + 1) +testit "Delete share" $NET_CMD conf delshare tmp_share || + failed=$(expr $failed + 1) +testit "Create share again" $NET_CMD conf addshare tmp_share /tmp || + failed=$(expr $failed + 1) +ACL=$($SHARESEC $CONF --view tmp_share | grep 'ACL:') +testit "Check for default ACL" \ + test "$ACL" = "ACL:S-1-1-0:ALLOWED/0x0/FULL" || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smb1_shadow_copy_torture.sh b/source3/script/tests/test_smb1_shadow_copy_torture.sh new file mode 100755 index 0000000..3ea3030 --- /dev/null +++ b/source3/script/tests/test_smb1_shadow_copy_torture.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Blackbox test for shadow_copy2 VFS - SMB1 only. +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBTORTURE +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +USERNAME=${4} +PASSWORD=${5} +WORKDIR=${6} +SMBTORTURE="$VALGRIND ${7}" +shift 7 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +SNAPSHOT="@GMT-2015.10.31-19.40.30" + +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +# build a hierarchy of files, symlinks, and directories +build_files() +{ + local destdir + destdir=$1 + + echo "$content" >$destdir/foo +} + +# build a snapshots directory +build_snapshots() +{ + local snapdir + + snapdir=$WORKDIR/.snapshots + + mkdir -p $snapdir + mkdir $snapdir/$SNAPSHOT + + build_files $snapdir/$SNAPSHOT +} + +test_shadow_copy_openroot() +{ + local msg + + msg=$1 + + #delete snapshots from previous tests + find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1 + build_snapshots + + testit "opening shadow copy root of share over SMB1" \ + $SMBTORTURE \ + -U$USERNAME%$PASSWORD \ + "//$SERVER/shadow_write" \ + --option="torture:twrp_snapshot=$SNAPSHOT" \ + base.smb1-twrp-openroot || + failed=$(expr $failed + 1) +} + +build_files $WORKDIR + +# test open for writing and write behaviour of snapshoted files +test_shadow_copy_openroot "opening root of shadow copy share" + +exit $failed diff --git a/source3/script/tests/test_smb1_system_security.sh b/source3/script/tests/test_smb1_system_security.sh new file mode 100755 index 0000000..dac8897 --- /dev/null +++ b/source3/script/tests/test_smb1_system_security.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Runs the smbtorture3 SMB1-SYSTEM-SECURITY test +# that requires SeSecurityPrivilege against Samba. +# + +if [ $# -lt 7 ]; then + echo "Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SMBTORTURE3 NET SHARE" + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBTORTURE3="$5" +NET="$6" +SHARE="$7" + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +smb1_system_security() +{ + out=$($SMBTORTURE3 //$SERVER_IP/$SHARE -U $USERNAME%$PASSWORD -mNT1 SMB1-SYSTEM-SECURITY) + if [ $? -ne 0 ]; then + echo "SMB1-SYSTEM-SECURITY failed" + echo "$out" + return 1 + fi +} + +# Grant SeSecurityPrivilege to the user +testit "grant SeSecurityPrivilege" $NET rpc rights grant $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +# Run the test. +testit "smb1-system-security" smb1_system_security || failed=$(expr $failed + 1) + +# Revoke SeSecurityPrivilege +testit "revoke SeSecurityPrivilege" $NET rpc rights revoke $USERNAME SeSecurityPrivilege -U $USERNAME%$PASSWORD -I $SERVER_IP || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smb2_not_casesensitive.sh b/source3/script/tests/test_smb2_not_casesensitive.sh new file mode 100755 index 0000000..7e85834 --- /dev/null +++ b/source3/script/tests/test_smb2_not_casesensitive.sh @@ -0,0 +1,81 @@ +#!/bin/sh +# +# Blackbox test for SMB2 case insensitivity +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smb2_not_casesensitive SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +USERNAME=${3} +PASSWORD=${4} +LOCAL_PATH=${5} +SMBCLIENT=${6} + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Test a file with different case works over SMB2 and later +test_access_with_different_case() +{ + tmpfile=$LOCAL_PATH/testfile.txt + echo "foobar" >$tmpfile + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -mSMB3 -U$USERNAME%$PASSWORD "$SERVER" -I $SERVER_IP -c "ls TeStFiLe.TxT" 2>&1' + out=$(eval $cmd) + ret=$? + + rm -f $tmpfile + + if [ $ret = 0 ]; then + return 0 + else + echo "$out" + echo "failed to get file with different case" + return 1 + fi +} + +# Test that a rename causes a conflict works when target name exists in +# different case +test_rename() +{ + set -x + tmpfile=$LOCAL_PATH/torename.txt + echo "foobar" >$tmpfile + targetfile=$LOCAL_PATH/target.txt + touch $targetfile + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -mSMB3 -U$USERNAME%$PASSWORD "$SERVER" -I $SERVER_IP -c "rename ToReNaMe.TxT TaRgEt.txt" 2>&1' + out=$(eval $cmd) + ret=$? + + rm -f $tmpfile + rm -f $targetfile + rm -f $LOCAL_PATH/TaRgEt.txt + + if [ $ret = 1 -a -z "${out##*COLLISION*}" ]; then + return 0 + else + echo "$out" + echo "failed to get file with different case" + return 1 + fi +} + +testit "accessing a file with different case succeeds" \ + test_access_with_different_case || + failed=$(expr $failed + 1) + +testit "renaming a file with different case succeeds" \ + test_rename || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smbXsrv_client_cross_node.sh b/source3/script/tests/test_smbXsrv_client_cross_node.sh new file mode 100755 index 0000000..5b412b2 --- /dev/null +++ b/source3/script/tests/test_smbXsrv_client_cross_node.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# +# Test smbd let cluster node 0 destroy the connection, +# if the client with a specific client-guid connections to node 1 +# + +if [ $# -lt 4 ]; then + echo Usage: test_smbXsrv_client_cross_node.sh SERVERCONFFILE NODE0 NODE1 SHARENAME + exit 1 +fi + +CONF=$1 +NODE0=$2 +NODE1=$3 +SHARE=$4 + +SMBCLIENT="$BINDIR/smbclient" +SMBSTATUS="$BINDIR/smbstatus" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +test_smbclient() +{ + name="$1" + server="$2" + share="$3" + cmd="$4" + shift + shift + subunit_start_test "$name" + output=$($VALGRIND $SMBCLIENT //$server/$share -c "$cmd" "$@" 2>&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +cd "$SELFTEST_TMPDIR" || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +smbstatus_num_sessions() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$SMBSTATUS" "$CONF" --json | jq -M '.sessions | length' +} + +testit_grep "step1: smbstatus 0 sessions" '^0$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +test_smbclient "smbclient against node0[${NODE0}]" "${NODE0}" "${SHARE}" "ls" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + || failed=$(expr $failed + 1) + +testit_grep "step2: smbstatus 0 sessions" '^0$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +testit "start backgroup smbclient against node0[${NODE0}]" true || failed=$(expr $failed + 1) + +# Connect a first time +${SMBCLIENT} //"${NODE0}"/"${SHARE}" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +testit "sleep 1 second" true || failed=$(expr $failed + 1) +sleep 1 + +testit_grep "step3: smbstatus 1 session" '^1$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +# Connect a second time +unset CLI_FORCE_INTERACTIVE +test_smbclient "smbclient against node1[${NODE1}]" "${NODE1}" "${SHARE}" "ls" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + || failed=$(expr $failed + 1) + +kill $CLIENT_PID +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +testit_grep "step24: smbstatus 0 sessions" '^0$' smbstatus_num_sessions || failed=$(expr $failed + 1) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbXsrv_client_ctdb_registered_ips.sh b/source3/script/tests/test_smbXsrv_client_ctdb_registered_ips.sh new file mode 100755 index 0000000..025a0fa --- /dev/null +++ b/source3/script/tests/test_smbXsrv_client_ctdb_registered_ips.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# +# Test smbd let cleanup registered ip addresses in a multichannel +# scenario +# + +if [ $# -lt 3 ]; then + echo Usage: test_smbXsrv_client_ctdb_registered_ips.sh SERVERCONFFILE CTDB_IFACE_IP SHARENAME + exit 1 +fi + +CONF=$1 +CTDB_IFACE_IP=$2 +SHARE=$3 + +SMBCLIENT="$BINDIR/smbclient" +SMBSTATUS="$BINDIR/smbstatus" +CTDB="$BINDIR/ctdb" +TIMELIMIT="$BINDIR/timelimit" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +test_smbclient() +{ + name="$1" + server="$2" + share="$3" + cmd="$4" + shift + shift + subunit_start_test "$name" + output=$($VALGRIND $SMBCLIENT //$server/$share -c "$cmd" "$@" 2>&1) + status=$? + if [ x$status = x0 ]; then + subunit_pass_test "$name" + else + echo "$output" | subunit_fail_test "$name" + fi + return $status +} + +cd "$SELFTEST_TMPDIR" || exit 1 + +# Create the smbclient communication pipes. +rm -f smbclient1-stdin smbclient1-stdout smbclient1-stderr +mkfifo smbclient1-stdin smbclient1-stdout smbclient1-stderr +rm -f smbclient2-stdin smbclient2-stdout smbclient2-stderr +mkfifo smbclient2-stdin smbclient2-stdout smbclient2-stderr + +smbstatus_num_sessions() +{ + # We don't check for died processes + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$SMBSTATUS" "$CONF" --fast --json | jq -M '.sessions | length' +} + +ctdb_add_public_ip() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" addip ${CTDB_IFACE_IP}/24 lo + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ipreallocate +} + +ctdb_ip() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ip +} + +ctdb_gettickles() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" gettickles ${CTDB_IFACE_IP} +} + +ctdb_reload_public_ips() +{ + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" reloadips 0 + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$CTDB" ipreallocate +} + +testit_grep_count "step1: smbstatus 0 sessions" '^0$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +test_smbclient "step2: smbclient against node0[${CTDB_IFACE_IP}]" "${CTDB_IFACE_IP}" "${SHARE}" "ls" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + || failed=$(expr $failed + 1) + +testit_grep_count "step2: smbstatus 0 sessions" '^0$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +testit "step3: start backgroup smbclient against node0[${CTDB_IFACE_IP}]" true || failed=$(expr $failed + 1) + +# Connect a first time +${SMBCLIENT} //"${CTDB_IFACE_IP}"/"${SHARE}" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + <smbclient1-stdin >smbclient1-stdout 2>smbclient1-stderr & +CLIENT1_PID=$! + +exec 100>smbclient1-stdin 101<smbclient1-stdout 102<smbclient1-stderr + +testit_grep_count "step3: smbclient1-stdout" 'Try "help" to get a list of possible commands.' 1 $TIMELIMIT 15 head -1 smbclient1-stdout || failed=$(expr $failed + 1) + +testit_grep_count "step3: smbstatus 1 session" '^1$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +testit_grep_count "step3: ctdb_ip" "${CTDB_IFACE_IP}" 0 ctdb_ip || failed=$(expr $failed + 1) +testit_expect_failure_grep "step3: ctdb_gettickles" "Control GET_TCP_TICKLE_LIST failed" ctdb_gettickles || failed=$(expr $failed + 1) + +testit "step4: ctdb_add_public_ip" ctdb_add_public_ip || failed=$(expr $failed + 1) + +testit_grep_count "step4: ctdb_ip" "^${CTDB_IFACE_IP} 0\$" 1 ctdb_ip || failed=$(expr $failed + 1) +testit_grep_count "step4: ctdb_gettickles" "Num connections: 0" 1 ctdb_gettickles || failed=$(expr $failed + 1) + +testit "step5: start backgroup 2nd smbclient against node0[${CTDB_IFACE_IP}]" true || failed=$(expr $failed + 1) +# Connect a second time +${SMBCLIENT} //"${CTDB_IFACE_IP}"/"${SHARE}" -U"${DC_USERNAME}"%"${DC_PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + <smbclient2-stdin >smbclient2-stdout 2>smbclient2-stderr & +CLIENT2_PID=$! + +exec 200>smbclient2-stdin 201<smbclient2-stdout 202<smbclient2-stderr + +testit_grep_count "step5: smbclient2-stdout" 'Try "help" to get a list of possible commands.' 1 $TIMELIMIT 15 head -1 smbclient2-stdout || failed=$(expr $failed + 1) + +testit_grep_count "step5: smbstatus 2 session" '^2$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +# Only one connection was registered with the public address +testit_grep_count "step5: ctdb_ip" "^${CTDB_IFACE_IP} 0\$" 1 ctdb_ip || failed=$(expr $failed + 1) +testit_grep_count "step5: ctdb_gettickles NUM" "Num connections: 1" 1 ctdb_gettickles || failed=$(expr $failed + 1) +testit_grep_count "step5: ctdb_gettickles DST" "DST: ${CTDB_IFACE_IP}" 1 ctdb_gettickles || failed=$(expr $failed + 1) + +unset CLI_FORCE_INTERACTIVE + +kill $CLIENT1_PID +rm -f smbclient1-stdin smbclient1-stdout smbclient1-stderr + +testit "step6: sleep 1 second" true || failed=$(expr $failed + 1) +sleep 1 + +testit_grep_count "step6: smbstatus 1 session" '^1$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +testit_grep_count "step6: ctdb_ip" "^${CTDB_IFACE_IP} 0\$" 1 ctdb_ip || failed=$(expr $failed + 1) +testit_grep_count "step6: ctdb_gettickles NUM" "Num connections: 1" 1 ctdb_gettickles || failed=$(expr $failed + 1) +testit_grep_count "step6: ctdb_gettickles DST" "DST: ${CTDB_IFACE_IP}" 1 ctdb_gettickles || failed=$(expr $failed + 1) + +testit "step7: ctdb_reload_public_ips" ctdb_reload_public_ips || failed=$(expr $failed + 1) + +testit_grep_count "step7: ctdb_ip" "${CTDB_IFACE_IP}" 0 ctdb_ip || failed=$(expr $failed + 1) +testit_expect_failure_grep "step3: ctdb_gettickles" "Control GET_TCP_TICKLE_LIST failed" ctdb_gettickles || failed=$(expr $failed + 1) + +testit "step7: sleep 2 second" true || failed=$(expr $failed + 1) +sleep 2 + +testit_grep_count "step7: smbstatus 0 sessions" '^0$' 1 smbstatus_num_sessions || failed=$(expr $failed + 1) + +kill $CLIENT2_PID +rm -f smbclient2-stdin smbclient2-stdout smbclient2-stderr + +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbXsrv_client_dead_rec.sh b/source3/script/tests/test_smbXsrv_client_dead_rec.sh new file mode 100755 index 0000000..e9e8f77 --- /dev/null +++ b/source3/script/tests/test_smbXsrv_client_dead_rec.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# +# Test smbd doesn't crash if there an existing dead record for a client with a +# specific client-guid in smbXsrv_client_global.tdb +# + +if [ $# -lt 2 ]; then + echo Usage: test_smbXsrv_client_dead_rec.sh SERVERCONFFILE IP SHARENAME + exit 1 +fi + +CONF=$1 +SERVER=$2 +SHARE=$3 + +SMBCLIENT="$BINDIR/smbclient" +SMBSTATUS="$BINDIR/smbstatus" + +SMBD_LOG_FILE="$SMBD_TEST_LOG" +if [ -n "$SMBD_DONT_LOG_STDOUT" ]; then + SMBD_LOG_FILE=$(dirname "$SMBD_TEST_LOG")/logs/log.smbd +fi +SMBD_LOG_FILE=$(realpath "$SMBD_LOG_FILE") + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +cd "$SELFTEST_TMPDIR" || exit 1 + +# +# Note if we already have any panics in the smbd log. +# +panic_count_0=$(grep -c PANIC "$SMBD_LOG_FILE") + +# Create the smbclient communication pipes. +rm -f smbclient-stdin smbclient-stdout smbclient-stderr +mkfifo smbclient-stdin smbclient-stdout smbclient-stderr + +CLI_FORCE_INTERACTIVE=1 +export CLI_FORCE_INTERACTIVE + +# Connect a first time +${SMBCLIENT} //"${SERVER}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + <smbclient-stdin >smbclient-stdout 2>smbclient-stderr & +CLIENT_PID=$! + +exec 100>smbclient-stdin 101<smbclient-stdout 102<smbclient-stderr + +SMBD_PID=$(UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 "$SMBSTATUS" -p "$CONF" | awk '/^[0-9]+/ {print $1}' | sort -u) + +# Kill the first connection, leaves dead record in smbXsrv_client_global.tdb +kill -KILL "$SMBD_PID" +kill $CLIENT_PID + +# Connect a second time +unset CLI_FORCE_INTERACTIVE +${SMBCLIENT} //"${SERVER}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" \ + --option="libsmb:client_guid=6112f7d3-9528-4a2a-8861-0ca129aae6c4" \ + -c exit + +rm -f smbclient-stdin smbclient-stdout smbclient-stderr + +# +# Ensure the panic count didn't change. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14882 +# +panic_count_1=$(grep -c PANIC "$SMBD_LOG_FILE") + +testit "check_panic" test "$panic_count_0" -eq "$panic_count_1" || + failed=$(expr $failed + 1) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbclient_auth.sh b/source3/script/tests/test_smbclient_auth.sh new file mode 100755 index 0000000..c6dcfc3 --- /dev/null +++ b/source3/script/tests/test_smbclient_auth.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 against shares with various options + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbclient_auth.sh SERVER SERVER_IP USERNAME PASSWORD SMBCLIENT <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBCLIENT="$5" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 5 +ADDARGS="$*" + +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +echo "${SERVER_IP}" | grep -q ':.*:' && { + # If we have an ipv6 address e.g. + # fd00:0000:0000:0000:0000:0000:5357:5f03 + # we also try + # fd00-0000-0000-0000-0000-0000-5357-5f03.ipv6-literal.net + IPV6LITERAL=$(echo "${SERVER_IP}.ipv6-literal.net" | sed -e 's!:!-!g' -e 's!%!s!') + testit "smbclient //${IPV6LITERAL}/tmpguest as user" $SMBCLIENT //${IPV6LITERAL}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS || failed=$(expr $failed + 1) + testit "smbclient //${IPV6LITERAL}./tmpguest as user" $SMBCLIENT //${IPV6LITERAL}./tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -c quit $ADDARGS || failed=$(expr $failed + 1) +} +testit "smbclient //${SERVER_IP}/tmpguest as user" $SMBCLIENT //${SERVER_IP}/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) + +testit "smbclient //$SERVER/guestonly as user" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/guestonly as anon" $SMBCLIENT //$SERVER/guestonly $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/tmpguest as user" $SMBCLIENT //$SERVER/tmpguest $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/tmpguest as anon" $SMBCLIENT //$SERVER/tmpguest $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser as user" $SMBCLIENT //$SERVER/forceuser $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser as anon" $SMBCLIENT //$SERVER/forceuser $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser_unixonly as user" $SMBCLIENT //$SERVER/forceuser_unixonly $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forceuser_wkngroup as user" $SMBCLIENT //$SERVER/forceuser_wkngroup $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forcegroup as user" $SMBCLIENT //$SERVER/forcegroup $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/forcegroup as anon" $SMBCLIENT //$SERVER/forcegroup $CONFIGURATION -U% -I $SERVER_IP -p 139 -c quit $ADDARGS || failed=$(expr $failed + 1) +exit $failed diff --git a/source3/script/tests/test_smbclient_basic.sh b/source3/script/tests/test_smbclient_basic.sh new file mode 100755 index 0000000..6e2a17c --- /dev/null +++ b/source3/script/tests/test_smbclient_basic.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 against shares with various options + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbclient_basic.sh SERVER SERVER_IP DOMAIN USERNAME PASSWORD SMBCLIENT <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +smbclient="$5" +CONFIGURATION="$6" +shift 6 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +# TEST using \ as the separator (default) +test_smbclient "smbclient as $DOMAIN\\$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN\\$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +# TEST using / as the separator (default) +test_smbclient "smbclient as $DOMAIN/$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN/$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) + +# TEST using 'winbind separator = +' +test_smbclient "smbclient as $DOMAIN+$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN+$USERNAME%$PASSWORD $ADDARGS --option=winbindseparator=+ || failed=$(expr $failed + 1) + +# TEST using 'winbind separator = +' set in a config file +smbclient_config="$PREFIX/tmpsmbconf" +cat >$smbclient_config <<EOF +[global] + include = $(echo $CONFIGURATION | cut -d= -f2) + winbind separator = + +EOF + +SAVE_CONFIGURATION="$CONFIGURATION" +CONFIGURATION="--configfile=$smbclient_config" +test_smbclient "smbclient as $DOMAIN+$USERNAME" 'ls' "//$SERVER/tmp" -U$DOMAIN+$USERNAME%$PASSWORD $ADDARGS || failed=$(expr $failed + 1) +CONFIGURATION="$SAVE_CONFIGURATION" +rm -rf $smbclient_config + +exit $failed diff --git a/source3/script/tests/test_smbclient_encryption.sh b/source3/script/tests/test_smbclient_encryption.sh new file mode 100755 index 0000000..2cbf5f0 --- /dev/null +++ b/source3/script/tests/test_smbclient_encryption.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbclient_encryption.sh USERNAME PASSWORD SERVER SMBCLIENT TARGET +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +SMBCLIENT="$VALGRIND $4" +TARGET="$5" +shift 5 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# +# Server configuration for fileserver: +# +# global: 'server smb encrypt = default' +# enc_desired: 'server smb encrypt = desired' +# tmpenc: 'server smb encrypt = required' +# tmp: has the global default 'server smb encrypt' +# +# Server configuration for simpleserver: +# +# global: 'server smb encrypt = off' +# enc_desired: 'server smb encrypt = desired' +# tmpenc: 'server smb encrypt = required' +# tmp: has the global default 'server smb encrypt' +# + +testit "smbclient.smb3.client.encrypt.desired[//$SERVER/enc_desired]" $SMBCLIENT //$SERVER/enc_desired -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=desired -c 'ls; quit' || failed=$(expr $failed + 1) +if [ "$TARGET" = "fileserver" ]; then + testit "smbclient.smb3.client.encrypt.desired[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=desired -c 'ls; quit' || failed=$(expr $failed + 1) +elif [ "$TARGET" = "simpleserver" ]; then # Encryption is globally disabled + testit_expect_failure "smbclient.smb3.client.encrypt.desired[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=desired -c 'ls; quit' || failed=$(expr $failed + 1) +fi +testit "smbclient.smb3.client.encrypt.desired[//$SERVER/tmp]" $SMBCLIENT //$SERVER/tmp -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=desired -c 'ls; quit' || failed=$(expr $failed + 1) + +testit "smbclient.smb3.client.encrypt.if_required[//$SERVER/enc_desired]" $SMBCLIENT //$SERVER/enc_desired -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=if_required -c 'ls; quit' || failed=$(expr $failed + 1) +if [ "$TARGET" = "fileserver" ]; then + testit "smbclient.smb3.client.encrypt.if_required[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=if_required -c 'ls; quit' || failed=$(expr $failed + 1) +elif [ "$TARGET" = "simpleserver" ]; then # Encryption is globally disabled + testit_expect_failure "smbclient.smb3.client.encrypt.if_required[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=if_required -c 'ls; quit' || failed=$(expr $failed + 1) +fi +testit "smbclient.smb3.client.encrypt.if_required[//$SERVER/tmp]" $SMBCLIENT //$SERVER/tmp -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=if_required -c 'ls; quit' || failed=$(expr $failed + 1) + +if [ "$TARGET" = "fileserver" ]; then + testit "smbclient.smb3.client.encrypt.required[//$SERVER/enc_desired]" $SMBCLIENT //$SERVER/enc_desired -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) + testit "smbclient.smb3.client.encrypt.required[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) + testit "smbclient.smb3.client.encrypt.required[//$SERVER/tmp]" $SMBCLIENT //$SERVER/tmp -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) +elif [ "$TARGET" = "simpleserver" ]; then # Encryption is globally disabled + testit_expect_failure "smbclient.smb3.client.encrypt.required[//$SERVER/enc_desired]" $SMBCLIENT //$SERVER/enc_desired -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) + testit_expect_failure "smbclient.smb3.client.encrypt.required[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) + testit_expect_failure "smbclient.smb3.client.encrypt.required[//$SERVER/tmp]" $SMBCLIENT //$SERVER/tmp -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=required -c 'ls; quit' || failed=$(expr $failed + 1) +fi + +testit "smbclient.smb3.client.encrypt.off[//$SERVER/enc_desired]" $SMBCLIENT //$SERVER/enc_desired -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=off -c 'ls; quit' || failed=$(expr $failed + 1) +if [ "$TARGET" = "fileserver" ]; then + testit "smbclient.smb3.client.encrypt.off[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=off -c 'ls; quit' || failed=$(expr $failed + 1) +elif [ "$TARGET" = "simpleserver" ]; then # Encryption is globally disabled + testit_expect_failure "smbclient.smb3.client.encrypt.off[//$SERVER/tmpenc]" $SMBCLIENT //$SERVER/tmpenc -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=off -c 'ls; quit' || failed=$(expr $failed + 1) +fi +testit "smbclient.smb3.client.encrypt.off[//$SERVER/tmp]" $SMBCLIENT //$SERVER/tmp -U$USERNAME%$PASSWORD -mSMB3 --option=clientsmbencrypt=off -c 'ls; quit' || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_encryption_off.sh b/source3/script/tests/test_smbclient_encryption_off.sh new file mode 100755 index 0000000..4bd99a0 --- /dev/null +++ b/source3/script/tests/test_smbclient_encryption_off.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_smbclient_encryption_off.sh USERNAME PASSWORD SERVER SMBCLIENT +EOF + exit 1 +fi + +USERNAME="$1" +PASSWORD="$2" +SERVER="$3" +SMBCLIENT="$VALGRIND $4" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# +# Let me introduce you to the shares used in this test: +# +# "tmp" has the default "smb encrypt" (which is "enabled") +# "tmpenc" has "smb encrypt = required" +# "enc_desired" has "smb encrypt = desired" +# + +# Unencrypted connections should work of course, let's test em to be sure... + +# SMB1 +testit "smbclient //$SERVER/enc_desired" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit "smbclient //$SERVER/tmp" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) +# SMB3_02 +testit "smbclient -m smb3_02 //$SERVER/enc_desired" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit "smbclient -m smb3_02 //$SERVER/tmp" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) +# SMB3_11 +testit "smbclient -m smb3_11 //$SERVER/enc_desired" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit "smbclient -m smb3_11 //$SERVER/tmp" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) + +# These tests must fail, as encryption is globally off and in combination with "smb +# encrypt=required" on the share "tmpenc" the server *must* reject the tcon. + +# SMB1 +testit_expect_failure "smbclient //$SERVER/tmpenc" $SMBCLIENT -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt //$SERVER/tmpenc" $SMBCLIENT --client-protection=encrypt -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) +# SMB3_02 +testit_expect_failure "smbclient -m smb3_02 //$SERVER/tmpenc" $SMBCLIENT -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_02 //$SERVER/tmpenc" $SMBCLIENT --client-protection=encrypt -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) +# SMB3_11 +testit_expect_failure "smbclient -m smb3_11 //$SERVER/tmpenc" $SMBCLIENT -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_11 //$SERVER/tmpenc" $SMBCLIENT --client-protection=encrypt -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmpenc -c quit || failed=$(expr $failed + 1) + +# These tests must fail, as the client requires encryption and it's off on the server + +# SMB1 +testit_expect_failure "smbclient --client-protection=encrypt //$SERVER/enc_desired" $SMBCLIENT --client-protection=encrypt -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt //$SERVER/tmp" $SMBCLIENT --client-protection=encrypt -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) +# SMB3_02 +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_02 //$SERVER/enc_desired" $SMBCLIENT --client-protection=encrypt -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_02 //$SERVER/tmp" $SMBCLIENT --client-protection=encrypt -m smb3_02 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) +# SMB3_11 +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_11 //$SERVER/enc_desired" $SMBCLIENT --client-protection=encrypt -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/enc_desired -c quit || failed=$(expr $failed + 1) +testit_expect_failure "smbclient --client-protection=encrypt -m smb3_11 //$SERVER/tmp" $SMBCLIENT --client-protection=encrypt -m smb3_11 -U $USERNAME%$PASSWORD //$SERVER/tmp -c quit || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_iconv.sh b/source3/script/tests/test_smbclient_iconv.sh new file mode 100755 index 0000000..e6cdc5e --- /dev/null +++ b/source3/script/tests/test_smbclient_iconv.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# This checks directory listing with a file containing +# an invalid CP850 conversion name returns NT_STATUS_INVALID_NETWORK_RESPONSE + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smbclient_iconv.sh SERVER SERVER_IP SHARENAME USERNAME PASSWORD SMBCLIENT +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +SHARENAME="$3" +USERNAME="$4" +PASSWORD="$5" +SMBCLIENT="$6" +shift 6 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_smbclient_iconv() +{ + normal_smbclient_config="$PREFIX/client/client.conf" + smbclient_config="$PREFIX/client/client_cp850_smbconf" + cat >$smbclient_config <<EOF +[global] + include = $normal_smbclient_config + unix charset = cp850 + client min protocol = core +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/$SHARENAME --configfile=$smbclient_config "$ADDARGS" -c ls 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + rm -f $smbclient_config + + echo "$out" | grep 'NT_STATUS_INVALID_NETWORK_RESPONSE' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo 'failed - should get: NT_STATUS_INVALID_NETWORK_RESPONSE.' + return 1 + fi + + return 0 +} + +testit "bad_iconv smbclient" test_smbclient_iconv || failed=$(expr $failed + 1) +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_kerberos.sh b/source3/script/tests/test_smbclient_kerberos.sh new file mode 100755 index 0000000..31678d1 --- /dev/null +++ b/source3/script/tests/test_smbclient_kerberos.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smbclient_kerberos.sh USERNAME REALM PASSWORD SERVER SMBCLIENT TARGET +EOF + exit 1 +fi + +USERNAME="$1" +REALM=$2 +PASSWORD="$3" +SERVER="$4" +smbclient="$5" +TARGET="$6" +shift 6 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. ${incdir}/subunit.sh +. ${incdir}/common_test_fns.inc + +failed=0 + +samba_kinit=kinit +if test -x ${BINDIR}/samba4kinit; then + samba_kinit=${BINDIR}/samba4kinit +fi + +samba_kdestroy=kdestroy +if test -x ${BINDIR}/samba4kdestroy; then + samba_kdestroy=${BINDIR}/samba4kdestroy +fi + +KRB5CCNAME_PATH="${PREFIX}/ccache_smbclient_kerberos" +KRB5CCNAME="FILE:${KRB5CCNAME_PATH}" +export KRB5CCNAME + +# For ad_dc_fips this should succeed as Kerberos is set to required by default +test_smbclient "smbclient.smb3.kerberos[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) + +test_smbclient "smbclient.smb3.kerberos.required[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-kerberos=required -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) + +test_smbclient "smbclient.smb3.kerberos.desired[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-kerberos=desired -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) + +if [ "$TARGET" = "ad_dc_fips" ] || [ "$TARGET" = "ad_member_fips" ]; then + test_smbclient_expect_failure "smbclient.smb3.kerberos.off[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-kerberos=off -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) +else + test_smbclient "smbclient.smb3.kerberos.off[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-kerberos=off -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) +fi + +kerberos_kinit $samba_kinit ${USERNAME}@${REALM} ${PASSWORD} +test_smbclient "smbclient.smb3.kerberos.ccache[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-krb5-ccache=${KRB5CCNAME} -mSMB3 || + failed=$(expr $failed + 1) +test_smbclient "smbclient.smb3.kerberos.desired[//${SERVER}/tmp]" \ + "ls; quit" //${SERVER}/tmp \ + --use-kerberos=desired -U${USERNAME}%${PASSWORD} -mSMB3 || + failed=$(expr $failed + 1) + +$samba_kdestroy + +rm -rf $KRB5CCNAME_PATH + +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbclient_krb5.sh b/source3/script/tests/test_smbclient_krb5.sh new file mode 100755 index 0000000..98fa789 --- /dev/null +++ b/source3/script/tests/test_smbclient_krb5.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_smbclient_krb5.sh ccache smbclient3 server <smbclient args> +EOF + exit 1 +fi + +KRB5CCNAME=$1 +export KRB5CCNAME +SMBCLIENT3=$2 +SERVER=$3 +shift 3 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "smbclient" $VALGRIND $SMBCLIENT3 //$SERVER/tmp -c 'ls' --use-krb5-ccache=$KRB5CCNAME $ADDARGS || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_large_file.sh b/source3/script/tests/test_smbclient_large_file.sh new file mode 100755 index 0000000..80816be --- /dev/null +++ b/source3/script/tests/test_smbclient_large_file.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_smbclient_large_file.sh ccache smbclient3 server prefix <smbclient args> +EOF + exit 1 +fi + +KRB5CCNAME=$1 +export KRB5CCNAME +SMBCLIENT3=$2 +SERVER=$3 +PREFIX=$4 +shift 4 +ADDARGS="$*" + +# Test that a noninteractive smbclient does not prompt +test_large_write_read() +{ + + cat >$PREFIX/largefile-script <<EOF +posix +put $PREFIX/largefile largefile +get largefile $PREFIX/largefile2 +rm largefile +quit +EOF + + cmd='$SMBCLIENT3 //$SERVER/xcopy_share $ADDARGS < $PREFIX/largefile-script 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + + if [ $? != 0 ]; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep "getting file" >/dev/null 2>&1 + + if [ $? = 0 ]; then + true + else + echo did not get success message + false + fi +} + +rm -f $PREFIX/largefile +dd if=/dev/zero of=$PREFIX/largefile seek=$((20 * 1024 * 1024)) count=1 bs=1 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "smbclient large posix write read" test_large_write_read || failed=$(expr $failed + 1) + +testit "cmp of read and written files" cmp $PREFIX/largefile $PREFIX/largefile2 || failed=$(expr $failed + 1) +rm -f $PREFIX/largefile2 + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_list_servers.sh b/source3/script/tests/test_smbclient_list_servers.sh new file mode 100755 index 0000000..237e82f --- /dev/null +++ b/source3/script/tests/test_smbclient_list_servers.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# +# Ensure we don't get an error smb1cli_req_writev_submit: called for dialect[SMB3_11] +# when listing servers via -L. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14939 + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbclient_list_servers.sh SERVER SERVER_IP USERNAME PASSWORD SMBCLIENT +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +SMBCLIENT="$5" +shift 5 +ADDARGS="$@" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir/subunit.sh" + +failed=0 + +test_smbclient_list_servers() +{ + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -L //$SERVER -U$USERNAME%$PASSWORD -I $SERVER_IP -p139 "$ADDARGS" </dev/null 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + + echo "$out" | grep 'smb1cli_req_writev_submit:' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo 'failed - should not get: smb1cli_req_writev_submit: error.' + return 1 + fi + + return 0 +} + +testit "smb1_list_servers" test_smbclient_list_servers || failed=$((failed + 1)) +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbclient_log_basename.sh b/source3/script/tests/test_smbclient_log_basename.sh new file mode 100755 index 0000000..f29009f --- /dev/null +++ b/source3/script/tests/test_smbclient_log_basename.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# this test checks whether smbclient can log into -l log-basename + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: test_smbclient_log_basename.sh SERVER SMBCLIENT PREFIX <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SMBCLIENT="$2" +PREFIX="$3" +shift 3 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +LOG_DIR=$PREFIX/st_log_basename_dir + +test_smbclient_log_basename() +{ + rm -rf $LOG_DIR + mkdir $LOG_DIR + cmd='$VALGRIND $SMBCLIENT -l $LOG_DIR -d3 //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -c quit $ADDARGS' + out=$(eval $cmd 2>&1) + grep 'Client started' $LOG_DIR/log.smbclient +} + +testit "smbclient log-basename" test_smbclient_log_basename || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_machine_auth.sh b/source3/script/tests/test_smbclient_machine_auth.sh new file mode 100755 index 0000000..c89f848 --- /dev/null +++ b/source3/script/tests/test_smbclient_machine_auth.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 against shares with various options + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: test_smbclient_machine_auth.sh SERVER SMBCLIENT CONFIGURATION <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SMBCLIENT="$2" +# This is used by test_smbclient() +# shellcheck disable=2034 +CONFIGURATION="${3}" +shift 3 +ADDARGS="$*" + +# This is used by test_smbclient() +# shellcheck disable=2034 +smbclient="${VALGRIND} ${SMBCLIENT}" + +incdir="$(dirname "${0}")/../../../testprogs/blackbox" +. "${incdir}/subunit.sh" +. "${incdir}/common_test_fns.inc" + +failed=0 + +test_smbclient "smbclient //${SERVER}/tmp" \ + "quit" "//${SERVER}/tmp" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +# Testing these here helps because we know the machine account isn't already +# this user/group. +test_smbclient "smbclient //${SERVER}/forceuser" \ + "quit" "//${SERVER}/forceuser" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +test_smbclient "smbclient //${SERVER}/forcegroup" \ + "quit" "//${SERVER}/forcegroup" --machine-pass -p 139 "${ADDARGS}" || \ + failed=$((failed + 1)) + +exit ${failed} diff --git a/source3/script/tests/test_smbclient_mget.sh b/source3/script/tests/test_smbclient_mget.sh new file mode 100755 index 0000000..5275d50 --- /dev/null +++ b/source3/script/tests/test_smbclient_mget.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 smbclient3 server share user password directory +EOF + exit 1 +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +SMBCLIENT3="$1" +shift +SERVER="$1" +shift +SHARE="$1" +shift +USERNAME="$1" +shift +PASSWORD="$1" +shift +DIRECTORY="$1" +shift + +cd $SELFTEST_TMPDIR || exit 1 + +# Can't use "testit" here -- it somehow breaks the -c command passed +# to smbclient into two, spoiling the "mget" + +name="smbclient mget" +subunit_start_test "$name" +output=$("$SMBCLIENT3" //"$SERVER"/"$SHARE" \ + -U"$USERNAME"%"$PASSWORD" -c "recurse;prompt;mget $DIRECTORY") +status=$? +if [ x$status = x0 ]; then + subunit_pass_test "$name" +else + echo "$output" | subunit_fail_test "$name" +fi + +testit "rm foo" rm "$DIRECTORY"/foo || failed=$(expr $failed + 1) +testit "rmdir $DIRECTORY" rmdir "$DIRECTORY" || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_netbios_aliases.sh b/source3/script/tests/test_smbclient_netbios_aliases.sh new file mode 100755 index 0000000..e48b46b --- /dev/null +++ b/source3/script/tests/test_smbclient_netbios_aliases.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smbclient_netbios_aliases.sh smbclient3 SERVER USERNAME PASSWORD PREFIX CONFIGURATION +EOF + exit 1 +fi + +smbclient=$1 +SERVER=$2 +USERNAME=$3 +PASSWORD=$4 +PREFIX=$5 +CONFIGURATION=$6 +shift 6 +ADDADS="$@" + +samba_bindir="$BINDIR" +samba_srcdir="$SRCDIR/source4" +samba_kinit=kinit +if test -x ${samba_bindir}/samba4kinit; then + samba_kinit=${samba_bindir}/samba4kinit +fi + +KRB5CCNAME_PATH="$PREFIX/test_smbclient_netbios_aliases_krb5ccache" +rm -rf $KRB5CCNAME_PATH + +KRB5CCNAME="FILE:$KRB5CCNAME_PATH" +export KRB5CCNAME + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +testit "kinit" kerberos_kinit ${samba_kinit} ${USERNAME} ${PASSWORD} + +test_smbclient "smbclient (krb5)" "ls" "//$SERVER/tmp" --use-krb5-ccache=$KRB5CCNAME || failed=$(expr $failed + 1) + +rm -rf $KRB5CCNAME_PATH + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_ntlm.sh b/source3/script/tests/test_smbclient_ntlm.sh new file mode 100755 index 0000000..1e53b1e --- /dev/null +++ b/source3/script/tests/test_smbclient_ntlm.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# this runs a smbclient based authentication tests + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smbclient_ntlm.sh SERVER USERNAME PASSWORD MAPTOGUEST SMBCLIENT PROTOCOL CONFIGURATION <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +MAPTOGUEST="$4" +SMBCLIENT="$5" +PROTOCOL="$6" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +CONFIGURATION=${7} +shift 7 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +if [ $PROTOCOL != "SMB3" -a $PROTOCOL != "NT1" ]; then + cat <<EOF +Uexpected protocol specified $PROTOCOL +EOF + exit 1 +fi + +failed=0 + +if [ $PROTOCOL = "NT1" ]; then + testit "smbclient username.password.NT1OLD" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U$USERNAME%$PASSWORD -mNT1 --option=clientusespnego=no --option=clientntlmv2auth=no -c quit $ADDARGS || failed=$((failed + 1)) + testit "smbclient username.password.NT1NEW" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U$USERNAME%$PASSWORD -mNT1 -c quit $ADDARGS || failed=$((failed + 1)) +fi +if [ $PROTOCOL = "SMB3" ]; then + testit "smbclient username.password.SMB3" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U$USERNAME%$PASSWORD -mSMB3 -c quit $ADDARGS || failed=$((failed + 1)) +fi + +if [ $PROTOCOL = "NT1" ]; then + testit "smbclient anonymous.nopassword.NT1OLD" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U% -mNT1 --option=clientusespnego=no --option=clientntlmv2auth=no -c quit $ADDARGS || failed=$((failed + 1)) + testit "smbclient anonymous.nopassword.NT1NEW" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U% -mNT1 -c quit $ADDARGS || failed=$((failed + 1)) +fi +if [ $PROTOCOL = "SMB3" ]; then + testit "smbclient anonymous.nopassword.SMB3" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U% -mSMB3 -c quit $ADDARGS || failed=$((failed + 1)) +fi +if test x"${MAPTOGUEST}" = x"never"; then + if [ $PROTOCOL = "NT1" ]; then + testit_expect_failure "smbclient anonymous.badpassword.NT1NEW.fail" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -mNT1 -c quit $ADDARGS || failed=$((failed + 1)) + fi + if [ $PROTOCOL = "SMB3" ]; then + testit_expect_failure "smbclient anonymous.badpassword.SMB3.fail" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -mSMB3 -c quit $ADDARGS || failed=$((failed + 1)) + fi +else + if [ $PROTOCOL = "NT1" ]; then + testit "smbclient anonymous.badpassword.NT1NEW.guest" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -mNT1 -c quit $ADDARGS || failed=$((failed + 1)) + fi + if [ $PROTOCOL = "SMB3" ]; then + testit "smbclient anonymous.badpassword.SMB3.guest" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -U%badpassword -mSMB3 -c quit $ADDARGS || failed=$((failed + 1)) + fi + + if [ $PROTOCOL = "NT1" ]; then + testit "smbclient baduser.badpassword.NT1NEW.guest" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -Ubaduser%badpassword -mNT1 -c quit $ADDARGS || failed=$((failed + 1)) + fi + if [ $PROTOCOL = "SMB3" ]; then + testit "smbclient baduser.badpassword.SMB3.guest" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -Ubaduser%badpassword -mSMB3 -c quit $ADDARGS || failed=$((failed + 1)) + fi + if [ $PROTOCOL = "NT1" ]; then + testit_expect_failure "smbclient baduser.badpassword.NT1OLD.signfail" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -Ubaduser%badpassword -mNT1 --option=clientusespnego=no --option=clientntlmv2auth=no --client-protection=sign -c quit $ADDARGS || failed=$((failed + 1)) + testit_expect_failure "smbclient baduser.badpassword.NT1NEW.signfail" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -Ubaduser%badpassword -mNT1 --client-protection=sign -c quit $ADDARGS || failed=$((failed + 1)) + fi + if [ $PROTOCOL = "SMB3" ]; then + testit_expect_failure "smbclient baduser.badpassword.SMB3.signfail" $SMBCLIENT //$SERVER/IPC\$ $CONFIGURATION -Ubaduser%badpassword -mSMB3 --client-protection=sign -c quit $ADDARGS || failed=$((failed + 1)) + fi +fi + +exit ${failed} diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh new file mode 100755 index 0000000..cbff502 --- /dev/null +++ b/source3/script/tests/test_smbclient_s3.sh @@ -0,0 +1,2364 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 + +if [ $# -lt 13 ]; then + cat <<EOF +Usage: test_smbclient_s3.sh SERVER SERVER_IP DOMAIN USERNAME PASSWORD USERID LOCAL_PATH PREFIX SMBCLIENT WBINFO NET CONFIGURATION PROTOCOL +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +DOMAIN="${3}" +USERNAME="${4}" +PASSWORD="${5}" +USERID="${6}" +LOCAL_PATH="${7}" +PREFIX="${8}" +SMBCLIENT="${9}" +WBINFO="${10}" +NET="${11}" +CONFIGURATION="${12}" +PROTOCOL="${13}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +WBINFO="$VALGRIND ${WBINFO}" +shift 13 +RAWARGS="${CONFIGURATION} -m${PROTOCOL}" +ADDARGS="${RAWARGS} $*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Test that a noninteractive smbclient does not prompt +test_noninteractive_no_prompt() +{ + prompt="smb" + + cmd='echo du | $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + + if [ $? != 0 ]; then + echo "$out" + echo "command failed" + return 1 + fi + + echo "$out" | grep $prompt >/dev/null 2>&1 + + if [ $? = 0 ]; then + # got a prompt .. fail + echo matched interactive prompt in non-interactive mode + return 1 + fi + + return 0 +} + +# Test that an interactive smbclient prompts to stdout +test_interactive_prompt_stdout() +{ + prompt="smb" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + cat >$tmpfile <<EOF +du +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed" + return 1 + fi + + echo "$out" | grep $prompt >/dev/null 2>&1 + + if [ $? != 0 ]; then + echo failed to match interactive prompt on stdout + return 1 + fi + + return 0 +} + +# Test creating a bad symlink and deleting it. +test_bad_symlink() +{ + prompt="posix_unlink deleted file /newname" + tmpfile=$PREFIX/smbclient_bad_symlinks_commands + + cat >$tmpfile <<EOF +posix +posix_unlink newname +symlink badname newname +posix_unlink newname +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed create then delete bad symlink with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed create then delete bad symlink - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test creating a good symlink and deleting it by path. +test_good_symlink() +{ + tmpfile=$PREFIX/smbclient.in.$$ + slink_name="$LOCAL_PATH/slink" + slink_target="$LOCAL_PATH/slink_target" + + touch $slink_target + ln -s $slink_target $slink_name + cat >$tmpfile <<EOF +del slink +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed delete good symlink with error $ret" + rm $slink_target + rm $slink_name + return 1 + fi + + if [ ! -e $slink_target ]; then + echo "failed delete good symlink - symlink target deleted !" + rm $slink_target + rm $slink_name + return 1 + fi + + if [ -e $slink_name ]; then + echo "failed delete good symlink - symlink still exists" + rm $slink_target + rm $slink_name + return 1 + fi + + rm $slink_target + return 0 +} + +# Test writing into a read-only directory (logon as guest) fails. +test_read_only_dir() +{ + prompt="NT_STATUS_ACCESS_DENIED making remote directory" + tmpfile=$PREFIX/smbclient.in.$$ + + ## + ## We can't do this as non-root. We always have rights to + ## create the directory. + ## + if [ "$USERID" != 0 ]; then + echo "skipping test_read_only_dir as non-root" + return 0 + fi + + ## + ## We can't do this with an encrypted connection. No credentials + ## to set up the channel. + ## + if [ "$ADDARGS" = "-e" ]; then + echo "skipping test_read_only_dir with encrypted connection" + return 0 + fi + + cat >$tmpfile <<EOF +mkdir a_test_dir +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U% "//$SERVER/$1" -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed writing into read-only directory with error $ret" + + return 1 + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed writing into read-only directory - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test sending a message +test_message() +{ + tmpfile=$PREFIX/message_in.$$ + + cat >$tmpfile <<EOF +Test message from pid $$ +EOF + + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD -M $SERVER -p 139 $ADDARGS -n msgtest < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed sending message to $SERVER with error $ret" + rm -f $tmpfile + return 1 + fi + + # The server writes this into a file message.msgtest, via message.%m to test the % sub code + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmpguest -p 139 $ADDARGS -c "get message.msgtest $PREFIX/message_out.$$" 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed getting sent message from $SERVER with error $ret" + return 1 + fi + + if cmp $PREFIX/message_out.$$ $tmpfile; then + echo "failed comparison of message from $SERVER" + return 1 + fi + + return 0 +} + +# Test reading an owner-only file (logon as guest) fails. +test_owner_only_file() +{ + prompt="NT_STATUS_ACCESS_DENIED opening remote file" + tmpfile=$PREFIX/smbclient.in.$$ + + ## + ## We can't do this as non-root. We always have rights to + ## read the file. + ## + if [ "$USERID" != 0 ]; then + echo "skipping test_owner_only_file as non-root" + return 0 + fi + + ## + ## We can't do this with an encrypted connection. No credentials + ## to set up the channel. + ## + if [ "$ADDARGS" = "-e" ]; then + echo "skipping test_owner_only_file with encrypted connection" + return 0 + fi + + cat >$tmpfile <<EOF +get unreadable_file +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U% //$SERVER/ro-tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed reading owner-only file with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed reading owner-only file - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test accessing an msdfs path. +test_msdfs_link() +{ + tmpfile=$PREFIX/smbclient.in.$$ + prompt=" msdfs-target " + + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS -m $PROTOCOL -c dir 2>&1' + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing msfds-share\ with error $ret" + return 1 + fi + + cat >$tmpfile <<EOF +ls +cd \\msdfs-src1 +ls msdfs-target +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing \\msdfs-src1 link with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\msdfs-src1 - grep failed with $ret" + return 1 + fi + + cat >$tmpfile <<EOF +ls +cd \\deeppath\\msdfs-src2 +ls msdfs-target +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing \\deeppath\\msdfs-src2 link with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\deeppath\\msdfs-src2 - grep failed with $ret" + return 1 + fi + + return 0 +} + +# Test recursive listing across msdfs links +test_msdfs_recursive_dir() +{ + tmpfile=$PREFIX/smbclient.in.$$ + + cat >$tmpfile <<EOF +recurse +dir +quit +EOF + + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS -m $PROTOCOL < $tmpfile 2>&1' + out=$(eval $cmd) + ret="$?" + + if [ "$ret" -ne 0 ]; then + echo "$out" + echo "failed listing msfds-share\ with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS_OBJECT_PATH_NOT_FOUND listing \widelinks\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\dot\*' > /dev/null 2>&1 + + ret="$?" + if [ "$ret" -ne 0 ]; then + echo "$out" + echo "Listing \\msdfs-share recursively did not properly end in symlink recursion" + fi + + return 0 +} + +# Test doing a normal file rename on an msdfs path. +test_msdfs_rename() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_dst="dest.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + # + # Use both non-force and force rename to + # ensure we test both codepaths inside libsmb. + # + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename_src +ren $filename_src $filename_dst -f +ren $filename_dst $filename_src +del $filename_src +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f "$tmpfile" + rm -f "$filename_src_path" + + if [ $ret != 0 ]; then + echo "$out" + echo "failed renaming $filename_src $filename_dst with error $ret" + return 1 + fi + + echo "$out" | grep "NT_STATUS" >/dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ]; then + echo "$out" + echo "renaming $filename_src $filename_dst got NT_STATUS_ error" + return 1 + fi + return 0 +} + +# Test doing a normal file hardlink on an msdfs path. +test_msdfs_hardlink() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_dst="dest.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename_src +hardlink $filename_src $filename_dst +del $filename_src +del $filename_dst +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f "$tmpfile" + rm -f "$filename_src_path" + + if [ $ret != 0 ]; then + echo "$out" + echo "failed hardlink $filename_src $filename_dst with error $ret" + return 1 + fi + + echo "$out" | grep "NT_STATUS" >/dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ]; then + echo "$out" + echo "hardlink $filename_src $filename_dst got NT_STATUS_ error" + return 1 + fi + return 0 +} + +test_msdfs_del() +{ + tmpfile="$PREFIX/smbclient.in.$$" + filename_src="src.$$" + filename_src_path="$PREFIX/$filename_src" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat > $tmpfile <<EOF +lcd $PREFIX +cd dfshop1 +cd dfshop2 +put $filename_src +del $filename_src +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=`eval $cmd` + ret=$? + rm -f "$tmpfile" + rm -f "$filename_src_path" + + if [ $ret != 0 ] ; then + echo "$out" + echo "failed deleting $filename_src with error $ret" + return 1 + fi + + echo "$out" | grep "NT_STATUS" >/dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ] ; then + echo "$out" + echo "del $filename_src NT_STATUS_ error" + return 1 + fi + return 0 +} + +test_msdfs_deltree() +{ + tmpfile="$PREFIX/smbclient.in.$$" + dirname_src="foodir.$$" + filename_src="src.$$" + filename_src_path="$PREFIX/$filename_src" + dirname_src_path="$PREFIX/$dirname" + rm -f "$filename_src_path" + touch "$filename_src_path" + + cat > $tmpfile <<EOF +lcd $PREFIX +cd dfshop1 +cd dfshop2 +mkdir $dirname_src +cd $dirname_src +put $filename_src +cd .. +deltree $dirname_src +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=`eval $cmd` + ret=$? + rm -f "$tmpfile" + rm -f "$filename_src_path" + rm -f "$dirname_src_path" + + if [ $ret != 0 ] ; then + echo "$out" + echo "deltree failed deleting dir $dirname_src with error $ret" + return 1 + fi + + echo "$out" | grep "NT_STATUS" >/dev/null 2>&1 + + ret="$?" + if [ "$ret" -eq 0 ] ; then + echo "$out" + echo "deltree $dirname_src NT_STATUS_ error" + return 1 + fi + return 0 +} + +# Archive bits are correctly set on file/dir creation and rename. +test_rename_archive_bit() +{ + prompt_file="attributes: A (20)" + prompt_dir="attributes: D (10)" + tmpfile="$PREFIX/smbclient.in.$$" + filename="foo.$$" + filename_ren="bar.$$" + dirname="foodir.$$" + dirname_ren="bardir.$$" + filename_path="$PREFIX/$filename" + local_name1="$LOCAL_PATH/$filename" + local_name2="$LOCAL_PATH/$filename_ren" + local_dir_name1="$LOCAL_PATH/$dirname" + local_dir_name2="$LOCAL_PATH/$dirname_ren" + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + # Create a new file, ensure it has 'A' attributes. + touch $filename_path + + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename +allinfo $filename +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating file $filename with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt_file" >/dev/null 2>&1 + + ret=$? + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on new file $ret" + return 1 + fi + + # Now check if we remove 'A' and rename, the A comes back. + touch $filename_path + + cat >$tmpfile <<EOF +lcd $PREFIX +put $filename +setmode $filename -a +ren $filename $filename_ren +allinfo $filename_ren +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating file and renaming $filename with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt_file" >/dev/null 2>&1 + + ret=$? + + rm -f $filename_path + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on renamed file $ret" + return 1 + fi + + rm -rf $local_dir_name1 + rm -rf $local_dir_name2 + + # Create a new directory, ensure it has 'D' but not 'A' attributes. + + cat >$tmpfile <<EOF +mkdir $dirname +allinfo $dirname +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating directory $dirname with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt_dir" >/dev/null 2>&1 + + ret=$? + + rm -rf $local_dir_name1 + rm -rf $local_dir_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on new directory $ret" + return 1 + fi + + # Now check if we rename, we still only have 'D' attributes + + cat >$tmpfile <<EOF +mkdir $dirname +ren $dirname $dirname_ren +allinfo $dirname_ren +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating directory $dirname and renaming with error $ret" + return 1 + fi + + echo "$out" | grep "$prompt_dir" >/dev/null 2>&1 + + ret=$? + + rm -f $local_name1 + rm -f $local_name2 + + if [ $ret != 0 ]; then + echo "$out" + echo "Attributes incorrect on renamed directory $ret" + return 1 + fi + + return 0 +} + +# Test authenticating using the winbind ccache +test_ccache_access() +{ + $WBINFO --ccache-save="${USERNAME}%${PASSWORD}" + ret=$? + + if [ $ret != 0 ]; then + echo "wbinfo failed to store creds in cache (user='${USERNAME}', pass='${PASSWORD}')" + return 1 + fi + + $SMBCLIENT //$SERVER_IP/tmp --use-winbind-ccache -U "${USERNAME}" $ADDARGS -c quit 2>&1 + ret=$? + + if [ $ret != 0 ]; then + echo "smbclient failed to use cached credentials" + return 1 + fi + + $WBINFO --ccache-save="${USERNAME}%GarBage" + ret=$? + + if [ $ret != 0 ]; then + echo "wbinfo failed to store creds in cache (user='${USERNAME}', pass='GarBage')" + return 1 + fi + + $SMBCLIENT //$SERVER_IP/tmp --use-winbind-ccache -U "${USERNAME}" $ADDARGS -c quit 2>&1 + ret=$? + + if [ $ret -eq 0 ]; then + echo "smbclient succeeded with wrong cached credentials" + return 1 + fi + + $WBINFO --logoff +} + +# Test authenticating using the winbind ccache +test_auth_file() +{ + tmpfile=$PREFIX/smbclient.in.$$ + cat >$tmpfile <<EOF +username=${USERNAME} +password=${PASSWORD} +domain=${DOMAIN} +EOF + $SMBCLIENT //$SERVER_IP/tmp --authentication-file=$tmpfile $ADDARGS -c quit 2>&1 + ret=$? + rm $tmpfile + + if [ $ret != 0 ]; then + echo "smbclient failed to use auth file" + return 1 + fi + + cat >$tmpfile <<EOF +username=${USERNAME} +password=xxxx +domain=${DOMAIN} +EOF + $SMBCLIENT //$SERVER_IP/tmp --authentication-file=$tmpfile $ADDARGS -c quit 2>&1 + ret=$? + rm $tmpfile + + if [ $ret -eq 0 ]; then + echo "smbclient succeeded with wrong auth file credentials" + return 1 + fi +} + +# Test doing a directory listing with backup privilege. +test_backup_privilege_list() +{ + tmpfile=$PREFIX/smbclient_backup_privilege_list + + # selftest uses the forward slash as a separator, but "net sam rights + # grant" requires the backslash separator + USER_TMP=$(printf '%s' "$USERNAME" | tr '/' '\\') + + # If we don't have a DOMAIN component to the username, add it. + printf '%s' "$USER_TMP" | grep '\\' 2>&1 + ret=$? + if [ $ret != 0 ]; then + priv_username="$DOMAIN\\$USER_TMP" + else + priv_username="$USER_TMP" + fi + + $NET sam rights grant $priv_username SeBackupPrivilege 2>&1 + ret=$? + if [ $ret != 0 ]; then + echo "Failed to add SeBackupPrivilege to user $priv_username - $ret" + return 1 + fi + + cat >$tmpfile <<EOF +backup +ls +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed backup privilege list $ret" + return 1 + fi + + # Now remove all privileges from this SID. + $NET sam rights revoke $priv_username SeBackupPrivilege 2>&1 + ret=$? + if [ $ret != 0 ]; then + echo "failed to remove SeBackupPrivilege from user $priv_username - $ret" + return 1 + fi +} + +# Test accessing an share with bad names (won't convert). +test_bad_names() +{ + # First with SMB1 + + if [ $PROTOCOL = "NT1" ]; then + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/badname-tmp -I $SERVER_IP $ADDARGS -m$PROTOCOL -c ls 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing badname-tmp (SMB1) with error $ret" + return 1 + fi + + echo "$out" | wc -l 2>&1 | grep 5 + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep of number of lines (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \.\. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (2) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ blank.txt *N' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (3) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ *$' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (4) failed with $ret" + return 1 + fi + + echo "$out" | grep 'blocks of size.*blocks available' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - grep (5) failed with $ret" + return 1 + fi + fi + + if [ $PROTOCOL = "SMB3" ]; then + + # Now check again with -mSMB3 + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/badname-tmp -I $SERVER_IP $ADDARGS -m$PROTOCOL -c ls 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing badname-tmp (SMB3) with error $ret" + return 1 + fi + + echo "$out" | wc -l 2>&1 | grep 5 + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep of number of lines (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (1) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ \.\. *D' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (2) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ blank.txt *N' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (3) failed with $ret" + return 1 + fi + + echo "$out" | grep '^ *$' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (4) failed with $ret" + return 1 + fi + + echo "$out" | grep 'blocks of size.*blocks available' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed listing \\badname-tmp - SMB3 grep (5) failed with $ret" + return 1 + fi + fi +} + +# Test accessing an share with a name that must be mangled - with acl_xattrs. +# We know foo:bar gets mangled to FF4GBY~Q with the default name-mangling algorithm (hash2). +test_mangled_names() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +ls +cd FF4GBY~Q +ls +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/manglenames_share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing manglenames_share with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS' + ret=$? + if [ $ret = 0 ]; then + echo "$out" + echo "failed - NT_STATUS_XXXX listing \\manglenames_share\\FF4GBY~Q" + return 1 + fi +} + +# Test using scopy to copy a file on the server. +test_scopy() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + scopy_file=$PREFIX/scopy_file + + rm -f $scopy_file + cat >$tmpfile <<EOF +put ${SMBCLIENT} +scopy smbclient scopy_file +lcd ${PREFIX} +get scopy_file +del smbclient +del scopy_file +quit +EOF + if [ $PROTOCOL = "SMB3" ]; then + # First SMB3 + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS -m$PROTOOCL < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + out1=$(md5sum ${SMBCLIENT} | sed -e 's/ .*//') + out2=$(md5sum ${scopy_file} | sed -e 's/ .*//') + rm -f $tmpfile + rm -f $scopy_file + + if [ $ret != 0 ]; then + echo "$out" + echo "failed scopy test (1) with output $ret" + return 1 + fi + + if [ $out1 != $out2 ]; then + echo "$out1 $out2" + echo "failed md5sum (1)" + return 1 + fi + fi + # + # Now do again using SMB1 + # to force client-side fallback. + # + + if [ $PROTOCOL = "NT1" ]; then + cat >$tmpfile <<EOF +put ${SMBCLIENT} +scopy smbclient scopy_file +lcd ${PREFIX} +get scopy_file +del smbclient +del scopy_file +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS -m$PROTOCOL < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + out1=$(md5sum ${SMBCLIENT} | sed -e 's/ .*//') + out2=$(md5sum ${scopy_file} | sed -e 's/ .*//') + rm -f $tmpfile + rm -f $scopy_file + + if [ $ret != 0 ]; then + echo "$out" + echo "failed scopy test (2) with output $ret" + return 1 + fi + + if [ $out1 != $out2 ]; then + echo "$out1 $out2" + echo "failed md5sum (2)" + return 1 + fi + fi +} + +# Test creating a stream on the root of the share directory filename - :foobar +test_toplevel_stream() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +put ${PREFIX}/smbclient_interactive_prompt_commands :foobar +allinfo \\ +setmode \\ -a +quit +EOF + # Only with SMB3??? + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS -mSMB3 < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating toplevel stream :foobar with error $ret" + return 1 + fi + + echo "$out" | grep '^stream:.*:foobar' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating toplevel stream :foobar" + return 1 + fi +} + +# Test wide links are restricted. +test_widelinks() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +cd dot +ls +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/widelinks_share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing widelinks_share with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS' + ret=$? + if [ $ret = 0 ]; then + echo "$out" + echo "failed - NT_STATUS_XXXX listing \\widelinks_share\\dot" + return 1 + fi + + cat >$tmpfile <<EOF +allinfo source +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/widelinks_share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing widelinks_share with error $ret" + return 1 + fi + + # This should fail with NT_STATUS_OBJECT_NAME_NOT_FOUND + echo "$out" | grep 'NT_STATUS_OBJECT_NAME_NOT_FOUND' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed - should get NT_STATUS_OBJECT_NAME_NOT_FOUND listing \\widelinks_share\\source" + return 1 + fi +} + +# Test creating then deleting a stream file doesn't leave a lost-XXXXX directory. +test_streams_depot_delete() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + rm -rf "$LOCAL_PATH/lost-*" + + cat >$tmpfile <<EOF +put ${PREFIX}/smbclient_interactive_prompt_commands foo:bar +del foo +ls lost* +quit +EOF + # This only works with SMB3? + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS -mSMB3 < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed creating then deleting foo:bar with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS_NO_SUCH_FILE listing \\lost\*' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "deleting foo:bar left lost-XXX directory" + rm -rf "$LOCAL_PATH/lost-*" + return 1 + fi +} + +# Test follow symlinks can't access symlinks +test_nosymlinks() +{ + # Setup test dirs. + local_test_dir="$LOCAL_PATH/nosymlinks/test" + local_slink_name="$local_test_dir/source" + local_slink_target="$local_test_dir/nosymlink_target_file" + + share_test_dir="test" + share_foo_dir="$share_test_dir/foo" + share_foobar_dir="$share_test_dir/foo/bar" + share_target_file="$share_test_dir/foo/bar/testfile" + + rm -rf $local_test_dir + + local_nosymlink_target_file="nosymlink_target_file" + echo "$local_slink_target" >$PREFIX/$local_nosymlink_target_file + + local_foobar_target_file="testfile" + echo "$share_target_file" >$PREFIX/$local_foobar_target_file + + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +mkdir $share_test_dir +mkdir $share_foo_dir +mkdir $share_foobar_dir +lcd $PREFIX +cd /$share_test_dir +put $local_nosymlink_target_file +cd /$share_foobar_dir +put $local_foobar_target_file +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $LOCAL_ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + rm -f $PREFIX/$local_nosymlink_target_file + rm -f $PREFIX/$local_foobar_target_file + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing local_symlinks with error $ret" + false + return + fi + + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - got an NT_STATUS error" + false + return + fi + + # Create the symlink locally + ln -s $local_slink_target $local_slink_name + + # Getting a file through a symlink name should fail. + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +get test\\source +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing nosymlinks with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS_OBJECT_NAME_NOT_FOUND' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed - should get NT_STATUS_OBJECT_NAME_NOT_FOUND getting \\nosymlinks\\source" + return 1 + fi + + # But we should be able to create and delete directories. + cat >$tmpfile <<EOF +mkdir test\\a +mkdir test\\a\\b +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing nosymlinks with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\\b on \\nosymlinks" + return 1 + fi + + # Ensure regular file/directory access also works. + cat >$tmpfile <<EOF +cd test\\foo\\bar +ls +get testfile - +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing nosymlinks with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - NT_STATUS_XXXX doing cd foo\\bar; get testfile on \\nosymlinks" + return 1 + fi + + # CLEANUP + rm -f $local_slink_name + + cat >$tmpfile <<EOF +deltree test +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing nosymlinks with error $ret" + return 1 + fi + + echo "$out" | grep 'NT_STATUS' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - NT_STATUS_XXXX doing cd foo\\bar; get testfile on \\nosymlinks" + return 1 + fi +} + +# Test we can follow normal symlinks. +# Bug: https://bugzilla.samba.org/show_bug.cgi?id=12860 +# Note - this needs to be tested over SMB3, not SMB1. + +test_local_symlinks() +{ + # Setup test dirs. + LOCAL_RAWARGS="${CONFIGURATION} -mSMB3" + LOCAL_ADDARGS="${LOCAL_RAWARGS} $*" + + share_test_dir="test" + share_slink_target_dir="$share_test_dir/dir1" + + local_test_dir="$LOCAL_PATH/local_symlinks/$share_test_dir" + local_slink_name="$local_test_dir/sym_name" + local_slink_target_dir="$local_test_dir/dir1" + + rm -rf $local_test_dir + + # Create the initial directories + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +mkdir $share_test_dir +mkdir $share_slink_target_dir +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I $SERVER_IP $LOCAL_ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing local_symlinks with error $ret" + false + return + fi + + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - got an NT_STATUS error" + false + return + fi + + # Create the symlink locally + ln -s $local_slink_target_dir $local_slink_name + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed - unable to create symlink" + ls -la $local_test_dir + false + return + fi + + # Can we cd into the symlink name and ls ? + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +cd $share_test_dir\\sym_name +ls +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I $SERVER_IP $LOCAL_ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing local_symlinks with error $ret" + false + return + fi + + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - got an NT_STATUS error" + false + return + fi + + # CLEANUP + rm -f $local_slink_name + + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +deltree $share_test_dir +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I $SERVER_IP $LOCAL_ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed accessing local_symlinks with error $ret" + false + return + fi + + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - got an NT_STATUS error" + false + return + fi +} + +# +# Regression test for CVE-2019-10197 +# we should always get ACCESS_DENIED +# +test_noperm_share_regression() +{ + cmd='$SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/noperm -I $SERVER_IP $LOCAL_ADDARGS -c "ls;ls" 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed accessing no perm share should not work" + return 1 + fi + + num=$(echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' | wc -l) + if [ "$num" -ne "2" ]; then + echo "$out" + echo "failed num[$num] - two NT_STATUS_ACCESS_DENIED lines expected" + return 1 + fi + + return 0 +} + +# Test smbclient deltree command +test_deltree() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + deltree_dir=$PREFIX/deltree_dir + + rm -rf $deltree_dir + cat >$tmpfile <<EOF +mkdir deltree_dir +mkdir deltree_dir/foo +mkdir deltree_dir/foo/bar +put ${SMBCLIENT} deltree_dir/foo/bar/client +deltree deltree_dir +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed deltree test with output $ret" + false + return + fi + + echo "$out" | grep 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed - got an NT_STATUS error" + false + return + fi + + if [ -d $deltree_dir ]; then + echo "deltree did not delete everything" + false + return + fi +} + +# Test smbclient setmode command +test_setmode() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + cat >$tmpfile <<EOF +del test_setmode +put ${SMBCLIENT} test_setmode +setmode test_setmode +r +s +h +a +allinfo test_setmode +setmode test_setmode -rsha +allinfo test_setmode +del test_setmode +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed setmode test with output $ret" + false + return + fi + + echo "$out" | grep 'attributes: RHSA' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed - should get attributes: RHSA" + false + return + fi + + echo "$out" | grep 'attributes: (80)' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed - should also get attributes: (80)" + false + return + fi +} + +# Test smbclient utimes command +test_utimes() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + saved_TZ="$TZ" + TZ=UTC + export TZ + saved_LANG="$LANG" + LANG=C + export LANG + + cat >$tmpfile <<EOF +del utimes_test +put ${SMBCLIENT} utimes_test +allinfo utimes_test +utimes utimes_test 2016:02:04-06:19:20 17:01:01-05:10:20 -1 -1 +allinfo utimes_test +del utimes_test +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ -n "$saved_TZ" ]; then + export TZ="$saved_TZ" + else + unset TZ + fi + if [ -n "$saved_LANG" ]; then + export LANG="$saved_LANG" + else + unset LANG + fi + + if [ $ret != 0 ]; then + echo "$out" + echo "failed utimes test with output $ret" + false + return + fi + + # Now, we should have 2 identical write_time and change_time + # values, but one access_time of Jan 1 05:10:20 AM, + # and one create_time of Feb 04 06:19:20 AM 2016 + out_sorted=$(echo "$out" | sort | uniq) + num_create=$(echo "$out_sorted" | grep -c 'create_time:') + num_access=$(echo "$out_sorted" | grep -c 'access_time:') + num_write=$(echo "$out_sorted" | grep -c 'write_time:') + num_change=$(echo "$out_sorted" | grep -c 'change_time:') + if [ "$num_create" != "2" ]; then + echo "failed - should get two create_time $out" + false + return + fi + if [ "$num_access" != "2" ]; then + echo "failed - should get two access_time $out" + false + return + fi + if [ "$num_write" != "1" ]; then + echo "failed - should only get one write_time $out" + false + return + fi + if [ "$num_change" != "1" ]; then + echo "failed - should only get one change_time $out" + false + return + fi + + # This could be: Sun Jan 1 05:10:20 AM 2017 + # or : Sun Jan 1 05:10:20 2017 CET + echo "$out" | grep 'access_time:.*Sun Jan.*1 05:10:20 .*2017.*' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo + echo "failed - should get access_time: Sun Jan 1 05:10:20 [AM] 2017" + false + return + fi + + # This could be: Thu Feb 4 06:19:20 AM 2016 + # or : Thu Feb 4 06:19:20 2016 CET + echo "$out" | grep 'create_time:.*Thu Feb.*4 06:19:20 .*2016.*' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo + echo "failed - should get access_time: Thu Feb 4 06:19:20 [AM] 2016" + false + return + fi +} + +# Test smbclient renames with pathnames containing '..' +test_rename_dotdot() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + + cat >$tmpfile <<EOF +deltree dotdot_test +mkdir dotdot_test +cd dotdot_test +mkdir dir1 +mkdir dir2 +cd dir1 +put ${SMBCLIENT} README +rename README ..\\dir2\\README +cd .. +cd dir2 +allinfo README +cd \\ +deltree dotdot_test +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed rename_dotdot test with output $ret" + false + return + fi + + # We are allowed to get NT_STATUS_NO_SUCH_FILE listing \dotdot_test + # as the top level directory should not exist, but no other errors. + + error_str=$(echo $out | grep NT_STATUS | grep -v "NT_STATUS_NO_SUCH_FILE listing .dotdot_test") + if [ "$error_str" != "" ]; then + echo "failed - unexpected NT_STATUS error in $out" + false + return + fi +} + +# Test doing a volume command. +test_volume() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +volume +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed doing volume command with error $ret" + return 1 + fi + + echo "$out" | grep '^Volume: |tmp| serial number' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed doing volume command" + return 1 + fi +} + +test_server_os_message() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +ls +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed to connect error $ret" + return 1 + fi + + echo "$out" | grep 'Try "help" to get a list of possible commands.' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo 'failed - should get: Try "help" to get a list of possible commands.' + return 1 + fi + + return 0 +} + +test_server_quiet_message() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +ls +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed to connect error $ret" + return 1 + fi + + echo "$out" | grep 'Try "help" to get a list of possible commands.' + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo 'failed - quiet should skip this message.' + return 1 + fi + + return 0 +} + +# Test xattr_stream correctly reports mode. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=13380 + +test_stream_directory_xattr() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + # + # Test against streams_xattr + # + cat >$tmpfile <<EOF +deltree foo +mkdir foo +put ${PREFIX}/smbclient_interactive_prompt_commands foo:bar +setmode foo -a +allinfo foo:bar +deltree foo +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/streams_xattr -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed checking attributes on xattr stream foo:bar with error $ret" + return 1 + fi + + echo "$out" | grep "attributes:.*80" + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed checking attributes on xattr stream foo:bar" + return 1 + fi + + # + # Test against streams_depot + # + cat >$tmpfile <<EOF +deltree foo +mkdir foo +put ${PREFIX}/smbclient_interactive_prompt_commands foo:bar +setmode foo -a +allinfo foo:bar +deltree foo +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed checking attributes on depot stream foo:bar with error $ret" + return 1 + fi + + echo "$out" | grep "attributes:.*80" + ret=$? + if [ $ret != 0 ]; then + echo "$out" + echo "failed checking attributes on depot stream foo:bar" + return 1 + fi +} + +# Test smbclient non-empty rmdir command +test_del_nedir() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + del_nedir="$LOCAL_PATH/del_nedir" + + rm -rf $del_nedir + mkdir $del_nedir + touch $del_nedir/afile + cat >$tmpfile <<EOF +rmdir del_nedir +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -rf $del_nedir + + if [ $ret != 0 ]; then + echo "$out" + echo "failed test_del_nedir test with output $ret" + false + return + fi + + # Should get NT_STATUS_DIRECTORY_NOT_EMPTY error from rmdir + echo "$out" | grep 'NT_STATUS_DIRECTORY_NOT_EMPTY' + ret=$? + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_del_nedir failed - should get an NT_STATUS_DIRECTORY_NOT_EMPTY error" + false + return + fi +} + +test_valid_users() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >$tmpfile <<EOF +ls +quit +EOF + # User in "valid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users 'User in 'valid users' can login to service' failed - $ret" + return 1 + fi + + # User from ad group in "valid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users_group 'User from ad group in 'valid users' can login to service' failed - $ret" + return 1 + fi + + # User from UNIX group in "valid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_unix_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users_unix_group 'User from UNIX group in 'valid users' can login to service' failed - $ret" + return 1 + fi + + # User not in NIS group in "valid users" can't login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_nis_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users_nis_group 'User not in NIS group in 'valid users' can't login to service' failed - $ret" + return 1 + fi + + # Check user in UNIX, then in NIS group in "valid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_unix_nis_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users_unix_nis_group 'Check user in UNIX, then in NIS group in 'valid users' can login to service' failed - $ret" + return 1 + fi + + # Check user in NIS, then in UNIX group in "valid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_nis_unix_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_users_nis_unix_group 'Check user in NIS, then in UNIX group in 'valid users' can login to service' failed - $ret" + return 1 + fi + + # User not in "invalid users" can login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -Ualice%Secret007 //$SERVER/invalid_users $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:invalid_users 'User not in 'invalid users' can login to service' failed - $ret" + return 1 + fi + + # User in "invalid users" can't login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/invalid_users $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:invalid_users 'User in 'invalid users' can't login to service' failed - $ret" + return 1 + fi + + # User is in "valid and invalid users" can't login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_and_invalid_users $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' + ret=$? + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_and_invalid_users 'User is in 'valid and invalid users' can't login to service' failed - $ret" + return 1 + fi + + # 2 Users are in "valid users" + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -Ualice%Secret007 //$SERVER/valid_and_invalid_users $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "test_valid_users:valid_and_invalid_users '2 Users are in 'valid users'' failed - $ret" + return 1 + fi + + return 0 +} + +test_smbclient_minus_e_stderr() +{ + cmd='$SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -c ls' + eval echo "$cmd" + out=$(eval $cmd) + if [ $? != 0 ]; then + echo "$out" + echo "command failed" + return 1 + fi + + # test smbclient 'ls' command output went to stdout + echo "$out" | grep "blocks available" >/dev/null 2>&1 + if [ $? != 0 ]; then + # didn't get output to stdout + echo "expected output was NOT output to stdout" + return 1 + fi + + # this time execute ls but redirect stdout alone to /dev/null + cmd='$SMBCLIENT -E "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -c "ls" 2>&1 > /dev/null' + eval echo "$cmd" + out=$(eval $cmd) + if [ $? != 0 ]; then + echo "$out" + echo "command failed" + return 1 + fi + + # test smbclient 'ls' command output went to stderr + echo "$out" | grep "blocks available" >/dev/null 2>&1 + if [ $? != 0 ]; then + # didn't get output to stderr + echo "expected output was NOT output to stderr" + return 1 + fi + + return 0 + +} + +# +# +LOGDIR_PREFIX=test_smbclient_s3 + +# possibly remove old logdirs: + +for OLDDIR in $(find ${PREFIX} -type d -name "${LOGDIR_PREFIX}_*"); do + echo "removing old directory ${OLDDIR}" + rm -rf ${OLDDIR} +done + +LOGDIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX) + +testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 ${RAWARGS} || failed=$(expr $failed + 1) +testit "smbclient -L $SERVER -I $SERVER_IP" $SMBCLIENT -L $SERVER -I $SERVER_IP -N -p 139 ${RAWARGS} -c quit || failed=$(expr $failed + 1) + +testit "noninteractive smbclient does not prompt" \ + test_noninteractive_no_prompt || + failed=$(expr $failed + 1) + +testit "noninteractive smbclient -l does not prompt" \ + test_noninteractive_no_prompt -l $LOGDIR || + failed=$(expr $failed + 1) + +testit "smbclient output goes to stderr when -E is passed" \ + test_smbclient_minus_e_stderr || + failed=$(expr $failed + 1) + +testit "interactive smbclient prompts on stdout" \ + test_interactive_prompt_stdout || + failed=$(expr $failed + 1) + +testit "interactive smbclient -l prompts on stdout" \ + test_interactive_prompt_stdout -l $LOGDIR || + failed=$(expr $failed + 1) + +testit "creating a bad symlink and deleting it" \ + test_bad_symlink || + failed=$(expr $failed + 1) + +testit "creating a good symlink and deleting it by path" \ + test_good_symlink || + failed=$(expr $failed + 1) + +testit "writing into a read-only directory fails" \ + test_read_only_dir ro-tmp || + failed=$(expr $failed + 1) + +testit "writing into a read-only share fails" \ + test_read_only_dir valid-users-tmp || + failed=$(expr $failed + 1) + +testit "Reading a owner-only file fails" \ + test_owner_only_file || + failed=$(expr $failed + 1) + +testit "Accessing an MS-DFS link" \ + test_msdfs_link || + failed=$(expr $failed + 1) + +testit "Recursive ls across MS-DFS links" \ + test_msdfs_recursive_dir || + failed=$(expr $failed + 1) + +testit "Rename on MS-DFS share" \ + test_msdfs_rename || + failed=$(expr $failed + 1) + +testit "Hardlink on MS-DFS share" \ + test_msdfs_hardlink || + failed=$(expr $failed + 1) + +testit "del on MS-DFS share" \ + test_msdfs_del || \ + failed=`expr $failed + 1` + +testit "deltree on MS-DFS share" \ + test_msdfs_deltree || \ + failed=`expr $failed + 1` + +testit "Ensure archive bit is set correctly on file/dir rename" \ + test_rename_archive_bit || + failed=$(expr $failed + 1) + +testit "ccache access works for smbclient" \ + test_ccache_access || + failed=$(expr $failed + 1) + +testit "sending a message to the remote server" \ + test_message || + failed=$(expr $failed + 1) + +testit "using an authentication file" \ + test_auth_file || + failed=$(expr $failed + 1) + +testit "list with backup privilege" \ + test_backup_privilege_list || + failed=$(expr $failed + 1) + +testit "list a share with bad names (won't convert)" \ + test_bad_names || + failed=$(expr $failed + 1) + +testit "list a share with a mangled name + acl_xattr object" \ + test_mangled_names || + failed=$(expr $failed + 1) + +testit "server-side file copy" \ + test_scopy || + failed=$(expr $failed + 1) + +testit "creating a :stream at root of share" \ + test_toplevel_stream || + failed=$(expr $failed + 1) + +testit "Ensure widelinks are restricted" \ + test_widelinks || + failed=$(expr $failed + 1) + +testit "streams_depot can delete correctly" \ + test_streams_depot_delete || + failed=$(expr $failed + 1) + +testit "stream_xattr attributes" \ + test_stream_directory_xattr || + failed=$(expr $failed + 1) + +testit "follow symlinks = no" \ + test_nosymlinks || + failed=$(expr $failed + 1) + +testit "follow local symlinks" \ + test_local_symlinks || + failed=$(expr $failed + 1) + +testit "noperm share regression" \ + test_noperm_share_regression || + failed=$(expr $failed + 1) + +testit "smbclient deltree command" \ + test_deltree || + failed=$(expr $failed + 1) + +testit "server os message" \ + test_server_os_message || + failed=$(expr $failed + 1) + +testit "test server quiet message" \ + test_server_quiet_message || + failed=$(expr $failed + 1) + +testit "setmode test" \ + test_setmode || + failed=$(expr $failed + 1) + +testit "utimes" \ + test_utimes || + failed=$(expr $failed + 1) + +testit "rename_dotdot" \ + test_rename_dotdot || + failed=$(expr $failed + 1) + +testit "volume" \ + test_volume || + failed=$(expr $failed + 1) + +testit "rm -rf $LOGDIR" \ + rm -rf $LOGDIR || + failed=$(expr $failed + 1) + +testit "delete a non empty directory" \ + test_del_nedir || + failed=$(expr $failed + 1) + +testit "valid users" \ + test_valid_users || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbclient_tarmode.pl b/source3/script/tests/test_smbclient_tarmode.pl new file mode 100755 index 0000000..fa69d28 --- /dev/null +++ b/source3/script/tests/test_smbclient_tarmode.pl @@ -0,0 +1,1723 @@ +#!/usr/bin/perl +# Unix SMB/CIFS implementation. +# Test suite for the tar backup mode of smbclient. +# Copyright (C) Aurélien Aptel 2013 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +=head1 NAME + +C<test_smbclient_tarmode.pl> - Test for smbclient tar backup feature + +=cut + +use v5.10; +use strict; +use warnings; + +use Archive::Tar; +use Data::Dumper; +use Digest::MD5 qw/md5_hex/; +use File::Path qw/make_path remove_tree/; +use File::Spec; +use File::Temp; +use Getopt::Long; +use Pod::Usage; +use Term::ANSIColor; + +sub d {print Dumper @_;} + +# DEFAULTS +# 'our' to make them available in the File package +our $USER = ''; +our $PW = ''; +our $HOST = ''; +our $IP = ''; +our $SHARE = ''; +our $DIR = 'tar_test_dir'; +our $LOCALPATH = ''; +our $TMP = File::Temp->newdir(); +our $BIN = 'smbclient'; +our $SUBUNIT = 0; + +my $SELECTED_TEST = ''; +my $LIST_TEST = 0; + +my @SMBARGS = (); + +our $DEBUG = 0; +our $VERBOSE = 0; +my $MAN = 0; +my $HELP = 0; +my $CLEAN = 0; + +# all tests +my @TESTS = ( +# ['test helper', \&test_helper], + ['create, normal files (no attributes)', \&test_creation_normal, 'normal'], + ['create, normal nested files (no attributes)', \&test_creation_normal, 'nested'], + ['create, normal files (interactive)', \&test_creation_normal, 'inter'], + ['create, large file', \&test_creation_large_file], + ['create, long path', \&test_creation_long_path], + ['create, incremental with -g', \&test_creation_incremental, '-g'], + ['create, incremental with tarmode', \&test_creation_incremental, 'tarmode inc'], + ['create, reset archived files with -a', \&test_creation_reset, '-a'], + ['create, reset archived files with tarmode', \&test_creation_reset, 'tarmode reset'], + ['create, files newer than a file', \&test_creation_newer], + ['create, combination of tarmode filter', \&test_creation_attr], + ['create, explicit include', \&test_creation_include], + ['create, explicit exclude', \&test_creation_exclude], + ['create, include w/ filelist (F)', \&test_creation_list], + ['create, wildcard simple', \&test_creation_wildcard_simple], + ['create, regex', \&test_creation_regex], + ['create, multiple backup in session', \&test_creation_multiple], + ['extract, normal files', \&test_extraction_normal], + ['extract, explicit include', \&test_extraction_include], + ['extract, explicit exclude', \&test_extraction_exclude], + ['extract, include w/ filelist (F)', \&test_extraction_list], + ['extract, regex', \&test_extraction_regex], +); + +=head1 SYNOPSIS + + test_smbclient_tarmode.pl [options] -- [smbclient options] + + Options: + -h, --help brief help message + --man full documentation + + Environment: + -u, --user USER + -p, --password PW + -n, --name HOST (required) + -i, --ip IP + -s, --share SHARE (required) + -d, --dir PATH + sub-path to use on the share + + -l, --local-path PATH (required) + path to the root of the samba share on the machine. + + -b, --bin BIN + path to the smbclient binary to use + + Test: + --list + list tests + + --test N + --test A-B + --test A,B,D-F + only run certain tests (accept list and intervals of numbers) + + -v, --verbose + be more verbose + + --debug + print command and their output (also set -v) + + --subunit + print output in subunit format + +=cut + +GetOptions('u|user=s' => \$USER, + 'p|password=s' => \$PW, + 'n|name=s' => \$HOST, + 'i|ip=s' => \$IP, + 's|share=s' => \$SHARE, + 'd|dir=s' => \$DIR, + 'l|local-path=s' => \$LOCALPATH, + 'b|bin=s' => \$BIN, + + 'test=s' => \$SELECTED_TEST, + 'list' => \$LIST_TEST, + + 'clean' => \$CLEAN, + 'subunit' => \$SUBUNIT, + 'debug' => \$DEBUG, + 'v|verbose' => \$VERBOSE, + 'h|help' => \$HELP, + 'man' => \$MAN) or pod2usage(2); + +pod2usage(0) if $HELP; +pod2usage(-exitval => 0, -verbose => 2) if $MAN; +list_test(), exit 0 if $LIST_TEST; +pod2usage(1) unless $HOST; +pod2usage(1) unless $SHARE; +pod2usage(1) unless $LOCALPATH; + +if ($USER xor $PW) { + die "Need both user and password when one is provided\n"; +} +elsif ($USER and $PW) { + push @SMBARGS, '-U'.$USER.'%'.$PW; +} +else { + push @SMBARGS, '-N'; +} + +if ($IP) { + push @SMBARGS, '-I', $IP; +} + +# remaining arguments are passed to smbclient +push @SMBARGS, @ARGV; + +# path to store the downloaded tarball +my $TAR = "$TMP/tarmode.tar"; + +##### + +# SANITIZATION + +# remove all final slashes from input paths +$LOCALPATH =~ s{[/\\]+$}{}g; +$SHARE =~ s{[/\\]+$}{}g; +$HOST =~ s{[/\\]+$}{}g; +$DIR =~ s{^\.[/\\]+$}{}g; +$DIR =~ s{[/\\]+$}{}g; + +if (!-d $LOCALPATH) { + die "Local path '$LOCALPATH' is not a directory.\n"; +} + +if ($CLEAN) { + # clean the whole root first + remove_tree($LOCALPATH, { keep_root => 1 }); +} + +if ($DEBUG) { + $VERBOSE = 1; +} + +##### + +# RUN TESTS + +my @selection = parse_test_string($SELECTED_TEST); + +if ($SELECTED_TEST eq '') { + run_test(@TESTS); +} elsif (@selection > 0) { + run_test(@selection); +} else { + die "Test selection '$SELECTED_TEST' is invalid\n"; +} + +################################# + +=head1 DOCUMENTATION + +=head2 Defining a test + +=over + +=item * Create a function C<test_yourtest> + +=item * Use the File module, documented below + +=item * Use C<smb_tar>, C<smb_client>, C<check_tar> or C<check_remote> + +=item * Return number of error + +=item * Add function to C<@TESTS> + +=back + +The function must be placed in the C<@TESTS> list along with a short +description and optional arguments. + +=cut + +sub test_creation_newer { + my @files; + my $dt = 3000; + + # create oldest file at - DT + my $oldest = File->new_remote('oldest'); + $oldest->set_time(time - $dt); + + # create limit file + my $limit = File->new_local("$TMP/limit"); + + # create newA file at + DT + my $newA = File->new_remote('newA'); + $newA->set_time(time + $dt); + + # create newB file at + DT + my $newB = File->new_remote('newB'); + $newB->set_time(time + $dt); + + # get files newer than limit_file + push @files, $newA, $newB; + + smb_tar('', '-TcN', $limit->localpath, $TAR, $DIR); + return check_tar($TAR, \@files); +} + +sub test_creation_attr { + my @attr = qw/r h s a/; + my @all; + my @inc; + my $err = 0; + + # one normal file + my $f = File->new_remote("file-n.txt"); + push @all, $f; + + # combinations of attributes + for my $n (1..@attr) { + for (combine(\@attr, $n)) { + my @t = @$_; + my $fn = "file-" . join('+', @t) . ".txt"; + my $f = File->new_remote($fn); + $f->set_attr(@t); + push @all, $f; + } + } + + @inc = grep { !$_->attr('s') } @all; + smb_tar('tarmode nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { !$_->attr('h') } @all; + smb_tar('tarmode nohidden', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { !$_->attr_any('h', 's') } @all; + smb_tar('tarmode nohidden nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + + @inc = grep { $_->attr('a') && !$_->attr_any('h', 's') } @all; + smb_tar('tarmode inc nohidden nosystem', '-Tc', $TAR, $DIR); + $err += check_tar($TAR, \@inc); + # adjust attr so remote files can be deleted with deltree + File::walk(sub { $_->set_attr(qw/n r s h/) }, File::tree($DIR)); + + $err; +} + +sub test_creation_reset { + my ($mode) = @_; + + my @files; + my $n = 3; + for (1..$n) { + my $f = File->new_remote("file-$_"); + $f->set_attr('a'); + push @files, $f; + } + + if ($mode =~ /reset/) { + smb_tar('tarmode full reset', '-Tc', $TAR, $DIR); + } else { + smb_tar('', '-Tca', $TAR, $DIR); + } + + my $err = check_tar($TAR, \@files); + return $err if ($err > 0); + + for my $f (File::list($DIR)) { + if ($f->{attr}{a}) { + printf " ! %s %s\n", $f->attr_str, $f->remotepath; + $err++; + } + } + return $err; +} + +sub test_creation_large_file { + my $size = int(15e6); # 15MB + my $f = File->new_remote("fat.jpg", 0, $size); + + smb_tar('', '-Tc', $TAR, $DIR); + return check_tar($TAR, [$f]); +} + +sub test_creation_long_path { + my $d = "a"x130; + my @all; + + for (qw( foo/a bar/b )) { + push @all, File->new_remote("$d/$_"); + } + + smb_tar('', '-Tc', $TAR, $DIR); + return check_tar($TAR, \@all); +} + +sub test_creation_normal { + my ($mode) = @_; + + my $prefix = ($mode =~ /nest/) ? "/foo/bar/bar/" : ''; + my @files; + my $n = 5; + for (1..$n) { + my $f = File->new_remote($prefix."file-$_"); + push @files, $f; + } + + if ($mode =~ /inter/) { + smb_tar("tar c $TAR $DIR", ''); + } else { + smb_tar('tarmode full', '-Tc', $TAR, $DIR); + } + return check_tar($TAR, \@files); +} + +sub test_creation_incremental { + my ($mode) = @_; + + my @files; + my $n = 10; + for (1..$n) { + my $f = File->new_remote("file-$_"); + + # set archive bit on ~half of them + if ($_ < $n/2) { + $f->set_attr('a'); + push @files, $f; + } + else { + $f->set_attr((qw/n r s h/)[$_ % 4]); + } + } + + if ($mode =~ /inc/) { + smb_tar('tarmode inc', '-Tc', $TAR, $DIR); + } else { + smb_tar('', '-Tcg', $TAR, $DIR); + } + my $res = check_tar($TAR, \@files); + # adjust attr so remote files can be deleted with deltree + File::walk(sub { $_->set_attr(qw/n r s h/) }, File::tree($DIR)); + return $res +} + + +sub test_extraction_normal { + my @files; + my $n = 5; + for (1..$n) { + my $f = File->new_remote("file-$_"); + push @files, $f; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-Tx', $TAR); + check_remote($DIR, \@files); +} + +sub test_extraction_include { + my @all_files; + my @inc_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if /inc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-TxI', $TAR, "$DIR/file_inc", "$DIR/inc"); + check_remote($DIR, \@inc_files); +} + +sub test_extraction_exclude { + my @all_files; + my @inc_files; + + for (qw(file_exc exc/b exc/c exc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if !/exc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + smb_tar('', '-TxX', $TAR, "$DIR/file_exc", "$DIR/exc"); + check_remote($DIR, \@inc_files); +} + + +sub test_creation_include { + my @files; + + for (qw(file_inc inc/b inc/c inc/dir/foo dir_ex/d zob)) { + my $f = File->new_remote($_); + push @files, $f if /inc/; + } + + smb_tar('', '-TcI', $TAR, "$DIR/file_inc", "$DIR/inc"); + return check_tar($TAR, \@files); +} + +sub test_creation_exclude { + my @files; + + for (qw(file_ex ex/b ex/c ex/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @files, $f if !/ex/; + } + + smb_tar('', '-TcX', $TAR, "$DIR/file_ex", "$DIR/ex"); + return check_tar($TAR, \@files); +} + +sub test_creation_list { + my @inc_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @inc_files, $f if /inc/; + } + + my $flist = File->new_local("$TMP/list", file_list(@inc_files)); + smb_tar('', '-TcF', $TAR, $flist->localpath); + return check_tar($TAR, \@inc_files); +} + +sub test_creation_regex { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + # EXCLUSION + + # skip *.exe + @inc = grep { $_->remotepath !~ m{exe$} } @all; + smb_tar('', '-TcrX', $TAR, '*.exe'); + $err += check_tar($TAR, \@inc); + + # if the pattern is a path, it doesn't skip anything + smb_tar('', '-TcrX', $TAR, "$DIR/*.exe"); + $err += check_tar($TAR, \@all); + smb_tar('', '-TcrX', $TAR, "$DIR/*"); + $err += check_tar($TAR, \@all); + smb_tar('', '-TcrX', $TAR, "$DIR"); + $err += check_tar($TAR, \@all); + + # no paths => include everything + smb_tar('', '-TcrX', $TAR); + $err += check_tar($TAR, \@all); + + + # skip everything + smb_tar('', '-TcrX', $TAR, "*.*"); + $err += check_tar($TAR, []); + smb_tar('', '-TcrX', $TAR, "*"); + $err += check_tar($TAR, []); + + # INCLUSION + + # no paths => include everything + smb_tar('', '-Tcr', $TAR); + $err += check_tar($TAR, \@all); + + # include everything + smb_tar('', '-Tcr', $TAR, '*'); + $err += check_tar($TAR, \@all); + + # include only .exe at root + @inc = grep { $_->remotepath =~ m{^[^/]+exe$}} @all; + smb_tar('', '-Tcr', $TAR, '*.exe'); + $err += check_tar($TAR, \@inc); + + # smb_tar('', '-Tcr', $TAR, "$DIR/*"); + ## in old version (bug?) + # $err += check_tar($TAR, []); + ## in rewrite + # @inc = grep { $_->remotepath =~ /^$DIR/ } @all; + # $err += check_tar($TAR, \@inc); + + $err; +} + +sub test_creation_wildcard_simple { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + @inc = grep { $_->remotepath =~ m{^[^/]+exe$} } @all; + smb_tar('', '-Tc', $TAR, "*.exe"); + $err += check_tar($TAR, \@inc); + + @inc = grep { $_->remotepath =~ m{$DIR/.+exe$} } @all; + smb_tar('', '-Tc', $TAR, "$DIR/*.exe"); + $err += check_tar($TAR, \@inc); + + $err; +} + +# NOT USED +# helper to test tests +sub test_helper { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my $err = 0; + my @inc; + + smb_tar('', '-Tc', $TAR); + return 1 if check_tar($TAR, \@all); + reset_remote(); + + my @exc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + @inc = grep { $_->remotepath !~ m!/dir/.+exe!} @all; + smb_tar('', '-TxXr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', \@all); # BUG: should be \@inc + reset_remote(); + + return 0; +} + +sub test_creation_multiple { + my @exts = qw(jpg exe); + my @dirs = ('', "$DIR/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my @inc; + my $err = 0; + + my ($tarA, $tarB) = ("$TMP/a.tar", "$TMP/b.tar"); + my @incA = grep { $_->remotepath =~ m{^[^/]+exe$} } @all; + my @incB = grep { $_->remotepath =~ m{^[^/]+jpg$} } @all; + + my $flistA = File->new_local("$TMP/listA", file_list(@incA))->localpath; + my $flistB = File->new_local("$TMP/listB", file_list(@incB))->localpath; + + smb_tar("tar cF $tarA $flistA ; tar cF $tarB $flistB ; quit"); + $err += check_tar($tarA, \@incA); + $err += check_tar($tarB, \@incB); + + $err; +} + +sub test_extraction_regex { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my @all = make_env(\@exts, \@dirs); + my $nb; + my $err = 0; + my (@inc, @exc); + + smb_tar('', '-Tc', $TAR); + return 1 if check_tar($TAR, \@all); + reset_remote(); + + # INCLUDE + + # only include file at root + @inc = grep { $_->remotepath =~ m!exe!} @all; + smb_tar('', '-Txr', $TAR, "*.exe"); + $err += check_remote('/', \@inc); + reset_remote(); + + @inc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + smb_tar('', '-Txr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', []); # BUG: should be \@inc + reset_remote(); + + # EXCLUDE + + # exclude file not directly at root + @inc = grep { $_->remotepath =~ m!^[^/]+$!} @all; + @exc = grep { $_->remotepath !~ m!^[^/]+$!} @all; + smb_tar('', '-TxrX', $TAR, map {$_->remotepath} @exc); + $err += check_remote('/', \@all); # BUG: should be @inc... + reset_remote(); + + # exclude only $DIR/dir/*exe + @exc = grep { $_->remotepath =~ m!/dir/.+exe!} @all; + @inc = grep { $_->remotepath !~ m!/dir/.+exe!} @all; + smb_tar('', '-TxXr', $TAR, "/$DIR/dir/*.exe"); + $err += check_remote('/', \@all); # BUG: should be \@inc + reset_remote(); + + $err; +} + +sub test_extraction_wildcard { + my @exts = qw(txt jpg exe); + my @dirs = ('', "$DIR/", "$DIR/dir/"); + my $nb; + my $err = 0; + + for my $dir (@dirs) { + + my @all; + + $nb = 0; + for my $dir (@dirs) { + for (@exts) { + my $fn = $dir . "file$nb." . $_; + my $f = File->new_remote($fn, 'ABSPATH'); + $f->delete_on_destruction(1); + push @all, $f; + $nb++; + } + } + + + my @inc; + my $ext = 'exe'; + my $fn = $dir."file$nb.".$ext; + my $pattern = $dir.'*.'.$ext; + my $flist; + + # with F + + $flist = File->new_local("$TMP/list", "$pattern\n"); + + # store + my $re = '^'.$dir.'.*file'; + @inc = grep { $dir eq '' or $_->remotepath =~ m{$re} } @all; + smb_tar('', '-Tc', $TAR, $dir); + $err += check_tar($TAR, \@inc); + + reset_remote(); + my $re2 = '^'.$dir.'file.+exe'; + @inc = grep { $_->remotepath =~ /$re2/ } @all; + smb_tar('', '-TxrF', $TAR, $flist->localpath); + $err += check_remote($dir, \@inc); + + reset_remote(); + } + + $err; +} + +sub test_extraction_list { + my @inc_files; + my @all_files; + + for (qw(file_inc inc/b inc/c inc/dir/foo foo/bar zob)) { + my $f = File->new_remote($_); + push @all_files, $f; + push @inc_files, $f if /inc/; + } + + # store + smb_tar('', '-Tc', $TAR, $DIR); + my $err = check_tar($TAR, \@all_files); + return $err if $err > 0; + + reset_remote(); + + my $flist = File->new_local("$TMP/list", file_list(@inc_files)); + smb_tar('', '-TxF', $TAR, $flist->localpath); + return check_remote($DIR, \@inc_files); +} + +################################# + +# IMPLEMENTATION + +=head2 Useful functions + +Here are a list of useful functions and helpers to define tests. + +=cut + +# list test number and description +sub list_test { + my $i = 0; + for (@TESTS) { + my ($desc, $f, @args) = @$_; + printf "%2d.\t%s\n", $i++, $desc; + } +} + +sub run_test { + if ($SUBUNIT) { + run_test_subunit(@_); + } else { + run_test_normal(@_); + } +} + +sub run_test_normal { + for (@_) { + my ($desc, $f, @args) = @$_; + my $err; + + reset_env(); + say "TEST: $desc"; + if ($VERBOSE) { + $err = $f->(@args); + } else { + # turn off STDOUT + open my $saveout, ">&STDOUT"; + open STDOUT, '>', File::Spec->devnull(); + $err = $f->(@args); + open STDOUT, ">&", $saveout; + } + print_res($err); + print "\n"; + } + reset_env(); +} + +sub run_test_subunit { + for (@_) { + my ($desc, $f, @args) = @$_; + my $err; + my $str = ''; + + reset_env(); + say "test: $desc"; + + # capture output in $buf + my $buf = ''; + open my $handle, '>', \$buf; + select $handle; + + # check for die() calls + eval { + $err = $f->(@args); + }; + if ($@) { + $str = $@; + $err = 1; + } + close $handle; + + # restore output + select STDOUT; + + # result string is output + eventual exception message + $str = $buf.$str; + + printf "%s: %s [\n%s]\n", ($err > 0 ? "failure" : "success"), $desc, $str; + } + reset_env(); +} + +sub parse_test_string { + my $s = shift; + my @tests = (); + + if (!length($s)) { + return (); + } + + for (split /,/, $s) { + if (/^\d+$/) { + if ($_ >= @TESTS) { + return (); + } + push @tests, $TESTS[$_]; + } + elsif (/^(\d+)-(\d+)$/) { + my ($min, $max) = sort ($1, $2); + if ($max >= @TESTS) { + return (); + } + + for ($min..$max) { + push @tests, $TESTS[$_]; + } + } + else { + return (); + } + } + + return @tests; +} + +sub print_res { + my $err = shift; + if ($err) { + printf " RES: %s%d ERR%s\n", color('bold red'), $err, color 'reset'; + } else { + printf " RES: %sOK%s\n", color('bold green'), color 'reset'; + } +} + +sub make_env { + my ($exts, $dirs) = @_; + my @all; + my $nb = 0; + for my $dir (@$dirs) { + for (@$exts) { + my $fn = $dir . "file$nb." . $_; + my $f = File->new_remote($fn, 'ABSPATH'); + $f->delete_on_destruction(1); + push @all, $f; + $nb++; + } + } + + @all; +} + +=head3 C<combine ( \@set, $n )> + +=head3 C<combine ( ['a', 'b', 'c'], 2 )> + +Return a list of all possible I<n>-uplet (or combination of C<$n> element) of C<@set>. + +=cut +sub combine { + my ($list, $n) = @_; + die "Insufficient list members" if $n > @$list; + + return map [$_], @$list if $n <= 1; + + my @comb; + + for (my $i = 0; $i+$n <= @$list; $i++) { + my $val = $list->[$i]; + my @rest = @$list[$i+1..$#$list]; + push @comb, [$val, @$_] for combine(\@rest, $n-1); + } + + return @comb; +} + + +=head3 C<reset_remote( )> + +Remove all files in the server C<$DIR> (not root) + +=cut +sub reset_remote { + # remove_tree($LOCALPATH . '/'. $DIR); + # make_path($LOCALPATH . '/'. $DIR); + my $DIR; + my @names; + my $name; + + smb_client_cmd(0, '-c', "deltree ./*"); + + # Ensure all files are gone. + + opendir(DIR,$LOCALPATH) or die "Can't open $LOCALPATH\n"; + @names = readdir(DIR) or die "Unable to read $LOCALPATH\n"; + closedir(DIR); + foreach $name (@names) { + next if ($name eq "."); # skip the current directory entry + next if ($name eq ".."); # skip the parent directory entry + die "$LOCALPATH not empty\n"; + } +} + +=head3 C<reset_tmp( )> + +Remove all files in the temp directory C<$TMP> + +=cut +sub reset_tmp { + remove_tree($TMP, { keep_root => 1 }); +} + + +=head3 C<reset_env( )> + +Remove both temp and remote (C<$DIR>) files + +=cut +sub reset_env { + reset_tmp(); + reset_remote(); +} + +=head3 C<file_list ( @files )> + +Make a multiline string of all the files remote path, one path per line. + +C<@files> must be a list of C<File> instance. + +=cut +sub file_list { + my @files = @_; + my $s = ''; + for (@files) { + $s .= $_->remotepath."\n"; + } + return $s; +} + +# remove leading "./" +sub remove_dot { + my $s = shift; + $s =~ s{^\./}{}; + $s; +} + +=head3 C<check_remote( $remotepath, \@files )> + +Check if C<$remotepath> has B<exactly> all the C<@files>. + +Print a summary on STDOUT. + +C<@files> must be a list of C<File> instance. + +=cut +sub check_remote { + my ($subpath, $files) = @_; + my (%done, %expected); + my (@less, @more, @diff); + + for (@$files) { + my $fn = remove_dot($_->remotepath); + $expected{$fn} = $_; + $done{$fn} = 0; + } + + my %remote; + File::walk(sub { $remote{remove_dot($_->remotepath)} = $_ }, File::tree($subpath)); + + for my $rfile (sort keys %remote) { + + # files that shouldn't be there + if (!exists $expected{$rfile}) { + say " + $rfile"; + push @more, $rfile; + next; + } + + # same file multiple times + if ($done{$rfile} > 0) { + $done{$rfile}++; + push @more, $rfile; + printf " +%3d %s\n", $done{$rfile}, $rfile; + next; + } + + $done{$rfile}++; + + # different file + my $rmd5 = $remote{$rfile}->md5; + if ($expected{$rfile}->md5 ne $rmd5) { + say " ! $rfile ($rmd5)"; + push @diff, $rfile; + next; + } + + say " $rfile"; + } + + # file that should have been in tar + @less = grep { $done{$_} == 0 } sort keys %done; + for (@less) { + say " - $_"; + } + + # summary + printf("\t%d files, +%d, -%d, !%d\n", + scalar keys %done, + scalar @more, + scalar @less, + scalar @diff); + return (@more + @less + @diff); # nb of errors +} + +=head3 C<check_tar( $path_to_tar, \@files )> + +Check if the archive C<$path_to_tar> has B<exactly> all the C<@files>. + +Print a summary on C<STDOUT>; + +C<@files> must be a list of C<File> instance. + +=cut +sub check_tar { + my ($tar, $files) = @_; + my %done; + my (@less, @more, @diff); + + my %h; + + + if (!-f $tar) { + say "no tar file $tar"; + return 1; + } + + for (@$files) { + $h{$_->tarpath} = $_; + $done{$_->tarpath} = 0; + } + + my $total = 0; + my $i = Archive::Tar->iter($tar, 1, {md5 => 1}); + while (my $f = $i->()) { + if ($f->has_content) { + my $p = $f->full_path; + + # we skip pseudo files of Pax format archives + next if ($p =~ m/\/PaxHeader/); + + $total++; + $p =~ s{^\./+}{}; + + # file that shouldn't be there + if (!exists $done{$p}) { + push @more, $p; + say " + $p"; + next; + } + + # same file multiple times + if ($done{$p} > 0) { + $done{$p}++; + push @more, $p; + printf " +%3d %s\n", $done{$p}, $p; + next; + } + + $done{$p}++; + + # different file + + my $md5 = $f->data; + if ($^V lt v5.16) { + $md5 = md5_hex($md5); + } + + if ($md5 ne $h{$p}->md5) { + say " ! $p ($md5)"; + push @diff, $p; + next; + } + + say " $p"; + } + } + + # file that should have been in tar + @less = grep { $done{$_} == 0 } keys %done; + for (sort @less) { + say " - $_"; + } + + # summary + printf("\t%d files, +%d, -%d, !%d\n", + $total, + scalar @more, + scalar @less, + scalar @diff); + return (@more + @less + @diff); # nb of errors +} + +=head3 C<smb_client_cmd( $will_die, @args)> + +=head3 C<smb_client_cmd( 0, '-c', 'deltree', $somedir )> + +Run smbclient with C<@args> passed as argument and return output. + +Each element of C<@args> becomes one escaped argument of smbclient. + +Host, share, user, password and the additional arguments provided on +the command-line are already inserted. + +The output contains both the C<STDOUT> and C<STDERR>. + +if C<$will_die> then Die if smbclient crashes or exits with an error code. +otherwise return output + +=cut +sub smb_client_cmd { + my ($will_die, @args) = @_; + + my $fullpath = "//$HOST/$SHARE"; + my $cmd = sprintf("%s %s %s", + quotemeta($BIN), + quotemeta($fullpath), + join(' ', map {quotemeta} (@SMBARGS, @args))); + + if ($DEBUG) { + my $tmp = $cmd; + $tmp =~ s{\\([./+-])}{$1}g; + say color('bold yellow'), $tmp, color('reset'); + } + + my $out = `$cmd 2>&1`; + my $err = $?; + my $errstr = ''; + # handle abnormal exit + if ($err == -1) { + $errstr = "failed to execute $cmd: $!\n"; + } + elsif ($err & 127) { + $errstr = sprintf "child died with signal %d (%s)\n", ($err & 127), $cmd; + } + elsif ($err >> 8) { + $errstr = sprintf "child exited with value %d (%s)\n", ($err >> 8), $cmd; + } + + if ($DEBUG) { + say $out; + } + + if ($err) { + if ($will_die) { + die "ERROR: $errstr"; + } else { + say "ERROR: $errstr"; + } + } + return $out; +} + +=head3 C<smb_client ( @args )> + +Run smbclient with C<@args> passed as argument and return output. + +Each element of C<@args> becomes one escaped argument of smbclient. + +Host, share, user, password and the additional arguments provided on +the command-line are already inserted. + +The output contains both the C<STDOUT> and C<STDERR>. + +Die if smbclient crashes or exits with an error code. + +=cut +sub smb_client { + my (@args) = @_; + return smb_client_cmd(1, @args) +} + +sub smb_cmd { + return smb_client('-c', join(' ', @_)); +} + +=head3 C<smb_tar( $cmd, @args )> + +=head3 C<smb_tar( 'tarmode inc', '-Tc', $TAR, $DIR )> + +Run C<$cmd> command and use C<@args> as argument and return output. + +Wrapper around C<smb_client> for tar calls. + +=cut +sub smb_tar { + my ($cmd, @rest) = @_; + printf " CMD: %s\n ARG: %s\n", $cmd, join(' ', @rest); + smb_client((length($cmd) ? ('-c', $cmd) : ()), @rest); +} + +=head3 C<random( $min, $max )> + +Return integer in C<[ $min ; $max ]> + +=cut +sub random { + my ($min, $max) = @_; + ($min, $max) = ($max, $min) if ($min > $max); + $min + int(rand($max - $min)); +} + +################################# + +package File; + +=head2 The File module + +All the test should use the C<File> class. It has nice functions and +methods to deal with paths, to create random files, to list the +content of the server, to change attributes, etc. + +There are 2 kinds of C<File>: remote and local. + +=over + +=item * Remote files are accessible on the server. + +=item * Local files are not. + +=back + +Thus, some methods only works on remote files. If they do not make +sense for local ones, they always return undef. + +=cut +use File::Basename; +use File::Path qw/make_path remove_tree/; +use Digest::MD5 qw/md5_hex/; +use Scalar::Util 'blessed'; + +=head3 Constructors + +=head4 C<< File->new_remote($path [, $abs, $size]) >> + +Creates a file accessible on the server at C<$DIR/$path> ie. not at the +root of the share and write C<$size> random bytes. + +If no size is provided, a random size is chosen. + +If you want to remove the automatic prefix C<$DIR>, set C<$abs> to 1. + +The file is created without any DOS attributes. + +If C<$path> contains non-existent directories, they are automatically +created. + +=cut +sub new_remote { + my ($class, $path, $abs, $size) = @_; + my ($file, $dir) = fileparse($path); + + $dir = '' if $dir eq './'; + my $loc; + + if ($abs) { + $loc = cleanpath($main::LOCALPATH.'/'.$dir); + } else { + $dir = cleanpath($main::DIR.'/'.$dir); + $loc = cleanpath($main::LOCALPATH.'/'.$dir); + } + + make_path($loc); + + my $self = bless { + 'attr' => {qw/r 0 s 0 h 0 a 0 d 0 n 0/}, + 'dir' => $dir, + 'name' => $file, + 'md5' => create_file($loc.'/'.$file, $size), + 'remote' => 1, + }, $class; + + $self->set_attr(); + + $self; +} + +=head4 C<< File->new_local($abs_path [, $data]) >> + +Creates a file at C<$abs_path> with $data in it on the system. +If $data is not provided, fill it with random bytes. + +=cut +sub new_local { + my ($class, $path, $data) = @_; + my ($file, $dir) = fileparse($path); + + make_path($dir); + + my $md5; + + if (defined $data) { + open my $f, '>', $path or die "can't write in $path: $!"; + print $f $data; + close $f; + $md5 = md5_hex($data); + } else { + $md5 = create_file($path); + } + + my $self = { + 'attr' => {qw/r 0 s 0 h 0 a 0 d 0 n 0/}, + 'dir' => $dir, + 'name' => $file, + 'md5' => $md5, + 'remote' => 0, + }; + + bless $self, $class; +} + +=head3 Methods + +=head4 C<< $f->localpath >> + +Return path on the system eg. F</opt/samba/share/test_tar_mode/file> + +=cut +sub localpath { + my $s = shift; + if ($s->{remote}) { + return cleanpath($main::LOCALPATH.'/'.$s->remotepath); + } + else { + return cleanpath($s->{dir}.'/'.$s->{name}); + } +} + +=head4 C<< $f->remotepath >> + +Return path on the server share. + +Return C<undef> if the file is local. + +=cut +sub remotepath { + my ($s) = @_; + return undef if !$s->{remote}; + my $r = $s->{dir}.'/'.$s->{name}; + $r =~ s{^/}{}; + return cleanpath($r); +} + + +=head4 C<< $f->remotedir >> + +Return the directory path of the file on the server. + +Like C<< $f->remotepath >> but without the final file name. + +=cut +sub remotedir { + my $s = shift; + return undef if !$s->{remote}; + cleanpath($s->{dir}); +} + +=head4 C<< $f->tarpath >> + +Return path as it would appear in a tar archive. + +Like C<< $f->remotepath >> but prefixed with F<./> + +=cut +sub tarpath { + my $s = shift; + return undef if !$s->{remote}; + my $r = $s->remotepath; + $r =~ s{^\./+}{}; + return $r; +} + +=head4 C<< $f->delete_on_destruction( 0 ) >> + +=head4 C<< $f->delete_on_destruction( 1 ) >> + +By default, a C<File> is not deleted on the filesystem when it is not +referenced anymore in Perl memory. + +When set to 1, the destructor unlink the file if it is not already removed. +If the C<File> created directories when constructed, it does not remove them. + +=cut +sub delete_on_destruction { + my ($s, $delete) = @_; + $s->{delete_on_destruction} = $delete; +} + +=head4 C<< $f->set_attr( ) >> + +=head4 C<< $f->set_attr( 'a' ) >> + +=head4 C<< $f->set_attr( 'a', 'r', 's', 'h' ) >> + +Remove all DOS attributes and only set the one provided. + +=cut +sub set_attr { + my ($s, @flags) = @_; + return undef if !$s->{remote}; + + $s->{attr} = {qw/r 0 s 0 h 0 a 0 d 0 n 0/}; + + for (@flags) { + $s->{attr}{lc($_)} = 1; + } + + my $file = $s->{name}; + my @args; + if ($s->remotedir) { + push @args, '-D', $s->remotedir; + } + main::smb_client(@args, '-c', qq{setmode "$file" -rsha}); + if (@flags && $flags[0] !~ /n/i) { + main::smb_client(@args, '-c', qq{setmode "$file" +}.join('', @flags)); + } +} + +=head4 C<< $f->attr_any( 'a' ) >> + +=head4 C<< $f->attr_any( 'a', 's', ... ) >> + +Return 1 if the file has any of the DOS attributes provided. + +=cut +sub attr_any { + my ($s, @flags) = @_; + for (@flags) { + return 1 if $s->{attr}{$_}; + } + 0; +} + + +=head4 C<< $f->attr( 'a' ) >> + +=head4 C<< $f->attr( 'a', 's', ... ) >> + +Return 1 if the file has all the DOS attributes provided. + +=cut +sub attr { + my ($s, @flags) = @_; + for (@flags) { + return 0 if !$s->{attr}{$_}; + } + 1; +} + +=head4 C<< $f->attr_str >> + +Return DOS attributes as a compact string. + + Read-only, hidden, system, archive => "rhsa" + +=cut +sub attr_str { + my $s = shift; + return undef if !$s->{remote}; + join('', map {$_ if $s->{attr}{$_}} qw/r h s a d n/); +} + +=head4 C<< $f->set_time($t) >> + +Set modification and access time of the file to C<$t>. + +C<$t> must be in Epoch time (number of seconds since 1970/1/1). + +=cut +sub set_time { + my ($s, $t) = @_; + utime $t, $t, $s->localpath; +} + +=head4 C<< $f->md5 >> + +Return md5 sum of the file. + +The result is cached. + +=cut +sub md5 { + my $s = shift; + + if (!$s->{md5}) { + open my $h, '<', $s->localpath() or die "can't read ".$s->localpath.": $!"; + binmode $h; + $s->{md5} = Digest::MD5->new->addfile($h)->hexdigest; + close $h; + } + + return $s->{md5}; +} + +sub DESTROY { + my $s = shift; + if ($s->{delete_on_destruction} && -f $s->localpath) { + if ($main::DEBUG) { + say "DESTROY ".$s->localpath; + } + unlink $s->localpath; + } +} + +=head3 Functions + +=head4 C<< File::walk( \&function, @files) >> + +=head4 C<< File::walk( sub { ... }, @files) >> + +Iterate on file hierarchy in C<@files> and return accumulated results. + +Use C<$_> in the sub to access the current C<File>. + +The C<@files> must come from a call to the C<File::tree> function. + +=cut +sub walk { + my $fun = \&{shift @_}; + + my @res; + + for (@_) { + if ($_->{attr}{d}) { + push @res, walk($fun, @{$_->{content}}); + } else { + push @res, $fun->($_); + } + } + + return @res; +} + +=head4 C<< File::list( $remotepath ) >> + +Return list of file (C<File> instance) in C<$remotepath>. + +C<$remotepath> must be a directory. + +=cut +sub list { + my ($path) = @_; + $path ||= '/'; + my @files; + my $out = main::smb_client('-D', $path, '-c', 'ls'); + $path =~ s{^/}{}; + + for (split /\n/, $out) { + next if !/^ (.+?)\s+([AHSRDN]*)\s+(\d+)\s+(.+)/o; + my ($fn, $attr, $size, $date) = ($1, $2, $3, $4); + next if $fn =~ /^\.{1,2}$/; + + push @files, bless { + 'remote' => 1, + 'dir' => $path, + 'name' => $fn, + 'size' => int($size), + 'date' => $date, + 'attr' => { + # list context returns something different than the + # boolean matching result => force scalar context + 'a' => scalar ($attr =~ /A/), + 'h' => scalar ($attr =~ /H/), + 's' => scalar ($attr =~ /S/), + 'r' => scalar ($attr =~ /R/), + 'd' => scalar ($attr =~ /D/), + 'n' => scalar ($attr =~ /N/), + }, + }, 'File'; + } + return @files; +} + +=head4 C<< File::tree( $remotepath ) >> + +Return recursive list of file in C<$remotepath>. + +C<$remotepath> must be a directory. + +Use C<File::walk()> to iterate over all the files. + +=cut +sub tree { + my ($d) = @_; + my @files; + + if (!defined $d) { + @files = list(); + } elsif (blessed $d) { + @files = list($d->remotepath); + } else { + @files = list($d); + } + + for my $f (@files) { + if ($f->{attr}{d}) { + $f->{content} = [tree($f)]; + } + } + + return @files; +} + +# remove trailing or duplicated slash +sub cleanpath { + my $p = shift; + $p =~ s{/+}{/}g; + $p =~ s{/$}{}; + $p; +} + +# create random file at path local path $fn +sub create_file { + my ($fn, $size) = @_; + my $buf = ''; + unlink $fn if -e $fn; + $size ||= main::random(512, 1024); + $size = int($size); + my $md5; + + # try /dev/urandom, faster + if (-e '/dev/urandom') { + my $cmd = sprintf('head -c %d /dev/urandom | tee %s | md5sum', + $size, quotemeta($fn)); + $md5 = (split / /, `$cmd`)[0]; + } else { + open my $out, '>', $fn or die "can't open $fn: $!\n"; + binmode $out; + for (1..$size) { + $buf .= pack('C', main::random(0, 256)); + } + print $out $buf; + close $out; + $md5 = md5_hex($buf); + } + return $md5; +} + + +=head3 Examples + + # create remote file in $DIR/foo/bar + my $f = File->new_remote("foo/bar/myfile"); + say $f->localpath; # /opt/share/$DIR/foo/bar/myfile + say $f->remotepath; # $DIR/foo/bar/myfile + say $f->remotedir; # $DIR/foo/bar + + + # same but in root dir + my $f = File->new_remote("myfile", 1); + say $f->localpath; # /opt/share/myfile + say $f->remotepath; # myfile + say $f->remotedir; # + + + # create local random temp file in $TMP + my $f = File->new_local("$TMP/temp"); + say $f->remotepath; # undef because it's not on the server + + + # same but file contains "hello" + my $f = File->new_local("$TMP/temp", "hello"); + + + # list of files in $DIR (1 level) + for (File::list($DIR)) { + say $_->remotepath; + } + + + # list of all files in dir and subdir of $DIR + File::walk(sub { say $_->remotepath }, File::tree($DIR)); + +=cut + +1; diff --git a/source3/script/tests/test_smbclient_tarmode.sh b/source3/script/tests/test_smbclient_tarmode.sh new file mode 100755 index 0000000..d48e412 --- /dev/null +++ b/source3/script/tests/test_smbclient_tarmode.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# this runs a simple tarmode test + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_smbclient_tarmode.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT [create|extract] <smbclient arguments> +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +LOCAL_PATH="$5" +PREFIX="$6" +SMBCLIENT="$7" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 7 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +FAILCOUNT=0 + +# Check command is available +have_command() +{ + type "$1" >/dev/null 2>&1 + return $? +} + +# Create a test corpus +create_test_data() +{ + + local DIR="$1" + local BS=1024 + local NUM_FILES=10 + local NORND_COUNT=25 + + # Bomb if dir exists + if [ -e "$DIR" ]; then + echo "Test data directory '$DIR' already exists!" + false + return + fi + + if ! mkdir -p "$DIR" >/dev/null 2>&1; then + echo "Couldn't create test data directory '$DIR'" + false + return + fi + + local I=1 + if have_command "od"; then # Use random file sizes + local RND_COUNT + for RND_COUNT in $(od -An -N$NUM_FILES -tu1 </dev/urandom); do + if ! dd if=/dev/urandom of="$DIR/file.$I" bs=$BS count=$RND_COUNT >/dev/null 2>&1; then + echo "Couldn't create test file '$DIR/file.$I' (random size)" + false + return + fi + I=$(expr $I + 1) + done + else # Fallback to same file sizes + while [ $I -le $NUM_FILES ]; do + if ! dd if=/dev/urandom of="$DIR/file.$I" bs=$BS count=$NORND_COUNT >/dev/null 2>&1; then + echo "Couldn't create test file '$DIR/file.$I' (static size)" + false + return + fi + I=$(expr $I + 1) + done + fi + + true + return + +} + +# Check that two directories are equivalent (In Data content) +validate_data() +{ + local DIR1="$1" + local DIR2="$2" + + diff -r "$DIR1" "$DIR2" + return $? +} + +# Test tarmode -Tc +test_tarmode_creation() +{ + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + + # Build the test data + if ! create_test_data "$LOCAL_PATH"; then + echo "Test data creation failed" + false + return + fi + + # Create tarfile with smbclient + if ! $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 \ + $ADDARGS -c "tarmode full" -Tc "$PREFIX/tarmode.tar" "/smbclient_tar"; then + echo "Couldn't create tar file with tarmode -Tc" + false + return + fi + + # Extract data to verify - this puts it into $PREFIX/smbclient_tar/ + # but we must leave it there as it's used to verify in test_tarmode_extraction() + if ! tar -xf "$PREFIX/tarmode.tar" -C "$PREFIX"; then + echo "Couldn't extract data from created tarfile" + false + return + fi + + # Verify data + if ! validate_data "$PREFIX/smbclient_tar" "$LOCAL_PATH"; then + echo "Data not equivalent" + false + return + fi + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + true + return + +} + +# Test tarmode -Tx +test_tarmode_extraction() +{ + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + + # Build the test data + if ! create_test_data "$PREFIX/tarmode"; then + echo "Test data creation failed" + false + return + fi + + # Create tarfile to extract on client + if ! tar -cf "$PREFIX/tarmode.tar" -C "$PREFIX" smbclient_tar; then + echo "Couldn't create tar archive" + false + return + fi + + # Extract tarfile with smbclient + if ! $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -I $SERVER_IP -p 139 \ + $ADDARGS -c "tarmode full" -Tx "$PREFIX/tarmode.tar"; then + echo "Couldn't extract tar file with tarmode -Tx" + false + return + fi + + # Verify data + if ! validate_data "$PREFIX/smbclient_tar" "$LOCAL_PATH"; then + echo "Data not equivalent" + false + return + fi + + # Clear temp data + rm -rf -- "$PREFIX"/tarmode >/dev/null 2>&1 + rm -f "$PREFIX"/tarmode.tar >/dev/null 2>&1 + $SMBCLIENT //$SERVER/tarmode $CONFIGURATION -U$USERNAME%$PASSWORD -c "deltree smbclient_tar" + # Cleanup the verification data created by test_tarmode_creation(). + rm -rf "$PREFIX"/smbclient_tar >/dev/null 2>&1 + true + return + +} + +testit "test_tarmode_creation" \ + test_tarmode_creation || FAILCOUNT=$(expr $FAILCOUNT + 1) + +testit "test_tarmode_extraction" \ + test_tarmode_extraction || FAILCOUNT=$(expr $FAILCOUNT + 1) + +testok $0 $FAILCOUNT diff --git a/source3/script/tests/test_smbcquota.py b/source3/script/tests/test_smbcquota.py new file mode 100755 index 0000000..02229d7 --- /dev/null +++ b/source3/script/tests/test_smbcquota.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Tests for smbcquotas +# Copyright (C) Noel Power 2017 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os, subprocess, sys +import traceback +import logging +import shutil + +USER_QUOTAS = 1 +USER_DEFAULT_QUOTAS = 2 +GROUP_QUOTAS = 3 +GROUP_DEFAULT_QUOTAS = 4 +BLOCK_SIZE = 1024 +DEFAULT_SOFTLIM = 2 +DEFAULT_HARDLIM = 4 + +class test_env: + def __init__(self): + self.server = None + self.domain = None + self.username = None + self.password = None + self.envdir = None + self.quota_db = None + self.smbcquotas = None + self.users = [] + +class user_info: + def __init__(self): + self.uid = 0 + self.username = "" + self.softlim = 0 + self.hardlim = 0 + +class Quota: + def __init__(self): + self.flags = 0 + self.quotatype = USER_DEFAULT_QUOTAS + self.uid = 0 + self.usedblocks = 0 + self.softlimit = 0 + self.hardlimit = 0 + self.hardlimit = 0 + self.usedinodes = 0 + self.slimitinodes = 0 + self.hlimitinodes = 0 + +def init_quota_db(users, output_file): + filecontents = open(output_file,"w+") + lines = "" + default_values = "0 " + str(DEFAULT_SOFTLIM) + " " + str(DEFAULT_HARDLIM) + " 0 0 0" + for user in users: + lines = lines + user.uid + " " + default_values + "\n" + filecontents.write(lines) + filecontents.close() + +def load_quotas(input_file): + fileContents = open(input_file,"r") + lineno = 0 + quotas = [] + for line in fileContents: + if line.strip().startswith("#"): + continue + content = line.strip().split() + quota = Quota() + if len(content) < 7: + logging.debug("ignoring line %d, doesn't have enough fields\n"%lineno) + else: + quota.flags = 2 + quota.uid = content[0] + quota.usedblocks = content[1] + quota.softlimit = content[2] + quota.hardlimit = content[3] + quota.usedinodes = content[4] + quota.slimitinodes = content[5] + quota.hlimitinodes = content[6] + quotas.append(quota) + + fileContents.close() + return quotas + +def get_quotas(uid, quota_list): + for quota in quota_list: + if quota.uid == uid: + return quota + return None + +def get_users(): + output = subprocess.Popen(['getent', 'passwd'], + stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + users = [] + for line in output: + info = line.split(':') + if len(info) > 3 and info[0]: + user = user_info() + user.username = info[0] + user.uid = info[2] + logging.debug("Adding user ->%s<-\n"%user.username) + users.append(user) + return users + + + +def smbcquota_output_to_userinfo(output): + infos = [] + for line in output: + if len(line) > 1: + username = line.strip(':').split()[0] + quota_info = line.split(':')[1].split('/') + if len(quota_info) > 2: + info = user_info() + info.username = username.strip() + info.softlim = int(quota_info[1].strip()) / BLOCK_SIZE + info.hardlim = int(quota_info[2].strip()) / BLOCK_SIZE + infos.append(info) + return infos + +def check_quota_limits(infos, softlim, hardlim): + if len(infos) < 1: + logging.debug("no users info to check :-(\n") + return False + for info in infos: + if int(info.softlim) != softlim: + logging.debug("expected softlimit %s got ->%s<-\n"%(softlim, info.softlim)) + return False + if int(info.hardlim) != hardlim: + logging.debug("expected hardlimit limit %s got %s\n"%(hardlim,info.hardlim)) + return False + return True + +class test_base: + def __init__(self, env): + self.env = env + def run(self, protocol): + pass + +class listtest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + args = [self.env.smbcquotas] + remaining_args = ['-U' + self.env.username + "%" + self.env.password, '-L', '//' + self.env.server + '/quotadir'] + if protocol == 'smb2': + args.append('-m smb2') + args.extend(remaining_args) + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '-L', '//' + self.env.server + '/quotadir'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + infos = smbcquota_output_to_userinfo(output) + return check_quota_limits(infos, DEFAULT_SOFTLIM, DEFAULT_HARDLIM) +def get_uid(name, users): + for user in users: + if user.username == name: + return user.uid + return None + +class gettest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + uid = get_uid(self.env.username, self.env.users) + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '-u' + self.env.username, '//' + self.env.server + '/quotadir'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + user_infos = smbcquota_output_to_userinfo(output) + db_user_info = get_quotas(uid, quotas) + # double check, we compare the results from the db file + # the quota script the server uses compared to what + # smbcquota is telling us + return check_quota_limits(user_infos, int(db_user_info.softlimit), int(db_user_info.hardlimit)) + +class settest(test_base): + def run(self, protocol): + init_quota_db(self.env.users, self.env.quota_db) + quotas = load_quotas(self.env.quota_db) + uid = get_uid(self.env.username, self.env.users) + old_db_user_info = get_quotas(uid, quotas) + + #increase limits by 2 blocks + new_soft_limit = (int(old_db_user_info.softlimit) + 2) * BLOCK_SIZE + new_hard_limit = (int(old_db_user_info.hardlimit) + 2) * BLOCK_SIZE + + new_limits = "UQLIM:%s:%d/%d"%(self.env.username, new_soft_limit, new_hard_limit) + logging.debug("setting new limits %s"%new_limits) + + output = subprocess.Popen([self.env.smbcquotas, '-U' + self.env.username + "%" + self.env.password, '//' + self.env.server + '/quotadir', '-S', new_limits], stdout=subprocess.PIPE).communicate()[0].decode("utf-8").split('\n') + logging.debug("output from smbcquota is %s"%output) + user_infos = smbcquota_output_to_userinfo(output) + return check_quota_limits(user_infos, new_soft_limit / BLOCK_SIZE, new_hard_limit / BLOCK_SIZE) + +# map of tests +subtest_descriptions = { + "list test" : listtest, + "get test" : gettest, + "set test" : settest +} + +def main(): + logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG) + + logging.debug("got args %s\n"%str(sys.argv)) + + if len(sys.argv) < 7: + logging.debug ("Usage: test_smbcquota.py server domain username password envdir smbcquotas\n") + sys.exit(1) + env = test_env() + env.server = sys.argv[1] + env.domain = sys.argv[2] + env.username = sys.argv[3] + env.password = sys.argv[4] + env.envdir = sys.argv[5] + env.smbcquotas = sys.argv[6] + quota_script = os.path.join(os.path.dirname(sys.argv[0]), + "getset_quota.py") + #copy the quota script to the environment + shutil.copy2(quota_script, env.envdir) + + env.quota_db = os.path.join(env.envdir, "quotas.db") + env.users = get_users() + for protocol in ['smb1', 'smb2']: + for key in subtest_descriptions.keys(): + test = subtest_descriptions[key](env) + logging.debug("running subtest '%s' using protocol '%s'\n"%(key,protocol)) + result = test.run(protocol) + if result == False: + logging.debug("subtest '%s' for '%s' failed\n"%(key,protocol)) + sys.exit(1) + else: + logging.debug("subtest '%s' for '%s' passed\n"%(key,protocol)) + sys.exit(0) + +if __name__ == '__main__': + main() diff --git a/source3/script/tests/test_smbcquota.sh b/source3/script/tests/test_smbcquota.sh new file mode 100755 index 0000000..c001192 --- /dev/null +++ b/source3/script/tests/test_smbcquota.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Unix SMB/CIFS implementation. +# Tests for smbcquotas +# Copyright (C) Noel Power 2017 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# +# Blackbox test wrapper for smbcquota +# +if [ $# -lt 6 ]; then + cat <<EOF +Usage: test_smbcquota.sh SERVER DOMAIN USERNAME PASSWORD LOCAL_PATH SMBCQUOTAS +EOF + exit 1 +fi + +SERVER=$1 +DOMAIN=$2 +USERNAME=$3 +PASSWORD=$4 +ENVDIR=$(dirname $5) +SMBCQUOTAS="$VALGRIND $6" +shift 6 + +TEST_SMBCQUOTAS=$(dirname $0)/test_smbcquota.py + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "smbcquotas" ${TEST_SMBCQUOTAS} ${SERVER} ${DOMAIN} ${USERNAME} ${PASSWORD} ${ENVDIR} ${SMBCQUOTAS} || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbd_error.sh b/source3/script/tests/test_smbd_error.sh new file mode 100755 index 0000000..d39b174 --- /dev/null +++ b/source3/script/tests/test_smbd_error.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# +# Test smbd with failing chdir system call. +# +# Verify that smbd does not panic when the chdir system call is +# returning an error. ensure that the output format for ACL entries +# +# Copyright (C) 2017 Christof Schmitt + +. $(dirname $0)/../../../testprogs/blackbox/subunit.sh +failed=0 + +if [ $SMBD_DONT_LOG_STDOUT -eq 1 ]; then + subunit_start_test "check_panic_0" + subunit_skip_test "check_panic_0" <<EOF +logging to stdout disabled +EOF + + testok $0 $failed +fi + +error_inject_conf=$(dirname $SMB_CONF_PATH)/error_inject.conf + +panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG) + +# +# Verify that a panic in smbd will result in a PANIC message in the log +# + +# As a panic is expected here, also overwrite the default "panic +# action" in selftest to not start a debugger +echo 'error_inject:chdir = panic' >$error_inject_conf +echo '[global]' >>$error_inject_conf +echo 'panic action = ""' >>$error_inject_conf + +testit_expect_failure "smbclient" $VALGRIND \ + $BINDIR/smbclient //$SERVER_IP/error_inject \ + -U$USERNAME%$PASSWORD -c dir || + failed=$(expr $failed + 1) + +rm $error_inject_conf + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +testit "check_panic_1" test $(expr $panic_count_0 + 1) -eq $panic_count_1 || + failed=$(expr $failed + 1) + +# +# Verify that a failing chdir vfs call does not result in a smbd panic +# + +echo 'error_inject:chdir = ESTALE' >$error_inject_conf + +testit_expect_failure "smbclient" $VALGRIND \ + $BINDIR/smbclient //$SERVER_IP/error_inject \ + -U$USERNAME%$PASSWORD -c dir || + failed=$(expr $failed + 1) + +panic_count_2=$(grep -c PANIC $SMBD_TEST_LOG) + +testit "check_panic_2" test $panic_count_1 -eq $panic_count_2 || + failed=$(expr $failed + 1) + +rm $error_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_smbd_no_krb5.sh b/source3/script/tests/test_smbd_no_krb5.sh new file mode 100755 index 0000000..faa46c9 --- /dev/null +++ b/source3/script/tests/test_smbd_no_krb5.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_smbd_no_krb5.sh SERVER USERNAME PASSWORD PREFIX +EOF + exit 1 +fi + +smbclient=$1 +SERVER=$2 +USERNAME=$3 +PASSWORD=$4 +PREFIX=$5 +shift 5 + +samba_bindir="$BINDIR" +samba_kinit=kinit +if test -x ${samba_bindir}/samba4kinit; then + samba_kinit=${samba_bindir}/samba4kinit +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +opt="--option=gensec:gse_krb5=yes -U${USERNAME}%${PASSWORD}" + +# check kerberos access +test_smbclient "test_krb5" "ls" "//$SERVER/tmp" $opt --use-kerberos=required || failed=$(expr $failed + 1) + +# disable krb5 globally so smbd won't accept it +global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf +echo 'gensec:gse_krb5=no' >$global_inject_conf + +# verify that kerberos fails +test_smbclient_expect_failure "smbd_no_krb5" "ls" "//$SERVER/tmp" --use-kerberos=required $opt || failed=$(expr $failed + 1) + +# verify downgrade to ntlmssp +test_smbclient "test_spnego_downgrade" "ls" "//$SERVER/tmp" $opt --use-kerberos=disabled || failed=$(expr $failed + 1) + +echo '' >$global_inject_conf + +testok $0 $failed diff --git a/source3/script/tests/test_smbget.sh b/source3/script/tests/test_smbget.sh new file mode 100755 index 0000000..acc492d --- /dev/null +++ b/source3/script/tests/test_smbget.sh @@ -0,0 +1,619 @@ +#!/usr/bin/env bash +# +# Blackbox test for smbget. +# + +if [ $# -lt 8 ]; then + cat <<EOF +Usage: test_smbget SERVER SERVER_IP DOMAIN REALM USERNAME PASSWORD WORKDIR SMBGET +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +REALM=${4} +USERNAME=${5} +PASSWORD=${6} +DOMAIN_USER=${7} +DOMAIN_USER_PASSWORD=${8} +WORKDIR=${9} +SMBGET="$VALGRIND ${10}" +shift 10 + +TMPDIR="$SELFTEST_TMPDIR" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. "${incdir}/common_test_fns.inc" + +samba_kinit=$(system_or_builddir_binary kinit "${BINDIR}" samba4kinit) +samba_texpect="${BINDIR}/texpect" + +create_test_data() +{ + pushd $WORKDIR + dd if=/dev/urandom bs=1024 count=128 of=testfile + chmod 644 testfile + mkdir dir1 + dd if=/dev/urandom bs=1024 count=128 of=dir1/testfile1 + mkdir dir2 + dd if=/dev/urandom bs=1024 count=128 of=dir2/testfile2 + popd +} + +remove_test_data() +{ + pushd $WORKDIR + rm -rf dir1 dir2 testfile + popd +} + +clear_download_area() +{ + rm -rf dir1 dir2 testfile dir001 dir004 readable_file +} + +test_singlefile_guest() +{ + clear_download_area + echo "$SMBGET --verbose --guest smb://$SERVER_IP/smbget_guest/testfile" + $SMBGET --verbose --guest smb://$SERVER_IP/smbget_guest/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_singlefile_U() +{ + clear_download_area + $SMBGET --verbose -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_singlefile_U_UPN() +{ + clear_download_area + + ${SMBGET} --verbose -U"${DOMAIN_USER}@${REALM}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER_IP}/smbget/testfile" + ret=${?} + if [ ${ret} -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent "${WORKDIR}/testfile" ./testfile + ret=${?} + if [ ${ret} -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_singlefile_U_domain() +{ + clear_download_area + + ${SMBGET} --verbose -U"${DOMAIN}/${DOMAIN_USER}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER_IP}/smbget/testfile" + ret=${?} + if [ ${ret} -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent "${WORKDIR}/testfile" ./testfile + ret=${?} + if [ ${ret} -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_singlefile_smburl() +{ + clear_download_area + $SMBGET --workgroup $DOMAIN smb://${DOMAIN_USER}:$DOMAIN_USER_PASSWORD@$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_singlefile_smburl2() +{ + clear_download_area + $SMBGET "smb://$DOMAIN;${DOMAIN_USER}:$DOMAIN_USER_PASSWORD@$SERVER_IP/smbget/testfile" + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_singlefile_smburl_interactive() +{ + clear_download_area + + tmpfile="$(mktemp --tmpdir="${TMPDIR}" expect_XXXXXXXXXX)" + + cat >"${tmpfile}" <<EOF +expect Password for +send ${DOMAIN_USER_PASSWORD}\n +EOF + + USER="hanswurst" ${samba_texpect} "${tmpfile}" ${SMBGET} "smb://${DOMAIN};${DOMAIN_USER}@${SERVER_IP}/smbget/testfile" + ret=$? + rm -f "${tmpfile}" + if [ ${ret} -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + ret=$? + if [ ${ret} -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_singlefile_authfile() +{ + clear_download_area + cat >"${TMPDIR}/authfile" << EOF +username = ${SERVER}/${USERNAME} +password = $PASSWORD +EOF + $SMBGET --verbose --authentication-file="${TMPDIR}/authfile" smb://$SERVER_IP/smbget/testfile + rc=$? + rm -f $TMPDIR/authfile + if [ $rc -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + return 0 +} + +test_recursive_U() +{ + clear_download_area + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_recursive_existing_dir() +{ + clear_download_area + mkdir dir1 + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_recursive_with_empty() +{ # see Bug 13199 + clear_download_area + # create some additional empty directories + mkdir -p $WORKDIR/dir001/dir002/dir003 + mkdir -p $WORKDIR/dir004/dir005/dir006 + $SMBGET --verbose --recursive -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/ + rc=$? + rm -rf $WORKDIR/dir001 + rm -rf $WORKDIR/dir004 + if [ $rc -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile && + cmp --silent $WORKDIR/dir1/testfile1 ./dir1/testfile1 && + cmp --silent $WORKDIR/dir2/testfile2 ./dir2/testfile2 + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + if [ ! -d dir001/dir002/dir003 ] || [ ! -d dir004/dir005/dir006 ]; then + echo 'ERROR: empty directories are not present' + return 1 + fi + + return 0 +} + +test_resume() +{ + clear_download_area + cp $WORKDIR/testfile . + truncate -s 1024 testfile + $SMBGET --verbose --resume -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_resume_modified() +{ + clear_download_area + dd if=/dev/urandom bs=1024 count=2 of=testfile + $SMBGET --verbose --resume -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 1 ]; then + echo 'ERROR: RC does not match, expected: 1' + return 1 + fi + + return 0 +} + +test_update() +{ + clear_download_area + $SMBGET --verbose -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + # secondary download should pass + $SMBGET --verbose --update -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + echo "modified" >>testfile + # touch source to trigger new download + sleep 1 + touch -m $WORKDIR/testfile + $SMBGET --verbose --update -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +# Test accessing an msdfs path. +test_msdfs_link() +{ + clear_download_area + + ${SMBGET} --verbose "-U${SERVER}/${USERNAME}%${PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +test_msdfs_link_domain() +{ + clear_download_area + + ${SMBGET} --verbose "-U${DOMAIN}/${DOMAIN_USER}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +test_msdfs_link_upn() +{ + clear_download_area + + ${SMBGET} --verbose "-U${DOMAIN_USER}@${REALM}%${DOMAIN_USER_PASSWORD}" \ + "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file" + ret=$? + if [ ${ret} -ne 0 ]; then + echo "ERROR: smbget failed with ${ret}" + return 1 + fi + + return 0 +} + +# Tests --limit-rate. Getting the testfile (128K in size) with --limit-rate 100 +# (that is 100KB/s) should take at least 1 sec to complete. +test_limit_rate() +{ + clear_download_area + echo "$SMBGET --verbose --guest --limit-rate 100 smb://$SERVER_IP/smbget_guest/testfile" + time_begin=$(date +%s) + $SMBGET --verbose --guest --limit-rate 100 smb://$SERVER_IP/smbget_guest/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + time_end=$(date +%s) + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + if [ $((time_end - time_begin)) -lt 1 ]; then + echo 'ERROR: It should take at least 1s to transfer 128KB with rate 100KB/s' + return 1 + fi + return 0 +} + +test_encrypt() +{ + clear_download_area + $SMBGET --verbose --encrypt -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + clear_download_area + $SMBGET --verbose --client-protection=encrypt -U${SERVER}/${USERNAME}%$PASSWORD smb://$SERVER_IP/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +test_kerberos() +{ + clear_download_area + + KRB5CCNAME_PATH="${TMPDIR}/smget_krb5ccache" + rm -f "${KRB5CCNAME_PATH}" + + KRB5CCNAME="FILE:${KRB5CCNAME_PATH}" + export KRB5CCNAME + kerberos_kinit "${samba_kinit}" \ + "${DOMAIN_USER}@${REALM}" "${DOMAIN_USER_PASSWORD}" + if [ $? -ne 0 ]; then + echo 'Failed to get Kerberos ticket' + return 1 + fi + + $SMBGET --verbose --use-krb5-ccache="${KRB5CCNAME}" \ + smb://$SERVER/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + rm -f "${KRB5CCNAME_PATH}" + + return 0 +} + +test_kerberos_trust() +{ + clear_download_area + + $SMBGET --verbose --use-kerberos=required \ + -U"${TRUST_F_BOTH_USERNAME}@${TRUST_F_BOTH_REALM}%${TRUST_F_BOTH_PASSWORD}" \ + smb://$SERVER.${REALM}/smbget/testfile + if [ $? -ne 0 ]; then + echo 'ERROR: RC does not match, expected: 0' + return 1 + fi + + cmp --silent $WORKDIR/testfile ./testfile + if [ $? -ne 0 ]; then + echo 'ERROR: file content does not match' + return 1 + fi + + return 0 +} + +# TODO FIXME +# This test does not work, as we can't tell the libsmb code that the +# principal is an enterprice principal. We need support for enterprise +# principals in kerberos_kinit_password_ext() and a way to pass it via the +# credenitals structure and commandline options. +# It works if you do: kinit -E testdenied_upn@${REALM}.upn +# +# test_kerberos_upn_denied() +# { +# set -x +# clear_download_area +# +# $SMBGET --verbose --use-kerberos=required \ +# -U"testdenied_upn@${REALM}.upn%${DC_PASSWORD}" \ +# "smb://${SERVER}.${REALM}/smbget/testfile" -d10 +# if [ $? -ne 0 ]; then +# echo 'ERROR: RC does not match, expected: 0' +# return 1 +# fi +# +# cmp --silent $WORKDIR/testfile ./testfile +# if [ $? -ne 0 ]; then +# echo 'ERROR: file content does not match' +# return 1 +# fi +# +# return 0 +# } + +create_test_data + +pushd $TMPDIR + +failed=0 +testit "download single file as guest" test_singlefile_guest || + failed=$(expr $failed + 1) + +testit "download single file with -U" test_singlefile_U || + failed=$(expr $failed + 1) + +testit "download single file with --update and domain" test_singlefile_U_domain || + failed=$((failed + 1)) + +testit "download single file with --update and UPN" test_singlefile_U_UPN || + failed=$((failed + 1)) + +testit "download single file with smb URL" test_singlefile_smburl || + failed=$(expr $failed + 1) + +testit "download single file with smb URL including domain" \ + test_singlefile_smburl2 || + failed=$(expr $failed + 1) + +testit "download single file with smb URL interactive" \ + test_singlefile_smburl_interactive || + failed=$(expr $failed + 1) + +testit "download single file with authfile" test_singlefile_authfile || + failed=$(expr $failed + 1) + +testit "recursive download" test_recursive_U || + failed=$(expr $failed + 1) + +testit "recursive download (existing target dir)" test_recursive_existing_dir || + failed=$(expr $failed + 1) + +testit "recursive download with empty directories" test_recursive_with_empty || + failed=$(expr $failed + 1) + +testit "resume download" test_resume || + failed=$(expr $failed + 1) + +testit "resume download (modified file)" test_resume_modified || + failed=$(expr $failed + 1) + +testit "update" test_update || + failed=$(expr $failed + 1) + +testit "msdfs" test_msdfs_link || + failed=$((failed + 1)) + +testit "msdfs.domain" test_msdfs_link_domain || + failed=$((failed + 1)) + +testit "msdfs.upn" test_msdfs_link_upn || + failed=$((failed + 1)) + +testit "limit rate" test_limit_rate || + failed=$((failed + 1)) + +testit "encrypt" test_encrypt || + failed=$((failed + 1)) + +testit "kerberos" test_kerberos || + failed=$((failed + 1)) + +testit "kerberos_trust" test_kerberos_trust || + failed=$((failed + 1)) + +# testit "kerberos_upn_denied" test_kerberos_upn_denied || +# failed=$((failed + 1)) + +clear_download_area + +popd # TMPDIR + +remove_test_data + +exit $failed diff --git a/source3/script/tests/test_smbpasswd.sh b/source3/script/tests/test_smbpasswd.sh new file mode 100755 index 0000000..b4d4f40 --- /dev/null +++ b/source3/script/tests/test_smbpasswd.sh @@ -0,0 +1,133 @@ +#!/bin/sh +# +# Blackbox tests for smbpasswd +# +# Copyright (c) 2015-2016 Andreas Schneider <asn@samba.org> +# + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_smbpasswd.sh SERVER USERNAME PASSWORD +EOF + exit 1 +fi + +SERVER=$1 +SERVER_IP=$2 +USERNAME=$3 +PASSWORD=$4 +shift 4 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +samba_bindir="$BINDIR" +samba_srcdir="$SRCDIR" + +samba_texpect="$samba_bindir/texpect" +samba_smbpasswd="$samba_bindir/smbpasswd" + +samba_test_user="alice_smbpasswd" +samba_test_user_pwd="Secret007" +samba_test_user_new_pwd="Secret008" + +create_local_smb_user() +{ + user=$1 + password=$2 + + tmpfile=$PREFIX/smbpasswd_create_user_script + cat >$tmpfile <<EOF +expect New SMB password: +send $password\n +expect Retype new SMB password: +send $password\n +EOF + + cmd='UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $samba_texpect $tmpfile $samba_smbpasswd -c $SMB_CONF_PATH -a $user 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to create smb user $user" + return 1 + fi + + getent passwd $user + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to create smb user $user" + return 1 + fi +} + +delete_local_smb_user() +{ + user=$1 + + # This also deletes the unix account! + UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $samba_smbpasswd -c $SMB_CONF_PATH -x $user + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to delete smb user $user" + return 1 + fi +} + +test_smbpasswd() +{ + user=$1 + oldpwd=$2 + newpwd=$3 + + user_id=$(id -u $user) + + tmpfile=$PREFIX/smbpasswd_change_password_script + cat >$tmpfile <<EOF +expect Old SMB password: +send $oldpwd\n +expect New SMB password: +send $newpwd\n +expect Retype new SMB password: +send $newpwd\n +EOF + + cmd='UID_WRAPPER_INITIAL_RUID=$user_id UID_WRAPPER_INITIAL_EUID=$user_id $samba_texpect $tmpfile $samba_smbpasswd -c $SMB_CONF_PATH -r $SERVER 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + if [ $ret -ne 0 ]; then + echo "Failed to change user password $user" + echo "${out}" + return 1 + fi + + prompt="Password changed for user $user" + echo "$out" | grep "$prompt" >/dev/null 2>&1 + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to change password for user $user" + echo "$out" + return 1 + fi +} + +testit "Create user $samba_test_user" \ + create_local_smb_user $samba_test_user $samba_test_user_pwd || + failed=$(expr $failed + 1) + +testit "Change user password" \ + test_smbpasswd $samba_test_user $samba_test_user_pwd $samba_test_user_new_pwd || + failed=$(expr $failed + 1) + +testit "Delete user $samba_test_user" \ + delete_local_smb_user $samba_test_user || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smbspool.sh b/source3/script/tests/test_smbspool.sh new file mode 100755 index 0000000..2036d57 --- /dev/null +++ b/source3/script/tests/test_smbspool.sh @@ -0,0 +1,294 @@ +#!/bin/sh + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_smbspool.sh SERVER SERVER_IP USERNAME PASSWORD TARGET_ENV +EOF + exit 1 +fi + +SERVER="$1" +SERVER_IP="$2" +USERNAME="$3" +PASSWORD="$4" +TARGET_ENV="$5" +shift 5 +ADDARGS="$@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +samba_bindir="$BINDIR" +samba_vlp="$samba_bindir/vlp" +samba_smbspool="$samba_bindir/smbspool" +samba_argv_wrapper="$samba_bindir/smbspool_argv_wrapper" +samba_smbtorture3="$samba_bindir/smbtorture3" +samba_smbspool_krb5="$samba_bindir/smbspool_krb5_wrapper" + +test_smbspool_noargs() +{ + cmd='$1 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "failed to execute $1" + fi + + echo "$out" | grep 'network smb "Unknown" "Windows Printer via SAMBA"' + ret=$? + if [ $ret != 0 ]; then + echo "$out" + return 1 + fi +} + +test_smbspool_authinforequired_none() +{ + cmd='$samba_smbspool_krb5 smb://$SERVER_IP/print4 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps 2>&1' + + AUTH_INFO_REQUIRED="none" + export AUTH_INFO_REQUIRED + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + unset AUTH_INFO_REQUIRED + + if [ $ret != 0 ]; then + echo "$out" + echo "failed to execute $samba_smbspool_krb5" + return 1 + fi + + return 0 +} + +test_smbspool_authinforequired_unknown() +{ + cmd='$samba_smbspool_krb5 smb://$SERVER_IP/print4 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps 2>&1' + + # smbspool_krb5_wrapper must ignore AUTH_INFO_REQUIRED unknown to him and pass the task to smbspool + # smbspool must fail with NT_STATUS_ACCESS_DENIED (22) + # "jjf4wgmsbc0" is just a random string + AUTH_INFO_REQUIRED="jjf4wgmsbc0" + export AUTH_INFO_REQUIRED + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + unset AUTH_INFO_REQUIRED + + case "$ret" in + 2) return 0 ;; + *) + echo "ret=$ret" + echo "$out" + echo "failed to test $samba_smbspool_krb5 against unknown value of AUTH_INFO_REQUIRED" + return 1 + ;; + esac +} + +# +# The test environment uses 'vlp' (virtual lp) as the printing backend. +# +# When using the vlp backend the print job is only written to the database. +# The job needs to removed manually using 'vlp lprm' command! +# +# This calls the 'vlp' command to check if the print job has been successfully +# added to the database and also makes sure the temporary print file has been +# created. +# +# The function removes the print job from the vlp database if successful. +# +test_vlp_verify() +{ + tdbfile="$PREFIX_ABS/$TARGET_ENV/lockdir/vlp.tdb" + if [ ! -w $tdbfile ]; then + echo "vlp tdbfile $tdbfile doesn't exist or is not writeable!" + return 1 + fi + + cmd='$samba_vlp tdbfile=$tdbfile lpq print1 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + if [ $ret != 0 ]; then + echo "failed to get print queue with $samba_vlp" + echo "$out" + fi + + jobid=$(echo "$out" | awk '/[0-9]+/ { print $1 };') + if [ -z "$jobid" ] || [ $jobid -lt 100 ] || [ $jobid -gt 2000 ]; then + echo "Invalid jobid: $jobid" + echo "$out" + return 1 + fi + + file=$(echo "$out" | awk '/[0-9]+/ { print $6 };') + if [ ! -r $PREFIX_ABS/$TARGET_ENV/share/$file ]; then + echo "$file doesn't exist" + echo "$out" + return 1 + fi + + $samba_vlp "tdbfile=$tdbfile" lprm print1 $jobid + ret=$? + if [ $ret != 0 ]; then + echo "Failed to remove jobid $jobid from $tdbfile" + return 1 + fi +} + +test_delete_on_close() +{ + tdbfile="$PREFIX_ABS/$TARGET_ENV/lockdir/vlp.tdb" + if [ ! -w $tdbfile ]; then + echo "vlp tdbfile $tdbfile doesn't exist or is not writeable!" + return 1 + fi + + cmd='$samba_vlp tdbfile=$tdbfile lpq print1 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + if [ $ret != 0 ]; then + echo "failed to lpq jobs on print1 with $samba_vlp" + echo "$out" + return 1 + fi + + num_jobs=$(echo "$out" | wc -l) + # + # Now run the test DELETE-PRINT from smbtorture3 + # + cmd='$samba_smbtorture3 //$SERVER_IP/print1 -U$USERNAME%$PASSWORD DELETE-PRINT 2>&1' + eval echo "$cmd" + out_t=$(eval $cmd) + ret=$? + if [ $ret != 0 ]; then + echo "failed to run DELETE-PRINT on print1" + echo "$out_t" + return 1 + fi + + cmd='$samba_vlp tdbfile=$tdbfile lpq print1 2>&1' + eval echo "$cmd" + out1=$(eval $cmd) + ret=$? + if [ $ret != 0 ]; then + echo "(2) failed to lpq jobs on print1 with $samba_vlp" + echo "$out1" + return 1 + fi + num_jobs1=$(echo "$out1" | wc -l) + + # + # Number of jobs should not change. Job + # should not have made it to backend. + # + if [ "$num_jobs1" -ne "$num_jobs" ]; then + echo "delete-on-close fail $num_jobs1 -ne $num_jobs" + echo "$out" + echo "$out_t" + echo "$out1" + return 1 + fi + + return 0 +} + +testit "smbspool no args" \ + test_smbspool_noargs $samba_smbspool || + failed=$(expr $failed + 1) + +testit "smbspool_krb5_wrapper no args" \ + test_smbspool_noargs $samba_smbspool_krb5 || + failed=$(expr $failed + 1) + +testit "smbspool_krb5_wrapper AuthInfoRequired=none" \ + test_smbspool_authinforequired_none || + failed=$(expr $failed + 1) + +testit "smbspool_krb5_wrapper AuthInfoRequired=(sth unknown)" \ + test_smbspool_authinforequired_unknown || + failed=$(expr $failed + 1) + +testit "smbspool print example.ps" \ + $samba_smbspool smb://$USERNAME:$PASSWORD@$SERVER_IP/print1 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +testit "smbspool print example.ps via stdin" \ + $samba_smbspool smb://$USERNAME:$PASSWORD@$SERVER_IP/print1 200 $USERNAME "Testprint" 1 "options" <$SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +DEVICE_URI="smb://$USERNAME:$PASSWORD@$SERVER_IP/print1" +export DEVICE_URI +testit "smbspool print DEVICE_URI example.ps" \ + $samba_smbspool 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) +unset DEVICE_URI + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +DEVICE_URI="smb://$USERNAME:$PASSWORD@$SERVER_IP/print1" +export DEVICE_URI +testit "smbspool print DEVICE_URI example.ps via stdin" \ + $samba_smbspool 200 $USERNAME "Testprint" 1 "options" <$SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) +unset DEVICE_URI + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +DEVICE_URI="smb://$USERNAME:$PASSWORD@$SERVER_IP/print1" +export DEVICE_URI +testit "smbspool print sanitized Device URI in argv0 example.ps" \ + $samba_argv_wrapper $samba_smbspool smb://$SERVER_IP/print1 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) +unset DEVICE_URI + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +DEVICE_URI="smb://$USERNAME:$PASSWORD@$SERVER_IP/print1" +export DEVICE_URI +testit "smbspool print sanitized Device URI in argv0 example.ps via stdin" \ + $samba_argv_wrapper $samba_smbspool smb://$SERVER_IP/print1 200 $USERNAME "Testprint" 1 "options" <$SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) +unset DEVICE_URI + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) + +AUTH_INFO_REQUIRED="username,password" +export AUTH_INFO_REQUIRED +testit "smbspool_krb5(username,password) print example.ps" \ + $samba_smbspool_krb5 smb://$USERNAME:$PASSWORD@$SERVER_IP/print1 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps || + failed=$(expr $failed + 1) + +testit "vlp verify example.ps" \ + test_vlp_verify || + failed=$(expr $failed + 1) +unset AUTH_INFO_REQUIRED + +testit "delete on close" \ + test_delete_on_close || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_smbspool_krb.sh b/source3/script/tests/test_smbspool_krb.sh new file mode 100755 index 0000000..a4aeeab --- /dev/null +++ b/source3/script/tests/test_smbspool_krb.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then + cat <<EOF +Usage: test_smbspool_krb.sh SERVER USERNAME PASSWORD REALM +EOF + exit 1 +fi + +SERVER="$1" +USERNAME="$2" +PASSWORD="$3" +REALM="$4" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +samba_bindir="$BINDIR" +samba_smbspool="$samba_bindir/smbspool" + +samba_kinit=kinit +if test -x "${BINDIR}/samba4kinit"; then + samba_kinit=${BINDIR}/samba4kinit +fi + +samba_kdestroy=kdestroy +if test -x "${BINDIR}/samba4kdestroy"; then + samba_kdestroy=${BINDIR}/samba4kdestroy +fi + +KRB5CCNAME_PATH="${PREFIX}/ccache_smbclient_kerberos" +KRB5CCNAME="FILE:${KRB5CCNAME_PATH}" +export KRB5CCNAME + +test_smbspool_authinforequired_negotiate() +{ + cmd='$samba_smbspool smb://$SERVER/print3 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps 2>&1' + + AUTH_INFO_REQUIRED="negotiate" + export AUTH_INFO_REQUIRED + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + unset AUTH_INFO_REQUIRED + + if [ $ret != 0 ]; then + echo "$out" + echo "failed to execute $samba_smbspool" + return 1 + fi + + return 0 +} + +test_smbspool_authinforequired_negative() +{ + cmd='$samba_smbspool smb://$SERVER/print3 200 $USERNAME "Testprint" 1 "options" $SRCDIR/testdata/printing/example.ps 2>&1' + + AUTH_INFO_REQUIRED="negotiate" + export AUTH_INFO_REQUIRED + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + unset AUTH_INFO_REQUIRED + + if [ $ret = 0 ]; then + echo "$out" + echo "Unexpected success to execute $samba_smbspool" + return 1 + fi + + return 0 +} + +kerberos_kinit "$samba_kinit" "${USERNAME}@${REALM}" "${PASSWORD}" +testit "smbspool krb5 AuthInfoRequired=negotiate" \ + test_smbspool_authinforequired_negotiate || + failed=$((failed + 1)) + +$samba_kdestroy +rm -rf "$KRB5CCNAME_PATH" + +# smbspool should fail after destroying kerberos credentials +testit "smbspool krb5 AuthInfoRequired=negotiate negative test" \ + test_smbspool_authinforequired_negative || + failed=$((failed + 1)) + + +testok "$0" "$failed" diff --git a/source3/script/tests/test_smbstatus.sh b/source3/script/tests/test_smbstatus.sh new file mode 100755 index 0000000..30ca239 --- /dev/null +++ b/source3/script/tests/test_smbstatus.sh @@ -0,0 +1,479 @@ +#!/bin/sh + +# This runs smbstatus tests + +if [ $# -lt 12 ]; then + echo "Usage: test_smbstatus.sh SERVER SERVER_IP DOMAIN USERNAME PASSWORD USERID LOCAL_PATH PREFIX SMBCLIENT CONFIGURATION PROTOCOL" + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +DOMAIN="${3}" +USERNAME="${4}" +PASSWORD="${5}" +USERID="${6}" +LOCAL_PATH="${7}" +PREFIX="${8}" +SMBCLIENT="${9}" +SMBSTATUS="${10}" +CONFIGURATION="${11}" +PROTOCOL="${12}" + +shift 12 + +RAWARGS="${CONFIGURATION} -m${PROTOCOL}" +ADDARGS="${RAWARGS} $@" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_smbstatus() +{ + local cmdfile=$PREFIX/smbclient_commands + local tmpfile=$PREFIX/smclient_lock_file + local file=smclient_lock_file + local cmd="" + local ret=0 + local userid=$(id -u $USERNAME) + + cat >$tmpfile <<EOF +What a Wurst! +EOF + cat >$cmdfile <<EOF +lcd $PREFIX_ABS +put $file +open $file +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $cmpfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + false + return + fi + + echo "$out" | grep -c 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "Failed: got an NT_STATUS error!" + echo "$out" + false + return + fi + + echo "$out" | grep "${userid}[ ]*DENY_NONE" + ret=$? + if [ $ret != 0 ]; then + echo "Failed to find userid in smbstatus locked file output" + echo "$out" + false + return + fi + + return 0 +} + +test_smbstatus_resolve_uids() +{ + local cmdfile=$PREFIX/smbclient_commands + local tmpfile=$PREFIX/smclient_lock_file + local file=smclient_lock_file + local cmd="" + local ret=0 + local userid=$(id -u $USERNAME) + + cat >$tmpfile <<EOF +What a Wurst! +EOF + cat >$cmdfile <<EOF +lcd $PREFIX_ABS +put $file +open $file +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --resolve-uids +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $cmpfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + false + return + fi + + echo "$out" | grep -c 'NT_STATUS_' + ret=$? + if [ $ret -eq 0 ]; then + echo "Failed: got an NT_STATUS error!" + echo "$out" + false + return + fi + + echo "$out" | grep "${USERNAME}[ ]*DENY_NONE" + ret=$? + if [ $ret != 0 ]; then + echo "Failed to find userid in smbstatus locked file output" + echo "$out" + false + return + fi + + return 0 +} + +test_smbstatus_output() +{ + local cmdfile=$PREFIX/smbclient_commands + local tmpfile=$PREFIX/smbclient_lock_file + local file=smbclient_lock_file + local status_shares=smbstatus_output_shares + local status_processes=smbstatus_output_processes + local status_locks=smbstatus_output_locks + + cat >$tmpfile <<EOF +Hello World! +EOF + cat >$cmdfile <<EOF +lcd $PREFIX_ABS +put $file +open $file +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --shares > $status_shares +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --processes > $status_processes +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --locks > $status_locks +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + + rm -f $cmpfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_processes) + echo "$out" | grep -c 'PID *Username' + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: Could not start smbstatus" + echo "$out" + return 1 + fi + echo "$out" | grep -c "$USERNAME" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: open connection not found" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_shares) + echo "$out" | grep -c 'Service *pid' + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: Could not start smbstatus" + echo "$out" + return 1 + fi + echo "$out" | grep -c "tmp" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: shares not found" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_locks) + echo "$out" | grep -c "Locked files:" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: locked file not found" + echo "$out" + return 1 + fi + echo "$out" | grep -c "$file" + ret=$? + if [ $ret -eq 1 ]; then + echo "Failed: wrong file locked" + echo "$out" + return 1 + fi + + rm $PREFIX/$status_shares + rm $PREFIX/$status_processes + rm $PREFIX/$status_locks + + return 0 +} + +test_smbstatus_json() +{ + local cmdfile=$PREFIX/smbclient_commands + local tmpfile=$PREFIX/smbclient_lock_file + local file=smbclient_lock_file + local status_json=smbstatus_output_json + local status_json_long=smbstatus_output_json_long + + cat > $tmpfile <<EOF +Hello World! +EOF + cat > $cmdfile <<EOF +lcd $PREFIX_ABS +put $file +open $file +posix +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --json > $status_json +!UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --json -vBN > $status_json_long +close 1 +rm $file +quit +EOF + + cmd="CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS --quiet < $cmdfile 2>&1" + out=$(eval $cmd) + echo $out + ret=$? + + rm -f $cmdfile + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "Failed to run smbclient with error $ret" + echo "$out" + return 1 + fi + + echo $out | grep -c 'JSON support not available, please install lib Jansson' + ret=$? + if [ $ret -eq 0 ]; then + subunit_start_test "test_smbstatus_json" + subunit_skip_test "test_smbstatus_json" <<EOF +Test needs Jansson +EOF + return 0 + fi + + out=$(cat $PREFIX/$status_json) + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed: Could not print json output with error $ret" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_json | jq ".") + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed: Could not parse json output from smbstatus with error $ret" + echo "$out" + return 1 + fi + + # keys in --json + expected='["open_files","sessions","smb_conf","tcons","timestamp","version"]' + out=$(cat $PREFIX/$status_json | jq keys -c) + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected keys in smbstatus --json" + echo "Expected: $expected" + echo "Output: $out" + return 1 + fi + + # keys in --json -vBN + expected='["byte_range_locks","notifies","open_files","sessions","smb_conf","tcons","timestamp","version"]' + out=$(cat $PREFIX/$status_json_long | jq keys -c) + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected keys in smbstatus --json" + echo "Expected: $expected" + echo "Output: $out" + return 1 + fi + + # shares information in --json + out=$(cat $PREFIX/$status_json | jq ".tcons|.[].machine") + if [ "\"$SERVER_IP\"" != "$out" ]; then + echo "Failed: Unexpected value for tcons.machine in smbstatus --json" + echo "Expected: $SERVER_IP" + echo "Output: $out" + return 1 + fi + out=$(cat $PREFIX/$status_json | jq ".tcons|.[].service") + if [ '"tmp"' != "$out" ]; then + echo "Failed: Unexpected value for tcons.service in smbstatus --json" + echo "Expected: tmp" + echo "Output: $out" + return 1 + fi + + # session information in --json + out=$(cat $PREFIX/$status_json | jq ".sessions|.[].username") + if [ "\"$USER\"" != "$out" ]; then + echo "Failed: Unexpected value for sessions.username in smbstatus --json" + echo "Expected: $USER" + echo "Output: $out" + return 1 + fi + out=$(cat $PREFIX/$status_json | jq -c ".sessions|.[].signing") + expected='{"cipher":"AES-128-GMAC","degree":"partial"}' + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected value for sessions.signing in smbstatus --json" + echo "Expected: partial(AES-128-GMAC)" + echo "Output: $out" + return 1 + fi + out=$(cat $PREFIX/$status_json | jq ".sessions|.[].remote_machine") + if [ "\"$SERVER_IP\"" != "$out" ]; then + echo "Failed: Unexpected value for sessions.remote_machine in smbstatus --json" + echo "Expected: $SERVER_IP" + echo "Output: $out" + return 1 + fi + + # open_files information in --json + out=$(cat $PREFIX/$status_json | jq ".open_files|.[].filename") + if [ "\"$file\"" != "$out" ]; then + echo "Failed: Unexpected value for open_files.denymode in smbstatus --json" + echo "Expected: \"$file\"" + echo "Output: $out" + return 1 + fi + out=$(cat $PREFIX/$status_json | jq ".open_files|.[].opens|.[].access_mask.hex") + if [ '"0x00000003"' != "$out" ]; then + echo "Failed: Unexpected value for open_files.access_mask.hex in smbstatus --json" + echo "Expected: 0x00000003" + echo "Output: $out" + return 1 + fi + + rm $PREFIX/$status_json + rm $PREFIX/$status_json_long + + return 0 +} +test_smbstatus_json_profile() +{ + local status_json=smbstatus_output_json_profile + + cmd="UID_WRAPPER_INITIAL_RUID=0 UID_WRAPPER_INITIAL_EUID=0 $SMBSTATUS --json --profile > $PREFIX/$status_json" + out=$(eval $cmd) + ret=$? + + if [ $ret -ne 0 ]; then + echo "Failed to run smbstatus -jP with error $ret" + echo "$out" + return 1 + fi + + echo $out | grep -c 'JSON support not available, please install lib Jansson' + ret=$? + if [ $ret -eq 0 ]; then + subunit_start_test "test_smbstatus_json_profile" + subunit_skip_test "test_smbstatus_json_profile" <<EOF +Test needs Jansson +EOF + return 0 + fi + + out=$(cat $PREFIX/$status_json) + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed: Could not print json profile output with error $ret" + echo "$out" + return 1 + fi + + out=$(cat $PREFIX/$status_json | jq ".") + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed: Could not parse json output from smbstatus -jP with error $ret" + echo "$out" + return 1 + fi + + # keys in --json --profile + expected='["ACL Calls","NT Transact Calls","SMB Calls","SMB2 Calls","SMBD loop","Stat Cache","System Calls","Trans2 Calls","smb_conf","timestamp","version"]' + out=$(cat $PREFIX/$status_json | jq keys -c) + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected keys in smbstatus -jP" + echo "Expected: $expected" + echo "Output: $out" + return 1 + fi + + # keys in ACL Calls + expected='["fget_nt_acl","fset_nt_acl","get_nt_acl","get_nt_acl_at"]' + out=$(cat $PREFIX/$status_json | jq -c '."ACL Calls"|keys') + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected keys in smbstatus -jP" + echo "Expected: $expected" + echo "Output: $out" + return 1 + fi + + # keys in ACL Calls, fget_nt_acl + expected='["count","time"]' + out=$(cat $PREFIX/$status_json | jq -c '."ACL Calls"."fget_nt_acl"|keys') + if [ "$expected" != "$out" ]; then + echo "Failed: Unexpected keys in smbstatus -jP" + echo "Expected: $expected" + echo "Output: $out" + return 1 + fi + + rm $PREFIX/$status_json + + return 0 +} + +testit "plain" \ + test_smbstatus || + failed=$(expr $failed + 1) + +testit "resolve_uids" \ + test_smbstatus || + failed=$(expr $failed + 1) + +testit "test_output" \ + test_smbstatus_output || + failed=$(expr $failed + 1) + +testit "test_json" \ + test_smbstatus_json || \ + failed=`expr $failed + 1` + +testit "test_json_profile" \ + test_smbstatus_json_profile || \ + failed=`expr $failed + 1` + +testok $0 $failed diff --git a/source3/script/tests/test_smbtorture_nocrash_s3.sh b/source3/script/tests/test_smbtorture_nocrash_s3.sh new file mode 100755 index 0000000..b6ef139 --- /dev/null +++ b/source3/script/tests/test_smbtorture_nocrash_s3.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +. $(dirname $0)/../../../testprogs/blackbox/subunit.sh + +# this runs the file serving tests that are expected to pass with samba3 + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbtorture_s3.sh TEST UNC USERNAME PASSWORD SMBTORTURE <smbtorture args> +EOF + exit 1 +fi + +t="$1" +unc="$2" +username="$3" +password="$4" +SMBTORTURE="$5" +shift 5 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG) + +echo "$panic_count_0" >/tmp/look + +failed=0 +testit "smbtorture" $VALGRIND $SMBTORTURE $unc -U"$username"%"$password" $ADDARGS $t || failed=$(expr $failed + 1) + +panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG) + +echo "$panic_count_1" >>/tmp/look + +testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh new file mode 100755 index 0000000..4376f4a --- /dev/null +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# this runs the file serving tests that are expected to pass with samba3 + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_smbtorture_s3.sh TEST UNC USERNAME PASSWORD SMBTORTURE <smbtorture args> +EOF + exit 1 +fi + +t="$1" +unc="$2" +username="$3" +password="$4" +SMBTORTURE="$5" +shift 5 +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 +testit "smbtorture" $VALGRIND $SMBTORTURE $unc -U"$username"%"$password" $ADDARGS $t || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_stream_dir_rename.sh b/source3/script/tests/test_stream_dir_rename.sh new file mode 100755 index 0000000..7ac3194 --- /dev/null +++ b/source3/script/tests/test_stream_dir_rename.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Test a stream can rename a directory once an invalid stream path below it was requested. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15314 + +if [ $# -lt 5 ]; then + cat <<EOF +Usage: test_stream_dir_rename.sh SERVER USERNAME PASSWORD PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +USERNAME="${2}" +PASSWORD="${3}" +PREFIX="${4}" +SMBCLIENT="${5}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 5 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +test_stream_xattr_rename() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + # + # Test against streams_xattr_nostrict + # + cat >$tmpfile <<EOF +deltree stream_xattr_test +deltree stream_xattr_test1 +mkdir stream_xattr_test +put ${PREFIX}/smbclient_interactive_prompt_commands stream_xattr_test/file.txt +get stream_xattr_test/file.txt:abcf +rename stream_xattr_test stream_xattr_test1 +deltree stream_xattr_test +deltree stream_xattr_test1 +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/streams_xattr_nostrict < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret -ne 0 ]; then + echo "$out" + echo "failed rename on xattr stream test to test1 with error $ret" + return 1 + fi + + echo "$out" | grep "NT_STATUS_ACCESS_DENIED" + ret=$? + if [ $ret -eq 0 ]; then + echo "$out" + echo "failed rename on xattr stream with NT_STATUS_ACCESS_DENIED" + return 1 + fi +} + +testit "stream_rename" \ + test_stream_xattr_rename || + failed=$((failed + 1)) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_substitutions.sh b/source3/script/tests/test_substitutions.sh new file mode 100755 index 0000000..aa0b38d --- /dev/null +++ b/source3/script/tests/test_substitutions.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# Blackbox tests for substitutions +# +# Copyright (c) 2016 Andreas Schneider <asn@samba.org> + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_substitutions.sh SERVER USERNAME PASSWORD PREFIX +EOF + exit 1 +fi + +SERVER=$1 +USERNAME=$2 +PASSWORD=$3 +PREFIX=$4 +shift 4 +failed=0 + +samba_bindir="$BINDIR" +samba_srcdir="$SRCDIR" +smbclient="$samba_bindir/smbclient" +rpcclient="$samba_bindir/rpcclient" + +. $samba_srcdir/testprogs/blackbox/subunit.sh +. $samba_srcdir/testprogs/blackbox/common_test_fns.inc + +SMB_UNC="//$SERVER/sub_dug" + +test_smbclient "Test login to share with substitution (DUG)" \ + "ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1) + +SMB_UNC="//$SERVER/sub_dug2" + +test_smbclient "Test login to share with substitution (Dug)" \ + "ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1) + +SMB_UNC="//$SERVER/sub_valid_users" + +test_smbclient "Test login to share with substitution for valid users" \ + "ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1) + +SMB_UNC="//$SERVER/sub_valid_users_domain" + +test_smbclient "Test login to share with substitution for valid user's domain" \ + "ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1) + +SMB_UNC="//$SERVER/sub_valid_users_group" + +test_smbclient "Test login to share with substitution for valid user's UNIX group" \ + "ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1) + +test_smbclient \ + "Test for login to share with include substitution [${USERNAME}]" \ + "ls" "//${SERVER}/${USERNAME}_share" "-U$USERNAME%$PASSWORD" || + failed=$((failed + 1)) + +test_smbclient_expect_failure \ + "Netative test for login to share with include substitution [${DC_USERNAME}]" \ + "ls" "//${SERVER}/${USERNAME}_share" "-U$DC_USERNAME%$DC_PASSWORD" || + failed=$((failed + 1)) + +testit_grep_count \ + "Test for share enum with include substitution" \ + "netname: ${USERNAME}_share" \ + 1 \ + ${rpcclient} "ncacn_np:${SERVER}" "-U$USERNAME%$PASSWORD" \ + -c netshareenum || + failed=$((failed + 1)) + +testit_grep_count \ + "Negative test for share enum with include substitution" \ + "netname: ${USERNAME}_share" \ + 0 \ + ${rpcclient} "ncacn_np:${SERVER}" "-U$DC_USERNAME%$DC_PASSWORD" \ + -c netshareenum || + failed=$((failed + 1)) + +exit $failed diff --git a/source3/script/tests/test_success.sh b/source3/script/tests/test_success.sh new file mode 100755 index 0000000..7ba8ddb --- /dev/null +++ b/source3/script/tests/test_success.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# Blackbox test that should simply succeed. +# +# Copyright (C) 2011 Michael Adam <obnox@samba.org> + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_success() +{ + true +} + +testit "success" \ + test_success || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_symlink_dosmode.sh b/source3/script/tests/test_symlink_dosmode.sh new file mode 100755 index 0000000..dd6cb6b --- /dev/null +++ b/source3/script/tests/test_symlink_dosmode.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_symlink_dosmode.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" + +rm -rf "$share_test_dir/testdir" + +mkdir -p "$share_test_dir/testdir/dir" +touch "$share_test_dir/testdir/file" +ln -s "../file" "$share_test_dir/testdir/dir/symlink" + +test_symlink_dosmode() +{ + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +ls testdir/dir/* +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing local_symlinks with error %s\n" "$ret" + return 1 + fi + + mode=$(printf "%s" "$out" | awk '/symlink/ {print $2}') + echo "mode: $mode" + if [ x"$mode" != x"N" ] ; then + printf "Bad mode: '%s', expected 'N'\n" "$mode" + printf "%s\n" "$out" + return 1 + fi + return 0 +} + +testit "symlink_dosmode" \ + test_symlink_dosmode || + failed=$((failed + 1)) + +rm -rf "$share_test_dir/testdir" + +testok "$0" "$failed" diff --git a/source3/script/tests/test_symlink_rename_smb1_posix.sh b/source3/script/tests/test_symlink_rename_smb1_posix.sh new file mode 100755 index 0000000..00acfee --- /dev/null +++ b/source3/script/tests/test_symlink_rename_smb1_posix.sh @@ -0,0 +1,185 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_symlink_rename_smb1_posix.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" +# +# These files/directories will be created. +# +file_outside_share="/tmp/symlink_rename_test_file.$$" +dir_outside_share="/tmp/symlink_rename_test_dir.$$" +file_outside_share_noperms="/tmp/symlink_rename_test_file_noperm.$$" +dir_outside_share_noperms="/tmp/symlink_rename_test_dir_noperm.$$" +# +# These two objects do not exist. +# +file_outside_share_noexist="/tmp/symlink_rename_test_noexist.$$" +dir_outside_share_noexist="/tmp/symlink_rename_test_dir_noexist.$$" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f "file_exists" + rm -f "symlink_noexist" + rm -f "symlink_file_outside_share" + rm -f "symlink_file_outside_share_noexist" + rm -f "symlink_dir_outside_share" + rm -f "symlink_dir_outside_share_noexist" + rm -f "symlink_file_outside_share_noperms" + rm -f "symlink_dir_outside_share_noperms" + # Links inside share. + rm -f "symlink_file_inside_share_noperms" + rm -f "file_inside_share_noperms" + rm -f "symlink_dir_inside_share_noperms" + chmod 755 "dir_inside_share_noperms" + rm -rf "dir_inside_share_noperms" + ) + rm -f "$file_outside_share" + rm -rf "$dir_outside_share" + rm -f "$file_outside_share_noperms" + rm -rf "$dir_outside_share_noperms" +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + +# +# Create the test files/directories/symlinks. +# +# File/directory explicitly outside share. +touch "$file_outside_share" +mkdir "$dir_outside_share" +# File/directory explicitly outside share with permission denied. +touch "$file_outside_share_noperms" +chmod 0 "$file_outside_share_noperms" +mkdir "$dir_outside_share_noperms" +chmod 0 "$dir_outside_share_noperms" +# +# Create links to these objects inside the share definition. +( + #subshell. + cd "$share_test_dir" || return + # Source file for all renames. None of these should succeed. + touch "file_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + # + # Create symlinks to access denied file and directory + # objects within the share + touch "file_inside_share_noperms" + chmod 0 "file_inside_share_noperms" + ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms" + mkdir "dir_inside_share_noperms" + touch "dir_inside_share_noperms/noperm_file_exists" + chmod 0 "dir_inside_share_noperms" + ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms" +) + +# +# smbclient function given command, path, expected error, and posix. +# +smbclient_expect_error() +{ + filecmd="$1" + filename1="$2" + filename2="$3" + expected_error="$4" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +posix +$filecmd $filename1 $filename2 +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP -mNT1 < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing local_symlinks with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep -v "NT_STATUS_" + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing posix \"%s %s %s\"\n" "$expected_error" "$filecmd" "$filename1" "$filename2" + return 1 + fi +} + +# +# SMB1+posix tests. +# +test_symlink_rename_SMB1_posix() +{ + # + # rename commands. + # As all the targets exist as symlinks, these should all fail. + # + smbclient_expect_error "rename" "file_exists" "symlink_noexist" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_file_outside_share" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_file_outside_share_noexist" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_dir_outside_share" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_dir_outside_share_noexist" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_file_outside_share_noperms" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_dir_outside_share_noperms" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_file_inside_share_noperms" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + smbclient_expect_error "rename" "file_exists" "symlink_dir_inside_share_noperms" "NT_STATUS_OBJECT_NAME_COLLISION" || return 1 + return 0 +} + +testit "symlink_rename_SMB1_posix" \ + test_symlink_rename_SMB1_posix || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_symlink_traversal_smb1.sh b/source3/script/tests/test_symlink_traversal_smb1.sh new file mode 100755 index 0000000..ff38210 --- /dev/null +++ b/source3/script/tests/test_symlink_traversal_smb1.sh @@ -0,0 +1,262 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_symlink_traversal_smb1.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" +# +# These files/directories will be created. +# +file_outside_share="/tmp/symlink_traverse_test_file.$$" +dir_outside_share="/tmp/symlink_traverse_test_dir.$$" +file_outside_share_noperms="/tmp/symlink_traverse_test_file_noperm.$$" +dir_outside_share_noperms="/tmp/symlink_traverse_test_dir_noperm.$$" +# +# These two objects do not exist. +# +file_outside_share_noexist="/tmp/symlink_traverse_test_noexist.$$" +dir_outside_share_noexist="/tmp/symlink_traverse_test_dir_noexist.$$" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f "file_exists" + rm -f "symlink_noexist" + rm -f "symlink_file_outside_share" + rm -f "symlink_file_outside_share_noexist" + rm -f "symlink_dir_outside_share" + rm -f "symlink_dir_outside_share_noexist" + rm -f "symlink_file_outside_share_noperms" + rm -f "symlink_dir_outside_share_noperms" + rm -rf "emptydir" + # Links inside share. + rm -f "symlink_file_inside_share_noperms" + rm -f "file_inside_share_noperms" + rm -f "symlink_dir_inside_share_noperms" + chmod 755 "dir_inside_share_noperms" + rm -rf "dir_inside_share_noperms" + ) + rm -f "$file_outside_share" + rm -rf "$dir_outside_share" + rm -f "$file_outside_share_noperms" + rm -rf "$dir_outside_share_noperms" +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + +# +# Create the test files/directories/symlinks. +# +# File/directory explicitly outside share. +touch "$file_outside_share" +mkdir "$dir_outside_share" +# File/directory explicitly outside share with permission denied. +touch "$file_outside_share_noperms" +chmod 0 "$file_outside_share_noperms" +mkdir "$dir_outside_share_noperms" +chmod 0 "$dir_outside_share_noperms" +# +# Create links to these objects inside the share definition. +( + #subshell. + cd "$share_test_dir" || return + touch "file_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + # + # Create the identical symlink set underneath "emptydir" + mkdir "emptydir" + ( + #subshell + cd "emptydir" || return + touch "file_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + ) + # + # Create symlinks to access denied file and directory + # objects within the share + touch "file_inside_share_noperms" + chmod 0 "file_inside_share_noperms" + ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms" + mkdir "dir_inside_share_noperms" + touch "dir_inside_share_noperms/noperm_file_exists" + chmod 0 "dir_inside_share_noperms" + ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms" +) + +# +# smbclient function given command, path, expected error, and posix. +# +smbclient_expect_error() +{ + filecmd="$1" + filename1="$2" + filename2="$3" + expected_error="$4" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +$filecmd $filename1 $filename2 +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP -mNT1 < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing local_symlinks with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep -v "NT_STATUS_" + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing \"%s %s %s\"\n" "$expected_error" "$filecmd" "$filename1" "$filename2" + return 1 + fi +} + +# +# SMB1 tests. +# +test_symlink_traversal_SMB1_onename() +{ + name="$1" + do_rename="$2" + # + # get commands. + # + smbclient_expect_error "get" "$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "get" "emptydir/$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # + # ls commands. + # + smbclient_expect_error "ls" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + + # + # del commands. + # smbclient internally does a cli_list, so we expect similar errors. + # + smbclient_expect_error "del" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "del" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + + if [ "$do_rename" = "do rename" ]; then + # + # rename commands. + # + smbclient_expect_error "rename" "file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "rename" "file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + fi + return 0 +} + +# +# Check error code returns traversing through different +# kinds of symlinks over SMB1. +# +test_symlink_traversal_SMB1() +{ + test_symlink_traversal_SMB1_onename "symlink_noexist" "no rename" || return 1 + test_symlink_traversal_SMB1_onename "symlink_file_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB1_onename "symlink_dir_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB1_onename "symlink_dir_outside_share_noexist" "no rename" || return 1 + test_symlink_traversal_SMB1_onename "symlink_file_outside_share_noperms" "do rename" || return 1 + test_symlink_traversal_SMB1_onename "symlink_dir_outside_share_noperms" "do rename" || return 1 + # + # Test paths within share with no permissions. + # + # Can't 'get' file with no perms or a symlink to it. + smbclient_expect_error "get" "file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # But can list it and the symlink to it. + smbclient_expect_error "ls" "file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + # Can't 'get' file inside a directory with no perms or a symlink to it. + smbclient_expect_error "get" "dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # But can list the directory with no perms and the symlink to it. + smbclient_expect_error "ls" "dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 +} + +testit "symlink_traversal_SMB1" \ + test_symlink_traversal_SMB1 || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_symlink_traversal_smb1_posix.sh b/source3/script/tests/test_symlink_traversal_smb1_posix.sh new file mode 100755 index 0000000..52d6cfb --- /dev/null +++ b/source3/script/tests/test_symlink_traversal_smb1_posix.sh @@ -0,0 +1,269 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_symlink_traversal_smb1_posix.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" +# +# These files/directories will be created. +# +file_outside_share="/tmp/symlink_traverse_test_file.$$" +dir_outside_share="/tmp/symlink_traverse_test_dir.$$" +file_outside_share_noperms="/tmp/symlink_traverse_test_file_noperm.$$" +dir_outside_share_noperms="/tmp/symlink_traverse_test_dir_noperm.$$" +# +# These two objects do not exist. +# +file_outside_share_noexist="/tmp/symlink_traverse_test_noexist.$$" +dir_outside_share_noexist="/tmp/symlink_traverse_test_dir_noexist.$$" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f "file_exists" + rm -f "symlink_noexist" + rm -f "symlink_file_outside_share" + rm -f "symlink_file_outside_share_noexist" + rm -f "symlink_dir_outside_share" + rm -f "symlink_dir_outside_share_noexist" + rm -f "symlink_file_outside_share_noperms" + rm -f "symlink_dir_outside_share_noperms" + rm -rf "emptydir" + # Links inside share. + rm -f "symlink_file_inside_share_noperms" + rm -f "file_inside_share_noperms" + rm -f "symlink_dir_inside_share_noperms" + chmod 755 "dir_inside_share_noperms" + rm -rf "dir_inside_share_noperms" + ) + rm -f "$file_outside_share" + rm -rf "$dir_outside_share" + rm -f "$file_outside_share_noperms" + rm -rf "$dir_outside_share_noperms" +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + +# +# Create the test files/directories/symlinks. +# +# File/directory explicitly outside share. +touch "$file_outside_share" +mkdir "$dir_outside_share" +# File/directory explicitly outside share with permission denied. +touch "$file_outside_share_noperms" +chmod 0 "$file_outside_share_noperms" +mkdir "$dir_outside_share_noperms" +chmod 0 "$dir_outside_share_noperms" +# +# Create links to these objects inside the share definition. +( + #subshell. + cd "$share_test_dir" || return + touch "file_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + # + # Create the identical symlink set underneath "emptydir" + mkdir "emptydir" + ( + #subshell + cd "emptydir" || return + touch "file_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + ) + # + # Create symlinks to access denied file and directory + # objects within the share + touch "file_inside_share_noperms" + chmod 0 "file_inside_share_noperms" + ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms" + mkdir "dir_inside_share_noperms" + touch "dir_inside_share_noperms/noperm_file_exists" + chmod 0 "dir_inside_share_noperms" + ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms" +) + +# +# smbclient function given command, path, expected error, and posix. +# +smbclient_expect_error() +{ + filecmd="$1" + filename1="$2" + filename2="$3" + expected_error="$4" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +posix +$filecmd $filename1 $filename2 +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP -mNT1 < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing local_symlinks with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep -v "NT_STATUS_" + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing posix \"%s %s %s\"\n" "$expected_error" "$filecmd" "$filename1" "$filename2" + return 1 + fi +} + +# +# SMB1+posix tests. +# +test_symlink_traversal_SMB1_posix_onename() +{ + name="$1" + do_rename="$2" + # + # get commands. + # + # Remember in SMB1+POSIX, "*" is a perfectly valid pathname component, + # and symlinks can be seen, but not necessarily followed. + # + smbclient_expect_error "get" "$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/*" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "get" "emptydir/$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/*" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # + # ls commands. + # + smbclient_expect_error "ls" "$name" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # + # SMB1+POSIX stat commands. All symlinks can be stat'ed. + # + smbclient_expect_error "stat" "$name" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "stat" "emptydir/$name" "" "NT_STATUS_OK" || return 1 + # + # del commands. Under SMB1+POSIX we can legitimately delete symlinks, so don't + # try and delete symlink targets, we need them for the later tests. + # + smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + + if [ "$do_rename" = "do rename" ]; then + # + # rename commands. Under SMB1+POSIX we can legitimately rename symlinks, so don't + # try and rename symlink targets, we need them for the later tests. + # + smbclient_expect_error "rename" "file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "rename" "file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + fi + return 0 +} + +# +# Check error code returns traversing through different +# kinds of symlinks over SMB1+posix. +# +test_symlink_traversal_SMB1_posix() +{ + test_symlink_traversal_SMB1_posix_onename "symlink_noexist" "no rename" || return 1 + test_symlink_traversal_SMB1_posix_onename "symlink_file_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share_noexist" "no rename" || return 1 + test_symlink_traversal_SMB1_posix_onename "symlink_file_outside_share_noperms" "do rename" || return 1 + test_symlink_traversal_SMB1_posix_onename "symlink_dir_outside_share_noperms" "do rename" || return 1 + # + # Test paths within share with no permissions. + # + # Can't 'get' file with no perms. + smbclient_expect_error "get" "file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # In SMB1+POSIX you can't "get" a symlink at all. + smbclient_expect_error "get" "symlink_file_inside_share_noperms" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + # But can list it and the symlink to it. + smbclient_expect_error "ls" "file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + # Can't 'get' file inside a directory with no perms. + smbclient_expect_error "get" "dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # In SMB1+POSIX you can't traverse through a symlink that points to a noperm directory. + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # But can list the directory with no perms and the symlink to it. + smbclient_expect_error "ls" "dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 +} + +testit "symlink_traversal_SMB1_posix" \ + test_symlink_traversal_SMB1_posix || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_symlink_traversal_smb2.sh b/source3/script/tests/test_symlink_traversal_smb2.sh new file mode 100755 index 0000000..38719cc --- /dev/null +++ b/source3/script/tests/test_symlink_traversal_smb2.sh @@ -0,0 +1,382 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_symlink_traversal_smb2.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 6 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" +# +# These files/directories will be created. +# +file_outside_share="/tmp/symlink_traverse_test_file.$$" +dir_outside_share="/tmp/symlink_traverse_test_dir.$$" +file_outside_share_noperms="/tmp/symlink_traverse_test_file_noperm.$$" +dir_outside_share_noperms="/tmp/symlink_traverse_test_dir_noperm.$$" +# +# These two objects do not exist. +# +file_outside_share_noexist="/tmp/symlink_traverse_test_noexist.$$" +dir_outside_share_noexist="/tmp/symlink_traverse_test_dir_noexist.$$" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f "symlink_to_dot" + rm -f "file_exists" + rm -f "symlink_to_file_exists" + rm -rf "dir_exists" + rm -f "symlink_to_dir_exists" + rm -f "symlink_noexist" + rm -f "symlink_file_outside_share" + rm -f "symlink_file_outside_share_noexist" + rm -f "symlink_dir_outside_share" + rm -f "symlink_dir_outside_share_noexist" + rm -f "symlink_file_outside_share_noperms" + rm -f "symlink_dir_outside_share_noperms" + rm -rf "emptydir" + # Links inside share. + rm -f "symlink_file_inside_share_noperms" + rm -f "file_inside_share_noperms" + rm -f "symlink_dir_inside_share_noperms" + chmod 755 "dir_inside_share_noperms" + rm -rf "dir_inside_share_noperms" + ) + rm -f "$file_outside_share" + rm -rf "$dir_outside_share" + rm -f "$file_outside_share_noperms" + rm -rf "$dir_outside_share_noperms" +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + +# +# Create the test files/directories/symlinks. +# +# File/directory explicitly outside share. +touch "$file_outside_share" +mkdir "$dir_outside_share" +# File/directory explicitly outside share with permission denied. +touch "$file_outside_share_noperms" +chmod 0 "$file_outside_share_noperms" +mkdir "$dir_outside_share_noperms" +chmod 0 "$dir_outside_share_noperms" +# +# Create links to these objects inside the share definition. +( + #subshell. + cd "$share_test_dir" || return + ln -s "." "symlink_to_dot" + touch "file_exists" + ln -s "file_exists" "symlink_to_file_exists" + mkdir "dir_exists" + ln -s "dir_exists" "symlink_to_dir_exists" + touch "dir_exists/subfile_exists" + mkdir "dir_exists/subdir_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + # + # Create the identical symlink set underneath "emptydir" + mkdir "emptydir" + ( + #subshell + cd "emptydir" || return + ln -s "." "symlink_to_dot" + touch "file_exists" + ln -s "file_exists" "symlink_to_file_exists" + mkdir "dir_exists" + ln -s "dir_exists" "symlink_to_dir_exists" + touch "dir_exists/subfile_exists" + mkdir "dir_exists/subdir_exists" + ln -s "noexist" "symlink_noexist" + ln -s "$file_outside_share" "symlink_file_outside_share" + ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist" + ln -s "$dir_outside_share" "symlink_dir_outside_share" + ln -s "$dir_outside_share_noexist" "symlink_dir_outside_share_noexist" + ln -s "$file_outside_share_noperms" "symlink_file_outside_share_noperms" + ln -s "$dir_outside_share_noperms" "symlink_dir_outside_share_noperms" + ) + # + # Create symlinks to access denied file and directory + # objects within the share + touch "file_inside_share_noperms" + chmod 0 "file_inside_share_noperms" + ln -s "file_inside_share_noperms" "symlink_file_inside_share_noperms" + mkdir "dir_inside_share_noperms" + touch "dir_inside_share_noperms/noperm_file_exists" + ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms" + mkdir "dir_inside_share_noperms/noperm_subdir_exists" + touch "dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists" + chmod 0 "dir_inside_share_noperms" + + # Symlink pointing out of the share + ln -s "$share_test_dir"a"/etc" x +) + +# +# smbclient function given command, path, expected error, and posix. +# +smbclient_expect_error() +{ + filecmd="$1" + filename1="$2" + filename2="$3" + expected_error="$4" + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +$filecmd $filename1 $filename2 +quit +EOF + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/local_symlinks -I$SERVER_IP < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing local_symlinks with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep -v "NT_STATUS_" + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing \"%s %s %s\"\n" "$expected_error" "$filecmd" "$filename1" "$filename2" + return 1 + fi +} + +# +# SMB2 tests. +# +test_symlink_traversal_SMB2_onename() +{ + name="$1" + do_rename="$2" + # + # get commands. + # + smbclient_expect_error "get" "$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "get" "emptydir/$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "emptydir/$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # + # ls commands. + # + smbclient_expect_error "ls" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "ls" "$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "ls" "emptydir/$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + + # + # del commands. + # smbclient internally does a cli_list, so we expect similar errors. + # + smbclient_expect_error "del" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "del" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "del" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "del" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + + if [ "$do_rename" = "do rename" ]; then + # + # rename commands. + # + smbclient_expect_error "rename" "file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "dir_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "dir_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_dir_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_dir_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + # Now in subdirectory emptydir + smbclient_expect_error "rename" "file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "dir_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "dir_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_dir_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "rename" "symlink_to_dir_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + fi + return 0 +} + +# +# Check error code returns traversing through different +# kinds of symlinks over SMB2. +# +test_symlink_traversal_SMB2() +{ + test_symlink_traversal_SMB2_onename "symlink_noexist" "no rename" || return 1 + test_symlink_traversal_SMB2_onename "symlink_file_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB2_onename "symlink_dir_outside_share" "do rename" || return 1 + test_symlink_traversal_SMB2_onename "symlink_dir_outside_share_noexist" "no rename" || return 1 + test_symlink_traversal_SMB2_onename "symlink_file_outside_share_noperms" "do rename" || return 1 + test_symlink_traversal_SMB2_onename "symlink_dir_outside_share_noperms" "do rename" || return 1 + + # Note the share has 'follow symlinks = yes' + smbclient_expect_error "ls" "." "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dot" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_to_dot/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "symlink_to_dot/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dot/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "file_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "file_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1 + smbclient_expect_error "ls" "file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "file_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_file_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_to_file_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1 + smbclient_expect_error "ls" "symlink_to_file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_file_exists/noexist1/noexist2/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "dir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists/subfile_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1 + smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists/subdir_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subfile_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subfile_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subfile_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subfile_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subdir_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subdir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "ls" "symlink_to_dir_exists/subdir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + smbclient_expect_error "get" "." "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1 + smbclient_expect_error "get" "noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dot" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1 + smbclient_expect_error "get" "symlink_to_dot/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dot/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "file_exists" "$dir_outside_share/file_exists" "NT_STATUS_OK" || return 1 + smbclient_expect_error "get" "file_exists/noexist1" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_file_exists" "$dir_outside_share/symlink_to_file_exists" "NT_STATUS_OK" || return 1 + smbclient_expect_error "get" "symlink_to_file_exists/noexist1" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1 + smbclient_expect_error "get" "dir_exists/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists/subfile_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "get" "dir_exists/subfile_exists/noexist1" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists/subfile_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists/subdir_exists" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1 + smbclient_expect_error "get" "dir_exists/subdir_exists/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subfile_exists" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subfile_exists/noexist1" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subfile_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_expect_error "get" "x/passwd" "passwd" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # + # Test paths within share with no permissions. + # + # Can't 'get' file with no perms or a symlink to it. + smbclient_expect_error "get" "file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_file_inside_share_noperms" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # But can list it and the symlink to it. + smbclient_expect_error "ls" "file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_file_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + # Can't 'get' file inside a directory with no perms or a symlink to it. + smbclient_expect_error "get" "dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + # But can list the directory with no perms and the symlink to it. + smbclient_expect_error "ls" "dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + smbclient_expect_error "ls" "symlink_dir_inside_share_noperms" "" "NT_STATUS_OK" || return 1 + # Check that 'get' on non existing subpaths also returns NT_STATUS_ACCESS_DENIED + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_file_exists/_none_" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists" "" "NT_STATUS_ACCESS_DENIED" || return 1 + smbclient_expect_error "get" "symlink_dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists/_none_" "" "NT_STATUS_ACCESS_DENIED" || return 1 +} + +testit "symlink_traversal_SMB2" \ + test_symlink_traversal_SMB2 || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_testparm_s3.sh b/source3/script/tests/test_testparm_s3.sh new file mode 100755 index 0000000..a11ef85 --- /dev/null +++ b/source3/script/tests/test_testparm_s3.sh @@ -0,0 +1,150 @@ +#!/bin/sh + +# Tests for lp_load() via testparm. +# +# The main purpose (for now) is to test all the special handlers +# and the macro expansions. + +if [ $# -lt 1 ]; then + cat <<EOF +Usage: test_testparm_s3.sh LOCAL_PATH +EOF + exit 1 +fi + +LOCAL_PATH="$1" + +TEMP_CONFFILE=${LOCAL_PATH}/smb.conf.tmp +TESTPARM="$VALGRIND ${TESTPARM:-$BINDIR/testparm} --suppress-prompt --skip-logic-checks" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +test_include_expand_macro() +{ + MACRO=$1 + rm -f ${TEMP_CONFFILE} + cat >${TEMP_CONFFILE} <<EOF +[global] + include = ${TEMP_CONFFILE}.%${MACRO} +EOF + ${TESTPARM} ${TEMP_CONFFILE} +} + +test_one_global_option() +{ + OPTION="$@" + rm -f ${TEMP_CONFFILE} + cat >${TEMP_CONFFILE} <<EOF +[global] + ${OPTION} +EOF + ${TESTPARM} ${TEMP_CONFFILE} +} + +test_copy() +{ + rm -f ${TEMP_CONFFILE} + cat >${TEMP_CONFFILE} <<EOF +[share1] + path = /tmp + read only = no + +[share2] + copy = share1 +EOF + ${TESTPARM} ${TEMP_CONFFILE} +} + +test_testparm_deprecated() +{ + name=$1 + old_SAMBA_DEPRECATED_SUPPRESS=$SAMBA_DEPRECATED_SUPPRESS + SAMBA_DEPRECATED_SUPPRESS= + export SAMBA_DEPRECATED_SUPPRESS + testit_grep $name 'WARNING: The "lsaovernetlogon" option is deprecated' $VALGRIND ${TESTPARM} ${TEMP_CONFFILE} --option='lsaovernetlogon=true' + SAMBA_DEPRECATED_SUPPRESS=$old_SAMBA_DEPRECATED_SUPPRESS + export SAMBA_DEPRECATED_SUPPRESS +} + +test_testparm_deprecated_suppress() +{ + name=$1 + subunit_start_test "$name" + output=$(SAMBA_DEPRECATED_SUPPRESS=1 $VALGRIND ${TESTPARM} ${TEMP_CONFFILE} --option='lsa over netlogon = true' 2>&1) + status=$? + if [ "$status" = "0" ]; then + echo "$output" | grep --quiet 'WARNING: The "lsa over netlogon " option is deprecated' + status=$? + if [ "$status" = "1" ]; then + subunit_pass_test "$name" + else + echo $output | subunit_fail_test "$name" + fi + else + echo $output | subunit_fail_test "$name" + fi +} + +testit "name resolve order = lmhosts wins host bcast" \ + test_one_global_option "name resolve order = lmhosts wins host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = bad wins host bcast" \ + test_one_global_option "name resolve order = bad wins host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts bad host bcast" \ + test_one_global_option "name resolve order = lmhosts bad host bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts wins bad bcast" \ + test_one_global_option "name resolve order = lmhosts wins bad bcast" || + failed=$(expr ${failed} + 1) + +testit_expect_failure "name resolve order = lmhosts wins host bad" \ + test_one_global_option "name resolve order = lmhosts wins host bad" || + failed=$(expr ${failed} + 1) + +testit "netbios name" \ + test_one_global_option "netbios name = funky" || + failed=$(expr ${failed} + 1) + +testit "netbios aliases" \ + test_one_global_option "netbios aliases = funky1 funky2 funky3" || + failed=$(expr ${failed} + 1) + +testit "netbios scope" \ + test_one_global_option "netbios scope = abc" || + failed=$(expr ${failed} + 1) + +testit "workgroup" \ + test_one_global_option "workgroup = samba" || + failed=$(expr ${failed} + 1) + +testit "display charset" \ + test_one_global_option "display charset = UTF8" || + failed=$(expr ${failed} + 1) + +testit "ldap debug level" \ + test_one_global_option "ldap debug level = 7" || + failed=$(expr ${failed} + 1) + +for LETTER in U G D I i L N M R T a d h m v w V; do + testit "include with %${LETTER} macro expansion" \ + test_include_expand_macro "${LETTER}" || + failed=$(expr ${failed} + 1) +done + +testit "copy" \ + test_copy || + failed=$(expr ${failed} + 1) + +test_testparm_deprecated "test_deprecated_warning_printed" +test_testparm_deprecated_suppress "test_deprecated_warning_suppressed" + +rm -f ${TEMP_CONFFILE} + +testok $0 ${failed} diff --git a/source3/script/tests/test_tevent_glib_glue.sh b/source3/script/tests/test_tevent_glib_glue.sh new file mode 100755 index 0000000..fa1d105 --- /dev/null +++ b/source3/script/tests/test_tevent_glib_glue.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 +TESTNAME="tevent_glib_glue_test" + +if [ ! -x $BINDIR/tevent_glib_glue_test ]; then + subunit_start_test "$TESTNAME" + subunit_skip_test "$TESTNAME" <<EOF +Test needs glib2-devel +EOF + testok $0 $failed +fi + +testit "$TESTNAME" $VALGRIND $BINDIR/tevent_glib_glue_test || + failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_timestamps.sh b/source3/script/tests/test_timestamps.sh new file mode 100755 index 0000000..a158beb --- /dev/null +++ b/source3/script/tests/test_timestamps.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# This verifies getting and setting timestamps with non-trivial values like 0 +# and < 0 works. +# + +if [ $# -lt 5 ]; then + echo "Usage: $0 SERVER_IP USERNAME PASSWORD PREFIX SMBCLIENT" + exit 1 +fi + +SERVER_IP="$1" +USERNAME="$2" +PASSWORD="$3" +PREFIX="$4" +SMBCLIENT="$5" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +failed=0 + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +export TZ=GMT + +setup_testfiles() +{ + touch -d "$(date --date=@0)" $PREFIX/time_0 + touch -d "$(date --date=@-1)" $PREFIX/time_-1 + touch -d "$(date --date=@-2)" $PREFIX/time_-2 + touch -t 196801010000 $PREFIX/time_1968 +} + +remove_testfiles() +{ + rm $PREFIX/time_0 + rm $PREFIX/time_-1 + rm $PREFIX/time_-2 + rm $PREFIX/time_1968 +} + +test_time() +{ + local file="$1" + local expected="$2" + + $SMBCLIENT //$SERVER/tmp -U $USERNAME%$PASSWORD -c "allinfo $file" + out=$($SMBCLIENT //$SERVER/tmp -U $USERNAME%$PASSWORD -c "allinfo $file" 2>&1) || return 1 + echo "smbclient allinfo on $file returned: \"$out\"" + + # Ignore create_time as that is synthesized + for time in access_time write_time change_time; do + echo "$out" | grep "$time" | grep "$expected" || { + echo "Expected \"$expected\", got: \"$(echo $out | grep $time)\"" + return 1 + } + done +} + +#Setup +testit "create testfiles" setup_testfiles || failed=$(expr $failed + 1) + +# Tests +testit "time=0" test_time time_0 "Thu Jan 1 12:00:00 AM 1970 GMT" || failed=$(expr $failed + 1) +testit "time=-1" test_time time_-1 "Wed Dec 31 11:59:59 PM 1969 GMT" || failed=$(expr $failed + 1) +testit "time=-2" test_time time_-2 "Wed Dec 31 11:59:58 PM 1969 GMT" || failed=$(expr $failed + 1) +testit "time=1968" test_time time_1968 "Mon Jan 1 12:00:00 AM 1968 GMT" || failed=$(expr $failed + 1) + +# Cleanup +testit "delete testfile" remove_testfiles || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_user_in_sharelist.sh b/source3/script/tests/test_user_in_sharelist.sh new file mode 100755 index 0000000..0069d6d --- /dev/null +++ b/source3/script/tests/test_user_in_sharelist.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +if [ $# -lt 2 ]; then + echo Usage: $0 RPCCLIENT SERVER + exit 1 +fi + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +RPCCLIENT="$1"; shift 1 +SERVER="$1"; shift 1 + +"${RPCCLIENT}" "${SERVER}" -U"${USER}"%"${PASSWORD}" -c netshareenum | + grep "^netname: $USER\$" +RC=$? +testit "Verify username is listed in netshareenum due to [homes]" \ + test $RC = 0 || failed=$((failed+1)) + +testok $0 $failed diff --git a/source3/script/tests/test_usernamemap.sh b/source3/script/tests/test_usernamemap.sh new file mode 100755 index 0000000..334070e --- /dev/null +++ b/source3/script/tests/test_usernamemap.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright (c) 2022 Pavel Filipenský <pfilipen@redhat.com> +# +# Tests for "username map" smb.conf parameter for UNIX groups + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: test_usernamemap.sh SERVER SMBCLIENT +EOF + exit 1 +fi + +SERVER="$1" +SMBCLIENT="$2" +SMBCLIENT="${VALGRIND} ${SMBCLIENT}" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "${incdir}"/subunit.sh + +failed=0 + +# jackthemapper is mapped to jacknomapper, so we need jacknomapper password +testit "jackthemapper" "${SMBCLIENT}" //"${SERVER}"/tmp -U"${SERVER}/jackthemapper%nOmApsEcrEt" -c ls || failed=$((failed + 1)) +# jacknomapper is not mapped, so we need jacknomapper password +testit "jacknomapper" "${SMBCLIENT}" //"${SERVER}"/tmp -U"${SERVER}/jacknomapper%nOmApsEcrEt" -c ls || failed=$((failed + 1)) + +testok "$0" "${failed}" diff --git a/source3/script/tests/test_valid_users.sh b/source3/script/tests/test_valid_users.sh new file mode 100755 index 0000000..659eb6a --- /dev/null +++ b/source3/script/tests/test_valid_users.sh @@ -0,0 +1,70 @@ +#!/bin/sh +# +# Blackbox test for valid users. +# + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: valid_users SERVER SERVER_IP DOMAIN USERNAME PASSWORD PREFIX SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +DOMAIN=${3} +USERNAME=${4} +PASSWORD=${5} +PREFIX=${6} +SMBCLIENT=${7} +shift 7 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$*" + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +# Test listing a share with valid users succeeds +test_valid_users_access() +{ + tmpfile=$PREFIX/smbclient.in.$$ + prompt="foo" + cat >$tmpfile <<EOF +ls +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$1" -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "failed accessing share with valid users with error $ret" + + false + return + fi + + echo "$out" | grep "$prompt" >/dev/null 2>&1 + + ret=$? + if [ $ret = 0 ]; then + # got the correct prompt .. succeed + true + else + echo "$out" + echo "failed listing share with valid users" + false + fi +} + +testit "accessing a valid users share succeeds" \ + test_valid_users_access valid-users-access || + failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/test_veto_files.sh b/source3/script/tests/test_veto_files.sh new file mode 100755 index 0000000..201883e --- /dev/null +++ b/source3/script/tests/test_veto_files.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# +# Check smbclient cannot get a file that matches a veto files +# parameter, or inside a directory that matches a veto files +# parameter. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15143 +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +USERNAME=${3} +PASSWORD=${4} +SHAREPATH=${5} +SMBCLIENT=${6} +shift 6 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +# Used by test_smbclient() +# shellcheck disable=2034 +smbclient="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh +. "${incdir}/common_test_fns.inc" + +failed=0 + +TMPDIR=${PREFIX_ABS}/$(basename "${0}") +mkdir -p "${TMPDIR}" || exit 1 +cd "${TMPDIR}" || exit 1 + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + rm -rf "$SHAREPATH/dir_1" + rm -rf "$SHAREPATH/veto_name_dir" + rm -rf "$SHAREPATH/veto_name_dir\"mangle" + rm -f "$SHAREPATH/veto_name_file" + rm -f "$SHAREPATH/veto_name_file\"mangle" + rm -f "${SHAREPATH}/regular_file" + rm -f "${SHAREPATH}/.hidden_file" + ) +} + +# +# smbclient function given path and expected error. +# +smbclient_get_expect_error() +{ + filename1="$1" + expected_error="$2" + tmpfile=${TMPDIR}/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +get $filename1 got_file +quit +EOF + rm -f got_file + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/veto_files -I$SERVER_IP < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + rm -f got_file + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing veto_files share with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep "NT_STATUS_" | wc -l | grep '^0$' + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing \"get %s got_file\"\n" "$expected_error" "$filename1" + return 1 + fi +} + +smbclient_create_expect_error() +{ + filename="$1.$$" + expected_error="$2" + tmpfile=${TMPDIR}/smbclient_interactive_prompt_commands + cat >"$tmpfile" <<EOF +put $tmpfile $filename +quit +EOF + + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/veto_files -I$SERVER_IP < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + rm -f "$SHAREPATH/$filename" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed accessing veto_files share with error %s\n" "$ret" + return 1 + fi + + if [ "$expected_error" = "NT_STATUS_OK" ]; then + printf "%s" "$out" | grep -c "NT_STATUS_" && false + else + printf "%s" "$out" | grep "$expected_error" + fi + ret=$? + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed - should get %s doing \"put %s\"\n" "$expected_error" "$filename" + return 1 + fi +} + +# +# Using the share "[veto_files]" ensure we +# cannot fetch a veto'd file or file in a veto'd directory. +# +test_get_veto_file() +{ + # toplevel + smbclient_get_expect_error "veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "veto_name_dir/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # toplevel mangle names + smbclient_get_expect_error "VHXE5P~M" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "VF5SKC~B/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "VF5SKC~B/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth1 + smbclient_get_expect_error "dir1/veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/veto_name_dir/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth1 mangle names + smbclient_get_expect_error "dir1/VHXE5P~M" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/VF5SKC~B/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/VF5SKC~B/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth2 + smbclient_get_expect_error "dir1/dir2/veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/veto_name_dir/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth2 mangle names + smbclient_get_expect_error "dir1/dir2/VHXE5P~M" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/VF5SKC~B/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/VF5SKC~B/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth3 + smbclient_get_expect_error "dir1/dir2/dir3/veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/dir3/veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/dir3/veto_name_dir/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + # depth3 mangle names + smbclient_get_expect_error "dir1/dir2/dir3/VHXE5P~M" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/dir3/VF5SKC~B/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_get_expect_error "dir1/dir2/dir3/VF5SKC~B/testdir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + + return 0 +} + +test_create_veto_file() +{ + # Test creating files + smbclient_create_expect_error "veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + smbclient_create_expect_error "veto_name_dir/file_inside_dir" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1 + smbclient_create_expect_error "dir1/veto_name_file" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1 + + return 0 +} + +do_cleanup + +echo "regular_file" > "${SHAREPATH}/regular_file" +echo "hidden_file" > "${SHAREPATH}/.hidden_file" + +test_smbclient "download regular file" \ + "get regular_file" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) +rm -f regular_file +test_smbclient_expect_failure "hidden file can't be downloaded" \ + "get .hidden_file" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) +test_smbclient "list files" \ + "ls" "//${SERVER}/veto_files_nohidden" \ + -U"${USERNAME}%${PASSWORD}" || + failed=$((failed + 1)) + +do_cleanup + +# Using hash2, veto_name_file\"mangle == VHXE5P~M +# Using hash2, veto_name_dir\"mangle == VF5SKC~B + +# I think a depth of 3 should be enough. +# toplevel +touch "$SHAREPATH/veto_name_file" +mkdir "$SHAREPATH/veto_name_dir" +touch "$SHAREPATH/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/veto_name_dir/testdir" +touch "$SHAREPATH/veto_name_dir/testdir/file_inside_dir" +# toplevel mangle names. +touch "$SHAREPATH/veto_name_file\"mangle" +mkdir "$SHAREPATH/veto_name_dir\"mangle" +touch "$SHAREPATH/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth1 +mkdir "$SHAREPATH/dir1" +touch "$SHAREPATH/dir1/veto_name_file" +mkdir "$SHAREPATH/dir1/veto_name_dir" +touch "$SHAREPATH/dir1/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/veto_name_dir/testdir/file_inside_dir" +# depth1 mangle names. +touch "$SHAREPATH/dir1/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth2 +mkdir "$SHAREPATH/dir1/dir2" +touch "$SHAREPATH/dir1/dir2/veto_name_file" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir/testdir/file_inside_dir" +# depth2 mangle names. +touch "$SHAREPATH/dir1/dir2/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/dir2/veto_name_dir\"mangle/testdir/file_inside_dir" + +#depth3 +mkdir "$SHAREPATH/dir1/dir2/dir3" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_file" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/testdir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir/testdir/file_inside_dir" +# depth3 mangle names. +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_file\"mangle" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/file_inside_dir" +mkdir "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir" +touch "$SHAREPATH/dir1/dir2/dir3/veto_name_dir\"mangle/testdir/file_inside_dir" + +testit "create_veto_file" test_create_veto_file || failed=$((failed + 1)) +testit "get_veto_file" test_get_veto_file || failed=$(("$failed" + 1)) + +do_cleanup + +cd "${PREFIX_ABS}" && rm -rf ${TMPDIR} + +exit "$failed" diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh new file mode 100755 index 0000000..4d7db9d --- /dev/null +++ b/source3/script/tests/test_veto_rmdir.sh @@ -0,0 +1,217 @@ +#!/bin/sh +# +# Check smbclient can (or cannot) delete a directory containing veto files. +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878 +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT +EOF + exit 1 +fi + +SERVER=${1} +SERVER_IP=${2} +USERNAME=${3} +PASSWORD=${4} +SHAREPATH=${5} +SMBCLIENT=${6} +shift 6 +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +rmdir_path="$SHAREPATH/dir" + +test_veto_nodelete_rmdir() +{ + local veto_path="$rmdir_path/veto_name1" + local msdfs_link_path="$rmdir_path/dfs_link" + local tmpfile=$PREFIX/smbclient.in.$$ + + # Create rmdir directory. + mkdir -p "$rmdir_path" + # Create veto file underneath. + touch "$veto_path" + # Create msdfs link underneath. + ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path" + + cat >"$tmpfile" <<EOF +cd dir +ls +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_nodelete - $ret" + echo "$out" + return 1 + fi + + # We should only see the dfs_link file. + echo "$out" | grep dfs_link + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to see dfs_link in share veto_files_nodelete" + echo "$out" + return 1 + fi + + # Now remove the dfs_link file. + rm -rf "$msdfs_link_path" + + # Try and remove the directory, should fail with NT_STATUS_DIRECTORY_NOT_EMPTY. + cat >"$tmpfile" <<EOF +rd dir +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_nodelete - $ret" + echo "$out" + return 1 + fi + + # We should get NT_STATUS_DIRECTORY_NOT_EMPTY. + echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to get error NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete" + echo "$out" + return 1 + fi + + # remove the veto file - directory should now be empty. + rm -rf "$veto_path" + + # Try and remove the directory, should now succeed. + cat >"$tmpfile" <<EOF +rd dir +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_nodelete - $ret" + echo "$out" + return 1 + fi + + # We should get no NT_STATUS_ errors. + echo "$out" | grep NT_STATUS_ + ret=$? + if [ $ret -eq 0 ]; then + echo "Got error NT_STATUS_ in share veto_files_nodelete" + echo "$out" + return 1 + fi + + return 0 +} + +test_veto_delete_rmdir() +{ + local veto_path="$rmdir_path/veto_name1" + local msdfs_link_path="$rmdir_path/dfs_link" + local tmpfile=$PREFIX/smbclient.in.$$ + + # Create rmdir directory. + mkdir -p "$rmdir_path" + # Create veto file underneath. + touch "$veto_path" + # Create msdfs link underneath. + ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path" + + cat >"$tmpfile" <<EOF +cd dir +ls +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_delete - $ret" + echo "$out" + return 1 + fi + + # We should only see the dfs_link file. + echo "$out" | grep dfs_link + ret=$? + if [ $ret -ne 0 ]; then + echo "Failed to see dfs_link in share veto_files_delete" + echo "$out" + return 1 + fi + + # Now remove the dfs_link file. + rm -rf "$msdfs_link_path" + + # Try and remove the directory, should now succeed. + cat >"$tmpfile" <<EOF +rd dir +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + if [ $ret != 0 ]; then + echo "Failed accessing share veto_files_delete - $ret" + echo "$out" + return 1 + fi + + # We should get no NT_STATUS_ errors. + echo "$out" | grep NT_STATUS_ + ret=$? + if [ $ret -eq 0 ]; then + echo "Got error NT_STATUS_ in share veto_files_delete" + echo "$out" + return 1 + fi + + return 0 +} + +testit "rmdir cannot delete directory containing a veto file" \ + test_veto_nodelete_rmdir || failed=$(expr "$failed" + 1) + +rm -rf "$rmdir_path" + +testit "rmdir can delete directory containing a veto file" \ + test_veto_delete_rmdir || failed=$(expr "$failed" + 1) + +rm -rf "$rmdir_path" + +exit "$failed" diff --git a/source3/script/tests/test_virus_scanner.sh b/source3/script/tests/test_virus_scanner.sh new file mode 100755 index 0000000..83b50df --- /dev/null +++ b/source3/script/tests/test_virus_scanner.sh @@ -0,0 +1,135 @@ +#!/bin/sh +# Copyright (c) 2022 Pavel Filipenský <pfilipen@redhat.com> +# shellcheck disable=1091 + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: $0 SERVER_IP SHARE LOCAL_PATH SMBCLIENT +EOF + exit 1 +fi + +SERVER_IP=${1} +SHARE=${2} +LOCAL_PATH=${3} +SMBCLIENT=${4} + +SMBCLIENT="${VALGRIND} ${SMBCLIENT}" + +failed=0 +sharedir="${LOCAL_PATH}/${SHARE}" + +incdir="$(dirname "$0")/../../../testprogs/blackbox" +. "${incdir}/subunit.sh" + +check_infected_read() +{ + rm -rf "${sharedir:?}"/* + + if ! mkdir "${sharedir}/read1"; then + echo "ERROR: Cannot create ${sharedir}/read1" + return 1 + fi + + if ! mkdir "${sharedir}/read1/read2"; then + echo "ERROR: Cannot create ${sharedir}/read1/read2" + return 1 + fi + + if ! touch "${sharedir}/read1/read2/infected.txt"; then + echo "ERROR: Cannot create ${sharedir}/read1/read2/infected.txt" + return 1 + fi + + ${SMBCLIENT} "//${SERVER_IP}/${SHARE}" -U"${USER}"%"${PASSWORD}" -c "get read1/read2/infected.txt ${sharedir}/read1/read2/infected.download.txt" + + # check that virusfilter:rename prefix/suffix was added + if [ ! -f "${sharedir}/read1/read2/virusfilter.infected.txt.infected" ]; then + echo "ERROR: ${sharedir}/read1/read2/virusfilter.infected.txt.infected is missing." + return 1 + fi + + # check that file was not downloaded + if [ -f "${sharedir}/read1/read2/infected.download.txt" ]; then + echo "ERROR: {sharedir}/read1/read2/infected.download.txt should not exist." + return 1 + fi + + rm -rf "${sharedir:?}"/* + return 0 +} + +check_infected_write() +{ + rm -rf "${sharedir:?}"/* + smbfile=infected.upload.txt + smbfilerenamed="virusfilter.${smbfile}.infected" + + # non empty file is needed + # vsf_virusfilter performs a scan only if fsp->fsp_flags.modified + if ! echo "Hello Virus!" >"${sharedir}/infected.txt"; then + echo "ERROR: Cannot create ${sharedir}/infected.txt" + return 1 + fi + + ${SMBCLIENT} "//${SERVER_IP}/${SHARE}" -U"${USER}"%"${PASSWORD}" -c "put ${sharedir}/infected.txt ${smbfile}" + + # check that virusfilter:rename prefix/suffix was added + if [ ! -f "${sharedir}/${smbfilerenamed}" ]; then + echo "ERROR: ${sharedir}/${smbfilerenamed} is missing." + return 1 + fi + + # check that file was not uploaded + if [ -f "${sharedir}/infected.upload.txt" ]; then + echo "ERROR: {sharedir}/${smbfile} should not exist." + return 1 + fi + + return 0 +} + +check_healthy_read() +{ + rm -rf "${sharedir:?}"/* + + if ! echo "Hello Samba!" >"${sharedir}/healthy.txt"; then + echo "ERROR: Cannot create ${sharedir}/healthy.txt" + return 1 + fi + + ${SMBCLIENT} //"${SERVER_IP}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" -c "get healthy.txt ${sharedir}/healthy.download.txt" + + if ! cmp "${sharedir}/healthy.txt" "${sharedir}/healthy.download.txt"; then + echo "ERROR: cmp ${sharedir}/healthy.txt ${sharedir}/healthy.download.txt FAILED" + return 1 + fi + + return 0 +} + +check_healthy_write() +{ + rm -rf "${sharedir:?}"/* + + if ! echo "Hello Samba!" >"${sharedir}/healthy.txt"; then + echo "ERROR: Cannot create ${sharedir}/healthy.txt" + return 1 + fi + + ${SMBCLIENT} //"${SERVER_IP}"/"${SHARE}" -U"${USER}"%"${PASSWORD}" -c "put ${sharedir}/healthy.txt healthy.upload.txt" + + if ! cmp "${sharedir}/healthy.txt" "${sharedir}/healthy.upload.txt"; then + echo "ERROR: cmp ${sharedir}/healthy.txt ${sharedir}/healthy.upload.txt FAILED" + return 1 + fi + + return 0 +} + +testit "check_infected_read" check_infected_read || failed=$((failed + 1)) +testit "check_infected_write" check_infected_write || failed=$((failed + 1)) +testit "check_healthy_read" check_healthy_read || failed=$((failed + 1)) +testit "check_healthy_write" check_healthy_write || failed=$((failed + 1)) + +testok "$0" "$failed" diff --git a/source3/script/tests/test_volume_serial_number.sh b/source3/script/tests/test_volume_serial_number.sh new file mode 100755 index 0000000..b156d70 --- /dev/null +++ b/source3/script/tests/test_volume_serial_number.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# This verifies setting the volume serial number parameter for a share works. +# + +if [ $# -lt 5 ]; then + echo "Usage: $0 SERVER_IP USERNAME PASSWORD SHARENAME SMBCLIENT" + exit 1 +fi + +SERVER_IP="$1" +USERNAME="$2" +PASSWORD="$3" +SHARENAME="$4" +SMBCLIENT="$5" + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +failed=0 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir/subunit.sh" + +test_serial_number() { + + output=$($SMBCLIENT "//$SERVER_IP/$SHARENAME" -U "$USERNAME%$PASSWORD" -c "volume") || return 1 + echo "smbclient volume on $SHARENAME returned: \"$output\"" + + expected="0xdeadbeef" + echo "$output" | grep $expected || { + echo "Expected output containing \"$expected\", got: \"$output\"" + return 1 + } +} + +testit "volume serial number for share $SHARENAME" test_serial_number || failed=$((failed+1)) + +exit "$failed" diff --git a/source3/script/tests/test_wbinfo_lookuprids_cache.sh b/source3/script/tests/test_wbinfo_lookuprids_cache.sh new file mode 100755 index 0000000..abb078b --- /dev/null +++ b/source3/script/tests/test_wbinfo_lookuprids_cache.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo}" +samba_tdbtool=tdbtool +if test -x $BINDIR/tdbtool; then + samba_tdbtool=$BINDIR/tdbtool +fi +TDBTOOL="${TDBTOOL:-$samba_tdbtool}" + +samba_tdbdump=tdbdump +if test -x $BINDIR/tdbdump; then + samba_tdbdump=$BINDIR/tdbdump +fi +TDBDUMP="${TDBDUMP:-$samba_tdbdump}" + +NET="$VALGRIND ${NET:-$BINDIR/net}" + +cache="$LOCK_DIR"/winbindd_cache.tdb + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "flush" "$NET" "cache" "flush" || failed=$(expr $failed + 1) +testit "lookuprids1" "$WBINFO" "-R" "512,12345" || failed=$(expr $failed + 1) + +key=$("$TDBDUMP" "$cache" | grep ^key.*NDR.*/16/ | cut -d\" -f2) + +testit "delete" "$TDBTOOL" "$cache" delete "$key" +testit "lookuprids2" "$WBINFO" "-R" "512,12345" || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_wbinfo_sids2xids.sh b/source3/script/tests/test_wbinfo_sids2xids.sh new file mode 100755 index 0000000..b07aebf --- /dev/null +++ b/source3/script/tests/test_wbinfo_sids2xids.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo} $CONFIGURATION" +NET="$VALGRIND ${NET:-$BINDIR/net} $CONFIGURATION" +TEST_INT=$(dirname $0)/test_wbinfo_sids2xids_int.py + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +testit "sids2xids" ${TEST_INT} ${WBINFO} ${NET} || failed=$(expr $failed + 1) + +testok $0 $failed diff --git a/source3/script/tests/test_wbinfo_sids2xids_int.py b/source3/script/tests/test_wbinfo_sids2xids_int.py new file mode 100755 index 0000000..4f2715c --- /dev/null +++ b/source3/script/tests/test_wbinfo_sids2xids_int.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import sys +import os +import subprocess +from samba.common import get_string + + +if len(sys.argv) != 3: + print("Usage: test_wbinfo_sids2xids_int.py wbinfo net") + sys.exit(1) + +wbinfo = sys.argv[1] +netcmd = sys.argv[2] + + +def run(cmd): + """ + Run a cmd, return bytes str for py2 and unicode str for py3. + + NOTE: subprocess api always return bytes, in both py2 and py3. + """ + output = subprocess.check_output(cmd).strip() + return get_string(output) + + +def flush_cache(sids=None, uids=None, gids=None): + if sids is None: + sids = [] + if uids is None: + uids = [] + if gids is None: + gids = [] + + for sid in sids: + os.system(netcmd + (" cache del IDMAP/SID2XID/%s" % (sid))) + for uid in uids: + os.system(netcmd + (" cache del IDMAP/UID2SID/%s" % (uid))) + for gid in gids: + os.system(netcmd + (" cache del IDMAP/GID2SID/%s" % (gid))) + + +def fill_cache(inids, idtype='gid'): + for inid in inids: + if inid is None: + continue + run([wbinfo, '--%s-to-sid=%s' % (idtype, inid)]) + + +domain = run([wbinfo, "--own-domain"]) +domsid = run([wbinfo, "-n", domain + "/"]) +domsid = domsid.split(' ')[0] + +# print domain +# print domsid + +sids = [domsid + '-512', 'S-1-5-32-545', domsid + '-513', 'S-1-1-0', 'S-1-3-1', 'S-1-5-1'] + +flush_cache(sids=sids) + +sids2xids = run([wbinfo, '--sids-to-unix-ids=' + ','.join(sids)]) + +gids = [] +uids = [] +idtypes = [] + +for line in sids2xids.split('\n'): + result = line.split(' ')[2:] + idtypes.append(result[0]) + + gid = None + uid = None + if result[0] == 'gid': + gid = result[1] + elif result[0] == 'uid': + uid = result[1] + elif result[0] == 'uid/gid': + gid = result[1] + uid = result[1] + + if gid == '-1': + gid = '' + gids.append(gid) + + if uid == '-1': + uid = '' + uids.append(uid) + +# Check the list produced by the sids-to-xids call with the +# singular variant (sid-to-xid) for each sid in turn. + + +def check_singular(sids, ids, idtype='gid'): + i = 0 + for sid in sids: + if ids[i] is None: + continue + + outid = run([wbinfo, '--sid-to-%s' % idtype, sid]) + if outid != ids[i]: + print("Expected %s, got %s\n" % (outid, ids[i])) + flush_cache(sids=sids, uids=uids, gids=gids) + sys.exit(1) + i += 1 + +# Check the list produced by the sids-to-xids call with the +# multiple variant (sid-to-xid) for each sid in turn. + + +def check_multiple(sids, idtypes): + sids2xids = run([wbinfo, '--sids-to-unix-ids=' + ','.join(sids)]) + # print sids2xids + i = 0 + for line in sids2xids.split('\n'): + result = line.split(' ')[2:] + + if result[0] != idtypes[i]: + print("Expected %s, got %s\n" % (idtypes[i], result[0])) + flush_cache(sids=sids, uids=uids, gids=gids) + sys.exit(1) + i += 1 + + +# first round: with filled cache via sid-to-id +check_singular(sids, gids, 'gid') +check_singular(sids, uids, 'uid') + +# second round: with empty cache +flush_cache(sids=sids, gids=gids) +check_singular(sids, gids, 'gid') +flush_cache(sids=sids, uids=uids) +check_singular(sids, uids, 'uid') + +# third round: with filled cache via uid-to-sid +flush_cache(sids=uids, uids=uids) +fill_cache(uids, 'uid') +check_multiple(sids, idtypes) + +# fourth round: with filled cache via gid-to-sid +flush_cache(sids=sids, gids=gids) +fill_cache(gids, 'gid') +check_multiple(sids, idtypes) + +# flush the cache so any incorrect mappings don't break other tests +flush_cache(sids=sids, uids=uids, gids=gids) + +sys.exit(0) diff --git a/source3/script/tests/test_wbinfo_u_large_ad.sh b/source3/script/tests/test_wbinfo_u_large_ad.sh new file mode 100755 index 0000000..ab5f0ca --- /dev/null +++ b/source3/script/tests/test_wbinfo_u_large_ad.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +LDBMODIFY="$VALGRIND ${LDBMODIFY:-$BINDIR/ldbmodify} $CONFIGURATION" +LDBSEARCH="$VALGRIND ${LDBSEARCH:-$BINDIR/ldbsearch} $CONFIGURATION" +WBINFO="$VALGRIND ${WBINFO:-$BINDIR/wbinfo} $CONFIGURATION" + +NUM_USERS=1234 + +BASE_DN=$($LDBSEARCH -H ldap://$DC_SERVER -b "" --scope=base defaultNamingContext | awk '/^defaultNamingContext/ {print $2}') + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh + +seq -w 1 "$NUM_USERS" | + xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:add\nobjectclass:user\nsamaccountname:large_ad_NUM\n" | + $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD" + +testit_grep_count \ + "Make sure $NUM_USERS $DOMAIN users are returned" \ + "$DOMAIN/large_ad_" \ + "$NUM_USERS" \ + ${WBINFO} -u || failed=$(expr $failed + 1) + +seq -w 1 "$NUM_USERS" | + xargs -INUM echo -e "dn:cn=large_ad_NUM,cn=users,$BASE_DN\nchangetype:delete\n" | + $LDBMODIFY -H ldap://$DC_SERVER -U "$DOMAIN\Administrator%$DC_PASSWORD" + +testok $0 $failed diff --git a/source3/script/tests/test_winbind_call_depth_trace.sh b/source3/script/tests/test_winbind_call_depth_trace.sh new file mode 100755 index 0000000..6d978be --- /dev/null +++ b/source3/script/tests/test_winbind_call_depth_trace.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +# Copyright (c) Pavel Filipenský <pfilipensky@samba.org> +# License: GPLv3 + +if [ $# -lt 4 ]; then + echo "Usage: test_winbind_call_depth_trace SMBCONTROL CONFIGURATION PREFIX TESTENV" + exit 1 +fi + +SMBCONTROL="${1}" +CONFIGURATION=${2} +PREFIX="${3}" +TESTENV="${4}" +shift 4 + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +PREFIX_ABS="$(readlink -f "${PREFIX}")" +# Strip from TESTENV the ':local' if present +TESTENV_SUBDIR=${TESTENV%:*} + +LOGFILE="${PREFIX_ABS}/${TESTENV_SUBDIR}/logs/log.winbindd" +# Add support for "WINBINDD_DONT_LOG_STDOUT=1" +if [ ! -r "${LOGFILE}" ]; then + TEST_LOGFILE="${PREFIX_ABS}/${TESTENV_SUBDIR}/winbindd_test.log" + subunit_start_test "test winbind call depth trace" + subunit_skip_test "test winbind call depth trace" <<EOF +Test is skipped, we need $LOGFILE but have only $TEST_LOGFILE which is missing debug headers (they are not printed to stdout). +EOF + exit 0 +fi + +saved_level=1 + +get_winbind_loglevel() +{ + s1=$(${SMBCONTROL} "${CONFIGURATION}" winbind debuglevel) + # We need to get the all level from output like this: + # "PID 664474: all:1 tdb:1 printdrivers:1 lanman:1 smb:1 rpc_parse:1 rpc_srv:1 rpc_cli:1 passdb:1 sam:1..." + # 1. remove PID 664474: + s2=${s1#PID*: } + # "all:1 tdb:1 printdrivers:1 lanman:1 smb:1 rpc_parse:1 rpc_srv:1 rpc_cli:1 passdb" + # 2. remove " tdb:1 printdrivers:1 ..." + s3=${s2%% *} + # "all:1" + # 3. remove "all:" + saved_level=${s3#all:} +} + +# Example of trace line +# [2023/01/25 00:20:33.307038, 5, pid=535581, effective(0, 0), real(0, 0), class=winbind, traceid=78, depth=4] ../../source3/winbindd/wb_group_members.c:310(wb_group_members_send) +test_winbind_call_depth_trace() +{ + get_winbind_loglevel + + # If loglevel < 10, set it to 10. + if [ "$saved_level" -lt 10 ]; then + ${SMBCONTROL} "${CONFIGURATION}" winbind debug 10 + fi + + COUNT1=$(grep -c wb_group_members_send "$LOGFILE") + + id ADDOMAIN/alice + ret=$? + + # Restore loglevel, if it was changed. + if [ "$saved_level" -lt 10 ]; then + ${SMBCONTROL} "${CONFIGURATION}" winbind debug "$saved_level" + fi + + if [ $ret != 0 ]; then + echo "Command 'id ADDOMAIN/alice' failed!" + return 1 + fi + + # Check that there are more lines with wb_group_members_send + COUNT2=$(grep -c wb_group_members_send "$LOGFILE") + if [ "$COUNT1" -eq "$COUNT2" ]; then + echo "The number of the trace lines in $LOGFILE has not increased." + return 1 + fi + + # Test that the depth of last line with 'wb_group_members_send' is: depth=4 + COUNT3=$(grep wb_group_members_send "$LOGFILE" | tail -1 | grep -c depth=4) + if [ "$COUNT3" -ne 1 ]; then + echo "The last line with wb_group_members_send should have depth=4." + return 1 + fi + + # Test that the indentation of the line below last 'wb_group_members_send' is indented by 2+4*4 spaces: + COUNT4=$(grep -A1 wb_group_members_send "$LOGFILE" | tail -1| grep -c '^ WB command group_members start') + if [ "$COUNT4" -ne 1 ]; then + echo "The line after the last line with wb_group_members_send should be indented by 18 spaces." + return 1 + fi + + return 0 +} + +case ${TESTENV} in +ad_member*) + ;; +*) + echo "Test is for ad_member only, but called for ${TESTENV}." | subunit_fail_test "test winbind call depth trace" + exit 1; +esac + +testit "test winbind call depth trace" test_winbind_call_depth_trace || failed=$((failed + 1)) +testok "$0" "$failed" diff --git a/source3/script/tests/test_winbind_ignore_domains.sh b/source3/script/tests/test_winbind_ignore_domains.sh new file mode 100755 index 0000000..1454eca --- /dev/null +++ b/source3/script/tests/test_winbind_ignore_domains.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +smbclient="$BINDIR/smbclient" +smbcontrol="$BINDIR/smbcontrol" +ldbmodify="$BINDIR/ldbmodify" +ldbsearch="$BINDIR/ldbsearch" +wbinfo="$BINDIR/wbinfo" +global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf +SERVER_FQDN=$(echo "$SERVER.$REALM" | awk '{print tolower($0)}') + +TRUST_BASE_DN=$($ldbsearch -H ldap://$TRUST_SERVER -b "" -s base defaultNamingContext | awk '/^defaultNamingContext/ {print $2}') +if [ $? -ne 0 ]; then + echo "Could not find trusted base DN" | subunit_fail_test "test_idmap_ad" + exit 1 +fi + +# +# Add POSIX ids to trusted domain +# +add_posix_ids() +{ + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Administrator,CN=Users,$TRUST_BASE_DN +changetype: modify +add: uidNumber +uidNumber: 2500000 +EOF + + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Users,CN=Users,$TRUST_BASE_DN +changetype: modify +add: gidNumber +gidNumber: 2500001 +EOF + + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Admins,CN=Users,$TRUST_BASE_DN +changetype: modify +add: gidNumber +gidNumber: 2500002 +EOF +} + +# +# Remove POSIX ids from trusted domain +# +remove_posix_ids() +{ + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Administrator,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: uidNumber +uidNumber: 2500000 +EOF + + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Users,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: gidNumber +gidNumber: 2500001 +EOF + + cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Admins,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: gidNumber +gidNumber: 2500002 +EOF +} + +add_posix_ids + +echo "" >$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient "test_winbind_ignore_domains_ok_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient "test_winbind_ignore_domains_ok_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient "test_winbind_ignore_domains_ok_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=$(expr $failed + 1) + +echo "winbind:ignore domains = $TRUST_DOMAIN" >$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=$(expr $failed + 1) +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=$(expr $failed + 1) + +echo "" >$global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p +remove_posix_ids + +testok $0 $failed diff --git a/source3/script/tests/test_worm.sh b/source3/script/tests/test_worm.sh new file mode 100755 index 0000000..f96c8ec --- /dev/null +++ b/source3/script/tests/test_worm.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +if [ $# -lt 7 ]; then + cat <<EOF +Usage: test_worm.sh SERVER SERVER_IP USERNAME PASSWORD LOCAL_PATH PREFIX SMBCLIENT ADDARGS +EOF + exit 1 +fi + +SERVER="${1}" +SERVER_IP="${2}" +USERNAME="${3}" +PASSWORD="${4}" +LOCAL_PATH="${5}" +PREFIX="${6}" +SMBCLIENT="${7}" +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +shift 7 +ADDARGS="$*" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# Do not let deprecated option warnings muck this up +SAMBA_DEPRECATED_SUPPRESS=1 +export SAMBA_DEPRECATED_SUPPRESS + +# Define the test environment/filenames. +# +share_test_dir="$LOCAL_PATH" + +# +# Cleanup function. +# +do_cleanup() +{ + ( + #subshell. + cd "$share_test_dir" || return + rm -f must-be-deleted must-not-be-deleted must-be-deleted-after-ctime-refresh + ) + rm -f $tmpfile +} + +# +# Ensure we start from a clean slate. +# +do_cleanup + +tmpfile=$PREFIX/smbclient_interactive_prompt_commands + +test_worm() +{ + # use echo because helo scripts don't support variables + echo " +put $tmpfile must-be-deleted +put $tmpfile must-be-deleted-after-ctime-refresh +put $tmpfile must-not-be-deleted +del must-be-deleted +quit" > $tmpfile + # make sure the directory is not too old for worm: + touch $share_test_dir + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/worm -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + rm -f "$tmpfile" + + if [ $ret != 0 ]; then + printf "%s\n" "$out" + printf "failed worm smbclient run with error %s\n" "$ret" + return 1 + fi + test -e $share_test_dir/must-be-deleted && { + printf "$0: ERROR: must-be-deleted was NOT deleted\n" + return 1 + } + + # now sleep grace_period (1s) and check if worm works properly: + sleep 1 + echo " +posix +chmod 700 must-not-be-deleted +del must-not-be-deleted +del must-be-deleted-after-ctime-refresh +quit" > $tmpfile + # make sure the directory itself is not too old for worm: + touch $share_test_dir + # set a fresh ctime by doing a chmod: + chmod 644 $share_test_dir/must-be-deleted-after-ctime-refresh + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/worm -I$SERVER_IP $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + test -e $share_test_dir/must-not-be-deleted || { + printf "$0: ERROR: must-not-be-deleted WAS deleted\n" + return 1 + } + # if we're not root, return here: + test "$UID" = "0" || { + return 0 + } + + test -e $share_test_dir/must-be-deleted-after-ctime-refresh && { + printf "$0: ERROR: must-be-deleted-after-ctime-refresh was NOT deleted\n" + return 1 + } + return 0 +} + + +testit "worm" \ + test_worm || + failed=$((failed + 1)) + +# +# Cleanup. +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/test_zero_data.sh b/source3/script/tests/test_zero_data.sh new file mode 100755 index 0000000..62ba856 --- /dev/null +++ b/source3/script/tests/test_zero_data.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Verify that smbtorture tests for manually testing ZERO_DATA +# +# Copyright (C) 2019 Christof Schmitt + +if [ $# -lt 4 ]; then + cat <<EOF +Usage: test_zero_data.sh SERVER_IP USERNAME PASSWORD LOCAL_PATH +EOF + exit 1 +fi + +SERVER=${1} +USERNAME=${2} +PASSWORD=${3} +LOCAL_PATH=${4} + +. $(dirname $0)/../../../testprogs/blackbox/subunit.sh +failed=0 + +cd $SELFTEST_TMPDIR || exit 1 + +TESTDIR=$LOCAL_PATH/zero_data + +mkdir -p $TESTDIR +chmod 777 p $TESTDIR + +dd if=/dev/urandom of=$TESTDIR/testfile bs=1024 count=128 +chmod 777 $TESTDIR/testfile + +alloc_kb=$(du -k $TESTDIR/testfile | sed -e 's/\t.*//') +testit "check allocation before zero-data" test $alloc_kb -eq 128 || + failed=$(expr $failed + 1) + +testit "set-sparse" $VALGRIND $BINDIR/smbtorture //$SERVER_IP/tmp \ + -U$USERNAME%$PASSWORD smb2.set-sparse-ioctl \ + --option=torture:filename=zero_data/testfile || + failed=$(expr $failed + 1) + +testit "zero-data" $VALGRIND $BINDIR/smbtorture //$SERVER_IP/tmp \ + -U$USERNAME%$PASSWORD smb2.zero-data-ioctl \ + --option=torture:filename=zero_data/testfile \ + --option=torture:offset=0 \ + --option=torture:beyond_final_zero=131072 || + failed=$(expr $failed + 1) + +alloc_kb=$(du -k $TESTDIR/testfile | sed -e 's/\t.*//') +testit "check allocation after zero-data" test $alloc_kb -eq 0 || + failed=$(expr $failed + 1) + +rm -rf $TESTDIR + +testok $0 $failed diff --git a/source3/script/tests/test_zero_readsize.sh b/source3/script/tests/test_zero_readsize.sh new file mode 100755 index 0000000..f859599 --- /dev/null +++ b/source3/script/tests/test_zero_readsize.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# +# Test setting smb2 max read = 0. +# +# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15306 +# + +if [ $# -lt 6 ]; then + cat <<EOF +Usage: $0 SERVERCONFFILE SMBCLIENT SMBCONTROL SERVER SHARE PREFIX +EOF + exit 1 +fi + +CONF=${1} +shift 1 +SMBCLIENT=${1} +shift 1 +SMBCONTROL=${1} +shift 1 +SERVER=${1} +shift 1 +SHARE=${1} +shift 1 +PREFIX=${1} +shift 1 + +SMBCLIENT="$VALGRIND ${SMBCLIENT}" +ADDARGS="$@" + +incdir=$(dirname "$0")/../../../testprogs/blackbox +. "$incdir"/subunit.sh + +failed=0 + +# +# Setup function +# +do_setup() +{ + rm -f "${PREFIX}/zero_read_testfile" + rm -f "${PREFIX}/zero_read_testfile_get" + dd if=/dev/zero of="${PREFIX}/zero_read_testfile" bs=1024 count=1 + global_inject_conf="$(dirname "${SERVERCONFFILE}")/global_inject.conf" + echo "smb2 max read = 0" >"$global_inject_conf" + ${SMBCONTROL} ${CONF} smbd reload-config +} + +do_cleanup() +{ + rm -f "${PREFIX}/zero_read_testfile" + rm -f "${PREFIX}/zero_read_testfile_get" + global_inject_conf="$(dirname "${SERVERCONFFILE}")/global_inject.conf" + rm "$global_inject_conf" + ${SMBCONTROL} ${CONF} smbd reload-config +} + +test_smb2_zero_readsize() +{ + local tmpfile="$PREFIX/smbclient.in.$$" + + cat >"$tmpfile" <<EOF +lcd $PREFIX +put zero_read_testfile zero_read_testfile_put +get zero_read_testfile_put zero_read_testfile_get +del zero_read_testfile_put +quit +EOF + + local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/$SHARE -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=$(eval "$cmd") + ret=$? + + # Check for smbclient error. + # We should have failed the protocol negotiation, returning 1. + if [ $ret != 1 ]; then + echo "smbclient protocol negotiation succeeded (should have failed) zero read testfile $ret" + echo "$out" + return 1 + fi + + # We should get NT_STATUS_INVALID_NETWORK_RESPONSE + echo "$out" | grep NT_STATUS_INVALID_NETWORK_RESPONSE + ret=$? + if [ $ret -ne 0 ]; then + echo "Should get NT_STATUS_INVALID_NETWORK_RESPONSE" + echo "$out" + return 1 + fi + rm "$tmpfile" + return 0 +} + +do_setup + +testit "smb2_zero_readsize" test_smb2_zero_readsize || failed=$((failed + 1)) + +do_cleanup + +testok "$0" "$failed" diff --git a/source3/script/tests/timelimit.c b/source3/script/tests/timelimit.c new file mode 100644 index 0000000..886256c --- /dev/null +++ b/source3/script/tests/timelimit.c @@ -0,0 +1,102 @@ +/* run a command with a limited timeout + tridge@samba.org, June 2005 + metze@samba.org, March 2006 + + attempt to be as portable as possible (fighting posix all the way) +*/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> + +static pid_t child_pid; + +static void usage(void) +{ + printf("usage: timelimit <time> <command>\n"); + printf(" SIGUSR1 - passes SIGTERM to command's process group\n"); + printf(" SIGALRM - passes SIGTERM to command's process group\n"); + printf(" after 5s SIGKILL will be passed and exit(1)\n"); + printf(" SIGTERM - passes SIGTERM to command's process group\n"); + printf(" after 1s SIGKILL will be passed and exit(1)\n"); +} + +static void sig_alrm_kill(int sig) +{ + fprintf(stderr, "\nMaximum time expired in timelimit - killing\n"); + kill(-child_pid, SIGKILL); + exit(1); +} + +static void sig_alrm_term(int sig) +{ + kill(-child_pid, SIGTERM); + alarm(5); + signal(SIGALRM, sig_alrm_kill); +} + +static void sig_term(int sig) +{ + kill(-child_pid, SIGTERM); + alarm(1); + signal(SIGALRM, sig_alrm_kill); +} + +static void sig_usr1(int sig) +{ + kill(-child_pid, SIGTERM); +} + +static void new_process_group(void) +{ + if (setpgid(0,0) == -1) { + perror("setpgid"); + exit(1); + } +} + + +int main(int argc, char *argv[]) +{ + int maxtime, ret=1; + + if (argc < 3) { + usage(); + exit(1); + } + + maxtime = atoi(argv[1]); + + child_pid = fork(); + if (child_pid == 0) { + new_process_group(); + execvp(argv[2], argv+2); + perror(argv[2]); + exit(1); + } + + signal(SIGTERM, sig_term); + signal(SIGINT, sig_term); + signal(SIGQUIT, sig_term); + signal(SIGUSR1, sig_usr1); + signal(SIGALRM, sig_alrm_term); + alarm(maxtime); + + do { + int status; + pid_t pid = wait(&status); + if (pid != -1) { + ret = WEXITSTATUS(status); + } else if (errno == ECHILD) { + break; + } + } while (1); + + kill(-child_pid, SIGKILL); + + exit(ret); +} diff --git a/source3/script/tests/vfstest-acl/run.sh b/source3/script/tests/vfstest-acl/run.sh new file mode 100755 index 0000000..eb32a95 --- /dev/null +++ b/source3/script/tests/vfstest-acl/run.sh @@ -0,0 +1,52 @@ +#!/bin/sh +if [ $# -lt 2 ]; then + cat <<EOF +Usage: run.sh VFSTEST PREFIX +EOF + exit 1 +fi + +TESTBASE=$(dirname $0) +VFSTEST=$1 +PREFIX=$2 +shift 2 +ADDARGS="$*" + +VFSTEST_PREFIX=vfstest +VFSTEST_TMPDIR=$(mktemp -d ${PREFIX}/${VFSTEST_PREFIX}_XXXXXX) + +incdir=$(dirname $0)/../../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $VFSTEST_TMPDIR || exit 1 + +test_vfstest() +{ + cmd='$VFSTEST -f $TESTBASE/vfstest.cmd $ADDARGS ' + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep "NT_STATUS_ACCESS_DENIED" >/dev/null 2>&1 + + if [ $? = 0 ]; then + # got ACCESS_DENIED .. fail + echo vfstest got NT_STATUS_ACCESS_DENIED + false + else + true + fi +} + +testit "vfstest" test_vfstest || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/vfstest-acl/vfstest.cmd b/source3/script/tests/vfstest-acl/vfstest.cmd new file mode 100644 index 0000000..6168671 --- /dev/null +++ b/source3/script/tests/vfstest-acl/vfstest.cmd @@ -0,0 +1,15 @@ +connect +open x RC 0700 +sys_acl_get_file . 0 +sys_acl_get_file . 1 +get_nt_acl . +set_nt_acl . G:DAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU) +get_nt_acl . +sys_acl_get_file . 0 +sys_acl_get_file . 1 +get_nt_acl x +sys_acl_get_file x 0 +set_nt_acl x G:DAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU) +get_nt_acl x +sys_acl_get_file x 0 + diff --git a/source3/script/tests/vfstest-catia/run.sh b/source3/script/tests/vfstest-catia/run.sh new file mode 100755 index 0000000..aca2a60 --- /dev/null +++ b/source3/script/tests/vfstest-catia/run.sh @@ -0,0 +1,102 @@ +#!/bin/sh +if [ $# -lt 2 ]; then + cat <<EOF +Usage: run.sh VFSTEST PREFIX +EOF + exit 1 +fi + +TESTBASE=$(dirname $0) +VFSTEST=$1 +PREFIX=$2 +shift 2 +ADDARGS="$*" + +VFSTEST_PREFIX=vfstest +VFSTEST_TMPDIR=$(mktemp -d ${PREFIX}/${VFSTEST_PREFIX}_XXXXXX) + +# We could pass in the --option=... via tests.py as ADDARGS +# Atm i've chosen to specify them here: + +MYARGS1="--option=vfsobjects=catia" +MYARGS2="--option=catia:mappings=0x22:0xa8,0x2a:0xa4,0x2f:0xf8,0x3a:0xf7,0x3c:0xab,0x3e:0xbb,0x3f:0xbf,0x5c:0xff,0x7c:0xa6,0x20:0xb1" + +# vars for the translation test: +# a) here for unix-to-windows test +UNIX_FILE="a\\a:a*a?a<a>a|a" +# translated window file name +WIN_FILE="aÿa÷a¤a¿a«a»a¦a" + +# b) here for windows-to-unix test +WIN_DIR="dir_aÿa÷a¤a¿a«a»a¦a" +# translated unix directory name +UNIX_DIR="dir_a\a:a*a?a<a>a|a" + +incdir=$(dirname $0)/../../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $VFSTEST_TMPDIR || exit 1 + +# create unix file in tmpdir +touch $UNIX_FILE || exit 1 + +# test "translate" unix-to-windows +test_vfstest() +{ + cmd='$VFSTEST --debug-stdout -f $TESTBASE/vfstest.cmd $MYARGS1 $MYARGS2 $ADDARGS ' + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep $WIN_FILE >/dev/null 2>&1 + + if [ $? = 0 ]; then + echo "ALL IS WORKING" + true + else + false + fi +} + +# test the mkdir call with special windows chars +# and then check the created unix directory name +test_vfstest_dir() +{ + cmd='$VFSTEST -f $TESTBASE/vfstest1.cmd $MYARGS1 $MYARGS2 $ADDARGS ' + out=$(eval $cmd) + ret=$? + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed" + false + return + fi + + NUM=$(find $UNIX_DIR | wc -l) + if [ $NUM -ne 1 ]; then + echo "Cannot find $UNIX_DIR" + false + else + true + fi +} + +testit "vfstest_catia" test_vfstest || failed=$(expr $failed + 1) + +if [ $failed = 0 ]; then + testit "vfstest1_catia" test_vfstest_dir || failed=$(expr $failed + 1) +fi + +# Cleanup: remove tempdir +rm -R $VFSTEST_TMPDIR + +exit $failed diff --git a/source3/script/tests/vfstest-catia/vfstest.cmd b/source3/script/tests/vfstest-catia/vfstest.cmd new file mode 100644 index 0000000..5acecbc --- /dev/null +++ b/source3/script/tests/vfstest-catia/vfstest.cmd @@ -0,0 +1,2 @@ +connect +translate_name a\a:a*a?a<a>a|a diff --git a/source3/script/tests/vfstest-catia/vfstest1.cmd b/source3/script/tests/vfstest-catia/vfstest1.cmd new file mode 100644 index 0000000..ef56159 --- /dev/null +++ b/source3/script/tests/vfstest-catia/vfstest1.cmd @@ -0,0 +1,2 @@ +connect +mkdir dir_aÿa÷a¤a¿a«a»a¦a diff --git a/source3/script/tests/wb_pad.sh b/source3/script/tests/wb_pad.sh new file mode 100755 index 0000000..f4dded6 --- /dev/null +++ b/source3/script/tests/wb_pad.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# Copyright (C) Guenther Deschner 2008 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +tempdir=$(mktemp -d /tmp/wb_padXXXXXX) +test -n "$tempdir" || exit 1 +cat >>$tempdir/wb_pad.c <<_EOF +#include "nsswitch/winbind_client.h" + +int main(int argc, const char **argv) +{ + struct winbindd_request req; + struct winbindd_response resp; + + if (argc != 2) { + printf("usage: %s [req|resp]\n", argv[0]); + return 0; + } + + if (strcmp(argv[1], "req") == 0) { + printf("%d\n", (uint32_t)sizeof(req)); + } + if (strcmp(argv[1], "resp") == 0) { + printf("%d\n", (uint32_t)sizeof(resp)); + } + + return 0; +} +_EOF + +cleanup() +{ + rm -f $tempdir/wb_pad_32 $tempdir/wb_pad_64 $tempdir/wb_pad.c + rmdir $tempdir +} + +cflags="-I. -I../ -I./../lib/replace -Iinclude" +${CC:-gcc} -m32 $RPM_OPT_FLAGS $CFLAGS -o $tempdir/wb_pad_32 $cflags $tempdir/wb_pad.c +if [ $? -ne 0 ]; then + cleanup + exit 1 +fi +${CC:-gcc} -m64 $RPM_OPT_FLAGS $CFLAGS -o $tempdir/wb_pad_64 $cflags $tempdir/wb_pad.c +if [ $? -ne 0 ]; then + cleanup + exit 1 +fi + +out_64_req=$($tempdir/wb_pad_64 req) +out_64_resp=$($tempdir/wb_pad_64 resp) +out_32_req=$($tempdir/wb_pad_32 req) +out_32_resp=$($tempdir/wb_pad_32 resp) + +cleanup + +if test "$out_64_req" != "$out_32_req"; then + echo "winbind request size differs!" + echo "64bit: $out_64_req" + echo "32bit: $out_32_req" + exit 1 +fi + +if test "$out_64_resp" != "$out_32_resp"; then + echo "winbind response size differs!" + echo "64bit: $out_64_resp" + echo "32bit: $out_32_resp" + exit 1 +fi + +exit 0 diff --git a/source3/script/tests/xattr-tdb-1/run.sh b/source3/script/tests/xattr-tdb-1/run.sh new file mode 100755 index 0000000..eb32a95 --- /dev/null +++ b/source3/script/tests/xattr-tdb-1/run.sh @@ -0,0 +1,52 @@ +#!/bin/sh +if [ $# -lt 2 ]; then + cat <<EOF +Usage: run.sh VFSTEST PREFIX +EOF + exit 1 +fi + +TESTBASE=$(dirname $0) +VFSTEST=$1 +PREFIX=$2 +shift 2 +ADDARGS="$*" + +VFSTEST_PREFIX=vfstest +VFSTEST_TMPDIR=$(mktemp -d ${PREFIX}/${VFSTEST_PREFIX}_XXXXXX) + +incdir=$(dirname $0)/../../../../testprogs/blackbox +. $incdir/subunit.sh + +failed=0 + +cd $VFSTEST_TMPDIR || exit 1 + +test_vfstest() +{ + cmd='$VFSTEST -f $TESTBASE/vfstest.cmd $ADDARGS ' + out=$(eval $cmd) + ret=$? + rm -f $tmpfile + + if [ $ret != 0 ]; then + echo "$out" + echo "command failed" + false + return + fi + + echo "$out" | grep "NT_STATUS_ACCESS_DENIED" >/dev/null 2>&1 + + if [ $? = 0 ]; then + # got ACCESS_DENIED .. fail + echo vfstest got NT_STATUS_ACCESS_DENIED + false + else + true + fi +} + +testit "vfstest" test_vfstest || failed=$(expr $failed + 1) + +exit $failed diff --git a/source3/script/tests/xattr-tdb-1/vfstest.cmd b/source3/script/tests/xattr-tdb-1/vfstest.cmd new file mode 100644 index 0000000..5eb7158 --- /dev/null +++ b/source3/script/tests/xattr-tdb-1/vfstest.cmd @@ -0,0 +1,6 @@ +connect +open x RC 0700 +setxattr x y z +listxattr x +stat x +unlink x |