summaryrefslogtreecommitdiff
path: root/source4/torture
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture')
-rw-r--r--source4/torture/auth/ntlmssp.c6
-rw-r--r--source4/torture/basic/base.c5
-rw-r--r--source4/torture/basic/locking.c3
-rw-r--r--source4/torture/basic/misc.c2
-rw-r--r--source4/torture/config.mk176
-rw-r--r--source4/torture/gentest.c47
-rw-r--r--source4/torture/gentest_smb2.c1907
-rw-r--r--source4/torture/ldap/cldap.c105
-rw-r--r--source4/torture/ldap/cldapbench.c6
-rw-r--r--source4/torture/ldap/common.c4
-rw-r--r--source4/torture/ldap/schema.c2
-rw-r--r--source4/torture/ldap/uptodatevector.c2
-rw-r--r--source4/torture/libnet/domain.c4
-rw-r--r--source4/torture/libnet/libnet.c2
-rw-r--r--source4/torture/libnet/libnet_BecomeDC.c4
-rw-r--r--source4/torture/libnet/libnet_domain.c4
-rw-r--r--source4/torture/libnet/libnet_user.c6
-rw-r--r--source4/torture/local/config.mk62
-rw-r--r--source4/torture/local/dbspeed.c4
-rw-r--r--source4/torture/local/local.c2
-rw-r--r--source4/torture/locktest.c26
-rw-r--r--source4/torture/locktest2.c26
-rw-r--r--source4/torture/masktest.c9
-rw-r--r--source4/torture/nbench/nbench.c3
-rw-r--r--source4/torture/nbt/browse.c2
-rw-r--r--source4/torture/nbt/dgram.c416
-rw-r--r--source4/torture/nbt/nbt.c4
-rw-r--r--source4/torture/nbt/query.c2
-rw-r--r--source4/torture/nbt/register.c4
-rw-r--r--source4/torture/nbt/wins.c2
-rw-r--r--source4/torture/nbt/winsbench.c2
-rw-r--r--source4/torture/nbt/winsreplication.c18
-rw-r--r--source4/torture/ndr/ndr.c2
-rw-r--r--source4/torture/rap/rap.c2
-rw-r--r--source4/torture/raw/composite.c4
-rw-r--r--source4/torture/raw/lockbench.c9
-rw-r--r--source4/torture/raw/lookuprate.c320
-rw-r--r--source4/torture/raw/offline.c13
-rw-r--r--source4/torture/raw/open.c10
-rw-r--r--source4/torture/raw/openbench.c9
-rw-r--r--source4/torture/raw/oplock.c3
-rw-r--r--source4/torture/raw/raw.c8
-rw-r--r--source4/torture/raw/samba3hide.c2
-rw-r--r--source4/torture/raw/samba3misc.c2
-rw-r--r--source4/torture/raw/streams.c95
-rw-r--r--source4/torture/raw/tconrate.c201
-rw-r--r--source4/torture/rpc/async_bind.c7
-rw-r--r--source4/torture/rpc/dfs.c4
-rw-r--r--source4/torture/rpc/dssync.c17
-rw-r--r--source4/torture/rpc/join.c4
-rw-r--r--source4/torture/rpc/rpc.c11
-rw-r--r--source4/torture/rpc/rpc.h2
-rw-r--r--source4/torture/rpc/samba3rpc.c26
-rw-r--r--source4/torture/rpc/samlogon.c2
-rw-r--r--source4/torture/rpc/samsync.c4
-rw-r--r--source4/torture/rpc/schannel.c365
-rw-r--r--source4/torture/rpc/session_key.c6
-rw-r--r--source4/torture/rpc/spoolss_notify.c1
-rw-r--r--source4/torture/rpc/spoolss_win.c1
-rw-r--r--source4/torture/rpc/testjoin.c6
-rw-r--r--source4/torture/smb2/config.mk12
-rw-r--r--source4/torture/smb2/getinfo.c12
-rw-r--r--source4/torture/smb2/lock.c162
-rw-r--r--source4/torture/smb2/oplocks.c178
-rw-r--r--source4/torture/smb2/persistent_handles.c184
-rw-r--r--source4/torture/smb2/scan.c4
-rw-r--r--source4/torture/smb2/smb2.c65
-rw-r--r--source4/torture/smb2/util.c44
-rw-r--r--source4/torture/smbtorture.c5
-rw-r--r--source4/torture/smbtorture.h (renamed from source4/torture/torture.h)9
-rw-r--r--source4/torture/torture.c3
-rw-r--r--source4/torture/torture.pc.in12
-rw-r--r--source4/torture/ui.c583
-rw-r--r--source4/torture/ui.h396
-rw-r--r--source4/torture/unix/unix.c2
-rw-r--r--source4/torture/unix/unix_info2.c4
-rw-r--r--source4/torture/unix/whoami.c2
-rw-r--r--source4/torture/util.h5
-rw-r--r--source4/torture/util_smb.c1
-rw-r--r--source4/torture/winbind/config.mk8
-rw-r--r--source4/torture/winbind/struct_based.c25
-rw-r--r--source4/torture/winbind/winbind.c2
82 files changed, 4174 insertions, 1547 deletions
diff --git a/source4/torture/auth/ntlmssp.c b/source4/torture/auth/ntlmssp.c
index 917a24ad59..739a048d29 100644
--- a/source4/torture/auth/ntlmssp.c
+++ b/source4/torture/auth/ntlmssp.c
@@ -33,7 +33,8 @@ static bool torture_ntlmssp_self_check(struct torture_context *tctx)
TALLOC_CTX *mem_ctx = tctx;
torture_assert_ntstatus_ok(tctx,
- gensec_client_start(mem_ctx, &gensec_security, NULL, tctx->lp_ctx),
+ gensec_client_start(mem_ctx, &gensec_security,
+ tctx->ev, tctx->lp_ctx),
"gensec client start");
gensec_set_credentials(gensec_security, cmdline_credentials);
@@ -87,7 +88,8 @@ static bool torture_ntlmssp_self_check(struct torture_context *tctx)
talloc_free(gensec_security);
torture_assert_ntstatus_ok(tctx,
- gensec_client_start(mem_ctx, &gensec_security, NULL, tctx->lp_ctx),
+ gensec_client_start(mem_ctx, &gensec_security,
+ tctx->ev, tctx->lp_ctx),
"Failed to start GENSEC for NTLMSSP");
gensec_set_credentials(gensec_security, cmdline_credentials);
diff --git a/source4/torture/basic/base.c b/source4/torture/basic/base.c
index 3a3a7c2fd5..2ab3f9ca91 100644
--- a/source4/torture/basic/base.c
+++ b/source4/torture/basic/base.c
@@ -19,7 +19,7 @@
*/
#include "includes.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/basic/proto.h"
#include "libcli/libcli.h"
#include "libcli/raw/raw_proto.h"
@@ -55,7 +55,8 @@ static struct smbcli_state *open_nbt_connection(struct torture_context *tctx)
lp_smbcli_options(tctx->lp_ctx, &options);
- if (!smbcli_socket_connect(cli, host, lp_smb_ports(tctx->lp_ctx), lp_resolve_context(tctx->lp_ctx), &options)) {
+ if (!smbcli_socket_connect(cli, host, lp_smb_ports(tctx->lp_ctx), tctx->ev,
+ lp_resolve_context(tctx->lp_ctx), &options)) {
torture_comment(tctx, "Failed to connect with %s\n", host);
goto failed;
}
diff --git a/source4/torture/basic/locking.c b/source4/torture/basic/locking.c
index 2e2585b976..3f399c97ef 100644
--- a/source4/torture/basic/locking.c
+++ b/source4/torture/basic/locking.c
@@ -23,9 +23,8 @@
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/libcli.h"
-#include "torture/ui.h"
+#include "torture/smbtorture.h"
#include "torture/util.h"
-#include "torture/torture.h"
#include "system/time.h"
#include "system/filesys.h"
diff --git a/source4/torture/basic/misc.c b/source4/torture/basic/misc.c
index 188fc1bc69..24e0324bc3 100644
--- a/source4/torture/basic/misc.c
+++ b/source4/torture/basic/misc.c
@@ -30,7 +30,7 @@
#include "libcli/resolve/resolve.h"
#include "auth/credentials/credentials.h"
#include "librpc/gen_ndr/ndr_nbt.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/util.h"
#include "libcli/smb_composite/smb_composite.h"
#include "libcli/composite/composite.h"
diff --git a/source4/torture/config.mk b/source4/torture/config.mk
index e6c54022c2..2857b99582 100644
--- a/source4/torture/config.mk
+++ b/source4/torture/config.mk
@@ -1,30 +1,14 @@
-# TORTURE subsystem
-[LIBRARY::torture]
-PRIVATE_PROTO_HEADER = proto.h
-PUBLIC_DEPENDENCIES = \
- LIBSAMBA-HOSTCONFIG \
- LIBSAMBA-UTIL \
- LIBTALLOC \
- LIBPOPT
-
-PC_FILES += torture/torture.pc
-torture_OBJ_FILES = $(addprefix torture/, torture.o ui.o)
-
-PUBLIC_HEADERS += torture/torture.h torture/ui.h
-
[SUBSYSTEM::TORTURE_UTIL]
PRIVATE_DEPENDENCIES = LIBCLI_RAW LIBPYTHON smbcalls PROVISION
PUBLIC_DEPENDENCIES = POPT_CREDENTIALS
-TORTURE_UTIL_OBJ_FILES = $(addprefix torture/, util_smb.o)
+TORTURE_UTIL_OBJ_FILES = $(addprefix $(torturesrcdir)/, util_smb.o)
#################################
# Start SUBSYSTEM TORTURE_BASIC
[MODULE::TORTURE_BASIC]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_base_init
-PRIVATE_PROTO_HEADER = \
- basic/proto.h
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB POPT_CREDENTIALS \
TORTURE_UTIL LIBCLI_RAW \
@@ -32,7 +16,7 @@ PRIVATE_DEPENDENCIES = \
# End SUBSYSTEM TORTURE_BASIC
#################################
-TORTURE_BASIC_OBJ_FILES = $(addprefix torture/basic/, \
+TORTURE_BASIC_OBJ_FILES = $(addprefix $(torturesrcdir)/basic/, \
base.o \
misc.o \
scanner.o \
@@ -52,21 +36,20 @@ TORTURE_BASIC_OBJ_FILES = $(addprefix torture/basic/, \
attr.o \
properties.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/basic/proto.h,$(TORTURE_BASIC_OBJ_FILES:.o=.c)))
#################################
# Start SUBSYSTEM TORTURE_RAW
[MODULE::TORTURE_RAW]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_raw_init
-PRIVATE_PROTO_HEADER = \
- raw/proto.h
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB LIBCLI_LSA LIBCLI_SMB_COMPOSITE \
POPT_CREDENTIALS TORTURE_UTIL
# End SUBSYSTEM TORTURE_RAW
#################################
-TORTURE_RAW_OBJ_FILES = $(addprefix torture/raw/, \
+TORTURE_RAW_OBJ_FILES = $(addprefix $(torturesrcdir)/raw/, \
qfsinfo.o \
qfileinfo.o \
setfileinfo.o \
@@ -86,6 +69,8 @@ TORTURE_RAW_OBJ_FILES = $(addprefix torture/raw/, \
lock.o \
pingpong.o \
lockbench.o \
+ lookuprate.o \
+ tconrate.o \
openbench.o \
rename.o \
eas.o \
@@ -98,22 +83,22 @@ TORTURE_RAW_OBJ_FILES = $(addprefix torture/raw/, \
raw.o \
offline.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/raw/proto.h,$(TORTURE_RAW_OBJ_FILES:.o=.c)))
mkinclude smb2/config.mk
mkinclude winbind/config.mk
[SUBSYSTEM::TORTURE_NDR]
-PRIVATE_PROTO_HEADER = ndr/proto.h
-TORTURE_NDR_OBJ_FILES = $(addprefix torture/ndr/, ndr.o winreg.o atsvc.o lsa.o epmap.o dfs.o netlogon.o drsuapi.o spoolss.o samr.o)
+TORTURE_NDR_OBJ_FILES = $(addprefix $(torturesrcdir)/ndr/, ndr.o winreg.o atsvc.o lsa.o epmap.o dfs.o netlogon.o drsuapi.o spoolss.o samr.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/ndr/proto.h,$(TORTURE_NDR_OBJ_FILES:.o=.c)))
[MODULE::torture_rpc]
# TORTURE_NET and TORTURE_NBT use functions from torture_rpc...
#OUTPUT_TYPE = MERGED_OBJ
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_rpc_init
-PRIVATE_PROTO_HEADER = \
- rpc/proto.h
PRIVATE_DEPENDENCIES = \
NDR_TABLE RPC_NDR_UNIXINFO dcerpc_samr RPC_NDR_WINREG RPC_NDR_INITSHUTDOWN \
RPC_NDR_OXIDRESOLVER RPC_NDR_EVENTLOG RPC_NDR_ECHO RPC_NDR_SVCCTL \
@@ -124,7 +109,7 @@ PRIVATE_DEPENDENCIES = \
LIBCLI_AUTH POPT_CREDENTIALS TORTURE_LDAP TORTURE_UTIL TORTURE_RAP \
dcerpc_server service process_model ntvfs SERVICE_SMB
-torture_rpc_OBJ_FILES = $(addprefix torture/rpc/, \
+torture_rpc_OBJ_FILES = $(addprefix $(torturesrcdir)/rpc/, \
join.o lsa.o lsa_lookup.o session_key.o echo.o dfs.o drsuapi.o \
drsuapi_cracknames.o dssync.o spoolss.o spoolss_notify.o spoolss_win.o \
unixinfo.o samr.o samr_accessmask.o wkssvc.o srvsvc.o svcctl.o atsvc.o \
@@ -133,99 +118,97 @@ torture_rpc_OBJ_FILES = $(addprefix torture/rpc/, \
samsync.o bind.o dssetup.o alter_context.o bench.o samba3rpc.o rpc.o async_bind.o \
handles.o frsapi.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/rpc/proto.h,$(torture_rpc_OBJ_FILES:.o=.c)))
+
#################################
# Start SUBSYSTEM TORTURE_RAP
[MODULE::TORTURE_RAP]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_rap_init
-PRIVATE_PROTO_HEADER = \
- rap/proto.h
PRIVATE_DEPENDENCIES = TORTURE_UTIL LIBCLI_SMB
# End SUBSYSTEM TORTURE_RAP
#################################
-TORTURE_RAP_OBJ_FILES = torture/rap/rap.o
+TORTURE_RAP_OBJ_FILES = $(torturesrcdir)/rap/rap.o
+
+$(eval $(call proto_header_template,$(torturesrcdir)/rap/proto.h,$(TORTURE_RAP_OBJ_FILES:.o=.c)))
#################################
# Start SUBSYSTEM TORTURE_AUTH
[MODULE::TORTURE_AUTH]
-SUBSYSTEM = torture
-PRIVATE_PROTO_HEADER = \
- auth/proto.h
+SUBSYSTEM = smbtorture
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB gensec auth KERBEROS \
POPT_CREDENTIALS SMBPASSWD
# End SUBSYSTEM TORTURE_AUTH
#################################
-TORTURE_AUTH_OBJ_FILES = $(addprefix torture/auth/, ntlmssp.o pac.o)
+TORTURE_AUTH_OBJ_FILES = $(addprefix $(torturesrcdir)/auth/, ntlmssp.o pac.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/auth/proto.h,$(TORTURE_AUTH_OBJ_FILES:.o=.c)))
mkinclude local/config.mk
#################################
# Start MODULE TORTURE_NBENCH
[MODULE::TORTURE_NBENCH]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_nbench_init
PRIVATE_DEPENDENCIES = TORTURE_UTIL
-PRIVATE_PROTO_HEADER = \
- nbench/proto.h
# End MODULE TORTURE_NBENCH
#################################
-TORTURE_NBENCH_OBJ_FILES = $(addprefix torture/nbench/, nbio.o nbench.o)
+TORTURE_NBENCH_OBJ_FILES = $(addprefix $(torturesrcdir)/nbench/, nbio.o nbench.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/nbench/proto.h,$(TORTURE_NBENCH_OBJ_FILES:.o=.c)))
#################################
# Start MODULE TORTURE_UNIX
[MODULE::TORTURE_UNIX]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_unix_init
PRIVATE_DEPENDENCIES = TORTURE_UTIL
-PRIVATE_PROTO_HEADER = \
- unix/proto.h
# End MODULE TORTURE_UNIX
#################################
-TORTURE_UNIX_OBJ_FILES = $(addprefix torture/unix/, unix.o whoami.o unix_info2.o)
+TORTURE_UNIX_OBJ_FILES = $(addprefix $(torturesrcdir)/unix/, unix.o whoami.o unix_info2.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/unix/proto.h,$(TORTURE_UNIX_OBJ_FILES:.o=.c)))
#################################
# Start SUBSYSTEM TORTURE_LDAP
[MODULE::TORTURE_LDAP]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_ldap_init
-PRIVATE_PROTO_HEADER = \
- ldap/proto.h
PRIVATE_DEPENDENCIES = \
LIBCLI_LDAP LIBCLI_CLDAP SAMDB POPT_CREDENTIALS
# End SUBSYSTEM TORTURE_LDAP
#################################
-TORTURE_LDAP_OBJ_FILES = $(addprefix torture/ldap/, common.o basic.o schema.o uptodatevector.o cldap.o cldapbench.o)
+TORTURE_LDAP_OBJ_FILES = $(addprefix $(torturesrcdir)/ldap/, common.o basic.o schema.o uptodatevector.o cldap.o cldapbench.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/ldap/proto.h,$(TORTURE_LDAP_OBJ_FILES:.o=.c)))
#################################
# Start SUBSYSTEM TORTURE_NBT
[MODULE::TORTURE_NBT]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_nbt_init
-PRIVATE_PROTO_HEADER = \
- nbt/proto.h
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB LIBCLI_NBT LIBCLI_DGRAM LIBCLI_WREPL torture_rpc
# End SUBSYSTEM TORTURE_NBT
#################################
-TORTURE_NBT_OBJ_FILES = $(addprefix torture/nbt/, query.o register.o \
+TORTURE_NBT_OBJ_FILES = $(addprefix $(torturesrcdir)/nbt/, query.o register.o \
wins.o winsbench.o winsreplication.o dgram.o nbt.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/nbt/proto.h,$(TORTURE_NBT_OBJ_FILES:.o=.c)))
#################################
# Start SUBSYSTEM TORTURE_NET
[MODULE::TORTURE_NET]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_net_init
-PRIVATE_PROTO_HEADER = \
- libnet/proto.h
PRIVATE_DEPENDENCIES = \
LIBSAMBA-NET \
POPT_CREDENTIALS \
@@ -233,11 +216,12 @@ PRIVATE_DEPENDENCIES = \
# End SUBSYSTEM TORTURE_NET
#################################
-TORTURE_NET_OBJ_FILES = $(addprefix torture/libnet/, libnet.o \
+TORTURE_NET_OBJ_FILES = $(addprefix $(torturesrcdir)/libnet/, libnet.o \
utils.o userinfo.o userman.o groupinfo.o groupman.o \
domain.o libnet_lookup.o libnet_user.o libnet_group.o \
libnet_share.o libnet_rpc.o libnet_domain.o libnet_BecomeDC.o)
+$(eval $(call proto_header_template,$(torturesrcdir)/libnet/proto.h,$(TORTURE_NET_OBJ_FILES:.o=.c)))
#################################
# Start BINARY smbtorture
@@ -254,9 +238,10 @@ PRIVATE_DEPENDENCIES = \
# End BINARY smbtorture
#################################
-smbtorture_OBJ_FILES = torture/smbtorture.o
+smbtorture_OBJ_FILES = $(torturesrcdir)/smbtorture.o $(torturesrcdir)/torture.o
-MANPAGES += torture/man/smbtorture.1
+PUBLIC_HEADERS += $(torturesrcdir)/smbtorture.h
+MANPAGES += $(torturesrcdir)/man/smbtorture.1
#################################
# Start BINARY gentest
@@ -273,9 +258,26 @@ PRIVATE_DEPENDENCIES = \
# End BINARY gentest
#################################
-gentest_OBJ_FILES = torture/gentest.o
+gentest_OBJ_FILES = $(torturesrcdir)/gentest.o
-MANPAGES += torture/man/gentest.1
+MANPAGES += $(torturesrcdir)/man/gentest.1
+
+#################################
+# Start BINARY gentest_smb2
+[BINARY::gentest_smb2]
+INSTALLDIR = BINDIR
+PRIVATE_DEPENDENCIES = \
+ LIBSAMBA-HOSTCONFIG \
+ LIBSAMBA-UTIL \
+ LIBPOPT \
+ POPT_SAMBA \
+ POPT_CREDENTIALS \
+ LIBCLI_SMB \
+ LIBCLI_RAW
+# End BINARY gentest_smb2
+#################################
+
+gentest_smb2_OBJ_FILES = $(torturesrcdir)/gentest_smb2.o
#################################
# Start BINARY masktest
@@ -291,9 +293,9 @@ PRIVATE_DEPENDENCIES = \
# End BINARY masktest
#################################
-masktest_OBJ_FILES = torture/masktest.o
+masktest_OBJ_FILES = $(torturesrcdir)/masktest.o
-MANPAGES += torture/man/masktest.1
+MANPAGES += $(torturesrcdir)/man/masktest.1
#################################
# Start BINARY locktest
@@ -309,36 +311,44 @@ PRIVATE_DEPENDENCIES = \
# End BINARY locktest
#################################
-locktest_OBJ_FILES = torture/locktest.o
+locktest_OBJ_FILES = $(torturesrcdir)/locktest.o
-MANPAGES += torture/man/locktest.1
+MANPAGES += $(torturesrcdir)/man/locktest.1
-COV_TARGET = test
+GCOV=0
-COV_VARS = \
- CFLAGS="$(CFLAGS) --coverage" \
- LDFLAGS="$(LDFLAGS) --coverage"
+ifeq ($(MAKECMDGOALS),gcov)
+GCOV=1
+endif
-test_cov:
- -$(MAKE) $(COV_TARGET) $(COV_VARS)
+ifeq ($(MAKECMDGOALS),lcov)
+GCOV=1
+endif
-gcov: test_cov
+ifeq ($(MAKECMDGOALS),testcov-html)
+GCOV=1
+endif
+
+ifeq ($(GCOV),1)
+CFLAGS += --coverage
+LDFLAGS += --coverage
+endif
+
+COV_TARGET = test
+
+gcov: test
for I in $(sort $(dir $(ALL_OBJS))); \
do $(GCOV) -p -o $$I $$I/*.c; \
done
-lcov-split:
- rm -f samba.info
- @$(MAKE) $(COV_TARGET) $(COV_VARS) \
- TEST_OPTIONS="--analyse-cmd=\"lcov --base-directory `pwd` --directory . --capture --output-file samba.info -t\""
+samba.info: test
-rm heimdal/lib/*/{lex,parse}.{gcda,gcno}
- -rm lib/policy/*/{lex,parse}.{gcda,gcno}
- genhtml -o coverage samba.info
-
-lcov: test_cov
- -rm heimdal/lib/*/{lex,parse}.{gcda,gcno}
- -rm lib/policy/*/{lex,parse}.{gcda,gcno}
lcov --base-directory `pwd` --directory . --capture --output-file samba.info
- genhtml -o coverage samba.info
+
+lcov: samba.info
+ genhtml -o coverage $<
testcov-html:: lcov
+
+clean::
+ @rm -f samba.info
diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c
index d5fc855f17..ae18fe809c 100644
--- a/source4/torture/gentest.c
+++ b/source4/torture/gentest.c
@@ -19,6 +19,7 @@
#include "includes.h"
#include "lib/cmdline/popt_common.h"
+#include "lib/events/events.h"
#include "system/time.h"
#include "system/filesys.h"
#include "libcli/raw/request.h"
@@ -36,18 +37,18 @@
/* global options */
static struct gentest_options {
- bool showall;
- bool analyze;
- bool analyze_always;
- bool analyze_continuous;
+ int showall;
+ int analyze;
+ int analyze_always;
+ int analyze_continuous;
uint_t max_open_handles;
uint_t seed;
uint_t numops;
- bool use_oplocks;
+ int use_oplocks;
char **ignore_patterns;
const char *seeds_file;
- bool use_preset_seeds;
- bool fast_reconnect;
+ int use_preset_seeds;
+ int fast_reconnect;
} options;
/* mapping between open handles on the server and local handles */
@@ -154,7 +155,8 @@ static bool connect_servers_fast(void)
/*****************************************************
connect to the servers
*******************************************************/
-static bool connect_servers(struct loadparm_context *lp_ctx)
+static bool connect_servers(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
int i, j;
@@ -193,7 +195,7 @@ static bool connect_servers(struct loadparm_context *lp_ctx)
servers[i].share_name, NULL,
servers[i].credentials,
lp_resolve_context(lp_ctx),
- NULL, &smb_options);
+ ev, &smb_options);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to \\\\%s\\%s - %s\n",
servers[i].server_name, servers[i].share_name,
@@ -1937,11 +1939,11 @@ static struct {
run the test with the current set of op_parms parameters
return the number of operations that completed successfully
*/
-static int run_test(struct loadparm_context *lp_ctx)
+static int run_test(struct event_context *ev, struct loadparm_context *lp_ctx)
{
int op, i;
- if (!connect_servers(lp_ctx)) {
+ if (!connect_servers(ev, lp_ctx)) {
printf("Failed to connect to servers\n");
exit(1);
}
@@ -2018,7 +2020,8 @@ static int run_test(struct loadparm_context *lp_ctx)
perform a backtracking analysis of the minimal set of operations
to generate an error
*/
-static void backtrack_analyze(struct loadparm_context *lp_ctx)
+static void backtrack_analyze(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
int chunk, ret;
@@ -2039,7 +2042,7 @@ static void backtrack_analyze(struct loadparm_context *lp_ctx)
}
printf("Testing %d ops with %d-%d disabled\n",
options.numops, base, max-1);
- ret = run_test(lp_ctx);
+ ret = run_test(ev, lp_ctx);
printf("Completed %d of %d ops\n", ret, options.numops);
for (i=base;i<max; i++) {
op_parms[i].disabled = false;
@@ -2071,7 +2074,7 @@ static void backtrack_analyze(struct loadparm_context *lp_ctx)
} while (chunk > 0);
printf("Reduced to %d ops\n", options.numops);
- ret = run_test(lp_ctx);
+ ret = run_test(ev, lp_ctx);
if (ret != options.numops - 1) {
printf("Inconsistent result? ret=%d numops=%d\n", ret, options.numops);
}
@@ -2080,7 +2083,8 @@ static void backtrack_analyze(struct loadparm_context *lp_ctx)
/*
start the main gentest process
*/
-static bool start_gentest(struct loadparm_context *lp_ctx)
+static bool start_gentest(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
{
int op;
int ret;
@@ -2116,15 +2120,15 @@ static bool start_gentest(struct loadparm_context *lp_ctx)
}
}
- ret = run_test(lp_ctx);
+ ret = run_test(ev, lp_ctx);
if (ret != options.numops && options.analyze) {
options.numops = ret+1;
- backtrack_analyze(lp_ctx);
+ backtrack_analyze(ev, lp_ctx);
} else if (options.analyze_always) {
- backtrack_analyze(lp_ctx);
+ backtrack_analyze(ev, lp_ctx);
} else if (options.analyze_continuous) {
- while (run_test(lp_ctx) == options.numops) ;
+ while (run_test(ev, lp_ctx) == options.numops) ;
}
return ret == options.numops;
@@ -2171,6 +2175,7 @@ static bool split_unc_name(const char *unc, char **server, char **share)
int i, username_count=0;
bool ret;
char *ignore_file=NULL;
+ struct event_context *ev;
struct loadparm_context *lp_ctx;
poptContext pc;
int argc_new;
@@ -2278,9 +2283,11 @@ static bool split_unc_name(const char *unc, char **server, char **share)
printf("seed=%u\n", options.seed);
+ ev = event_context_init(talloc_autofree_context());
+
gensec_init(lp_ctx);
- ret = start_gentest(lp_ctx);
+ ret = start_gentest(ev, lp_ctx);
if (ret) {
printf("gentest completed - no errors\n");
diff --git a/source4/torture/gentest_smb2.c b/source4/torture/gentest_smb2.c
new file mode 100644
index 0000000000..6546ba6768
--- /dev/null
+++ b/source4/torture/gentest_smb2.c
@@ -0,0 +1,1907 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ generic testing tool - version with SMB2 support
+
+ Copyright (C) Andrew Tridgell 2003-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/>.
+*/
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "lib/events/events.h"
+#include "system/time.h"
+#include "system/filesys.h"
+#include "libcli/raw/request.h"
+#include "libcli/libcli.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "librpc/gen_ndr/security.h"
+#include "auth/credentials/credentials.h"
+#include "libcli/resolve/resolve.h"
+#include "auth/gensec/gensec.h"
+#include "param/param.h"
+#include "dynconfig.h"
+
+#define NSERVERS 2
+#define NINSTANCES 2
+
+/* global options */
+static struct gentest_options {
+ int showall;
+ int analyze;
+ int analyze_always;
+ int analyze_continuous;
+ uint_t max_open_handles;
+ uint_t seed;
+ uint_t numops;
+ int use_oplocks;
+ char **ignore_patterns;
+ const char *seeds_file;
+ int use_preset_seeds;
+ int fast_reconnect;
+ int mask_indexing;
+ int no_eas;
+} options;
+
+/* mapping between open handles on the server and local handles */
+static struct {
+ bool active;
+ uint_t instance;
+ struct smb2_handle server_handle[NSERVERS];
+ const char *name;
+} *open_handles;
+static uint_t num_open_handles;
+
+/* state information for the servers. We open NINSTANCES connections to
+ each server */
+static struct {
+ struct smb2_tree *tree[NINSTANCES];
+ char *server_name;
+ char *share_name;
+ struct cli_credentials *credentials;
+} servers[NSERVERS];
+
+/* the seeds and flags for each operation */
+static struct {
+ uint_t seed;
+ bool disabled;
+} *op_parms;
+
+
+/* oplock break info */
+static struct {
+ bool got_break;
+ struct smb2_handle server_handle;
+ uint16_t handle;
+ uint8_t level;
+ bool do_close;
+} oplocks[NSERVERS][NINSTANCES];
+
+/* change notify reply info */
+static struct {
+ int notify_count;
+ NTSTATUS status;
+ union smb_notify notify;
+} notifies[NSERVERS][NINSTANCES];
+
+/* info relevant to the current operation */
+static struct {
+ const char *name;
+ uint_t seed;
+ NTSTATUS status;
+ uint_t opnum;
+ TALLOC_CTX *mem_ctx;
+} current_op;
+
+static struct smb2_handle bad_smb2_handle;
+
+
+#define BAD_HANDLE 0xFFFE
+
+static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private);
+static void idle_func(struct smb2_transport *transport, void *private);
+
+/*
+ check if a string should be ignored. This is used as the basis
+ for all error ignore settings
+*/
+static bool ignore_pattern(const char *str)
+{
+ int i;
+ if (!options.ignore_patterns) return false;
+
+ for (i=0;options.ignore_patterns[i];i++) {
+ if (strcmp(options.ignore_patterns[i], str) == 0 ||
+ gen_fnmatch(options.ignore_patterns[i], str) == 0) {
+ DEBUG(2,("Ignoring '%s'\n", str));
+ return true;
+ }
+ }
+ return false;
+}
+
+/*****************************************************
+connect to the servers
+*******************************************************/
+static bool connect_servers_fast(void)
+{
+ int h, i;
+
+ /* close all open files */
+ for (h=0;h<options.max_open_handles;h++) {
+ if (!open_handles[h].active) continue;
+ for (i=0;i<NSERVERS;i++) {
+ NTSTATUS status = smb2_util_close(servers[i].tree[open_handles[h].instance],
+ open_handles[h].server_handle[i]);
+ if (NT_STATUS_IS_ERR(status)) {
+ return false;
+ }
+ open_handles[h].active = false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+/*****************************************************
+connect to the servers
+*******************************************************/
+static bool connect_servers(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
+{
+ int i, j;
+
+ if (options.fast_reconnect && servers[0].tree[0]) {
+ if (connect_servers_fast()) {
+ return true;
+ }
+ }
+
+ /* close any existing connections */
+ for (i=0;i<NSERVERS;i++) {
+ for (j=0;j<NINSTANCES;j++) {
+ if (servers[i].tree[j]) {
+ smb2_tdis(servers[i].tree[j]);
+ talloc_free(servers[i].tree[j]);
+ servers[i].tree[j] = NULL;
+ }
+ }
+ }
+
+ for (i=0;i<NSERVERS;i++) {
+ for (j=0;j<NINSTANCES;j++) {
+ NTSTATUS status;
+ printf("Connecting to \\\\%s\\%s as %s - instance %d\n",
+ servers[i].server_name, servers[i].share_name,
+ servers[i].credentials->username, j);
+
+ cli_credentials_set_workstation(servers[i].credentials,
+ "gentest", CRED_SPECIFIED);
+
+ status = smb2_connect(NULL, servers[i].server_name,
+ servers[i].share_name,
+ lp_resolve_context(lp_ctx),
+ servers[i].credentials,
+ &servers[i].tree[j],
+ ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to connect to \\\\%s\\%s - %s\n",
+ servers[i].server_name, servers[i].share_name,
+ nt_errstr(status));
+ return false;
+ }
+
+// smb2_oplock_handler(servers[i].cli[j]->transport, oplock_handler, NULL);
+ smb2_transport_idle_handler(servers[i].tree[j]->session->transport, idle_func, 50000, NULL);
+ }
+ }
+
+ return true;
+}
+
+/*
+ work out the time skew between the servers - be conservative
+*/
+static uint_t time_skew(void)
+{
+ uint_t ret;
+ ret = labs(servers[0].tree[0]->session->transport->negotiate.system_time -
+ servers[1].tree[0]->session->transport->negotiate.system_time);
+ return ret + 300;
+}
+
+
+static bool smb2_handle_equal(const struct smb2_handle *h1, const struct smb2_handle *h2)
+{
+ return memcmp(h1, h2, sizeof(struct smb2_handle)) == 0;
+}
+
+/*
+ turn a server handle into a local handle
+*/
+static uint_t fnum_to_handle(int server, int instance, struct smb2_handle server_handle)
+{
+ uint_t i;
+ for (i=0;i<options.max_open_handles;i++) {
+ if (!open_handles[i].active ||
+ instance != open_handles[i].instance) continue;
+ if (smb2_handle_equal(&open_handles[i].server_handle[server], &server_handle)) {
+ return i;
+ }
+ }
+ printf("Invalid server handle in fnum_to_handle on server %d instance %d\n",
+ server, instance);
+ return BAD_HANDLE;
+}
+
+/*
+ add some newly opened handles
+*/
+static void gen_add_handle(int instance, const char *name, struct smb2_handle handles[NSERVERS])
+{
+ int i, h;
+ for (h=0;h<options.max_open_handles;h++) {
+ if (!open_handles[h].active) break;
+ }
+ if (h == options.max_open_handles) {
+ /* we have to force close a random handle */
+ h = random() % options.max_open_handles;
+ for (i=0;i<NSERVERS;i++) {
+ NTSTATUS status;
+ status = smb2_util_close(servers[i].tree[open_handles[h].instance],
+ open_handles[h].server_handle[i]);
+ if (NT_STATUS_IS_ERR(status)) {
+ printf("INTERNAL ERROR: Close failed when recovering handle! - %s\n",
+ nt_errstr(status));
+ }
+ }
+ printf("Recovered handle %d\n", h);
+ num_open_handles--;
+ }
+ for (i=0;i<NSERVERS;i++) {
+ open_handles[h].server_handle[i] = handles[i];
+ open_handles[h].instance = instance;
+ open_handles[h].active = true;
+ open_handles[h].name = name;
+ }
+ num_open_handles++;
+
+ printf("OPEN num_open_handles=%d h=%d (%s)\n",
+ num_open_handles, h, name);
+}
+
+/*
+ remove a closed handle
+*/
+static void gen_remove_handle(int instance, struct smb2_handle handles[NSERVERS])
+{
+ int h;
+ for (h=0;h<options.max_open_handles;h++) {
+ if (instance == open_handles[h].instance &&
+ smb2_handle_equal(&open_handles[h].server_handle[0], &handles[0])) {
+ open_handles[h].active = false;
+ num_open_handles--;
+ printf("CLOSE num_open_handles=%d h=%d (%s)\n",
+ num_open_handles, h,
+ open_handles[h].name);
+ return;
+ }
+ }
+ printf("Removing invalid handle!?\n");
+ exit(1);
+}
+
+/*
+ return true with 'chance' probability as a percentage
+*/
+static bool gen_chance(uint_t chance)
+{
+ return ((random() % 100) <= chance);
+}
+
+/*
+ map an internal handle number to a server handle
+*/
+static struct smb2_handle gen_lookup_handle(int server, uint16_t handle)
+{
+ if (handle == BAD_HANDLE) return bad_smb2_handle;
+ return open_handles[handle].server_handle[server];
+}
+
+/*
+ return a file handle
+*/
+static uint16_t gen_fnum(int instance)
+{
+ uint16_t h;
+ int count = 0;
+
+ if (gen_chance(20)) return BAD_HANDLE;
+
+ while (num_open_handles > 0 && count++ < 10*options.max_open_handles) {
+ h = random() % options.max_open_handles;
+ if (open_handles[h].active &&
+ open_handles[h].instance == instance) {
+ return h;
+ }
+ }
+ return BAD_HANDLE;
+}
+
+/*
+ return a file handle, but skewed so we don't close the last
+ couple of handles too readily
+*/
+static uint16_t gen_fnum_close(int instance)
+{
+ if (num_open_handles < 5) {
+ if (gen_chance(90)) return BAD_HANDLE;
+ }
+
+ return gen_fnum(instance);
+}
+
+/*
+ generate an integer in a specified range
+*/
+static int gen_int_range(uint64_t min, uint64_t max)
+{
+ uint_t r = random();
+ return min + (r % (1+max-min));
+}
+
+/*
+ return a fnum for use as a root fid
+ be careful to call GEN_SET_FNUM() when you use this!
+*/
+static uint16_t gen_root_fid(int instance)
+{
+ if (gen_chance(5)) return gen_fnum(instance);
+ return 0;
+}
+
+/*
+ generate a file offset
+*/
+static int gen_offset(void)
+{
+ if (gen_chance(20)) return 0;
+// if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
+ return gen_int_range(0, 1024*1024);
+}
+
+/*
+ generate a io count
+*/
+static int gen_io_count(void)
+{
+ if (gen_chance(20)) return 0;
+// if (gen_chance(5)) return gen_int_range(0, 0xFFFFFFFF);
+ return gen_int_range(0, 4096);
+}
+
+/*
+ generate a filename
+*/
+static const char *gen_fname(void)
+{
+ const char *names[] = {"gentest\\gentest.dat",
+ "gentest\\foo",
+ "gentest\\foo2.sym",
+ "gentest\\foo3.dll",
+ "gentest\\foo4",
+ "gentest\\foo4:teststream1",
+ "gentest\\foo4:teststream2",
+ "gentest\\foo5.exe",
+ "gentest\\foo5.exe:teststream3",
+ "gentest\\foo5.exe:teststream4",
+ "gentest\\foo6.com",
+ "gentest\\blah",
+ "gentest\\blah\\blergh.txt",
+ "gentest\\blah\\blergh2",
+ "gentest\\blah\\blergh3.txt",
+ "gentest\\blah\\blergh4",
+ "gentest\\blah\\blergh5.txt",
+ "gentest\\blah\\blergh5",
+ "gentest\\blah\\.",
+#if 0
+ /* this causes problem with w2k3 */
+ "gentest\\blah\\..",
+#endif
+ "gentest\\a_very_long_name.bin",
+ "gentest\\x.y",
+ "gentest\\blah"};
+ int i;
+
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(names)-1);
+ } while (ignore_pattern(names[i]));
+
+ return names[i];
+}
+
+/*
+ generate a filename with a higher chance of choosing an already
+ open file
+*/
+static const char *gen_fname_open(int instance)
+{
+ uint16_t h;
+ h = gen_fnum(instance);
+ if (h == BAD_HANDLE) {
+ return gen_fname();
+ }
+ return open_handles[h].name;
+}
+
+/*
+ generate a wildcard pattern
+*/
+static const char *gen_pattern(void)
+{
+ int i;
+ const char *names[] = {"gentest\\*.dat",
+ "gentest\\*",
+ "gentest\\*.*",
+ "gentest\\blah\\*.*",
+ "gentest\\blah\\*",
+ "gentest\\?"};
+
+ if (gen_chance(50)) return gen_fname();
+
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(names)-1);
+ } while (ignore_pattern(names[i]));
+
+ return names[i];
+}
+
+static uint32_t gen_bits_levels(int nlevels, ...)
+{
+ va_list ap;
+ uint32_t pct;
+ uint32_t mask;
+ int i;
+ va_start(ap, nlevels);
+ for (i=0;i<nlevels;i++) {
+ pct = va_arg(ap, uint32_t);
+ mask = va_arg(ap, uint32_t);
+ if (pct == 100 || gen_chance(pct)) {
+ va_end(ap);
+ return mask & random();
+ }
+ }
+ va_end(ap);
+ return 0;
+}
+
+/*
+ generate a bitmask
+*/
+static uint32_t gen_bits_mask(uint_t mask)
+{
+ uint_t ret = random();
+ return ret & mask;
+}
+
+/*
+ generate a bitmask with high probability of the first mask
+ and low of the second
+*/
+static uint32_t gen_bits_mask2(uint32_t mask1, uint32_t mask2)
+{
+ if (gen_chance(10)) return gen_bits_mask(mask2);
+ return gen_bits_mask(mask1);
+}
+
+/*
+ generate a boolean
+*/
+static bool gen_bool(void)
+{
+ return gen_bits_mask2(0x1, 0xFF);
+}
+
+/*
+ generate ntrename flags
+*/
+static uint16_t gen_rename_flags(void)
+{
+ if (gen_chance(30)) return RENAME_FLAG_RENAME;
+ if (gen_chance(30)) return RENAME_FLAG_HARD_LINK;
+ if (gen_chance(30)) return RENAME_FLAG_COPY;
+ return gen_bits_mask(0xFFFF);
+}
+
+
+/*
+ return a set of lock flags
+*/
+static uint16_t gen_lock_flags(void)
+{
+ if (gen_chance(5)) return gen_bits_mask(0xFFFF);
+ if (gen_chance(20)) return gen_bits_mask(0x1F);
+ if (gen_chance(50)) return SMB2_LOCK_FLAG_UNLOCK;
+ return gen_bits_mask(SMB2_LOCK_FLAG_SHARED |
+ SMB2_LOCK_FLAG_EXCLUSIVE |
+ SMB2_LOCK_FLAG_FAIL_IMMEDIATELY);
+}
+
+/*
+ generate a lock count
+*/
+static off_t gen_lock_count(void)
+{
+ return gen_int_range(0, 3);
+}
+
+/*
+ generate a ntcreatex flags field
+*/
+static uint32_t gen_ntcreatex_flags(void)
+{
+ if (gen_chance(70)) return NTCREATEX_FLAGS_EXTENDED;
+ return gen_bits_mask2(0x1F, 0xFFFFFFFF);
+}
+
+/*
+ generate a NT access mask
+*/
+static uint32_t gen_access_mask(void)
+{
+ if (gen_chance(70)) return SEC_FLAG_MAXIMUM_ALLOWED;
+ if (gen_chance(70)) return SEC_FILE_ALL;
+ return gen_bits_mask(0xFFFFFFFF);
+}
+
+/*
+ generate a ntcreatex create options bitfield
+*/
+static uint32_t gen_create_options(void)
+{
+ if (gen_chance(20)) return gen_bits_mask(0xFFFFFFFF);
+ if (gen_chance(50)) return 0;
+ return gen_bits_mask(NTCREATEX_OPTIONS_DELETE_ON_CLOSE | NTCREATEX_OPTIONS_DIRECTORY);
+}
+
+/*
+ generate a ntcreatex open disposition
+*/
+static uint32_t gen_open_disp(void)
+{
+ if (gen_chance(50)) return NTCREATEX_DISP_OPEN_IF;
+ if (gen_chance(10)) return gen_bits_mask(0xFFFFFFFF);
+ return gen_int_range(0, 5);
+}
+
+/*
+ generate a file attrib combination
+*/
+static uint32_t gen_attrib(void)
+{
+ if (gen_chance(20)) return gen_bits_mask(0xFFFFFFFF);
+ return gen_bits_mask(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY);
+}
+
+/*
+ generate a unix timestamp
+*/
+static time_t gen_timet(void)
+{
+ if (gen_chance(30)) return 0;
+ return (time_t)random();
+}
+
+/*
+ generate a unix timestamp
+*/
+static NTTIME gen_nttime(void)
+{
+ NTTIME ret;
+ unix_to_nt_time(&ret, gen_timet());
+ return ret;
+}
+
+/*
+ generate a milliseconds protocol timeout
+*/
+static uint32_t gen_timeout(void)
+{
+ if (gen_chance(98)) return 0;
+ return random() % 50;
+}
+
+/*
+ generate a file allocation size
+*/
+static uint_t gen_alloc_size(void)
+{
+ uint_t ret;
+
+ if (gen_chance(30)) return 0;
+
+ ret = random() % 4*1024*1024;
+ /* give a high chance of a round number */
+ if (gen_chance(60)) {
+ ret &= ~(1024*1024 - 1);
+ }
+ return ret;
+}
+
+/*
+ generate an ea_struct
+*/
+static struct ea_struct gen_ea_struct(void)
+{
+ struct ea_struct ea;
+ const char *names[] = {"EAONE",
+ "",
+ "FOO!",
+ " WITH SPACES ",
+ ".",
+ "AVERYLONGATTRIBUTENAME"};
+ const char *values[] = {"VALUE1",
+ "",
+ "NOT MUCH FOO",
+ " LEADING SPACES ",
+ ":",
+ "ASOMEWHATLONGERATTRIBUTEVALUE"};
+ int i;
+
+ ZERO_STRUCT(ea);
+
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(names)-1);
+ } while (ignore_pattern(names[i]));
+
+ ea.name.s = names[i];
+
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(values)-1);
+ } while (ignore_pattern(values[i]));
+
+ ea.value = data_blob(values[i], strlen(values[i]));
+
+ if (gen_chance(10)) ea.flags = gen_bits_mask(0xFF);
+ ea.flags = 0;
+
+ return ea;
+}
+
+/*
+ generate an ea_struct
+*/
+static struct smb_ea_list gen_ea_list(void)
+{
+ struct smb_ea_list eas;
+ int i;
+ if (options.no_eas) {
+ ZERO_STRUCT(eas);
+ return eas;
+ }
+ eas.num_eas = gen_int_range(0, 3);
+ eas.eas = talloc_array(current_op.mem_ctx, struct ea_struct, eas.num_eas);
+ for (i=0;i<eas.num_eas;i++) {
+ eas.eas[i] = gen_ea_struct();
+ }
+ return eas;
+}
+
+/*
+ the idle function tries to cope with getting an oplock break on a connection, and
+ an operation on another connection blocking until that break is acked
+ we check for operations on all transports in the idle function
+*/
+static void idle_func(struct smb2_transport *transport, void *private)
+{
+ int i, j;
+ for (i=0;i<NSERVERS;i++) {
+ for (j=0;j<NINSTANCES;j++) {
+ if (servers[i].tree[j] &&
+ transport != servers[i].tree[j]->session->transport) {
+ // smb2_transport_process(servers[i].tree[j]->session->transport);
+ }
+ }
+ }
+
+}
+
+
+/*
+ compare NTSTATUS, using checking ignored patterns
+*/
+static bool compare_status(NTSTATUS status1, NTSTATUS status2)
+{
+ if (NT_STATUS_EQUAL(status1, status2)) return true;
+
+ /* one code being an error and the other OK is always an error */
+ if (NT_STATUS_IS_OK(status1) || NT_STATUS_IS_OK(status2)) return false;
+
+ /* if we are ignoring one of the status codes then consider this a match */
+ if (ignore_pattern(nt_errstr(status1)) ||
+ ignore_pattern(nt_errstr(status2))) {
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ check for pending packets on all connections
+*/
+static void check_pending(void)
+{
+ int i, j;
+
+ msleep(20);
+
+ for (j=0;j<NINSTANCES;j++) {
+ for (i=0;i<NSERVERS;i++) {
+ // smb2_transport_process(servers[i].tree[j]->session->transport);
+ }
+ }
+}
+
+/*
+ check that the same oplock breaks have been received by all instances
+*/
+static bool check_oplocks(const char *call)
+{
+#if 0
+ int i, j;
+ int tries = 0;
+
+again:
+ check_pending();
+
+ for (j=0;j<NINSTANCES;j++) {
+ for (i=1;i<NSERVERS;i++) {
+ if (oplocks[0][j].got_break != oplocks[i][j].got_break ||
+ oplocks[0][j].handle != oplocks[i][j].handle ||
+ oplocks[0][j].level != oplocks[i][j].level) {
+ if (tries++ < 10) goto again;
+ printf("oplock break inconsistent - %d/%d/%d vs %d/%d/%d\n",
+ oplocks[0][j].got_break,
+ oplocks[0][j].handle,
+ oplocks[0][j].level,
+ oplocks[i][j].got_break,
+ oplocks[i][j].handle,
+ oplocks[i][j].level);
+ return false;
+ }
+ }
+ }
+
+ /* if we got a break and closed then remove the handle */
+ for (j=0;j<NINSTANCES;j++) {
+ if (oplocks[0][j].got_break &&
+ oplocks[0][j].do_close) {
+ uint16_t fnums[NSERVERS];
+ for (i=0;i<NSERVERS;i++) {
+ fnums[i] = oplocks[i][j].fnum;
+ }
+ gen_remove_handle(j, fnums);
+ break;
+ }
+ }
+#endif
+ return true;
+}
+
+
+/*
+ check that the same change notify info has been received by all instances
+*/
+static bool check_notifies(const char *call)
+{
+#if 0
+ int i, j;
+ int tries = 0;
+
+again:
+ check_pending();
+
+ for (j=0;j<NINSTANCES;j++) {
+ for (i=1;i<NSERVERS;i++) {
+ int n;
+ union smb_notify not1, not2;
+
+ if (notifies[0][j].notify_count != notifies[i][j].notify_count) {
+ if (tries++ < 10) goto again;
+ printf("Notify count inconsistent %d %d\n",
+ notifies[0][j].notify_count,
+ notifies[i][j].notify_count);
+ return false;
+ }
+
+ if (notifies[0][j].notify_count == 0) continue;
+
+ if (!NT_STATUS_EQUAL(notifies[0][j].status,
+ notifies[i][j].status)) {
+ printf("Notify status mismatch - %s - %s\n",
+ nt_errstr(notifies[0][j].status),
+ nt_errstr(notifies[i][j].status));
+ return false;
+ }
+
+ if (!NT_STATUS_IS_OK(notifies[0][j].status)) {
+ continue;
+ }
+
+ not1 = notifies[0][j].notify;
+ not2 = notifies[i][j].notify;
+
+ for (n=0;n<not1.nttrans.out.num_changes;n++) {
+ if (not1.nttrans.out.changes[n].action !=
+ not2.nttrans.out.changes[n].action) {
+ printf("Notify action %d inconsistent %d %d\n", n,
+ not1.nttrans.out.changes[n].action,
+ not2.nttrans.out.changes[n].action);
+ return false;
+ }
+ if (strcmp(not1.nttrans.out.changes[n].name.s,
+ not2.nttrans.out.changes[n].name.s)) {
+ printf("Notify name %d inconsistent %s %s\n", n,
+ not1.nttrans.out.changes[n].name.s,
+ not2.nttrans.out.changes[n].name.s);
+ return false;
+ }
+ if (not1.nttrans.out.changes[n].name.private_length !=
+ not2.nttrans.out.changes[n].name.private_length) {
+ printf("Notify name length %d inconsistent %d %d\n", n,
+ not1.nttrans.out.changes[n].name.private_length,
+ not2.nttrans.out.changes[n].name.private_length);
+ return false;
+ }
+ }
+ }
+ }
+
+ ZERO_STRUCT(notifies);
+
+#endif
+ return true;
+}
+
+#define GEN_COPY_PARM do { \
+ int i; \
+ for (i=1;i<NSERVERS;i++) { \
+ parm[i] = parm[0]; \
+ } \
+} while (0)
+
+#define GEN_CALL(call) do { \
+ int i; \
+ ZERO_STRUCT(oplocks); \
+ ZERO_STRUCT(notifies); \
+ for (i=0;i<NSERVERS;i++) { \
+ struct smb2_tree *tree = servers[i].tree[instance]; \
+ status[i] = call; \
+ } \
+ current_op.status = status[0]; \
+ for (i=1;i<NSERVERS;i++) { \
+ if (!compare_status(status[i], status[0])) { \
+ printf("status different in %s - %s %s\n", #call, \
+ nt_errstr(status[0]), nt_errstr(status[i])); \
+ return false; \
+ } \
+ } \
+ if (!check_oplocks(#call)) return false; \
+ if (!check_notifies(#call)) return false; \
+ if (!NT_STATUS_IS_OK(status[0])) { \
+ return true; \
+ } \
+} while(0)
+
+#define ADD_HANDLE(name, field) do { \
+ struct smb2_handle handles[NSERVERS]; \
+ int i; \
+ for (i=0;i<NSERVERS;i++) { \
+ handles[i] = parm[i].field; \
+ } \
+ gen_add_handle(instance, name, handles); \
+} while(0)
+
+#define REMOVE_HANDLE(field) do { \
+ struct smb2_handle handles[NSERVERS]; \
+ int i; \
+ for (i=0;i<NSERVERS;i++) { \
+ handles[i] = parm[i].field; \
+ } \
+ gen_remove_handle(instance, handles); \
+} while(0)
+
+#define GEN_SET_FNUM(field) do { \
+ int i; \
+ for (i=0;i<NSERVERS;i++) { \
+ parm[i].field = gen_lookup_handle(i, parm[i].field.data[0]); \
+ } \
+} while(0)
+
+#define CHECK_EQUAL(field) do { \
+ if (parm[0].field != parm[1].field && !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - 0x%llx 0x%llx\n", #field, \
+ (unsigned long long)parm[0].field, (unsigned long long)parm[1].field); \
+ return false; \
+ } \
+} while(0)
+
+#define CHECK_ATTRIB(field) do { \
+ if (!options.mask_indexing) { \
+ CHECK_EQUAL(field); \
+ } else if ((~FILE_ATTRIBUTE_NONINDEXED & parm[0].field) != (~FILE_ATTRIBUTE_NONINDEXED & parm[1].field) && !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
+ (int)parm[0].field, (int)parm[1].field); \
+ return false; \
+ } \
+} while(0)
+
+#define CHECK_WSTR_EQUAL(field) do { \
+ if ((!parm[0].field.s && parm[1].field.s) || (parm[0].field.s && !parm[1].field.s)) { \
+ printf("%s is NULL!\n", #field); \
+ return false; \
+ } \
+ if (parm[0].field.s && strcmp(parm[0].field.s, parm[1].field.s) != 0 && !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - %s %s\n", #field, \
+ parm[0].field.s, parm[1].field.s); \
+ return false; \
+ } \
+ CHECK_EQUAL(field.private_length); \
+} while(0)
+
+#define CHECK_BLOB_EQUAL(field) do { \
+ if (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0 && !ignore_pattern(#field)) { \
+ printf("Mismatch in %s\n", #field); \
+ return false; \
+ } \
+ CHECK_EQUAL(field.length); \
+} while(0)
+
+#define CHECK_TIMES_EQUAL(field) do { \
+ if (labs(parm[0].field - parm[1].field) > time_skew() && \
+ !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
+ (int)parm[0].field, (int)parm[1].field); \
+ return false; \
+ } \
+} while(0)
+
+#define CHECK_NTTIMES_EQUAL(field) do { \
+ if (labs(nt_time_to_unix(parm[0].field) - \
+ nt_time_to_unix(parm[1].field)) > time_skew() && \
+ !ignore_pattern(#field)) { \
+ printf("Mismatch in %s - 0x%x 0x%x\n", #field, \
+ (int)nt_time_to_unix(parm[0].field), \
+ (int)nt_time_to_unix(parm[1].field)); \
+ return false; \
+ } \
+} while(0)
+
+/*
+ generate ntcreatex operations
+*/
+static bool handler_create(int instance)
+{
+ struct smb2_create parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ ZERO_STRUCT(parm[0]);
+ parm[0].in.security_flags = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFF);
+ parm[0].in.oplock_level = gen_bits_levels(3, 90, 0x0, 70, 0x9, 100, 0xFF);
+ parm[0].in.impersonation_level = gen_bits_levels(3, 90, 0x0, 70, 0x3, 100, 0xFFFFFFFF);
+ parm[0].in.create_flags = gen_bits_levels(2, 90, 0x0, 100, 0xFFFFFFFF);
+ if (gen_chance(2)) {
+ parm[0].in.create_flags |= gen_bits_mask(0xFFFFFFFF);
+ }
+ parm[0].in.reserved = gen_bits_levels(2, 95, 0x0, 100, 0xFFFFFFFF);
+ if (gen_chance(2)) {
+ parm[0].in.reserved |= gen_bits_mask(0xFFFFFFFF);
+ }
+ parm[0].in.desired_access = gen_access_mask();
+ parm[0].in.file_attributes = gen_attrib();
+ parm[0].in.share_access = gen_bits_mask2(0x7, 0xFFFFFFFF);
+ parm[0].in.create_disposition = gen_open_disp();
+ parm[0].in.create_options = gen_create_options();
+ parm[0].in.fname = gen_fname_open(instance);
+ parm[0].in.eas = gen_ea_list();
+
+ if (!options.use_oplocks) {
+ /* mask out oplocks */
+ parm[0].in.oplock_level = 0;
+ }
+
+ GEN_COPY_PARM;
+ GEN_CALL(smb2_create(tree, current_op.mem_ctx, &parm[i]));
+
+ CHECK_EQUAL(out.oplock_level);
+ CHECK_EQUAL(out.reserved);
+ CHECK_EQUAL(out.create_action);
+ CHECK_NTTIMES_EQUAL(out.create_time);
+ CHECK_NTTIMES_EQUAL(out.access_time);
+ CHECK_NTTIMES_EQUAL(out.write_time);
+ CHECK_NTTIMES_EQUAL(out.change_time);
+ CHECK_EQUAL(out.alloc_size);
+ CHECK_EQUAL(out.size);
+ CHECK_ATTRIB(out.file_attr);
+ CHECK_EQUAL(out.reserved2);
+
+ /* ntcreatex creates a new file handle */
+ ADD_HANDLE(parm[0].in.fname, out.file.handle);
+
+ return true;
+}
+
+/*
+ generate close operations
+*/
+static bool handler_close(int instance)
+{
+ struct smb2_close parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ ZERO_STRUCT(parm[0]);
+ parm[0].in.file.handle.data[0] = gen_fnum_close(instance);
+ parm[0].in.flags = gen_bits_mask2(0x1, 0xFFFF);
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(in.file.handle);
+ GEN_CALL(smb2_close(tree, &parm[i]));
+
+ CHECK_EQUAL(out.flags);
+ CHECK_EQUAL(out._pad);
+ CHECK_NTTIMES_EQUAL(out.create_time);
+ CHECK_NTTIMES_EQUAL(out.access_time);
+ CHECK_NTTIMES_EQUAL(out.write_time);
+ CHECK_NTTIMES_EQUAL(out.change_time);
+ CHECK_EQUAL(out.alloc_size);
+ CHECK_EQUAL(out.size);
+ CHECK_ATTRIB(out.file_attr);
+
+ REMOVE_HANDLE(in.file.handle);
+
+ return true;
+}
+
+/*
+ generate read operations
+*/
+static bool handler_read(int instance)
+{
+ struct smb2_read parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ parm[0].in.file.handle.data[0] = gen_fnum(instance);
+ parm[0].in.reserved = gen_bits_mask2(0x0, 0xFF);
+ parm[0].in.length = gen_io_count();
+ parm[0].in.offset = gen_offset();
+ parm[0].in.min_count = gen_io_count();
+ parm[0].in.channel = gen_bits_mask2(0x0, 0xFFFFFFFF);
+ parm[0].in.remaining = gen_bits_mask2(0x0, 0xFFFFFFFF);
+ parm[0].in.channel_offset = gen_bits_mask2(0x0, 0xFFFF);
+ parm[0].in.channel_length = gen_bits_mask2(0x0, 0xFFFF);
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(in.file.handle);
+ GEN_CALL(smb2_read(tree, current_op.mem_ctx, &parm[i]));
+
+ CHECK_EQUAL(out.remaining);
+ CHECK_EQUAL(out.reserved);
+ CHECK_EQUAL(out.data.length);
+
+ return true;
+}
+
+/*
+ generate write operations
+*/
+static bool handler_write(int instance)
+{
+ struct smb2_write parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ parm[0].in.file.handle.data[0] = gen_fnum(instance);
+ parm[0].in.offset = gen_offset();
+ parm[0].in.unknown1 = gen_bits_mask2(0, 0xFFFFFFFF);
+ parm[0].in.unknown2 = gen_bits_mask2(0, 0xFFFFFFFF);
+ parm[0].in.data = data_blob_talloc(current_op.mem_ctx, NULL,
+ gen_io_count());
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(in.file.handle);
+ GEN_CALL(smb2_write(tree, &parm[i]));
+
+ CHECK_EQUAL(out._pad);
+ CHECK_EQUAL(out.nwritten);
+ CHECK_EQUAL(out.unknown1);
+
+ return true;
+}
+
+/*
+ generate lockingx operations
+*/
+static bool handler_lock(int instance)
+{
+ struct smb2_lock parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+ int n;
+
+ parm[0].level = RAW_LOCK_LOCKX;
+ parm[0].in.file.handle.data[0] = gen_fnum(instance);
+ parm[0].in.lock_count = gen_lock_count();
+ parm[0].in.reserved = gen_bits_mask2(0, 0xFFFFFFFF);
+
+ parm[0].in.locks = talloc_array(current_op.mem_ctx,
+ struct smb2_lock_element,
+ parm[0].in.lock_count);
+ for (n=0;n<parm[0].in.lock_count;n++) {
+ parm[0].in.locks[n].offset = gen_offset();
+ parm[0].in.locks[n].length = gen_io_count();
+ /* don't yet cope with async replies */
+ parm[0].in.locks[n].flags = gen_lock_flags() |
+ SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+ parm[0].in.locks[n].reserved = gen_bits_mask2(0x0, 0xFFFFFFFF);
+ }
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(in.file.handle);
+ GEN_CALL(smb2_lock(tree, &parm[i]));
+
+ return true;
+}
+
+/*
+ generate flush operations
+*/
+static bool handler_flush(int instance)
+{
+ struct smb2_flush parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ ZERO_STRUCT(parm[0]);
+ parm[0].in.file.handle.data[0] = gen_fnum(instance);
+ parm[0].in.reserved1 = gen_bits_mask2(0x0, 0xFFFF);
+ parm[0].in.reserved2 = gen_bits_mask2(0x0, 0xFFFFFFFF);
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(in.file.handle);
+ GEN_CALL(smb2_flush(tree, &parm[i]));
+
+ CHECK_EQUAL(out.reserved);
+
+ return true;
+}
+
+/*
+ generate echo operations
+*/
+static bool handler_echo(int instance)
+{
+ NTSTATUS status[NSERVERS];
+
+ GEN_CALL(smb2_keepalive(tree->session->transport));
+
+ return true;
+}
+
+
+
+/*
+ generate a fileinfo query structure
+*/
+static void gen_fileinfo(int instance, union smb_fileinfo *info)
+{
+ int i;
+ #define LVL(v) {RAW_FILEINFO_ ## v, "RAW_FILEINFO_" #v}
+ struct {
+ enum smb_fileinfo_level level;
+ const char *name;
+ } levels[] = {
+ LVL(BASIC_INFORMATION),
+ LVL(STANDARD_INFORMATION), LVL(INTERNAL_INFORMATION), LVL(EA_INFORMATION),
+ LVL(ACCESS_INFORMATION), LVL(NAME_INFORMATION), LVL(POSITION_INFORMATION),
+ LVL(MODE_INFORMATION), LVL(ALIGNMENT_INFORMATION), LVL(SMB2_ALL_INFORMATION),
+ LVL(ALT_NAME_INFORMATION), LVL(STREAM_INFORMATION), LVL(COMPRESSION_INFORMATION),
+ LVL(NETWORK_OPEN_INFORMATION), LVL(ATTRIBUTE_TAG_INFORMATION),
+ LVL(SMB2_ALL_EAS), LVL(SMB2_ALL_INFORMATION),
+ };
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(levels)-1);
+ } while (ignore_pattern(levels[i].name));
+
+ info->generic.level = levels[i].level;
+}
+
+/*
+ compare returned fileinfo structures
+*/
+static bool cmp_fileinfo(int instance,
+ union smb_fileinfo parm[NSERVERS],
+ NTSTATUS status[NSERVERS])
+{
+ int i;
+
+ switch (parm[0].generic.level) {
+ case RAW_FILEINFO_GENERIC:
+ return false;
+
+ case RAW_FILEINFO_BASIC_INFORMATION:
+ CHECK_NTTIMES_EQUAL(basic_info.out.create_time);
+ CHECK_NTTIMES_EQUAL(basic_info.out.access_time);
+ CHECK_NTTIMES_EQUAL(basic_info.out.write_time);
+ CHECK_NTTIMES_EQUAL(basic_info.out.change_time);
+ CHECK_ATTRIB(basic_info.out.attrib);
+ break;
+
+ case RAW_FILEINFO_STANDARD_INFORMATION:
+ CHECK_EQUAL(standard_info.out.alloc_size);
+ CHECK_EQUAL(standard_info.out.size);
+ CHECK_EQUAL(standard_info.out.nlink);
+ CHECK_EQUAL(standard_info.out.delete_pending);
+ CHECK_EQUAL(standard_info.out.directory);
+ break;
+
+ case RAW_FILEINFO_EA_INFORMATION:
+ CHECK_EQUAL(ea_info.out.ea_size);
+ break;
+
+ case RAW_FILEINFO_NAME_INFORMATION:
+ CHECK_WSTR_EQUAL(name_info.out.fname);
+ break;
+
+ case RAW_FILEINFO_ALT_NAME_INFORMATION:
+ CHECK_WSTR_EQUAL(alt_name_info.out.fname);
+ break;
+
+ case RAW_FILEINFO_STREAM_INFORMATION:
+ CHECK_EQUAL(stream_info.out.num_streams);
+ for (i=0;i<parm[0].stream_info.out.num_streams;i++) {
+ CHECK_EQUAL(stream_info.out.streams[i].size);
+ CHECK_EQUAL(stream_info.out.streams[i].alloc_size);
+ CHECK_WSTR_EQUAL(stream_info.out.streams[i].stream_name);
+ }
+ break;
+
+ case RAW_FILEINFO_COMPRESSION_INFORMATION:
+ CHECK_EQUAL(compression_info.out.compressed_size);
+ CHECK_EQUAL(compression_info.out.format);
+ CHECK_EQUAL(compression_info.out.unit_shift);
+ CHECK_EQUAL(compression_info.out.chunk_shift);
+ CHECK_EQUAL(compression_info.out.cluster_shift);
+ break;
+
+ case RAW_FILEINFO_INTERNAL_INFORMATION:
+ CHECK_EQUAL(internal_information.out.file_id);
+ break;
+
+ case RAW_FILEINFO_ACCESS_INFORMATION:
+ CHECK_EQUAL(access_information.out.access_flags);
+ break;
+
+ case RAW_FILEINFO_POSITION_INFORMATION:
+ CHECK_EQUAL(position_information.out.position);
+ break;
+
+ case RAW_FILEINFO_MODE_INFORMATION:
+ CHECK_EQUAL(mode_information.out.mode);
+ break;
+
+ case RAW_FILEINFO_ALIGNMENT_INFORMATION:
+ CHECK_EQUAL(alignment_information.out.alignment_requirement);
+ break;
+
+ case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
+ CHECK_NTTIMES_EQUAL(network_open_information.out.create_time);
+ CHECK_NTTIMES_EQUAL(network_open_information.out.access_time);
+ CHECK_NTTIMES_EQUAL(network_open_information.out.write_time);
+ CHECK_NTTIMES_EQUAL(network_open_information.out.change_time);
+ CHECK_EQUAL(network_open_information.out.alloc_size);
+ CHECK_EQUAL(network_open_information.out.size);
+ CHECK_ATTRIB(network_open_information.out.attrib);
+ break;
+
+ case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
+ CHECK_ATTRIB(attribute_tag_information.out.attrib);
+ CHECK_EQUAL(attribute_tag_information.out.reparse_tag);
+ break;
+
+ case RAW_FILEINFO_ALL_INFORMATION:
+ case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+ CHECK_NTTIMES_EQUAL(all_info2.out.create_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.access_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.write_time);
+ CHECK_NTTIMES_EQUAL(all_info2.out.change_time);
+ CHECK_ATTRIB(all_info2.out.attrib);
+ CHECK_EQUAL(all_info2.out.unknown1);
+ CHECK_EQUAL(all_info2.out.alloc_size);
+ CHECK_EQUAL(all_info2.out.size);
+ CHECK_EQUAL(all_info2.out.nlink);
+ CHECK_EQUAL(all_info2.out.delete_pending);
+ CHECK_EQUAL(all_info2.out.directory);
+ CHECK_EQUAL(all_info2.out.file_id);
+ CHECK_EQUAL(all_info2.out.ea_size);
+ CHECK_EQUAL(all_info2.out.access_mask);
+ CHECK_EQUAL(all_info2.out.position);
+ CHECK_EQUAL(all_info2.out.mode);
+ CHECK_EQUAL(all_info2.out.alignment_requirement);
+ CHECK_WSTR_EQUAL(all_info2.out.fname);
+ break;
+
+ case RAW_FILEINFO_SMB2_ALL_EAS:
+ CHECK_EQUAL(all_eas.out.num_eas);
+ for (i=0;i<parm[0].all_eas.out.num_eas;i++) {
+ CHECK_EQUAL(all_eas.out.eas[i].flags);
+ CHECK_WSTR_EQUAL(all_eas.out.eas[i].name);
+ CHECK_BLOB_EQUAL(all_eas.out.eas[i].value);
+ }
+ break;
+
+ /* Unhandled levels */
+
+ case RAW_FILEINFO_SEC_DESC:
+ case RAW_FILEINFO_EA_LIST:
+ case RAW_FILEINFO_UNIX_BASIC:
+ case RAW_FILEINFO_UNIX_LINK:
+ case RAW_FILEINFO_UNIX_INFO2:
+ break;
+ }
+
+ return true;
+}
+
+/*
+ generate qfileinfo operations
+*/
+static bool handler_qfileinfo(int instance)
+{
+ union smb_fileinfo parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ parm[0].generic.in.file.handle.data[0] = gen_fnum(instance);
+
+ gen_fileinfo(instance, &parm[0]);
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(generic.in.file.handle);
+ GEN_CALL(smb2_getinfo_file(tree, current_op.mem_ctx, &parm[i]));
+
+ return cmp_fileinfo(instance, parm, status);
+}
+
+
+/*
+ generate a fileinfo query structure
+*/
+static void gen_setfileinfo(int instance, union smb_setfileinfo *info)
+{
+ int i;
+ #undef LVL
+ #define LVL(v) {RAW_SFILEINFO_ ## v, "RAW_SFILEINFO_" #v}
+ struct {
+ enum smb_setfileinfo_level level;
+ const char *name;
+ } levels[] = {
+ LVL(BASIC_INFORMATION),
+ LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION),
+ LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION),
+ LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION),
+ LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040)
+ };
+ do {
+ i = gen_int_range(0, ARRAY_SIZE(levels)-1);
+ } while (ignore_pattern(levels[i].name));
+
+ info->generic.level = levels[i].level;
+
+ switch (info->generic.level) {
+ case RAW_SFILEINFO_BASIC_INFORMATION:
+ info->basic_info.in.create_time = gen_nttime();
+ info->basic_info.in.access_time = gen_nttime();
+ info->basic_info.in.write_time = gen_nttime();
+ info->basic_info.in.change_time = gen_nttime();
+ info->basic_info.in.attrib = gen_attrib();
+ break;
+ case RAW_SFILEINFO_DISPOSITION_INFORMATION:
+ info->disposition_info.in.delete_on_close = gen_bool();
+ break;
+ case RAW_SFILEINFO_ALLOCATION_INFORMATION:
+ info->allocation_info.in.alloc_size = gen_alloc_size();
+ break;
+ case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
+ info->end_of_file_info.in.size = gen_offset();
+ break;
+ case RAW_SFILEINFO_RENAME_INFORMATION:
+ case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
+ info->rename_information.in.overwrite = gen_bool();
+ info->rename_information.in.root_fid = gen_root_fid(instance);
+ info->rename_information.in.new_name = gen_fname_open(instance);
+ break;
+ case RAW_SFILEINFO_POSITION_INFORMATION:
+ info->position_information.in.position = gen_offset();
+ break;
+ case RAW_SFILEINFO_MODE_INFORMATION:
+ info->mode_information.in.mode = gen_bits_mask(0xFFFFFFFF);
+ break;
+ case RAW_SFILEINFO_GENERIC:
+ case RAW_SFILEINFO_SEC_DESC:
+ case RAW_SFILEINFO_1023:
+ case RAW_SFILEINFO_1025:
+ case RAW_SFILEINFO_1029:
+ case RAW_SFILEINFO_1032:
+ case RAW_SFILEINFO_1039:
+ case RAW_SFILEINFO_1040:
+ /* Untested */
+ break;
+ }
+}
+
+/*
+ generate setfileinfo operations
+*/
+static bool handler_sfileinfo(int instance)
+{
+ union smb_setfileinfo parm[NSERVERS];
+ NTSTATUS status[NSERVERS];
+
+ parm[0].generic.in.file.fnum = gen_fnum(instance);
+
+ gen_setfileinfo(instance, &parm[0]);
+
+ GEN_COPY_PARM;
+ GEN_SET_FNUM(generic.in.file.handle);
+ GEN_CALL(smb2_setinfo_file(tree, &parm[i]));
+
+ return true;
+}
+
+/*
+ wipe any relevant files
+*/
+static void wipe_files(void)
+{
+ int i;
+ NTSTATUS status;
+
+ for (i=0;i<NSERVERS;i++) {
+ int n = smb2_deltree(servers[i].tree[0], "gentest");
+ if (n == -1) {
+ printf("Failed to wipe tree on server %d\n", i);
+ exit(1);
+ }
+ status = smb2_util_mkdir(servers[i].tree[0], "gentest");
+ if (NT_STATUS_IS_ERR(status)) {
+ printf("Failed to create gentest on server %d - %s\n", i, nt_errstr(status));
+ exit(1);
+ }
+ if (n > 0) {
+ printf("Deleted %d files on server %d\n", n, i);
+ }
+ }
+}
+
+/*
+ dump the current seeds - useful for continuing a backtrack
+*/
+static void dump_seeds(void)
+{
+ int i;
+ FILE *f;
+
+ if (!options.seeds_file) {
+ return;
+ }
+ f = fopen("seeds.tmp", "w");
+ if (!f) return;
+
+ for (i=0;i<options.numops;i++) {
+ fprintf(f, "%u\n", op_parms[i].seed);
+ }
+ fclose(f);
+ rename("seeds.tmp", options.seeds_file);
+}
+
+
+
+/*
+ the list of top-level operations that we will generate
+*/
+static struct {
+ const char *name;
+ bool (*handler)(int instance);
+ int count, success_count;
+} gen_ops[] = {
+ {"CREATE", handler_create},
+ {"CLOSE", handler_close},
+ {"READ", handler_read},
+ {"WRITE", handler_write},
+ {"LOCK", handler_lock},
+ {"FLUSH", handler_flush},
+ {"ECHO", handler_echo},
+ {"QFILEINFO", handler_qfileinfo},
+ {"SFILEINFO", handler_sfileinfo},
+};
+
+
+/*
+ run the test with the current set of op_parms parameters
+ return the number of operations that completed successfully
+*/
+static int run_test(struct event_context *ev, struct loadparm_context *lp_ctx)
+{
+ int op, i;
+
+ if (!connect_servers(ev, lp_ctx)) {
+ printf("Failed to connect to servers\n");
+ exit(1);
+ }
+
+ dump_seeds();
+
+ /* wipe any leftover files from old runs */
+ wipe_files();
+
+ /* reset the open handles array */
+ memset(open_handles, 0, options.max_open_handles * sizeof(open_handles[0]));
+ num_open_handles = 0;
+
+ for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
+ gen_ops[i].count = 0;
+ gen_ops[i].success_count = 0;
+ }
+
+ for (op=0; op<options.numops; op++) {
+ int instance, which_op;
+ bool ret;
+
+ if (op_parms[op].disabled) continue;
+
+ srandom(op_parms[op].seed);
+
+ instance = gen_int_range(0, NINSTANCES-1);
+
+ /* generate a non-ignored operation */
+ do {
+ which_op = gen_int_range(0, ARRAY_SIZE(gen_ops)-1);
+ } while (ignore_pattern(gen_ops[which_op].name));
+
+ DEBUG(3,("Generating op %s on instance %d\n",
+ gen_ops[which_op].name, instance));
+
+ current_op.seed = op_parms[op].seed;
+ current_op.opnum = op;
+ current_op.name = gen_ops[which_op].name;
+ current_op.status = NT_STATUS_OK;
+ current_op.mem_ctx = talloc_named(NULL, 0, "%s", current_op.name);
+
+ ret = gen_ops[which_op].handler(instance);
+
+ talloc_free(current_op.mem_ctx);
+
+ gen_ops[which_op].count++;
+ if (NT_STATUS_IS_OK(current_op.status)) {
+ gen_ops[which_op].success_count++;
+ }
+
+ if (!ret) {
+ printf("Failed at operation %d - %s\n",
+ op, gen_ops[which_op].name);
+ return op;
+ }
+
+ if (op % 100 == 0) {
+ printf("%d\n", op);
+ }
+ }
+
+ for (i=0;i<ARRAY_SIZE(gen_ops);i++) {
+ printf("Op %-10s got %d/%d success\n",
+ gen_ops[i].name,
+ gen_ops[i].success_count,
+ gen_ops[i].count);
+ }
+
+ return op;
+}
+
+/*
+ perform a backtracking analysis of the minimal set of operations
+ to generate an error
+*/
+static void backtrack_analyze(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
+{
+ int chunk, ret;
+
+ chunk = options.numops / 2;
+
+ do {
+ int base;
+ for (base=0;
+ chunk > 0 && base+chunk < options.numops && options.numops > 1; ) {
+ int i, max;
+
+ chunk = MIN(chunk, options.numops / 2);
+
+ /* mark this range as disabled */
+ max = MIN(options.numops, base+chunk);
+ for (i=base;i<max; i++) {
+ op_parms[i].disabled = true;
+ }
+ printf("Testing %d ops with %d-%d disabled\n",
+ options.numops, base, max-1);
+ ret = run_test(ev, lp_ctx);
+ printf("Completed %d of %d ops\n", ret, options.numops);
+ for (i=base;i<max; i++) {
+ op_parms[i].disabled = false;
+ }
+ if (ret == options.numops) {
+ /* this chunk is needed */
+ base += chunk;
+ } else if (ret < base) {
+ printf("damn - inconsistent errors! found early error\n");
+ options.numops = ret+1;
+ base = 0;
+ } else {
+ /* it failed - this chunk isn't needed for a failure */
+ memmove(&op_parms[base], &op_parms[max],
+ sizeof(op_parms[0]) * (options.numops - max));
+ options.numops = (ret+1) - (max - base);
+ }
+ }
+
+ if (chunk == 2) {
+ chunk = 1;
+ } else {
+ chunk *= 0.4;
+ }
+
+ if (options.analyze_continuous && chunk == 0 && options.numops != 1) {
+ chunk = 1;
+ }
+ } while (chunk > 0);
+
+ printf("Reduced to %d ops\n", options.numops);
+ ret = run_test(ev, lp_ctx);
+ if (ret != options.numops - 1) {
+ printf("Inconsistent result? ret=%d numops=%d\n", ret, options.numops);
+ }
+}
+
+/*
+ start the main gentest process
+*/
+static bool start_gentest(struct event_context *ev,
+ struct loadparm_context *lp_ctx)
+{
+ int op;
+ int ret;
+
+ /* allocate the open_handles array */
+ open_handles = calloc(options.max_open_handles, sizeof(open_handles[0]));
+
+ srandom(options.seed);
+ op_parms = calloc(options.numops, sizeof(op_parms[0]));
+
+ /* generate the seeds - after this everything is deterministic */
+ if (options.use_preset_seeds) {
+ int numops;
+ char **preset = file_lines_load(options.seeds_file, &numops, NULL);
+ if (!preset) {
+ printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno));
+ exit(1);
+ }
+ if (numops < options.numops) {
+ options.numops = numops;
+ }
+ for (op=0;op<options.numops;op++) {
+ if (!preset[op]) {
+ printf("Not enough seeds in %s\n", options.seeds_file);
+ exit(1);
+ }
+ op_parms[op].seed = atoi(preset[op]);
+ }
+ printf("Loaded %d seeds from %s\n", options.numops, options.seeds_file);
+ } else {
+ for (op=0; op<options.numops; op++) {
+ op_parms[op].seed = random();
+ }
+ }
+
+ ret = run_test(ev, lp_ctx);
+
+ if (ret != options.numops && options.analyze) {
+ options.numops = ret+1;
+ backtrack_analyze(ev, lp_ctx);
+ } else if (options.analyze_always) {
+ backtrack_analyze(ev, lp_ctx);
+ } else if (options.analyze_continuous) {
+ while (run_test(ev, lp_ctx) == options.numops) ;
+ }
+
+ return ret == options.numops;
+}
+
+
+static void usage(poptContext pc)
+{
+ printf(
+"Usage:\n\
+ gentest //server1/share1 //server2/share2 [options..]\n\
+");
+ poptPrintUsage(pc, stdout, 0);
+}
+
+/**
+ split a UNC name into server and share names
+*/
+static bool split_unc_name(const char *unc, char **server, char **share)
+{
+ char *p = strdup(unc);
+ if (!p) return false;
+ all_string_sub(p, "\\", "/", 0);
+ if (strncmp(p, "//", 2) != 0) return false;
+
+ (*server) = p+2;
+ p = strchr(*server, '/');
+ if (!p) return false;
+
+ *p = 0;
+ (*share) = p+1;
+
+ return true;
+}
+
+
+
+/****************************************************************************
+ main program
+****************************************************************************/
+ int main(int argc, char *argv[])
+{
+ int opt;
+ int i, username_count=0;
+ bool ret;
+ char *ignore_file=NULL;
+ struct event_context *ev;
+ struct loadparm_context *lp_ctx;
+ poptContext pc;
+ int argc_new;
+ char **argv_new;
+ enum {OPT_UNCLIST=1000};
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"seed", 0, POPT_ARG_INT, &options.seed, 0, "Seed to use for randomizer", NULL},
+ {"num-ops", 0, POPT_ARG_INT, &options.numops, 0, "num ops", NULL},
+ {"oplocks", 0, POPT_ARG_NONE, &options.use_oplocks,0, "use oplocks", NULL},
+ {"showall", 0, POPT_ARG_NONE, &options.showall, 0, "display all operations", NULL},
+ {"analyse", 0, POPT_ARG_NONE, &options.analyze, 0, "do backtrack analysis", NULL},
+ {"analysealways", 0, POPT_ARG_NONE, &options.analyze_always, 0, "analysis always", NULL},
+ {"analysecontinuous", 0, POPT_ARG_NONE, &options.analyze_continuous, 0, "analysis continuous", NULL},
+ {"ignore", 0, POPT_ARG_STRING, &ignore_file, 0, "ignore from file", NULL},
+ {"preset", 0, POPT_ARG_NONE, &options.use_preset_seeds, 0, "use preset seeds", NULL},
+ {"fast", 0, POPT_ARG_NONE, &options.fast_reconnect, 0, "use fast reconnect", NULL},
+ {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
+ {"seedsfile", 0, POPT_ARG_STRING, &options.seeds_file, 0, "seed file", NULL},
+ { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" },
+ {"maskindexing", 0, POPT_ARG_NONE, &options.mask_indexing, 0, "mask out the indexed file attrib", NULL},
+ {"noeas", 0, POPT_ARG_NONE, &options.no_eas, 0, "don't use extended attributes", NULL},
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CONNECTION
+ POPT_COMMON_CREDENTIALS
+ POPT_COMMON_VERSION
+ { NULL }
+ };
+
+ memset(&bad_smb2_handle, 0xFF, sizeof(bad_smb2_handle));
+
+ setlinebuf(stdout);
+ options.seed = time(NULL);
+ options.numops = 1000;
+ options.max_open_handles = 20;
+ options.seeds_file = "gentest_seeds.dat";
+
+ pc = poptGetContext("gentest", argc, (const char **) argv, long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+
+ poptSetOtherOptionHelp(pc, "<unc1> <unc2>");
+
+ lp_ctx = cmdline_lp_ctx;
+ servers[0].credentials = cli_credentials_init(talloc_autofree_context());
+ servers[1].credentials = cli_credentials_init(talloc_autofree_context());
+ cli_credentials_guess(servers[0].credentials, lp_ctx);
+ cli_credentials_guess(servers[1].credentials, lp_ctx);
+
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_UNCLIST:
+ lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
+ break;
+ case 'U':
+ if (username_count == 2) {
+ usage(pc);
+ exit(1);
+ }
+ cli_credentials_parse_string(servers[username_count].credentials, poptGetOptArg(pc), CRED_SPECIFIED);
+ username_count++;
+ break;
+ }
+ }
+
+ if (ignore_file) {
+ options.ignore_patterns = file_lines_load(ignore_file, NULL, NULL);
+ }
+
+ argv_new = discard_const_p(char *, poptGetArgs(pc));
+ argc_new = argc;
+ for (i=0; i<argc; i++) {
+ if (argv_new[i] == NULL) {
+ argc_new = i;
+ break;
+ }
+ }
+
+ if (!(argc_new >= 3)) {
+ usage(pc);
+ exit(1);
+ }
+
+ setlinebuf(stdout);
+
+ setup_logging("gentest", DEBUG_STDOUT);
+
+ if (argc < 3 || argv[1][0] == '-') {
+ usage(pc);
+ exit(1);
+ }
+
+ setup_logging(argv[0], DEBUG_STDOUT);
+
+ for (i=0;i<NSERVERS;i++) {
+ const char *share = argv[1+i];
+ if (!split_unc_name(share, &servers[i].server_name, &servers[i].share_name)) {
+ printf("Invalid share name '%s'\n", share);
+ return -1;
+ }
+ }
+
+ if (username_count == 0) {
+ usage(pc);
+ return -1;
+ }
+ if (username_count == 1) {
+ servers[1].credentials = servers[0].credentials;
+ }
+
+ printf("seed=%u\n", options.seed);
+
+ ev = event_context_init(talloc_autofree_context());
+
+ gensec_init(lp_ctx);
+
+ ret = start_gentest(ev, lp_ctx);
+
+ if (ret) {
+ printf("gentest completed - no errors\n");
+ } else {
+ printf("gentest failed\n");
+ }
+
+ return ret?0:-1;
+}
diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c
index dbe9d2f9a4..5d4acd581b 100644
--- a/source4/torture/ldap/cldap.c
+++ b/source4/torture/ldap/cldap.c
@@ -38,18 +38,21 @@
*/
static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
{
- struct cldap_socket *cldap = cldap_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct cldap_socket *cldap;
NTSTATUS status;
struct cldap_netlogon search, empty_search;
- union nbt_cldap_netlogon n1;
+ struct netlogon_samlogon_response n1;
struct GUID guid;
int i;
+ cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
ZERO_STRUCT(search);
search.in.dest_address = dest;
search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
search.in.acct_control = -1;
- search.in.version = 6;
+ search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+ search.in.map_response = true;
empty_search = search;
@@ -61,7 +64,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
n1 = search.out.netlogon;
search.in.user = "Administrator";
- search.in.realm = n1.logon5.dns_domain;
+ search.in.realm = n1.nt5_ex.dns_domain;
search.in.host = "__cldap_torture__";
printf("Scanning for netlogon levels\n");
@@ -80,7 +83,8 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
CHECK_STATUS(status, NT_STATUS_OK);
}
- search.in.version = 0x20000006;
+ search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
+
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
@@ -89,8 +93,8 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
search.in.user = NULL;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
printf("Trying with User=Administrator\n");
@@ -98,10 +102,10 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.user_name, search.in.user);
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC_USER);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, search.in.user);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
- search.in.version = 6;
+ search.in.version = NETLOGON_NT_VERSION_5;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
@@ -110,8 +114,8 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
search.in.user = NULL;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
printf("Trying with User=Administrator\n");
@@ -119,16 +123,18 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.user_name, search.in.user);
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC_USER);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, search.in.user);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN);
+
+ search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
printf("Trying with a GUID\n");
search.in.realm = NULL;
- search.in.domain_guid = GUID_string(tctx, &n1.logon5.domain_uuid);
+ search.in.domain_guid = GUID_string(tctx, &n1.nt5_ex.domain_uuid);
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC_USER);
- CHECK_STRING(GUID_string(tctx, &search.out.netlogon.logon5.domain_uuid), search.in.domain_guid);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
+ CHECK_STRING(GUID_string(tctx, &search.out.netlogon.nt5_ex.domain_uuid), search.in.domain_guid);
printf("Trying with a incorrect GUID\n");
guid = GUID_random();
@@ -138,33 +144,54 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
printf("Trying with a AAC\n");
- search.in.acct_control = 0x180;
- search.in.realm = n1.logon5.dns_domain;
+ search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
+ search.in.realm = n1.nt5_ex.dns_domain;
+ status = cldap_netlogon(cldap, tctx, &search);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+
+ printf("Trying with a zero AAC\n");
+ search.in.acct_control = 0x0;
+ search.in.realm = n1.nt5_ex.dns_domain;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+
+ printf("Trying with a zero AAC and user=Administrator\n");
+ search.in.acct_control = 0x0;
+ search.in.user = "Administrator";
+ search.in.realm = n1.nt5_ex.dns_domain;
+ status = cldap_netlogon(cldap, tctx, &search);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "Administrator");
printf("Trying with a bad AAC\n");
+ search.in.user = NULL;
search.in.acct_control = 0xFF00FF00;
- search.in.realm = n1.logon5.dns_domain;
+ search.in.realm = n1.nt5_ex.dns_domain;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
printf("Trying with a user only\n");
search = empty_search;
search.in.user = "Administrator";
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.dns_domain, n1.logon5.dns_domain);
- CHECK_STRING(search.out.netlogon.logon5.user_name, search.in.user);
+ CHECK_STRING(search.out.netlogon.nt5_ex.dns_domain, n1.nt5_ex.dns_domain);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, search.in.user);
printf("Trying with just a bad username\n");
search.in.user = "___no_such_user___";
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.user_name, search.in.user);
- CHECK_STRING(search.out.netlogon.logon5.dns_domain, n1.logon5.dns_domain);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, search.in.user);
+ CHECK_STRING(search.out.netlogon.nt5_ex.dns_domain, n1.nt5_ex.dns_domain);
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
printf("Trying with just a bad domain\n");
search = empty_search;
@@ -173,29 +200,29 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
printf("Trying with a incorrect domain and correct guid\n");
- search.in.domain_guid = GUID_string(tctx, &n1.logon5.domain_uuid);
+ search.in.domain_guid = GUID_string(tctx, &n1.nt5_ex.domain_uuid);
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.dns_domain, n1.logon5.dns_domain);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
+ CHECK_STRING(search.out.netlogon.nt5_ex.dns_domain, n1.nt5_ex.dns_domain);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
printf("Trying with a incorrect domain and incorrect guid\n");
search.in.domain_guid = GUID_string(tctx, &guid);
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
- CHECK_STRING(search.out.netlogon.logon5.dns_domain, n1.logon5.dns_domain);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
+ CHECK_STRING(search.out.netlogon.nt5_ex.dns_domain, n1.nt5_ex.dns_domain);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
printf("Trying with a incorrect GUID and correct domain\n");
search.in.domain_guid = GUID_string(tctx, &guid);
- search.in.realm = n1.logon5.dns_domain;
+ search.in.realm = n1.nt5_ex.dns_domain;
status = cldap_netlogon(cldap, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_STRING(search.out.netlogon.logon5.dns_domain, n1.logon5.dns_domain);
- CHECK_STRING(search.out.netlogon.logon5.user_name, "");
- CHECK_VAL(search.out.netlogon.logon5.type, NETLOGON_RESPONSE_FROM_PDC2);
+ CHECK_STRING(search.out.netlogon.nt5_ex.dns_domain, n1.nt5_ex.dns_domain);
+ CHECK_STRING(search.out.netlogon.nt5_ex.user_name, "");
+ CHECK_VAL(search.out.netlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
return true;
}
@@ -244,13 +271,15 @@ static void cldap_dump_results(struct cldap_search *search)
*/
static bool test_cldap_generic(struct torture_context *tctx, const char *dest)
{
- struct cldap_socket *cldap = cldap_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct cldap_socket *cldap;
NTSTATUS status;
struct cldap_search search;
const char *attrs1[] = { "currentTime", "highestCommittedUSN", NULL };
const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
const char *attrs3[] = { "netlogon", NULL };
+ cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
ZERO_STRUCT(search);
search.in.dest_address = dest;
search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
diff --git a/source4/torture/ldap/cldapbench.c b/source4/torture/ldap/cldapbench.c
index 83e505e164..df2a5b0551 100644
--- a/source4/torture/ldap/cldapbench.c
+++ b/source4/torture/ldap/cldapbench.c
@@ -51,7 +51,7 @@ static void request_handler(struct cldap_request *req)
*/
static bool bench_cldap(struct torture_context *tctx, const char *address)
{
- struct cldap_socket *cldap = cldap_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct cldap_socket *cldap;
int num_sent=0;
struct timeval tv = timeval_current();
bool ret = true;
@@ -59,6 +59,8 @@ static bool bench_cldap(struct torture_context *tctx, const char *address)
struct cldap_netlogon search;
struct bench_state *state;
+ cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
state = talloc_zero(tctx, struct bench_state);
ZERO_STRUCT(search);
@@ -116,7 +118,7 @@ bool torture_bench_cldap(struct torture_context *torture)
make_nbt_name_server(&name, torture_setting_string(torture, "host", NULL));
/* do an initial name resolution to find its IP */
- status = resolve_name(lp_resolve_context(torture->lp_ctx), &name, torture, &address, event_context_find(torture));
+ status = resolve_name(lp_resolve_context(torture->lp_ctx), &name, torture, &address, torture->ev);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to resolve %s - %s\n",
name.name, nt_errstr(status));
diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c
index 65b02ed5e8..2c11de729c 100644
--- a/source4/torture/ldap/common.c
+++ b/source4/torture/ldap/common.c
@@ -22,7 +22,7 @@
#include "includes.h"
#include "libcli/ldap/ldap_client.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/ldap/proto.h"
NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, const char *password)
@@ -65,7 +65,7 @@ NTSTATUS torture_ldap_connection(struct torture_context *tctx,
return NT_STATUS_INVALID_PARAMETER;
}
- *conn = ldap4_new_connection(tctx, tctx->lp_ctx, NULL);
+ *conn = ldap4_new_connection(tctx, tctx->lp_ctx, tctx->ev);
status = ldap_connect(*conn, url);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/torture/ldap/schema.c b/source4/torture/ldap/schema.c
index 4cfce11eb5..8437e7f79d 100644
--- a/source4/torture/ldap/schema.c
+++ b/source4/torture/ldap/schema.c
@@ -376,7 +376,7 @@ bool torture_ldap_schema(struct torture_context *torture)
url = talloc_asprintf(torture, "ldap://%s/", host);
- ldb = ldb_wrap_connect(torture, torture->lp_ctx, url,
+ ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
NULL,
cmdline_credentials,
0, NULL);
diff --git a/source4/torture/ldap/uptodatevector.c b/source4/torture/ldap/uptodatevector.c
index cec330b2f6..87b7e09e13 100644
--- a/source4/torture/ldap/uptodatevector.c
+++ b/source4/torture/ldap/uptodatevector.c
@@ -162,7 +162,7 @@ bool torture_ldap_uptodatevector(struct torture_context *torture)
url = talloc_asprintf(torture, "ldap://%s/", host);
if (!url) goto failed;
- ldb = ldb_wrap_connect(torture, torture->lp_ctx, url,
+ ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
NULL,
cmdline_credentials,
0, NULL);
diff --git a/source4/torture/libnet/domain.c b/source4/torture/libnet/domain.c
index ff1fbcab78..ab7846e5e1 100644
--- a/source4/torture/libnet/domain.c
+++ b/source4/torture/libnet/domain.c
@@ -74,7 +74,6 @@ bool torture_domainopen(struct torture_context *torture)
{
NTSTATUS status;
struct libnet_context *net_ctx;
- struct event_context *evt_ctx;
TALLOC_CTX *mem_ctx;
bool ret = true;
struct policy_handle h;
@@ -82,8 +81,7 @@ bool torture_domainopen(struct torture_context *torture)
mem_ctx = talloc_init("test_domain_open");
- evt_ctx = event_context_find(torture);
- net_ctx = libnet_context_init(evt_ctx, torture->lp_ctx);
+ net_ctx = libnet_context_init(torture->ev, torture->lp_ctx);
status = torture_rpc_connection(torture,
&net_ctx->samr.pipe,
diff --git a/source4/torture/libnet/libnet.c b/source4/torture/libnet/libnet.c
index 3a75ffcae3..8c8353e8d6 100644
--- a/source4/torture/libnet/libnet.c
+++ b/source4/torture/libnet/libnet.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "librpc/rpc/dcerpc.h"
#include "librpc/gen_ndr/security.h"
#include "librpc/gen_ndr/lsa.h"
diff --git a/source4/torture/libnet/libnet_BecomeDC.c b/source4/torture/libnet/libnet_BecomeDC.c
index 4d57a84582..bc92b4ebc2 100644
--- a/source4/torture/libnet/libnet_BecomeDC.c
+++ b/source4/torture/libnet/libnet_BecomeDC.c
@@ -322,7 +322,7 @@ static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
DEBUG(0,("Reopen the SAM LDB with system credentials and a already stored schema: %s\n", sam_ldb_path));
- s->ldb = ldb_wrap_connect(s, s->tctx->lp_ctx, sam_ldb_path,
+ s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->tctx->lp_ctx, sam_ldb_path,
system_session(s, s->tctx->lp_ctx),
NULL, 0, NULL);
if (!s->ldb) {
@@ -654,7 +654,7 @@ bool torture_net_become_dc(struct torture_context *torture)
sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
DEBUG(0,("Reopen the SAM LDB with system credentials and all replicated data: %s\n", sam_ldb_path));
- s->ldb = ldb_wrap_connect(s, s->lp_ctx, sam_ldb_path,
+ s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->lp_ctx, sam_ldb_path,
system_session(s, s->lp_ctx),
NULL, 0, NULL);
if (!s->ldb) {
diff --git a/source4/torture/libnet/libnet_domain.c b/source4/torture/libnet/libnet_domain.c
index eb6abc45d5..7d5be368c2 100644
--- a/source4/torture/libnet/libnet_domain.c
+++ b/source4/torture/libnet/libnet_domain.c
@@ -201,7 +201,7 @@ bool torture_domain_close_lsa(struct torture_context *torture)
mem_ctx = talloc_init("torture_domain_close_lsa");
status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_lsarpc,
- cmdline_credentials, NULL, torture->lp_ctx);
+ cmdline_credentials, torture->ev, torture->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
d_printf("failed to connect to server: %s\n", nt_errstr(status));
ret = false;
@@ -330,7 +330,7 @@ bool torture_domain_close_samr(struct torture_context *torture)
mem_ctx = talloc_init("torture_domain_close_samr");
status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_samr,
- ctx->cred, NULL, torture->lp_ctx);
+ ctx->cred, torture->ev, torture->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
d_printf("failed to connect to server: %s\n", nt_errstr(status));
ret = false;
diff --git a/source4/torture/libnet/libnet_user.c b/source4/torture/libnet/libnet_user.c
index 15e3f03506..6d3e682976 100644
--- a/source4/torture/libnet/libnet_user.c
+++ b/source4/torture/libnet/libnet_user.c
@@ -530,7 +530,8 @@ bool torture_modifyuser(struct torture_context *torture)
ZERO_STRUCT(user_req);
user_req.in.domain_name = lp_workgroup(torture->lp_ctx);
- user_req.in.user_name = name;
+ user_req.in.data.user_name = name;
+ user_req.in.level = USER_INFO_BY_NAME;
status = libnet_UserInfo(ctx, torture, &user_req);
if (!NT_STATUS_IS_OK(status)) {
@@ -642,7 +643,8 @@ bool torture_userinfo_api(struct torture_context *torture)
ZERO_STRUCT(req);
req.in.domain_name = domain_name.string;
- req.in.user_name = name;
+ req.in.data.user_name = name;
+ req.in.level = USER_INFO_BY_NAME;
status = libnet_UserInfo(ctx, mem_ctx, &req);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/torture/local/config.mk b/source4/torture/local/config.mk
index efdea7f66a..cd1c7b1422 100644
--- a/source4/torture/local/config.mk
+++ b/source4/torture/local/config.mk
@@ -1,10 +1,8 @@
#################################
# Start SUBSYSTEM TORTURE_LOCAL
[MODULE::TORTURE_LOCAL]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_local_init
-PRIVATE_PROTO_HEADER = \
- proto.h
PRIVATE_DEPENDENCIES = \
RPC_NDR_ECHO \
TDR \
@@ -21,32 +19,34 @@ PRIVATE_DEPENDENCIES = \
#################################
TORTURE_LOCAL_OBJ_FILES = \
- lib/charset/tests/iconv.o \
- lib/talloc/testsuite.o \
- lib/replace/test/getifaddrs.o \
- lib/replace/test/os2_delete.o \
- lib/replace/test/strptime.o \
- lib/replace/test/testsuite.o \
- lib/messaging/tests/messaging.o \
- lib/messaging/tests/irpc.o \
- librpc/tests/binding_string.o \
- lib/util/tests/idtree.o \
- lib/socket/testsuite.o \
- lib/socket_wrapper/testsuite.o \
- libcli/resolve/testsuite.o \
- lib/util/tests/strlist.o \
- lib/util/tests/str.o \
- lib/util/tests/file.o \
- lib/util/tests/genrand.o \
- lib/compression/testsuite.o \
- lib/charset/tests/charset.o \
- libcli/security/tests/sddl.o \
- lib/tdr/testsuite.o \
- lib/events/testsuite.o \
- param/tests/share.o \
- param/tests/loadparm.o \
- auth/credentials/tests/simple.o \
- torture/local/local.o \
- torture/local/dbspeed.o \
- torture/local/torture.o
+ $(torturesrcdir)/../lib/charset/tests/iconv.o \
+ $(torturesrcdir)/../lib/talloc/testsuite.o \
+ $(torturesrcdir)/../lib/replace/test/getifaddrs.o \
+ $(torturesrcdir)/../lib/replace/test/os2_delete.o \
+ $(torturesrcdir)/../lib/replace/test/strptime.o \
+ $(torturesrcdir)/../lib/replace/test/testsuite.o \
+ $(torturesrcdir)/../lib/messaging/tests/messaging.o \
+ $(torturesrcdir)/../lib/messaging/tests/irpc.o \
+ $(torturesrcdir)/../librpc/tests/binding_string.o \
+ $(torturesrcdir)/../lib/util/tests/idtree.o \
+ $(torturesrcdir)/../lib/socket/testsuite.o \
+ $(torturesrcdir)/../lib/socket_wrapper/testsuite.o \
+ $(torturesrcdir)/../libcli/resolve/testsuite.o \
+ $(torturesrcdir)/../lib/util/tests/strlist.o \
+ $(torturesrcdir)/../lib/util/tests/str.o \
+ $(torturesrcdir)/../lib/util/tests/file.o \
+ $(torturesrcdir)/../lib/util/tests/genrand.o \
+ $(torturesrcdir)/../lib/compression/testsuite.o \
+ $(torturesrcdir)/../lib/charset/tests/charset.o \
+ $(torturesrcdir)/../libcli/security/tests/sddl.o \
+ $(torturesrcdir)/../lib/tdr/testsuite.o \
+ $(torturesrcdir)/../lib/events/testsuite.o \
+ $(torturesrcdir)/../param/tests/share.o \
+ $(torturesrcdir)/../param/tests/loadparm.o \
+ $(torturesrcdir)/../auth/credentials/tests/simple.o \
+ $(torturesrcdir)/local/local.o \
+ $(torturesrcdir)/local/dbspeed.o \
+ $(torturesrcdir)/local/torture.o
+
+$(eval $(call proto_header_template,$(torturesrcdir)/local/proto.h,$(TORTURE_LOCAL_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/local/dbspeed.c b/source4/torture/local/dbspeed.c
index 34083cd204..017c8568f4 100644
--- a/source4/torture/local/dbspeed.c
+++ b/source4/torture/local/dbspeed.c
@@ -26,7 +26,7 @@
#include "lib/ldb/include/ldb_errors.h"
#include "lib/ldb_wrap.h"
#include "lib/tdb_wrap.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "param/param.h"
float tdb_speed;
@@ -176,7 +176,7 @@ static bool test_ldb_speed(struct torture_context *torture, const void *_data)
torture_comment(torture, "Testing ldb speed for sidmap\n");
- ldb = ldb_wrap_connect(tmp_ctx, torture->lp_ctx, "tdb://test.ldb",
+ ldb = ldb_wrap_connect(tmp_ctx, torture->ev, torture->lp_ctx, "tdb://test.ldb",
NULL, NULL, LDB_FLG_NOSYNC, NULL);
if (!ldb) {
unlink("./test.ldb");
diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c
index e4dfadd3d1..1c3274adcd 100644
--- a/source4/torture/local/local.c
+++ b/source4/torture/local/local.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/local/proto.h"
#include "torture/ndr/ndr.h"
#include "torture/ndr/proto.h"
diff --git a/source4/torture/locktest.c b/source4/torture/locktest.c
index 618568acf9..8959232edb 100644
--- a/source4/torture/locktest.c
+++ b/source4/torture/locktest.c
@@ -19,6 +19,7 @@
#include "includes.h"
#include "lib/cmdline/popt_common.h"
+#include "lib/events/events.h"
#include "system/filesys.h"
#include "system/time.h"
#include "pstring.h"
@@ -107,7 +108,8 @@ static struct record *recorded;
/*****************************************************
return a connection to a server
*******************************************************/
-static struct smbcli_state *connect_one(struct loadparm_context *lp_ctx,
+static struct smbcli_state *connect_one(struct event_context *ev,
+ struct loadparm_context *lp_ctx,
char *share, int snum, int conn)
{
struct smbcli_state *c;
@@ -162,7 +164,7 @@ static struct smbcli_state *connect_one(struct loadparm_context *lp_ctx,
share, NULL,
servers[snum],
lp_resolve_context(lp_ctx),
- NULL, &options);
+ ev, &options);
if (!NT_STATUS_IS_OK(status)) {
sleep(2);
}
@@ -176,7 +178,8 @@ static struct smbcli_state *connect_one(struct loadparm_context *lp_ctx,
}
-static void reconnect(struct loadparm_context *lp_ctx,
+static void reconnect(struct event_context *ev,
+ struct loadparm_context *lp_ctx,
struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES],
char *share[NSERVERS])
{
@@ -193,7 +196,7 @@ static void reconnect(struct loadparm_context *lp_ctx,
}
talloc_free(cli[server][conn]);
}
- cli[server][conn] = connect_one(lp_ctx, share[server],
+ cli[server][conn] = connect_one(ev, lp_ctx, share[server],
server, conn);
if (!cli[server][conn]) {
DEBUG(0,("Failed to connect to %s\n", share[server]));
@@ -396,7 +399,9 @@ static int retest(struct smbcli_state *cli[NSERVERS][NCONNECTIONS],
we then do random locking ops in tamdem on the 4 fnums from each
server and ensure that the results match
*/
-static int test_locks(struct loadparm_context *lp_ctx, char *share[NSERVERS])
+static int test_locks(struct event_context *ev,
+ struct loadparm_context *lp_ctx,
+ char *share[NSERVERS])
{
struct smbcli_state *cli[NSERVERS][NCONNECTIONS];
int fnum[NSERVERS][NCONNECTIONS][NFILES];
@@ -447,7 +452,7 @@ static int test_locks(struct loadparm_context *lp_ctx, char *share[NSERVERS])
#endif
}
- reconnect(lp_ctx, cli, fnum, share);
+ reconnect(ev, lp_ctx, cli, fnum, share);
open_files(cli, fnum);
n = retest(cli, fnum, numops);
@@ -465,7 +470,7 @@ static int test_locks(struct loadparm_context *lp_ctx, char *share[NSERVERS])
n1 = n;
close_files(cli, fnum);
- reconnect(lp_ctx, cli, fnum, share);
+ reconnect(ev, lp_ctx, cli, fnum, share);
open_files(cli, fnum);
for (i=0;i<n-skip;i+=skip) {
@@ -503,7 +508,7 @@ static int test_locks(struct loadparm_context *lp_ctx, char *share[NSERVERS])
}
close_files(cli, fnum);
- reconnect(lp_ctx, cli, fnum, share);
+ reconnect(ev, lp_ctx, cli, fnum, share);
open_files(cli, fnum);
showall = true;
n1 = retest(cli, fnum, n);
@@ -543,6 +548,7 @@ static void usage(poptContext pc)
int opt;
int seed, server;
int username_count=0;
+ struct event_context *ev;
struct loadparm_context *lp_ctx;
poptContext pc;
int argc_new, i;
@@ -631,12 +637,14 @@ static void usage(poptContext pc)
servers[1] = servers[0];
}
+ ev = event_context_init(talloc_autofree_context());
+
gensec_init(lp_ctx);
DEBUG(0,("seed=%u base=%d range=%d min_length=%d\n",
seed, lock_base, lock_range, min_length));
srandom(seed);
- return test_locks(lp_ctx, share);
+ return test_locks(ev, lp_ctx, share);
}
diff --git a/source4/torture/locktest2.c b/source4/torture/locktest2.c
index 0fe3725385..1784a0a729 100644
--- a/source4/torture/locktest2.c
+++ b/source4/torture/locktest2.c
@@ -19,6 +19,7 @@
#include "includes.h"
#include "system/passwd.h"
+#include "lib/events/events.h"
static fstring password;
static fstring username;
@@ -137,7 +138,8 @@ static bool try_unlock(struct smbcli_state *c, int fstype,
return a connection to a server
*******************************************************/
static struct smbcli_state *connect_one(char *share, const char **ports,
- struct smb_options *options)
+ struct smb_options *optionsi,
+ struct event_context *ev)
{
struct smbcli_state *c;
char *server_n;
@@ -165,7 +167,7 @@ static struct smbcli_state *connect_one(char *share, const char **ports,
nt_status = smbcli_full_connection(NULL,
&c, myname, server_n, ports, share, NULL,
- username, lp_workgroup(), password, NULL,
+ username, lp_workgroup(), password, ev,
options);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("smbcli_full_connection failed with error %s\n", nt_errstr(nt_status)));
@@ -183,6 +185,7 @@ static void reconnect(struct smbcli_state *cli[NSERVERS][NCONNECTIONS],
int fnum[NSERVERS][NUMFSTYPES][NCONNECTIONS][NFILES],
const char **ports,
struct smbcli_options *options,
+ struct event_context *ev,
char *share1, char *share2)
{
int server, conn, f, fstype;
@@ -201,7 +204,7 @@ static void reconnect(struct smbcli_state *cli[NSERVERS][NCONNECTIONS],
smbcli_ulogoff(cli[server][conn]);
talloc_free(cli[server][conn]);
}
- cli[server][conn] = connect_one(share[server], ports, options);
+ cli[server][conn] = connect_one(share[server], ports, options, ev);
if (!cli[server][conn]) {
DEBUG(0,("Failed to connect to %s\n", share[server]));
exit(1);
@@ -347,7 +350,11 @@ static int retest(struct smbcli_state *cli[NSERVERS][NCONNECTIONS],
we then do random locking ops in tamdem on the 4 fnums from each
server and ensure that the results match
*/
-static void test_locks(char *share1, char *share2, char *nfspath1, char *nfspath2, const char **ports, struct smbcli_options *options)
+static void test_locks(char *share1, char *share2,
+ char *nfspath1, char *nfspath2,
+ const char **ports,
+ struct smbcli_options *options,
+ struct event_context *ev)
{
struct smbcli_state *cli[NSERVERS][NCONNECTIONS];
char *nfs[NSERVERS];
@@ -376,7 +383,7 @@ static void test_locks(char *share1, char *share2, char *nfspath1, char *nfspath
recorded[n].needed = true;
}
- reconnect(cli, nfs, fnum, ports, options, share1, share2);
+ reconnect(cli, nfs, fnum, ports, options, ev, share1, share2);
open_files(cli, nfs, fnum);
n = retest(cli, nfs, fnum, numops);
@@ -387,7 +394,7 @@ static void test_locks(char *share1, char *share2, char *nfspath1, char *nfspath
n1 = n;
close_files(cli, nfs, fnum);
- reconnect(cli, nfs, fnum, ports, options, share1, share2);
+ reconnect(cli, nfs, fnum, ports, options, ev, share1, share2);
open_files(cli, nfs, fnum);
for (i=0;i<n-1;i++) {
@@ -414,7 +421,7 @@ static void test_locks(char *share1, char *share2, char *nfspath1, char *nfspath
}
close_files(cli, nfs, fnum);
- reconnect(cli, nfs, fnum, ports, options, share1, share2);
+ reconnect(cli, nfs, fnum, ports, options, ev, share1, share2);
open_files(cli, nfs, fnum);
showall = true;
n1 = retest(cli, nfs, fnum, n);
@@ -466,6 +473,7 @@ static void usage(void)
char *p;
int seed;
struct loadparm_context *lp_ctx;
+ struct event_context *ev;
setlinebuf(stdout);
@@ -542,10 +550,12 @@ static void usage(void)
DEBUG(0,("seed=%u\n", seed));
srandom(seed);
+ ev = event_context_init(talloc_autofree_context());
+
locking_init(1);
lp_smbcli_options(lp_ctx, &options);
test_locks(share1, share2, nfspath1, nfspath2, lp_smb_ports(lp_ctx),
- &options);
+ &options, ev);
return(0);
}
diff --git a/source4/torture/masktest.c b/source4/torture/masktest.c
index ac7029aa50..39b1296dbe 100644
--- a/source4/torture/masktest.c
+++ b/source4/torture/masktest.c
@@ -30,6 +30,7 @@
#include "param/param.h"
#include "dynconfig.h"
#include "libcli/resolve/resolve.h"
+#include "lib/events/events.h"
static bool showall = false;
static bool old_list = false;
@@ -73,6 +74,7 @@ static char *reg_test(struct smbcli_state *cli, char *pattern, char *long_name,
return a connection to a server
*******************************************************/
static struct smbcli_state *connect_one(struct resolve_context *resolve_ctx,
+ struct event_context *ev,
char *share, const char **ports,
struct smbcli_options *options)
{
@@ -92,7 +94,7 @@ static struct smbcli_state *connect_one(struct resolve_context *resolve_ctx,
server,
ports,
share, NULL,
- cmdline_credentials, resolve_ctx, NULL,
+ cmdline_credentials, resolve_ctx, ev,
options);
if (!NT_STATUS_IS_OK(status)) {
@@ -291,6 +293,7 @@ static void usage(poptContext pc)
struct smbcli_state *cli;
int opt;
int seed;
+ struct event_context *ev;
struct loadparm_context *lp_ctx;
struct smbcli_options options;
poptContext pc;
@@ -352,11 +355,13 @@ static void usage(poptContext pc)
lp_ctx = cmdline_lp_ctx;
+ ev = event_context_init(talloc_autofree_context());
+
gensec_init(lp_ctx);
lp_smbcli_options(lp_ctx, &options);
- cli = connect_one(lp_resolve_context(lp_ctx), share,
+ cli = connect_one(lp_resolve_context(lp_ctx), ev, share,
lp_smb_ports(lp_ctx), &options);
if (!cli) {
DEBUG(0,("Failed to connect to %s\n", share));
diff --git a/source4/torture/nbench/nbench.c b/source4/torture/nbench/nbench.c
index e9bd32cce0..96144c4773 100644
--- a/source4/torture/nbench/nbench.c
+++ b/source4/torture/nbench/nbench.c
@@ -19,9 +19,8 @@
#include "includes.h"
#include "libcli/libcli.h"
-#include "torture/ui.h"
#include "torture/util.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "system/filesys.h"
#include "system/locale.h"
#include "pstring.h"
diff --git a/source4/torture/nbt/browse.c b/source4/torture/nbt/browse.c
index e609e72055..a0e7b7d9ca 100644
--- a/source4/torture/nbt/browse.c
+++ b/source4/torture/nbt/browse.c
@@ -40,7 +40,7 @@ bool torture_nbt_browse(struct torture_context *torture)
name.scope = NULL;
/* do an initial name resolution to find its IP */
- status = resolve_name(&name, mem_ctx, &address, NULL);
+ status = resolve_name(&name, mem_ctx, &address, torture->ev);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to resolve %s - %s\n",
name.name, nt_errstr(status));
diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c
index e1680877e8..887c6f32ab 100644
--- a/source4/torture/nbt/dgram.c
+++ b/source4/torture/nbt/dgram.c
@@ -42,21 +42,24 @@ static void netlogon_handler(struct dgram_mailslot_handler *dgmslot,
struct socket_address *src)
{
NTSTATUS status;
- struct nbt_netlogon_packet netlogon;
- int *replies = (int *)dgmslot->private;
+ struct nbt_netlogon_response *netlogon = dgmslot->private;
+ dgmslot->private = netlogon = talloc(dgmslot, struct nbt_netlogon_response);
+
+ if (!dgmslot->private) {
+ return;
+ }
+
printf("netlogon reply from %s:%d\n", src->addr, src->port);
- status = dgram_mailslot_netlogon_parse(dgmslot, dgmslot, packet, &netlogon);
+ /* Fills in the netlogon pointer */
+ status = dgram_mailslot_netlogon_parse_response(dgmslot, netlogon, packet, netlogon);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to parse netlogon packet from %s:%d\n",
src->addr, src->port);
return;
}
- NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);
-
- (*replies)++;
}
@@ -64,15 +67,15 @@ static void netlogon_handler(struct dgram_mailslot_handler *dgmslot,
static bool nbt_test_netlogon(struct torture_context *tctx)
{
struct dgram_mailslot_handler *dgmslot;
- struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL,
+ struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
struct socket_address *dest;
const char *myaddress;
struct nbt_netlogon_packet logon;
+ struct nbt_netlogon_response *response;
struct nbt_name myname;
NTSTATUS status;
struct timeval tv = timeval_current();
- int replies = 0;
struct socket_address *socket_address;
@@ -80,14 +83,14 @@ static bool nbt_test_netlogon(struct torture_context *tctx)
struct nbt_name name;
struct interface *ifaces;
-
+
name.name = lp_workgroup(tctx->lp_ctx);
name.type = NBT_NAME_LOGON;
name.scope = NULL;
/* do an initial name resolution to find its IP */
torture_assert_ntstatus_ok(tctx,
- resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, event_context_find(tctx)),
+ resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
talloc_asprintf(tctx, "Failed to resolve %s", name.name));
load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
@@ -101,7 +104,7 @@ static bool nbt_test_netlogon(struct torture_context *tctx)
/* try receiving replies on port 138 first, which will only
work if we are root and smbd/nmbd are not running - fall
back to listening on any port, which means replies from
- some windows versions won't be seen */
+ most windows versions won't be seen */
status = socket_listen(dgmsock->sock, socket_address, 0, 0);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(socket_address);
@@ -114,10 +117,10 @@ static bool nbt_test_netlogon(struct torture_context *tctx)
/* setup a temporary mailslot listener for replies */
dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
- netlogon_handler, &replies);
+ netlogon_handler, NULL);
ZERO_STRUCT(logon);
- logon.command = NETLOGON_QUERY_FOR_PDC;
+ logon.command = LOGON_PRIMARY_QUERY;
logon.req.pdc.computer_name = TEST_NAME;
logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
logon.req.pdc.unicode_name = TEST_NAME;
@@ -132,13 +135,21 @@ static bool nbt_test_netlogon(struct torture_context *tctx)
torture_assert(tctx, dest != NULL, "Error getting address");
status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
&myname, &logon);
torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
- while (timeval_elapsed(&tv) < 5 && replies == 0) {
+ while (timeval_elapsed(&tv) < 5 && !dgmslot->private) {
event_loop_once(dgmsock->event_ctx);
}
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert(tctx, response->response_type == NETLOGON_GET_PDC, "Got incorrect type of netlogon response");
+ torture_assert(tctx, response->get_pdc.command == NETLOGON_RESPONSE_FROM_PDC, "Got incorrect netlogon response command");
+
return true;
}
@@ -147,15 +158,15 @@ static bool nbt_test_netlogon(struct torture_context *tctx)
static bool nbt_test_netlogon2(struct torture_context *tctx)
{
struct dgram_mailslot_handler *dgmslot;
- struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL,
+ struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
struct socket_address *dest;
const char *myaddress;
struct nbt_netlogon_packet logon;
+ struct nbt_netlogon_response *response;
struct nbt_name myname;
NTSTATUS status;
struct timeval tv = timeval_current();
- int replies = 0;
struct socket_address *socket_address;
@@ -163,6 +174,9 @@ static bool nbt_test_netlogon2(struct torture_context *tctx)
struct nbt_name name;
struct interface *ifaces;
+ struct test_join *join_ctx;
+ struct cli_credentials *machine_credentials;
+ const struct dom_sid *dom_sid;
name.name = lp_workgroup(tctx->lp_ctx);
name.type = NBT_NAME_LOGON;
@@ -170,7 +184,7 @@ static bool nbt_test_netlogon2(struct torture_context *tctx)
/* do an initial name resolution to find its IP */
torture_assert_ntstatus_ok(tctx,
- resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, event_context_find(tctx)),
+ resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
talloc_asprintf(tctx, "Failed to resolve %s", name.name));
load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
@@ -196,18 +210,18 @@ static bool nbt_test_netlogon2(struct torture_context *tctx)
/* setup a temporary mailslot listener for replies */
dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
- netlogon_handler, &replies);
+ netlogon_handler, NULL);
ZERO_STRUCT(logon);
- logon.command = NETLOGON_QUERY_FOR_PDC2;
- logon.req.pdc2.request_count = 0;
- logon.req.pdc2.computer_name = TEST_NAME;
- logon.req.pdc2.user_name = "";
- logon.req.pdc2.mailslot_name = dgmslot->mailslot_name;
- logon.req.pdc2.nt_version = 11;
- logon.req.pdc2.lmnt_token = 0xFFFF;
- logon.req.pdc2.lm20_token = 0xFFFF;
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = "";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.nt_version = NETLOGON_NT_VERSION_5EX_WITH_IP|NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
make_nbt_name_client(&myname, TEST_NAME);
@@ -216,40 +230,191 @@ static bool nbt_test_netlogon2(struct torture_context *tctx)
torture_assert(tctx, dest != NULL, "Error getting address");
status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
&myname, &logon);
torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
- while (timeval_elapsed(&tv) < 5 && replies == 0) {
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
event_loop_once(dgmsock->event_ctx);
}
- return true;
-}
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
-/*
- reply handler for ntlogon request
-*/
-static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
- struct nbt_dgram_packet *packet,
- struct socket_address *src)
-{
- NTSTATUS status;
- struct nbt_ntlogon_packet ntlogon;
- int *replies = (int *)dgmslot->private;
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
- printf("ntlogon reply from %s:%d\n", src->addr, src->port);
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX, "Got incorrect netlogon response command");
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.nt_version, NETLOGON_NT_VERSION_5EX_WITH_IP|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_1, "Got incorrect netlogon response command");
- status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
- if (!NT_STATUS_IS_OK(status)) {
- printf("Failed to parse ntlogon packet from %s:%d\n",
- src->addr, src->port);
- return;
+ /* setup (another) temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
+
+ torture_assert_str_equal(tctx, response->samlogon.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
+
+ join_ctx = torture_join_domain(tctx, TEST_NAME,
+ ACB_WSTRUST, &machine_credentials);
+
+ dom_sid = torture_join_sid(join_ctx);
+
+ /* setup (another) temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.sid = *dom_sid;
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
+
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
+
+ /* setup (another) temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.sid = *dom_sid;
+ logon.req.logon.acct_control = ACB_WSTRUST;
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
+
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
+
+ dgmslot->private = NULL;
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.sid = *dom_sid;
+ logon.req.logon.acct_control = ACB_NORMAL;
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock, &name, dest,
+ NBT_MAILSLOT_NETLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send netlogon request");
+
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
}
- NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
- (*replies)++;
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN, "Got incorrect netlogon response command");
+
+ torture_leave_domain(join_ctx);
+ return true;
}
@@ -257,19 +422,19 @@ static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
static bool nbt_test_ntlogon(struct torture_context *tctx)
{
struct dgram_mailslot_handler *dgmslot;
- struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, NULL,
+ struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
struct socket_address *dest;
struct test_join *join_ctx;
- struct cli_credentials *machine_credentials;
const struct dom_sid *dom_sid;
+ struct cli_credentials *machine_credentials;
const char *myaddress;
- struct nbt_ntlogon_packet logon;
+ struct nbt_netlogon_packet logon;
+ struct nbt_netlogon_response *response;
struct nbt_name myname;
NTSTATUS status;
struct timeval tv = timeval_current();
- int replies = 0;
struct socket_address *socket_address;
const char *address;
@@ -283,7 +448,7 @@ static bool nbt_test_ntlogon(struct torture_context *tctx)
/* do an initial name resolution to find its IP */
torture_assert_ntstatus_ok(tctx,
- resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, event_context_find(tctx)),
+ resolve_name(lp_resolve_context(tctx->lp_ctx), &name, tctx, &address, tctx->ev),
talloc_asprintf(tctx, "Failed to resolve %s", name.name));
load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
@@ -296,7 +461,7 @@ static bool nbt_test_ntlogon(struct torture_context *tctx)
/* try receiving replies on port 138 first, which will only
work if we are root and smbd/nmbd are not running - fall
back to listening on any port, which means replies from
- some windows versions won't be seen */
+ most windows versions won't be seen */
status = socket_listen(dgmsock->sock, socket_address, 0, 0);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(socket_address);
@@ -309,24 +474,25 @@ static bool nbt_test_ntlogon(struct torture_context *tctx)
join_ctx = torture_join_domain(tctx, TEST_NAME,
ACB_WSTRUST, &machine_credentials);
+ dom_sid = torture_join_sid(join_ctx);
+
torture_assert(tctx, join_ctx != NULL,
talloc_asprintf(tctx, "Failed to join domain %s as %s\n",
lp_workgroup(tctx->lp_ctx), TEST_NAME));
- dom_sid = torture_join_sid(join_ctx);
-
/* setup a temporary mailslot listener for replies */
dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
- ntlogon_handler, &replies);
+ netlogon_handler, NULL);
ZERO_STRUCT(logon);
- logon.command = NTLOGON_SAM_LOGON;
+ logon.command = LOGON_SAM_LOGON_REQUEST;
logon.req.logon.request_count = 0;
logon.req.logon.computer_name = TEST_NAME;
logon.req.logon.user_name = TEST_NAME"$";
logon.req.logon.mailslot_name = dgmslot->mailslot_name;
logon.req.logon.acct_control = ACB_WSTRUST;
+ /* Try with a SID this time */
logon.req.logon.sid = *dom_sid;
logon.req.logon.nt_version = 1;
logon.req.logon.lmnt_token = 0xFFFF;
@@ -337,15 +503,145 @@ static bool nbt_test_ntlogon(struct torture_context *tctx)
dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
address, lp_dgram_port(tctx->lp_ctx));
torture_assert(tctx, dest != NULL, "Error getting address");
- status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
- &name, dest, &myname, &logon);
+ status = dgram_mailslot_netlogon_send(dgmsock,
+ &name, dest,
+ NBT_MAILSLOT_NTLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
+
+ torture_assert_str_equal(tctx, response->samlogon.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
+
+
+ /* setup a temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_SAM_LOGON_REQUEST;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.acct_control = ACB_WSTRUST;
+ /* Leave sid as all zero */
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock,
+ &name, dest,
+ NBT_MAILSLOT_NTLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
+
+ while (timeval_elapsed(&tv) < 5 && dgmslot->private == NULL) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_SAMLOGON, "Got incorrect type of netlogon response");
+ map_netlogon_samlogon_response(&response->samlogon);
+
+ torture_assert_int_equal(tctx, response->samlogon.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE, "Got incorrect netlogon response command");
+
+ torture_assert_str_equal(tctx, response->samlogon.nt5_ex.user_name, TEST_NAME"$", "Got incorrect user in netlogon response");
+
+
+ /* setup (another) temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_PRIMARY_QUERY;
+ logon.req.pdc.computer_name = TEST_NAME;
+ logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
+ logon.req.pdc.unicode_name = TEST_NAME;
+ logon.req.pdc.nt_version = 1;
+ logon.req.pdc.lmnt_token = 0xFFFF;
+ logon.req.pdc.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock,
+ &name, dest,
+ NBT_MAILSLOT_NTLOGON,
+ &myname, &logon);
torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
- while (timeval_elapsed(&tv) < 5 && replies == 0) {
+ while (timeval_elapsed(&tv) < 5 && !dgmslot->private) {
event_loop_once(dgmsock->event_ctx);
}
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
+ torture_assert_int_equal(tctx, response->get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
+
torture_leave_domain(join_ctx);
+
+ /* setup (another) temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ netlogon_handler, NULL);
+
+ ZERO_STRUCT(logon);
+ logon.command = LOGON_PRIMARY_QUERY;
+ logon.req.pdc.computer_name = TEST_NAME;
+ logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
+ logon.req.pdc.unicode_name = TEST_NAME;
+ logon.req.pdc.nt_version = 1;
+ logon.req.pdc.lmnt_token = 0xFFFF;
+ logon.req.pdc.lm20_token = 0xFFFF;
+
+ make_nbt_name_client(&myname, TEST_NAME);
+
+ dest = socket_address_from_strings(dgmsock, dgmsock->sock->backend_name,
+ address, lp_dgram_port(tctx->lp_ctx));
+ torture_assert(tctx, dest != NULL, "Error getting address");
+ status = dgram_mailslot_netlogon_send(dgmsock,
+ &name, dest,
+ NBT_MAILSLOT_NTLOGON,
+ &myname, &logon);
+ torture_assert_ntstatus_ok(tctx, status, "Failed to send ntlogon request");
+
+ while (timeval_elapsed(&tv) < 5 && !dgmslot->private) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ response = talloc_get_type(dgmslot->private, struct nbt_netlogon_response);
+
+ torture_assert(tctx, response != NULL, "Failed to receive a netlogon reply packet");
+
+ torture_assert_int_equal(tctx, response->response_type, NETLOGON_GET_PDC, "Got incorrect type of ntlogon response");
+ torture_assert_int_equal(tctx, response->get_pdc.command, NETLOGON_RESPONSE_FROM_PDC, "Got incorrect ntlogon response command");
+
+
return true;
}
diff --git a/source4/torture/nbt/nbt.c b/source4/torture/nbt/nbt.c
index 6cb9507398..422261884f 100644
--- a/source4/torture/nbt/nbt.c
+++ b/source4/torture/nbt/nbt.c
@@ -21,7 +21,7 @@
#include "libcli/nbt/libnbt.h"
#include "torture/torture.h"
#include "torture/nbt/proto.h"
-#include "torture/ui.h"
+#include "torture/smbtorture.h"
#include "libcli/resolve/resolve.h"
#include "param/param.h"
@@ -34,7 +34,7 @@ bool torture_nbt_get_name(struct torture_context *tctx,
/* do an initial name resolution to find its IP */
torture_assert_ntstatus_ok(tctx,
- resolve_name(lp_resolve_context(tctx->lp_ctx), name, tctx, address, NULL),
+ resolve_name(lp_resolve_context(tctx->lp_ctx), name, tctx, address, tctx->ev),
talloc_asprintf(tctx,
"Failed to resolve %s", name->name));
diff --git a/source4/torture/nbt/query.c b/source4/torture/nbt/query.c
index 1ba6172e5c..3f3a15cca5 100644
--- a/source4/torture/nbt/query.c
+++ b/source4/torture/nbt/query.c
@@ -47,7 +47,7 @@ static void increment_handler(struct nbt_name_request *req)
*/
static bool bench_namequery(struct torture_context *tctx)
{
- struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL,
+ struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
int num_sent=0;
struct result_struct *result;
diff --git a/source4/torture/nbt/register.c b/source4/torture/nbt/register.c
index b9f06c479d..a8681f828f 100644
--- a/source4/torture/nbt/register.c
+++ b/source4/torture/nbt/register.c
@@ -44,7 +44,7 @@ static bool nbt_register_own(struct torture_context *tctx)
{
struct nbt_name_register io;
NTSTATUS status;
- struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL,
+ struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
struct socket_address *socket_address;
struct nbt_name name;
@@ -114,7 +114,7 @@ static bool nbt_refresh_own(struct torture_context *tctx)
{
struct nbt_name_refresh io;
NTSTATUS status;
- struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL,
+ struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, tctx->ev,
lp_iconv_convenience(tctx->lp_ctx));
const char *myaddress;
struct socket_address *socket_address;
diff --git a/source4/torture/nbt/wins.c b/source4/torture/nbt/wins.c
index 059b2dc919..ae20de6e2f 100644
--- a/source4/torture/nbt/wins.c
+++ b/source4/torture/nbt/wins.c
@@ -53,7 +53,7 @@ static bool nbt_test_wins_name(struct torture_context *tctx, const char *address
struct nbt_name_refresh_wins refresh;
struct nbt_name_release release;
NTSTATUS status;
- struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
const char *myaddress;
struct socket_address *socket_address;
struct interface *ifaces;
diff --git a/source4/torture/nbt/winsbench.c b/source4/torture/nbt/winsbench.c
index ea4abaf21b..a0d90fb653 100644
--- a/source4/torture/nbt/winsbench.c
+++ b/source4/torture/nbt/winsbench.c
@@ -225,7 +225,7 @@ static void generate_request(struct nbt_name_socket *nbtsock, struct wins_state
*/
static bool bench_wins(struct torture_context *tctx)
{
- struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
int num_sent=0;
struct timeval tv = timeval_current();
bool ret = true;
diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c
index 470eee8310..ee7a1510d5 100644
--- a/source4/torture/nbt/winsreplication.c
+++ b/source4/torture/nbt/winsreplication.c
@@ -103,8 +103,8 @@ static bool test_assoc_ctx1(struct torture_context *tctx)
torture_comment(tctx, "Test if assoc_ctx is only valid on the conection it was created on\n");
- wrepl_socket1 = wrepl_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
- wrepl_socket2 = wrepl_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ wrepl_socket1 = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ wrepl_socket2 = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
torture_comment(tctx, "Setup 2 wrepl connections\n");
status = wrepl_connect(wrepl_socket1, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, address), address);
@@ -186,7 +186,7 @@ static bool test_assoc_ctx2(struct torture_context *tctx)
torture_comment(tctx, "Test if we always get back the same assoc_ctx\n");
- wrepl_socket = wrepl_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ wrepl_socket = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
torture_comment(tctx, "Setup wrepl connections\n");
status = wrepl_connect(wrepl_socket, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, address), address);
@@ -255,7 +255,7 @@ static bool test_wins_replication(struct torture_context *tctx)
torture_comment(tctx, "Test one pull replication cycle\n");
- wrepl_socket = wrepl_socket_init(tctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ wrepl_socket = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
torture_comment(tctx, "Setup wrepl connections\n");
status = wrepl_connect(wrepl_socket, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, address), address);
@@ -553,7 +553,7 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(
if (!ctx) return NULL;
ctx->address = address;
- ctx->pull = wrepl_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ ctx->pull = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
if (!ctx->pull) return NULL;
torture_comment(tctx, "Setup wrepl conflict pull connection\n");
@@ -610,7 +610,7 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(
talloc_free(pull_table.out.partners);
- ctx->nbtsock = nbt_name_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ ctx->nbtsock = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
if (!ctx->nbtsock) return NULL;
load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
@@ -628,7 +628,7 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(
status = socket_listen(ctx->nbtsock->sock, ctx->myaddr, 0, 0);
if (!NT_STATUS_IS_OK(status)) return NULL;
- ctx->nbtsock_srv = nbt_name_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ ctx->nbtsock_srv = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
if (!ctx->nbtsock_srv) return NULL;
/* Make a port 137 version of ctx->myaddr */
@@ -645,7 +645,7 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(
}
if (ctx->myaddr2 && ctx->nbtsock_srv) {
- ctx->nbtsock2 = nbt_name_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ ctx->nbtsock2 = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
if (!ctx->nbtsock2) return NULL;
status = socket_listen(ctx->nbtsock2->sock, ctx->myaddr2, 0, 0);
@@ -722,7 +722,7 @@ static bool test_wrepl_update_one(struct torture_context *tctx,
uint32_t assoc_ctx;
NTSTATUS status;
- wrepl_socket = wrepl_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ wrepl_socket = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
status = wrepl_connect(wrepl_socket, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, ctx->address), ctx->address);
CHECK_STATUS(tctx, status, NT_STATUS_OK);
diff --git a/source4/torture/ndr/ndr.c b/source4/torture/ndr/ndr.c
index 55b00d1fb8..63636f8c5f 100644
--- a/source4/torture/ndr/ndr.c
+++ b/source4/torture/ndr/ndr.c
@@ -21,7 +21,7 @@
#include "includes.h"
#include "torture/ndr/ndr.h"
#include "torture/ndr/proto.h"
-#include "torture/ui.h"
+#include "torture/torture.h"
#include "util/dlinklist.h"
#include "param/param.h"
diff --git a/source4/torture/rap/rap.c b/source4/torture/rap/rap.c
index 4b5f4b582c..1ccd1254dd 100644
--- a/source4/torture/rap/rap.c
+++ b/source4/torture/rap/rap.c
@@ -21,7 +21,7 @@
#include "includes.h"
#include "libcli/libcli.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/util.h"
#include "libcli/rap/rap.h"
#include "libcli/raw/libcliraw.h"
diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c
index 1f31fbc515..d73ac1327e 100644
--- a/source4/torture/raw/composite.c
+++ b/source4/torture/raw/composite.c
@@ -296,7 +296,7 @@ static bool test_appendacl(struct smbcli_state *cli, struct torture_context *tct
c[i]->async.private_data = count;
}
- event_ctx = talloc_reference(tctx, cli->tree->session->transport->socket->event.ctx);
+ event_ctx = tctx->ev;
printf("waiting for completion\n");
while (*count != num_ops) {
event_loop_once(event_ctx);
@@ -354,7 +354,7 @@ static bool test_fsinfo(struct smbcli_state *cli, struct torture_context *tctx)
printf("testing parallel queryfsinfo [Object ID] with %d ops\n", torture_numops);
- event_ctx = talloc_reference(tctx, cli->tree->session->transport->socket->event.ctx);
+ event_ctx = tctx->ev;
c = talloc_array(tctx, struct composite_context *, torture_numops);
for (i=0; i<torture_numops; i++) {
diff --git a/source4/torture/raw/lockbench.c b/source4/torture/raw/lockbench.c
index 86030c538a..21541d003b 100644
--- a/source4/torture/raw/lockbench.c
+++ b/source4/torture/raw/lockbench.c
@@ -316,7 +316,6 @@ bool torture_bench_lock(struct torture_context *torture)
int i;
int timelimit = torture_setting_int(torture, "timelimit", 10);
struct timeval tv;
- struct event_context *ev = event_context_find(mem_ctx);
struct benchlock_state *state;
int total = 0, minops=0;
struct smbcli_state *cli;
@@ -333,8 +332,8 @@ bool torture_bench_lock(struct torture_context *torture)
state[i].tctx = torture;
state[i].mem_ctx = talloc_new(state);
state[i].client_num = i;
- state[i].ev = ev;
- if (!torture_open_connection_ev(&cli, i, torture, ev)) {
+ state[i].ev = torture->ev;
+ if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
return false;
}
talloc_steal(mem_ctx, state);
@@ -375,12 +374,12 @@ bool torture_bench_lock(struct torture_context *torture)
tv = timeval_current();
if (progress) {
- event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state);
+ event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state);
}
printf("Running for %d seconds\n", timelimit);
while (timeval_elapsed(&tv) < timelimit) {
- event_loop_once(ev);
+ event_loop_once(torture->ev);
if (lock_failed) {
DEBUG(0,("locking failed\n"));
diff --git a/source4/torture/raw/lookuprate.c b/source4/torture/raw/lookuprate.c
new file mode 100644
index 0000000000..782cb1b31b
--- /dev/null
+++ b/source4/torture/raw/lookuprate.c
@@ -0,0 +1,320 @@
+/*
+ File lookup rate test.
+
+ Copyright (C) James Peach 2006
+
+ 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 "includes.h"
+#include "param/param.h"
+#include "system/filesys.h"
+#include "torture/smbtorture.h"
+#include "torture/basic/proto.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "lib/cmdline/popt_common.h"
+#include "auth/credentials/credentials.h"
+
+#define BASEDIR "\\lookuprate"
+#define MISSINGNAME BASEDIR "\\foo"
+
+#define FUZZ_PERCENT 10
+
+#define usec_to_sec(s) ((s) / 1000000)
+#define sec_to_usec(s) ((s) * 1000000)
+
+struct rate_record
+{
+ unsigned dirent_count;
+ unsigned querypath_persec;
+ unsigned findfirst_persec;
+};
+
+static struct rate_record records[] =
+{
+ { 0, 0, 0 }, /* Base (optimal) lookup rate. */
+ { 100, 0, 0},
+ { 1000, 0, 0},
+ { 10000, 0, 0},
+ { 100000, 0, 0}
+};
+
+typedef NTSTATUS lookup_function(struct smbcli_tree *tree, const char * path);
+
+/* Test whether rhs is within fuzz% of lhs. */
+static bool fuzzily_equal(unsigned lhs, unsigned rhs, int percent)
+{
+ double fuzz = (double)lhs * (double)percent/100.0;
+
+ if (((double)rhs >= ((double)lhs - fuzz)) &&
+ ((double)rhs <= ((double)lhs + fuzz))) {
+ return true;
+ }
+
+ return false;
+
+}
+
+static NTSTATUS fill_directory(struct smbcli_tree *tree,
+ const char * path, unsigned count)
+{
+ NTSTATUS status;
+ char *fname = NULL;
+ unsigned i;
+ unsigned current;
+
+ struct timeval start;
+ struct timeval now;
+
+ status = smbcli_mkdir(tree, path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ printf("filling directory %s with %u files... ", path, count);
+ fflush(stdout);
+
+ current = random();
+ start = timeval_current();
+
+ for (i = 0; i < count; ++i) {
+ int fnum;
+
+ ++current;
+ fname = talloc_asprintf(NULL, "%s\\fill%u",
+ path, current);
+
+ fnum = smbcli_open(tree, fname, O_RDONLY|O_CREAT,
+ OPENX_MODE_DENY_NONE);
+ if (fnum < 0) {
+ talloc_free(fname);
+ return smbcli_nt_error(tree);
+ }
+
+ smbcli_close(tree, fnum);
+ talloc_free(fname);
+ }
+
+ if (count) {
+ double rate;
+ now = timeval_current();
+ rate = (double)count / usec_to_sec((double)usec_time_diff(&now, &start));
+ printf("%u/sec\n", (unsigned)rate);
+ } else {
+ printf("done\n");
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS squash_lookup_error(NTSTATUS status)
+{
+ if (NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_OK;
+ }
+
+ /* We don't care if the file isn't there. */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
+ return NT_STATUS_OK;
+ }
+
+ return status;
+}
+
+/* Look up a pathname using TRANS2_QUERY_PATH_INFORMATION. */
+static NTSTATUS querypath_lookup(struct smbcli_tree *tree, const char * path)
+{
+ NTSTATUS status;
+ time_t ftimes[3];
+ size_t fsize;
+ uint16_t fmode;
+
+ status = smbcli_qpathinfo(tree, path, &ftimes[0], &ftimes[1], &ftimes[2],
+ &fsize, &fmode);
+
+ return squash_lookup_error(status);
+}
+
+/* Look up a pathname using TRANS2_FIND_FIRST2. */
+static NTSTATUS findfirst_lookup(struct smbcli_tree *tree, const char * path)
+{
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (smbcli_list(tree, path, 0, NULL, NULL) < 0) {
+ status = smbcli_nt_error(tree);
+ }
+
+ return squash_lookup_error(status);
+}
+
+static NTSTATUS lookup_rate_convert(struct smbcli_tree *tree,
+ lookup_function lookup, const char * path, unsigned * rate)
+{
+ NTSTATUS status;
+
+ struct timeval start;
+ struct timeval now;
+ unsigned count = 0;
+ int64_t elapsed = 0;
+
+#define LOOKUP_PERIOD_SEC (2)
+
+ start = timeval_current();
+ while (elapsed < sec_to_usec(LOOKUP_PERIOD_SEC)) {
+
+ status = lookup(tree, path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ ++count;
+ now = timeval_current();
+ elapsed = usec_time_diff(&now, &start);
+ }
+
+#undef LOOKUP_PERIOD_SEC
+
+ *rate = (unsigned)((double)count / (double)usec_to_sec(elapsed));
+ return NT_STATUS_OK;
+}
+
+static bool remove_working_directory(struct smbcli_tree *tree,
+ const char * path)
+{
+ int tries;
+
+ /* Using smbcli_deltree to delete a very large number of files
+ * doesn't work against all servers. Work around this by
+ * retrying.
+ */
+ for (tries = 0; tries < 5; ) {
+ int ret;
+
+ ret = smbcli_deltree(tree, BASEDIR);
+ if (ret == -1) {
+ tries++;
+ printf("(%s) failed to deltree %s: %s\n",
+ __location__, BASEDIR,
+ smbcli_errstr(tree));
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+
+}
+
+/* Verify that looking up a file name takes constant time.
+ *
+ * This test samples the lookup rate for a non-existant filename in a
+ * directory, while varying the number of files in the directory. The
+ * lookup rate should continue to approximate the lookup rate for the
+ * empty directory case.
+ */
+bool torture_bench_lookup(struct torture_context *torture)
+{
+ NTSTATUS status;
+ bool result = false;
+
+ int i, tries;
+ struct smbcli_state *cli = NULL;
+
+ if (!torture_open_connection(&cli, torture, 0)) {
+ goto done;
+ }
+
+ remove_working_directory(cli->tree, BASEDIR);
+
+ for (i = 0; i < ARRAY_SIZE(records); ++i) {
+ printf("testing lookup rate with %u directory entries\n",
+ records[i].dirent_count);
+
+ status = fill_directory(cli->tree, BASEDIR,
+ records[i].dirent_count);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("failed to fill directory: %s\n", nt_errstr(status));
+ goto done;
+ }
+
+ status = lookup_rate_convert(cli->tree, querypath_lookup,
+ MISSINGNAME, &records[i].querypath_persec);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("querypathinfo of %s failed: %s\n",
+ MISSINGNAME, nt_errstr(status));
+ goto done;
+ }
+
+ status = lookup_rate_convert(cli->tree, findfirst_lookup,
+ MISSINGNAME, &records[i].findfirst_persec);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("findfirst of %s failed: %s\n",
+ MISSINGNAME, nt_errstr(status));
+ goto done;
+ }
+
+ printf("entries = %u, querypath = %u/sec, findfirst = %u/sec\n",
+ records[i].dirent_count,
+ records[i].querypath_persec,
+ records[i].findfirst_persec);
+
+ if (!remove_working_directory(cli->tree, BASEDIR)) {
+ goto done;
+ }
+ }
+
+ /* Ok. We have run all our tests. Walk through the records we
+ * accumulated and figure out whether the lookups took constant
+ * time of not.
+ */
+ for (i = 0; i < ARRAY_SIZE(records); ++i) {
+ if (!fuzzily_equal(records[0].querypath_persec,
+ records[i].querypath_persec,
+ FUZZ_PERCENT)) {
+ printf("querypath rate for %d entries differed by "
+ "more than %d%% from base rate\n",
+ records[i].dirent_count, FUZZ_PERCENT);
+ result = false;
+ }
+
+ if (!fuzzily_equal(records[0].findfirst_persec,
+ records[i].findfirst_persec,
+ FUZZ_PERCENT)) {
+ printf("findfirst rate for %d entries differed by "
+ "more than %d%% from base rate\n",
+ records[i].dirent_count, FUZZ_PERCENT);
+ result = false;
+ }
+ }
+
+done:
+ if (cli) {
+ remove_working_directory(cli->tree, BASEDIR);
+ talloc_free(cli);
+ }
+
+ return result;
+}
+
+/* vim: set sts=8 sw=8 : */
diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c
index 1340692faa..9c66c3be9c 100644
--- a/source4/torture/raw/offline.c
+++ b/source4/torture/raw/offline.c
@@ -389,7 +389,6 @@ bool torture_test_offline(struct torture_context *torture)
int i;
int timelimit = torture_setting_int(torture, "timelimit", 10);
struct timeval tv;
- struct event_context *ev = event_context_find(mem_ctx);
struct offline_state *state;
struct smbcli_state *cli;
bool progress;
@@ -404,8 +403,8 @@ bool torture_test_offline(struct torture_context *torture)
for (i=0;i<nconnections;i++) {
state[i].tctx = torture;
state[i].mem_ctx = talloc_new(state);
- state[i].ev = ev;
- if (!torture_open_connection_ev(&cli, i, torture, ev)) {
+ state[i].ev = torture->ev;
+ if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
return false;
}
state[i].tree = cli->tree;
@@ -418,7 +417,7 @@ bool torture_test_offline(struct torture_context *torture)
for (i=nconnections;i<numstates;i++) {
state[i].tctx = torture;
state[i].mem_ctx = talloc_new(state);
- state[i].ev = ev;
+ state[i].ev = torture->ev;
state[i].tree = state[i % nconnections].tree;
state[i].client = i;
}
@@ -468,12 +467,12 @@ bool torture_test_offline(struct torture_context *torture)
tv = timeval_current();
if (progress) {
- event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state);
+ event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state);
}
printf("Running for %d seconds\n", timelimit);
while (timeval_elapsed(&tv) < timelimit) {
- event_loop_once(ev);
+ event_loop_once(torture->ev);
if (test_failed) {
DEBUG(0,("test failed\n"));
@@ -487,7 +486,7 @@ bool torture_test_offline(struct torture_context *torture)
while (state[i].loadfile ||
state[i].savefile ||
state[i].req) {
- event_loop_once(ev);
+ event_loop_once(torture->ev);
}
}
diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c
index d28a8bd14e..c6ba0d2571 100644
--- a/source4/torture/raw/open.c
+++ b/source4/torture/raw/open.c
@@ -1350,21 +1350,19 @@ static bool test_raw_open_multi(struct torture_context *tctx)
const char *host = torture_setting_string(tctx, "host", NULL);
const char *share = torture_setting_string(tctx, "share", NULL);
int i, num_files = 3;
- struct event_context *ev;
int num_ok = 0;
int num_collision = 0;
- ev = cli_credentials_get_event_context(cmdline_credentials);
clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
ios = talloc_array(mem_ctx, union smb_open, num_files);
- if ((ev == NULL) || (clients == NULL) || (requests == NULL) ||
+ if ((tctx->ev == NULL) || (clients == NULL) || (requests == NULL) ||
(ios == NULL)) {
DEBUG(0, ("talloc failed\n"));
return false;
}
- if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, ev)) {
+ if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, tctx->ev)) {
return false;
}
@@ -1372,7 +1370,7 @@ static bool test_raw_open_multi(struct torture_context *tctx)
for (i=0; i<num_files; i++) {
if (!torture_open_connection_share(mem_ctx, &(clients[i]),
- tctx, host, share, ev)) {
+ tctx, host, share, tctx->ev)) {
DEBUG(0, ("Could not open %d'th connection\n", i));
return false;
}
@@ -1441,7 +1439,7 @@ static bool test_raw_open_multi(struct torture_context *tctx)
break;
}
- if (event_loop_once(ev) != 0) {
+ if (event_loop_once(tctx->ev) != 0) {
DEBUG(0, ("event_loop_once failed\n"));
return false;
}
diff --git a/source4/torture/raw/openbench.c b/source4/torture/raw/openbench.c
index a5b1434a47..26b862c33f 100644
--- a/source4/torture/raw/openbench.c
+++ b/source4/torture/raw/openbench.c
@@ -369,7 +369,6 @@ bool torture_bench_open(struct torture_context *torture)
int i;
int timelimit = torture_setting_int(torture, "timelimit", 10);
struct timeval tv;
- struct event_context *ev = event_context_find(mem_ctx);
struct benchopen_state *state;
int total = 0;
int total_retries = 0;
@@ -387,8 +386,8 @@ bool torture_bench_open(struct torture_context *torture)
state[i].tctx = torture;
state[i].mem_ctx = talloc_new(state);
state[i].client_num = i;
- state[i].ev = ev;
- if (!torture_open_connection_ev(&state[i].cli, i, torture, ev)) {
+ state[i].ev = torture->ev;
+ if (!torture_open_connection_ev(&state[i].cli, i, torture, torture->ev)) {
return false;
}
talloc_steal(mem_ctx, state);
@@ -428,13 +427,13 @@ bool torture_bench_open(struct torture_context *torture)
tv = timeval_current();
if (progress) {
- report_te = event_add_timed(ev, state, timeval_current_ofs(1, 0),
+ report_te = event_add_timed(torture->ev, state, timeval_current_ofs(1, 0),
report_rate, state);
}
printf("Running for %d seconds\n", timelimit);
while (timeval_elapsed(&tv) < timelimit) {
- event_loop_once(ev);
+ event_loop_once(torture->ev);
if (open_failed) {
DEBUG(0,("open failed\n"));
diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index 1927a0f027..fd8d292980 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -2841,13 +2841,12 @@ bool torture_bench_oplock(struct torture_context *torture)
int timelimit = torture_setting_int(torture, "timelimit", 10);
union smb_open io;
struct timeval tv;
- struct event_context *ev = event_context_find(mem_ctx);
cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
torture_comment(torture, "Opening %d connections\n", torture_nprocs);
for (i=0;i<torture_nprocs;i++) {
- if (!torture_open_connection_ev(&cli[i], i, torture, ev)) {
+ if (!torture_open_connection_ev(&cli[i], i, torture, torture->ev)) {
return false;
}
talloc_steal(mem_ctx, cli[i]);
diff --git a/source4/torture/raw/raw.c b/source4/torture/raw/raw.c
index bb3dde728f..0a7fc3ebfd 100644
--- a/source4/torture/raw/raw.c
+++ b/source4/torture/raw/raw.c
@@ -18,10 +18,10 @@
*/
#include "includes.h"
-#include "torture/torture.h"
#include "libcli/raw/libcliraw.h"
-#include "torture/raw/proto.h"
#include "torture/util.h"
+#include "torture/smbtorture.h"
+#include "torture/raw/proto.h"
NTSTATUS torture_raw_init(void)
{
@@ -33,6 +33,10 @@ NTSTATUS torture_raw_init(void)
torture_suite_add_simple_test(suite, "PING-PONG", torture_ping_pong);
torture_suite_add_simple_test(suite, "BENCH-LOCK", torture_bench_lock);
torture_suite_add_simple_test(suite, "BENCH-OPEN", torture_bench_open);
+ torture_suite_add_simple_test(suite, "BENCH-LOOKUP",
+ torture_bench_lookup);
+ torture_suite_add_simple_test(suite, "BENCH-TCON",
+ torture_bench_treeconnect);
torture_suite_add_simple_test(suite, "OFFLINE", torture_test_offline);
torture_suite_add_1smb_test(suite, "QFSINFO", torture_raw_qfsinfo);
torture_suite_add_1smb_test(suite, "QFILEINFO", torture_raw_qfileinfo);
diff --git a/source4/torture/raw/samba3hide.c b/source4/torture/raw/samba3hide.c
index 814b5f57f4..1f1501045c 100644
--- a/source4/torture/raw/samba3hide.c
+++ b/source4/torture/raw/samba3hide.c
@@ -136,7 +136,7 @@ bool torture_samba3_hide(struct torture_context *torture)
if (!torture_open_connection_share(
torture, &cli, torture, torture_setting_string(torture, "host", NULL),
- torture_setting_string(torture, "share", NULL), NULL)) {
+ torture_setting_string(torture, "share", NULL), torture->ev)) {
d_printf("torture_open_connection_share failed\n");
return false;
}
diff --git a/source4/torture/raw/samba3misc.c b/source4/torture/raw/samba3misc.c
index 15a7f6c4a3..27b4d42dd8 100644
--- a/source4/torture/raw/samba3misc.c
+++ b/source4/torture/raw/samba3misc.c
@@ -56,7 +56,7 @@ bool torture_samba3_checkfsp(struct torture_context *torture)
if (!torture_open_connection_share(
torture, &cli, torture, torture_setting_string(torture, "host", NULL),
- torture_setting_string(torture, "share", NULL), NULL)) {
+ torture_setting_string(torture, "share", NULL), torture->ev)) {
d_printf("torture_open_connection_share failed\n");
ret = false;
goto done;
diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c
index 1dab36c28b..8b2d327653 100644
--- a/source4/torture/raw/streams.c
+++ b/source4/torture/raw/streams.c
@@ -135,6 +135,11 @@ static bool check_stream_list(struct smbcli_state *cli, const char *fname,
goto fail;
}
+ if (num_exp == 0) {
+ ret = true;
+ goto fail;
+ }
+
exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
if (exp_sort == NULL) {
@@ -170,7 +175,81 @@ static bool check_stream_list(struct smbcli_state *cli, const char *fname,
}
/*
- test basic io on streams
+ test bahavior of streams on directories
+*/
+static bool test_stream_dir(struct torture_context *tctx,
+ struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+ union smb_open io;
+ const char *fname = BASEDIR "\\stream.txt";
+ const char *sname1;
+ bool ret = true;
+ const char *basedir_data;
+
+ basedir_data = talloc_asprintf(mem_ctx, "%s::$DATA", BASEDIR);
+ sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
+
+ printf("(%s) opening non-existant directory stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = sname1;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
+
+ printf("(%s) opening basedir stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = basedir_data;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
+
+ printf("(%s) opening basedir ::$DATA stream\n", __location__);
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.flags = 0x10;
+ io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
+ io.ntcreatex.in.create_options = 0;
+ io.ntcreatex.in.file_attr = 0;
+ io.ntcreatex.in.share_access = 0;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = basedir_data;
+ status = smb_raw_open(cli->tree, mem_ctx, &io);
+ if (torture_setting_bool(tctx, "samba3", false)) {
+ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ } else {
+ CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
+ }
+
+ printf("(%s) list the streams on the basedir\n", __location__);
+ ret &= check_stream_list(cli, BASEDIR, 0, NULL);
+done:
+ return ret;
+}
+
+/*
+ test basic behavior of streams on directories
*/
static bool test_stream_io(struct torture_context *tctx,
struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
@@ -191,12 +270,12 @@ static bool test_stream_io(struct torture_context *tctx,
sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
sname2 = talloc_asprintf(mem_ctx, "%s:%s:$DaTa", fname, "Second Stream");
- printf("(%s) opening non-existant directory stream\n", __location__);
+ printf("(%s) creating a stream on a non-existant file\n", __location__);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid = 0;
io.ntcreatex.in.flags = 0;
io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
- io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+ io.ntcreatex.in.create_options = 0;
io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
io.ntcreatex.in.share_access = 0;
io.ntcreatex.in.alloc_size = 0;
@@ -205,12 +284,6 @@ static bool test_stream_io(struct torture_context *tctx,
io.ntcreatex.in.security_flags = 0;
io.ntcreatex.in.fname = sname1;
status = smb_raw_open(cli->tree, mem_ctx, &io);
- CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
-
- printf("(%s) creating a stream on a non-existant file\n", __location__);
- io.ntcreatex.in.create_options = 0;
- io.ntcreatex.in.fname = sname1;
- status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.file.fnum;
@@ -423,7 +496,7 @@ static bool test_stream_delete(struct torture_context *tctx,
sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
- printf("(%s) opening non-existant directory stream\n", __location__);
+ printf("(%s) opening non-existant file stream\n", __location__);
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid = 0;
io.ntcreatex.in.flags = 0;
@@ -559,6 +632,8 @@ bool torture_raw_streams(struct torture_context *torture,
return false;
}
+ ret &= test_stream_dir(torture, cli, torture);
+ smb_raw_exit(cli->session);
ret &= test_stream_io(torture, cli, torture);
smb_raw_exit(cli->session);
ret &= test_stream_sharemodes(torture, cli, torture);
diff --git a/source4/torture/raw/tconrate.c b/source4/torture/raw/tconrate.c
new file mode 100644
index 0000000000..6f0ba0d617
--- /dev/null
+++ b/source4/torture/raw/tconrate.c
@@ -0,0 +1,201 @@
+/*
+ SMB tree connection rate test
+
+ Copyright (C) 2006-2007 James Peach
+
+ 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 "includes.h"
+#include "libcli/libcli.h"
+#include "libcli/resolve/resolve.h"
+#include "torture/smbtorture.h"
+#include "lib/cmdline/popt_common.h"
+#include "param/param.h"
+
+#include "system/filesys.h"
+#include "system/shmem.h"
+
+#define TIME_LIMIT_SECS 30
+#define usec_to_sec(s) ((s) / 1000000)
+#define sec_to_usec(s) ((s) * 1000000)
+
+/* Map a shared memory buffer of at least nelem counters. */
+static void * map_count_buffer(unsigned nelem, size_t elemsz)
+{
+ void * buf;
+ size_t bufsz;
+ size_t pagesz = getpagesize();
+
+ bufsz = nelem * elemsz;
+ bufsz = (bufsz + pagesz) % pagesz; /* round up to pagesz */
+
+#ifdef MAP_ANON
+ /* BSD */
+ buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
+ -1 /* fd */, 0 /* offset */);
+#else
+ buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
+ open("/dev/zero", O_RDWR), 0 /* offset */);
+#endif
+
+ if (buf == MAP_FAILED) {
+ printf("failed to map count buffer: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ return buf;
+
+}
+
+static int fork_tcon_client(struct torture_context *tctx,
+ int *tcon_count, unsigned tcon_timelimit,
+ const char *host, const char *share)
+{
+ pid_t child;
+ struct smbcli_state *cli;
+ struct timeval end;
+ struct timeval now;
+ struct smbcli_options options;
+
+ lp_smbcli_options(tctx->lp_ctx, &options);
+
+ child = fork();
+ if (child == -1) {
+ printf("failed to fork child: %s\n,", strerror(errno));
+ return -1;
+ } else if (child != 0) {
+ /* Parent, just return. */
+ return 0;
+ }
+
+ /* Child. Just make as many connections as possible within the
+ * time limit. Don't bother synchronising the child start times
+ * because it's probably not work the effort, and a bit of startup
+ * jitter is probably a more realistic test.
+ */
+
+
+ end = timeval_current();
+ now = timeval_current();
+ end.tv_sec += tcon_timelimit;
+ *tcon_count = 0;
+
+ while (timeval_compare(&now, &end) == -1) {
+ NTSTATUS status;
+
+ status = smbcli_full_connection(NULL, &cli,
+ host, lp_smb_ports(tctx->lp_ctx), share,
+ NULL, cmdline_credentials,
+ lp_resolve_context(tctx->lp_ctx),
+ tctx->ev, &options);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("failed to connect to //%s/%s: %s\n",
+ host, share, nt_errstr(status));
+ goto done;
+ }
+
+ smbcli_tdis(cli);
+
+ *tcon_count = *tcon_count + 1;
+ now = timeval_current();
+ }
+
+done:
+ exit(0);
+}
+
+static bool children_remain(void)
+{
+ /* Reap as many children as possible. */
+ for (;;) {
+ pid_t ret = waitpid(-1, NULL, WNOHANG);
+ if (ret == 0) {
+ /* no children ready */
+ return true;
+ }
+ if (ret == -1) {
+ /* no children left. maybe */
+ return errno == ECHILD ? false : true;
+ }
+ }
+
+ /* notreached */
+ return false;
+}
+
+static double rate_convert_secs(unsigned count,
+ const struct timeval *start, const struct timeval *end)
+{
+ return (double)count /
+ usec_to_sec((double)usec_time_diff(end, start));
+}
+
+/* Test the rate at which the server will accept connections. */
+bool torture_bench_treeconnect(struct torture_context *tctx)
+{
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+
+ int timelimit = torture_setting_int(tctx, "timelimit",
+ TIME_LIMIT_SECS);
+ int nprocs = torture_setting_int(tctx, "nprocs", 4);
+
+ int *curr_counts = map_count_buffer(nprocs, sizeof(int));
+ int *last_counts = talloc_array(NULL, int, nprocs);
+
+ struct timeval now, last, start;
+ int i, delta;
+
+ torture_assert(tctx, nprocs > 0, "bad proc count");
+ torture_assert(tctx, timelimit > 0, "bad timelimit");
+ torture_assert(tctx, curr_counts, "allocation failure");
+ torture_assert(tctx, last_counts, "allocation failure");
+
+ start = last = timeval_current();
+ for (i = 0; i < nprocs; ++i) {
+ fork_tcon_client(tctx, &curr_counts[i], timelimit, host, share);
+ }
+
+ while (children_remain()) {
+
+ sleep(1);
+ now = timeval_current();
+
+ for (i = 0, delta = 0; i < nprocs; ++i) {
+ delta += curr_counts[i] - last_counts[i];
+ }
+
+ printf("%u connections/sec\n",
+ (unsigned)rate_convert_secs(delta, &last, &now));
+
+ memcpy(last_counts, curr_counts, nprocs * sizeof(int));
+ last = timeval_current();
+ }
+
+ now = timeval_current();
+
+ for (i = 0, delta = 0; i < nprocs; ++i) {
+ delta += curr_counts[i];
+ }
+
+ printf("TOTAL: %u connections/sec over %u secs\n",
+ (unsigned)rate_convert_secs(delta, &start, &now),
+ timelimit);
+ return true;
+}
+
+/* vim: set sts=8 sw=8 : */
diff --git a/source4/torture/rpc/async_bind.c b/source4/torture/rpc/async_bind.c
index 1ca3c62df0..0ebbef1ce6 100644
--- a/source4/torture/rpc/async_bind.c
+++ b/source4/torture/rpc/async_bind.c
@@ -39,7 +39,6 @@ bool torture_async_bind(struct torture_context *torture)
{
NTSTATUS status;
TALLOC_CTX *mem_ctx;
- struct event_context *evt_ctx;
int i;
const char *binding_string;
struct cli_credentials *creds;
@@ -70,15 +69,11 @@ bool torture_async_bind(struct torture_context *torture)
/* credentials */
creds = cmdline_credentials;
- /* event context */
- evt_ctx = cli_credentials_get_event_context(creds);
- if (evt_ctx == NULL) return false;
-
/* send bind requests */
for (i = 0; i < torture_numasync; i++) {
table[i] = &ndr_table_lsarpc;
bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, binding_string,
- table[i], creds, evt_ctx, torture->lp_ctx);
+ table[i], creds, torture->ev, torture->lp_ctx);
}
/* recv bind requests */
diff --git a/source4/torture/rpc/dfs.c b/source4/torture/rpc/dfs.c
index 5656476922..1c81766ebe 100644
--- a/source4/torture/rpc/dfs.c
+++ b/source4/torture/rpc/dfs.c
@@ -124,7 +124,7 @@ static bool test_CreateDir(TALLOC_CTX *mem_ctx,
{
printf("Creating directory %s\n", dir);
- if (!torture_open_connection_share(mem_ctx, cli, tctx, host, share, NULL)) {
+ if (!torture_open_connection_share(mem_ctx, cli, tctx, host, share, tctx->ev)) {
return false;
}
@@ -494,7 +494,7 @@ static void test_cleanup_stdroot(struct dcerpc_pipe *p,
test_RemoveStdRoot(p, mem_ctx, host, sharename);
test_NetShareDel(mem_ctx, tctx, host, sharename);
- torture_open_connection_share(mem_ctx, &cli, tctx, host, "C$", NULL);
+ torture_open_connection_share(mem_ctx, &cli, tctx, host, "C$", tctx->ev);
test_DeleteDir(cli, dir);
torture_close_connection(cli);
}
diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c
index b28e429a75..989a1faf27 100644
--- a/source4/torture/rpc/dssync.c
+++ b/source4/torture/rpc/dssync.c
@@ -178,12 +178,11 @@ static bool _test_DsBind(struct torture_context *tctx,
{
NTSTATUS status;
bool ret = true;
- struct event_context *event = NULL;
status = dcerpc_pipe_connect_b(ctx,
&b->pipe, ctx->drsuapi_binding,
&ndr_table_drsuapi,
- credentials, event, tctx->lp_ctx);
+ credentials, tctx->ev, tctx->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status));
@@ -254,10 +253,11 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
struct drsuapi_DsCrackNames r;
struct drsuapi_DsNameString names[1];
bool ret = true;
-
- struct cldap_socket *cldap = cldap_socket_init(ctx, NULL, lp_iconv_convenience(tctx->lp_ctx));
+ struct cldap_socket *cldap;
struct cldap_netlogon search;
-
+
+ cldap = cldap_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
r.in.bind_handle = &ctx->admin.drsuapi.bind_handle;
r.in.level = 1;
r.in.req.req1.codepage = 1252; /* western european */
@@ -288,16 +288,17 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
search.in.dest_address = ctx->drsuapi_binding->host;
search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
search.in.acct_control = -1;
- search.in.version = 6;
+ search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+ search.in.map_response = true;
status = cldap_netlogon(cldap, ctx, &search);
if (!NT_STATUS_IS_OK(status)) {
const char *errstr = nt_errstr(status);
ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name");
printf("cldap_netlogon() returned %s. Defaulting to Site-Name: %s\n", errstr, ctx->site_name);
} else {
- ctx->site_name = talloc_steal(ctx, search.out.netlogon.logon5.client_site);
+ ctx->site_name = talloc_steal(ctx, search.out.netlogon.nt5_ex.client_site);
printf("cldap_netlogon() returned Client Site-Name: %s.\n",ctx->site_name);
- printf("cldap_netlogon() returned Server Site-Name: %s.\n",search.out.netlogon.logon5.server_site);
+ printf("cldap_netlogon() returned Server Site-Name: %s.\n",search.out.netlogon.nt5_ex.server_site);
}
return ret;
diff --git a/source4/torture/rpc/join.c b/source4/torture/rpc/join.c
index 849b9fd1e9..cd5eb32fa8 100644
--- a/source4/torture/rpc/join.c
+++ b/source4/torture/rpc/join.c
@@ -39,7 +39,7 @@ bool torture_rpc_join(struct torture_context *torture)
"IPC$", NULL,
machine_account,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("%s failed to connect to IPC$ with workstation credentials\n",
TORTURE_NETBIOS_NAME));
@@ -65,7 +65,7 @@ bool torture_rpc_join(struct torture_context *torture)
"IPC$", NULL,
machine_account,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("%s failed to connect to IPC$ with workstation credentials\n",
TORTURE_NETBIOS_NAME));
diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c
index 6e38d0465a..acc1220ccc 100644
--- a/source4/torture/rpc/rpc.c
+++ b/source4/torture/rpc/rpc.c
@@ -23,7 +23,7 @@
#include "lib/cmdline/popt_common.h"
#include "librpc/rpc/dcerpc.h"
#include "torture/rpc/rpc.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "librpc/ndr/ndr_table.h"
#include "lib/util/dlinklist.h"
@@ -83,7 +83,7 @@ _PUBLIC_ NTSTATUS torture_rpc_connection(struct torture_context *tctx,
status = dcerpc_pipe_connect_b(tctx,
p, binding, table,
- cmdline_credentials, NULL, tctx->lp_ctx);
+ cmdline_credentials, tctx->ev, tctx->lp_ctx);
if (NT_STATUS_IS_ERR(status)) {
printf("Failed to connect to remote server: %s %s\n",
@@ -113,7 +113,7 @@ NTSTATUS torture_rpc_connection_transport(struct torture_context *tctx,
binding->assoc_group_id = assoc_group_id;
status = dcerpc_pipe_connect_b(tctx, p, binding, table,
- cmdline_credentials, NULL, tctx->lp_ctx);
+ cmdline_credentials, tctx->ev, tctx->lp_ctx);
if (NT_STATUS_IS_ERR(status)) {
*p = NULL;
@@ -147,7 +147,7 @@ static bool torture_rpc_setup_machine(struct torture_context *tctx,
&(tcase_data->pipe),
binding,
tcase->table,
- tcase_data->credentials, NULL, tctx->lp_ctx);
+ tcase_data->credentials, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
@@ -205,7 +205,7 @@ static bool torture_rpc_setup_anonymous(struct torture_context *tctx,
&(tcase_data->pipe),
binding,
tcase->table,
- tcase_data->credentials, NULL, tctx->lp_ctx);
+ tcase_data->credentials, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
@@ -399,6 +399,7 @@ NTSTATUS torture_rpc_init(void)
torture_suite_add_simple_test(suite, "SAMSYNC", torture_rpc_samsync);
torture_suite_add_simple_test(suite, "SCHANNEL", torture_rpc_schannel);
torture_suite_add_simple_test(suite, "SCHANNEL2", torture_rpc_schannel2);
+ torture_suite_add_simple_test(suite, "BENCH-SCHANNEL1", torture_rpc_schannel_bench1);
torture_suite_add_suite(suite, torture_rpc_srvsvc(suite));
torture_suite_add_suite(suite, torture_rpc_svcctl(suite));
torture_suite_add_suite(suite, torture_rpc_samr_accessmask(suite));
diff --git a/source4/torture/rpc/rpc.h b/source4/torture/rpc/rpc.h
index d0a0727787..48db814b7a 100644
--- a/source4/torture/rpc/rpc.h
+++ b/source4/torture/rpc/rpc.h
@@ -28,7 +28,7 @@
#include "librpc/rpc/dcerpc.h"
#include "libcli/raw/libcliraw.h"
#include "torture/rpc/proto.h"
-#include "torture/ui.h"
+#include "torture/torture.h"
struct torture_rpc_tcase {
struct torture_tcase tcase;
diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c
index 8eb1f54b4f..17342f9b86 100644
--- a/source4/torture/rpc/samba3rpc.c
+++ b/source4/torture/rpc/samba3rpc.c
@@ -89,7 +89,7 @@ bool torture_bind_authcontext(struct torture_context *torture)
lp_smb_ports(torture->lp_ctx),
"IPC$", NULL, cmdline_credentials,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("smbcli_full_connection failed: %s\n",
nt_errstr(status));
@@ -303,7 +303,7 @@ bool torture_bind_samba3(struct torture_context *torture)
lp_smb_ports(torture->lp_ctx),
"IPC$", NULL, cmdline_credentials,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("smbcli_full_connection failed: %s\n",
nt_errstr(status));
@@ -426,7 +426,7 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli,
"builtin") ? 1:0;
l.in.connect_handle = &conn_handle;
- domain_name.string = enumdom.out.sam->entries[0].name.string;
+ domain_name.string = enumdom.out.sam->entries[dom_idx].name.string;
*domain = talloc_strdup(mem_ctx, domain_name.string);
l.in.domain_name = &domain_name;
@@ -1220,7 +1220,7 @@ bool torture_netlogon_samba3(struct torture_context *torture)
lp_smb_ports(torture->lp_ctx),
"IPC$", NULL, anon_creds,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("smbcli_full_connection failed: %s\n",
nt_errstr(status));
@@ -1307,7 +1307,7 @@ static bool test_join3(struct torture_context *tctx,
lp_smb_ports(tctx->lp_ctx),
"IPC$", NULL, smb_creds,
lp_resolve_context(tctx->lp_ctx),
- NULL, &options);
+ tctx->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("smbcli_full_connection failed: %s\n",
nt_errstr(status));
@@ -1682,7 +1682,7 @@ bool torture_samba3_rpc_getusername(struct torture_context *torture)
lp_smb_ports(torture->lp_ctx),
"IPC$", NULL, cmdline_credentials,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("(%s) smbcli_full_connection failed: %s\n",
__location__, nt_errstr(status));
@@ -1709,7 +1709,7 @@ bool torture_samba3_rpc_getusername(struct torture_context *torture)
lp_smb_ports(torture->lp_ctx),
"IPC$", NULL, anon_creds,
lp_resolve_context(torture->lp_ctx),
- NULL, &options);
+ torture->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
d_printf("(%s) anon smbcli_full_connection failed: %s\n",
__location__, nt_errstr(status));
@@ -1924,7 +1924,7 @@ bool torture_samba3_rpc_srvsvc(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli, torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
talloc_free(mem_ctx);
return false;
}
@@ -1986,7 +1986,7 @@ bool torture_samba3_rpc_randomauth2(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli,
torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
d_printf("IPC$ connection failed\n");
goto done;
}
@@ -2281,7 +2281,7 @@ bool torture_samba3_rpc_sharesec(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli, torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
d_printf("IPC$ connection failed\n");
talloc_free(mem_ctx);
return false;
@@ -2329,7 +2329,7 @@ bool torture_samba3_rpc_lsa(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli, torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
d_printf("IPC$ connection failed\n");
talloc_free(mem_ctx);
return false;
@@ -2611,7 +2611,7 @@ bool torture_samba3_rpc_spoolss(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli, torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
d_printf("IPC$ connection failed\n");
talloc_free(mem_ctx);
return false;
@@ -2797,7 +2797,7 @@ bool torture_samba3_rpc_wkssvc(struct torture_context *torture)
if (!(torture_open_connection_share(
mem_ctx, &cli, torture, torture_setting_string(torture, "host", NULL),
- "IPC$", NULL))) {
+ "IPC$", torture->ev))) {
d_printf("IPC$ connection failed\n");
talloc_free(mem_ctx);
return false;
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 24b2511bc7..ab3283a952 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -1602,7 +1602,7 @@ bool torture_rpc_samlogon(struct torture_context *torture)
status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
&ndr_table_netlogon,
- machine_credentials, NULL, torture->lp_ctx);
+ machine_credentials, torture->ev, torture->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index 3b152d92aa..9705f7b0de 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -1560,7 +1560,7 @@ bool torture_rpc_samsync(struct torture_context *torture)
status = dcerpc_pipe_connect_b(samsync_state,
&samsync_state->p, b,
&ndr_table_netlogon,
- credentials, NULL, torture->lp_ctx);
+ credentials, torture->ev, torture->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status));
@@ -1598,7 +1598,7 @@ bool torture_rpc_samsync(struct torture_context *torture)
&samsync_state->p_netlogon_wksta,
b_netlogon_wksta,
&ndr_table_netlogon,
- credentials_wksta, NULL, torture->lp_ctx);
+ credentials_wksta, torture->ev, torture->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to server as a Workstation: %s\n", nt_errstr(status));
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
index 19b871f9c0..a8f70b2ea9 100644
--- a/source4/torture/rpc/schannel.c
+++ b/source4/torture/rpc/schannel.c
@@ -33,6 +33,8 @@
#include "param/param.h"
#include "librpc/rpc/dcerpc_proto.h"
#include "auth/gensec/gensec.h"
+#include "libcli/composite/composite.h"
+#include "lib/events/events.h"
#define TEST_MACHINE_NAME "schannel"
@@ -258,7 +260,7 @@ static bool test_schannel(struct torture_context *tctx,
b->flags |= dcerpc_flags;
status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr,
- credentials, NULL, tctx->lp_ctx);
+ credentials, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status,
"Failed to connect with schannel");
@@ -270,7 +272,7 @@ static bool test_schannel(struct torture_context *tctx,
* the second */
/* Swap the binding details from SAMR to NETLOGON */
- status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, NULL, tctx->lp_ctx);
+ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "epm map");
status = dcerpc_secondary_connection(p, &p_netlogon,
@@ -296,7 +298,7 @@ static bool test_schannel(struct torture_context *tctx,
"Failed to process schannel secured NETLOGON EX ops");
/* Swap the binding details from SAMR to LSARPC */
- status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, NULL, tctx->lp_ctx);
+ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "epm map");
status = dcerpc_secondary_connection(p, &p_lsa,
@@ -328,7 +330,7 @@ static bool test_schannel(struct torture_context *tctx,
b->flags |= dcerpc_flags;
status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr,
- credentials, NULL, tctx->lp_ctx);
+ credentials, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status,
"Failed to connect with schannel");
@@ -337,7 +339,7 @@ static bool test_schannel(struct torture_context *tctx,
"Failed to process schannel secured SAMR ops (on fresh connection)");
/* Swap the binding details from SAMR to NETLOGON */
- status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, NULL, tctx->lp_ctx);
+ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "epm");
status = dcerpc_secondary_connection(p_samr2, &p_netlogon2,
@@ -370,7 +372,7 @@ static bool test_schannel(struct torture_context *tctx,
b->flags &= ~DCERPC_AUTH_OPTIONS;
status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon,
- credentials, NULL, tctx->lp_ctx);
+ credentials, tctx->ev, tctx->lp_ctx);
torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel");
torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds),
@@ -453,12 +455,12 @@ bool torture_rpc_schannel2(struct torture_context *torture)
printf("Opening first connection\n");
status = dcerpc_pipe_connect_b(torture, &p1, b, &ndr_table_netlogon,
- credentials1, NULL, torture->lp_ctx);
+ credentials1, torture->ev, torture->lp_ctx);
torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
torture_comment(torture, "Opening second connection\n");
status = dcerpc_pipe_connect_b(torture, &p2, b, &ndr_table_netlogon,
- credentials2, NULL, torture->lp_ctx);
+ credentials2, torture->ev, torture->lp_ctx);
torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
credentials1->netlogon_creds = NULL;
@@ -484,3 +486,350 @@ bool torture_rpc_schannel2(struct torture_context *torture)
return true;
}
+struct torture_schannel_bench;
+
+struct torture_schannel_bench_conn {
+ struct torture_schannel_bench *s;
+ int index;
+ struct cli_credentials *wks_creds;
+ struct dcerpc_pipe *pipe;
+ struct netr_LogonSamLogonEx r;
+ struct netr_NetworkInfo ninfo;
+ TALLOC_CTX *tmp;
+ uint64_t total;
+ uint32_t count;
+};
+
+struct torture_schannel_bench {
+ struct torture_context *tctx;
+ bool progress;
+ int timelimit;
+ int nprocs;
+ int nconns;
+ struct torture_schannel_bench_conn *conns;
+ struct test_join *join_ctx1;
+ struct cli_credentials *wks_creds1;
+ struct test_join *join_ctx2;
+ struct cli_credentials *wks_creds2;
+ struct cli_credentials *user1_creds;
+ struct cli_credentials *user2_creds;
+ struct dcerpc_binding *b;
+ NTSTATUS error;
+ uint64_t total;
+ uint32_t count;
+ bool stopped;
+};
+
+static void torture_schannel_bench_connected(struct composite_context *c)
+{
+ struct torture_schannel_bench_conn *conn =
+ (struct torture_schannel_bench_conn *)c->async.private_data;
+ struct torture_schannel_bench *s = talloc_get_type(conn->s,
+ struct torture_schannel_bench);
+
+ s->error = dcerpc_pipe_connect_b_recv(c, s->conns, &conn->pipe);
+ torture_comment(s->tctx, "conn[%u]: %s\n", conn->index, nt_errstr(s->error));
+ if (NT_STATUS_IS_OK(s->error)) {
+ s->nconns++;
+ }
+}
+
+static void torture_schannel_bench_recv(struct rpc_request *req);
+
+static bool torture_schannel_bench_start(struct torture_schannel_bench_conn *conn)
+{
+ struct torture_schannel_bench *s = conn->s;
+ NTSTATUS status;
+ DATA_BLOB names_blob, chal, lm_resp, nt_resp;
+ int flags = CLI_CRED_NTLM_AUTH;
+ struct rpc_request *req;
+ struct cli_credentials *user_creds;
+
+ if (conn->total % 2) {
+ user_creds = s->user1_creds;
+ } else {
+ user_creds = s->user2_creds;
+ }
+
+ if (lp_client_lanman_auth(s->tctx->lp_ctx)) {
+ flags |= CLI_CRED_LANMAN_AUTH;
+ }
+
+ if (lp_client_ntlmv2_auth(s->tctx->lp_ctx)) {
+ flags |= CLI_CRED_NTLMv2_AUTH;
+ }
+
+ talloc_free(conn->tmp);
+ conn->tmp = talloc_new(s);
+ ZERO_STRUCT(conn->ninfo);
+ ZERO_STRUCT(conn->r);
+
+ cli_credentials_get_ntlm_username_domain(user_creds, conn->tmp,
+ &conn->ninfo.identity_info.account_name.string,
+ &conn->ninfo.identity_info.domain_name.string);
+
+ generate_random_buffer(conn->ninfo.challenge,
+ sizeof(conn->ninfo.challenge));
+ chal = data_blob_const(conn->ninfo.challenge,
+ sizeof(conn->ninfo.challenge));
+
+ names_blob = NTLMv2_generate_names_blob(conn->tmp, lp_iconv_convenience(s->tctx->lp_ctx),
+ cli_credentials_get_workstation(conn->wks_creds),
+ cli_credentials_get_domain(conn->wks_creds));
+
+ status = cli_credentials_get_ntlm_response(user_creds, conn->tmp,
+ &flags,
+ chal,
+ names_blob,
+ &lm_resp, &nt_resp,
+ NULL, NULL);
+ torture_assert_ntstatus_ok(s->tctx, status,
+ "cli_credentials_get_ntlm_response failed");
+
+ conn->ninfo.lm.data = lm_resp.data;
+ conn->ninfo.lm.length = lm_resp.length;
+
+ conn->ninfo.nt.data = nt_resp.data;
+ conn->ninfo.nt.length = nt_resp.length;
+
+ conn->ninfo.identity_info.parameter_control = 0;
+ conn->ninfo.identity_info.logon_id_low = 0;
+ conn->ninfo.identity_info.logon_id_high = 0;
+ conn->ninfo.identity_info.workstation.string = cli_credentials_get_workstation(conn->wks_creds);
+
+ conn->r.in.server_name = talloc_asprintf(conn->tmp, "\\\\%s", dcerpc_server_name(conn->pipe));
+ conn->r.in.computer_name = cli_credentials_get_workstation(conn->wks_creds);
+ conn->r.in.logon_level = 2;
+ conn->r.in.logon.network = &conn->ninfo;
+ conn->r.in.flags = 0;
+ conn->r.in.validation_level = 2;
+
+ req = dcerpc_netr_LogonSamLogonEx_send(conn->pipe, conn->tmp, &conn->r);
+ torture_assert(s->tctx, req, "Failed to setup LogonSamLogonEx request");
+
+ req->async.callback = torture_schannel_bench_recv;
+ req->async.private_data = conn;
+
+ return true;
+}
+
+static void torture_schannel_bench_recv(struct rpc_request *req)
+{
+ bool ret;
+ struct torture_schannel_bench_conn *conn =
+ (struct torture_schannel_bench_conn *)req->async.private_data;
+ struct torture_schannel_bench *s = talloc_get_type(conn->s,
+ struct torture_schannel_bench);
+
+ s->error = dcerpc_ndr_request_recv(req);
+ if (!NT_STATUS_IS_OK(s->error)) {
+ return;
+ }
+
+ conn->total++;
+ conn->count++;
+
+ if (s->stopped) {
+ return;
+ }
+
+ ret = torture_schannel_bench_start(conn);
+ if (!ret) {
+ s->error = NT_STATUS_INTERNAL_ERROR;
+ }
+}
+
+/*
+ test multiple schannel connection in parallel
+ */
+bool torture_rpc_schannel_bench1(struct torture_context *torture)
+{
+ bool ret = true;
+ NTSTATUS status;
+ const char *binding = torture_setting_string(torture, "binding", NULL);
+ struct torture_schannel_bench *s;
+ struct timeval start;
+ struct timeval end;
+ int i;
+ const char *tmp;
+
+ s = talloc_zero(torture, struct torture_schannel_bench);
+ s->tctx = torture;
+ s->progress = torture_setting_bool(torture, "progress", true);
+ s->timelimit = torture_setting_int(torture, "timelimit", 10);
+ s->nprocs = torture_setting_int(torture, "nprocs", 4);
+ s->conns = talloc_zero_array(s, struct torture_schannel_bench_conn, s->nprocs);
+
+ s->user1_creds = (struct cli_credentials *)talloc_memdup(s,
+ cmdline_credentials,
+ sizeof(*s->user1_creds));
+ tmp = torture_setting_string(s->tctx, "extra_user1", NULL);
+ if (tmp) {
+ cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
+ }
+ s->user2_creds = (struct cli_credentials *)talloc_memdup(s,
+ cmdline_credentials,
+ sizeof(*s->user1_creds));
+ tmp = torture_setting_string(s->tctx, "extra_user2", NULL);
+ if (tmp) {
+ cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
+ }
+
+ s->join_ctx1 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sb", TEST_MACHINE_NAME),
+ ACB_WSTRUST, &s->wks_creds1);
+ torture_assert(torture, s->join_ctx1 != NULL,
+ "Failed to join domain with acct_flags=ACB_WSTRUST");
+ s->join_ctx2 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sc", TEST_MACHINE_NAME),
+ ACB_WSTRUST, &s->wks_creds2);
+ torture_assert(torture, s->join_ctx2 != NULL,
+ "Failed to join domain with acct_flags=ACB_WSTRUST");
+
+ cli_credentials_set_kerberos_state(s->wks_creds1, CRED_DONT_USE_KERBEROS);
+ cli_credentials_set_kerberos_state(s->wks_creds2, CRED_DONT_USE_KERBEROS);
+
+ for (i=0; i < s->nprocs; i++) {
+ s->conns[i].s = s;
+ s->conns[i].index = i;
+ s->conns[i].wks_creds = (struct cli_credentials *)talloc_memdup(
+ s->conns, s->wks_creds1,sizeof(*s->wks_creds1));
+ if ((i % 2) && (torture_setting_bool(torture, "multijoin", false))) {
+ memcpy(s->conns[i].wks_creds, s->wks_creds2,
+ talloc_get_size(s->conns[i].wks_creds));
+ }
+ s->conns[i].wks_creds->netlogon_creds = NULL;
+ }
+
+ status = dcerpc_parse_binding(s, binding, &s->b);
+ torture_assert_ntstatus_ok(torture, status, "Bad binding string");
+ s->b->flags &= ~DCERPC_AUTH_OPTIONS;
+ s->b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN;
+
+ torture_comment(torture, "Opening %d connections in parallel\n", s->nprocs);
+ for (i=0; i < s->nprocs; i++) {
+#if 1
+ s->error = dcerpc_pipe_connect_b(s->conns, &s->conns[i].pipe, s->b,
+ &ndr_table_netlogon,
+ s->conns[i].wks_creds,
+ torture->ev, torture->lp_ctx);
+ torture_assert_ntstatus_ok(torture, s->error, "Failed to connect with schannel");
+#else
+ /*
+ * This path doesn't work against windows,
+ * because of windows drops the connections
+ * which haven't reached a session setup yet
+ *
+ * The same as the reset on zero vc stuff.
+ */
+ struct composite_context *c;
+ c = dcerpc_pipe_connect_b_send(s->conns, s->b,
+ &ndr_table_netlogon,
+ s->conns[i].wks_creds,
+ torture->ev,
+ torture->lp_ctx);
+ torture_assert(torture, c != NULL, "Failed to setup connect");
+ c->async.fn = torture_schannel_bench_connected;
+ c->async.private_data = &s->conns[i];
+ }
+
+ while (NT_STATUS_IS_OK(s->error) && s->nprocs != s->nconns) {
+ int ev_ret = event_loop_once(torture->ev);
+ torture_assert(torture, ev_ret == 0, "event_loop_once failed");
+#endif
+ }
+ torture_assert_ntstatus_ok(torture, s->error, "Failed establish a connect");
+
+ /*
+ * Change the workstation password after establishing the netlogon
+ * schannel connections to prove that existing connections are not
+ * affected by a wks pwchange.
+ */
+
+ {
+ struct netr_ServerPasswordSet pwset;
+ char *password = generate_random_str(s->join_ctx1, 8);
+ struct creds_CredentialState *creds_state;
+ struct dcerpc_pipe *net_pipe;
+
+ status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
+ &ndr_table_netlogon,
+ s->wks_creds1,
+ torture->ev, torture->lp_ctx);
+
+ torture_assert_ntstatus_ok(torture, status,
+ "dcerpc_pipe_connect_b failed");
+
+ pwset.in.server_name = talloc_asprintf(
+ net_pipe, "\\\\%s", dcerpc_server_name(net_pipe));
+ pwset.in.computer_name =
+ cli_credentials_get_workstation(s->wks_creds1);
+ pwset.in.account_name = talloc_asprintf(
+ net_pipe, "%s$", pwset.in.computer_name);
+ pwset.in.secure_channel_type = SEC_CHAN_WKSTA;
+ E_md4hash(password, pwset.in.new_password.hash);
+
+ creds_state = cli_credentials_get_netlogon_creds(
+ s->wks_creds1);
+ creds_des_encrypt(creds_state, &pwset.in.new_password);
+ creds_client_authenticator(creds_state, &pwset.in.credential);
+
+ status = dcerpc_netr_ServerPasswordSet(net_pipe, torture, &pwset);
+ torture_assert_ntstatus_ok(torture, status,
+ "ServerPasswordSet failed");
+
+ if (!creds_client_check(creds_state,
+ &pwset.out.return_authenticator.cred)) {
+ printf("Credential chaining failed\n");
+ }
+
+ cli_credentials_set_password(s->wks_creds1, password,
+ CRED_SPECIFIED);
+
+ talloc_free(net_pipe);
+
+ /* Just as a test, connect with the new creds */
+
+ talloc_free(s->wks_creds1->netlogon_creds);
+ s->wks_creds1->netlogon_creds = NULL;
+
+ status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
+ &ndr_table_netlogon,
+ s->wks_creds1,
+ torture->ev, torture->lp_ctx);
+
+ torture_assert_ntstatus_ok(torture, status,
+ "dcerpc_pipe_connect_b failed");
+
+ talloc_free(net_pipe);
+ }
+
+ torture_comment(torture, "Start looping LogonSamLogonEx on %d connections for %d secs\n",
+ s->nprocs, s->timelimit);
+ for (i=0; i < s->nprocs; i++) {
+ ret = torture_schannel_bench_start(&s->conns[i]);
+ torture_assert(torture, ret, "Failed to setup LogonSamLogonEx");
+ }
+
+ start = timeval_current();
+ end = timeval_add(&start, s->timelimit, 0);
+
+ while (NT_STATUS_IS_OK(s->error) && !timeval_expired(&end)) {
+ int ev_ret = event_loop_once(torture->ev);
+ torture_assert(torture, ev_ret == 0, "event_loop_once failed");
+ }
+ torture_assert_ntstatus_ok(torture, s->error, "Failed some request");
+ s->stopped = true;
+ talloc_free(s->conns);
+
+ for (i=0; i < s->nprocs; i++) {
+ s->total += s->conns[i].total;
+ }
+
+ torture_comment(torture,
+ "Total ops[%llu] (%u ops/s)\n",
+ (unsigned long long)s->total,
+ (unsigned)s->total/s->timelimit);
+
+ torture_leave_domain(s->join_ctx1);
+ torture_leave_domain(s->join_ctx2);
+ return true;
+}
diff --git a/source4/torture/rpc/session_key.c b/source4/torture/rpc/session_key.c
index fcb828ddb2..0df7e576ee 100644
--- a/source4/torture/rpc/session_key.c
+++ b/source4/torture/rpc/session_key.c
@@ -158,7 +158,11 @@ static bool test_secrets(struct torture_context *torture, const void *_data)
binding->flags |= settings->bindoptions;
torture_assert_ntstatus_ok(torture,
- dcerpc_pipe_connect_b(torture, &p, binding, &ndr_table_lsarpc, cmdline_credentials, NULL, torture->lp_ctx),
+ dcerpc_pipe_connect_b(torture, &p, binding,
+ &ndr_table_lsarpc,
+ cmdline_credentials,
+ torture->ev,
+ torture->lp_ctx),
"connect");
if (!test_lsa_OpenPolicy2(p, torture, &handle)) {
diff --git a/source4/torture/rpc/spoolss_notify.c b/source4/torture/rpc/spoolss_notify.c
index 19cff53d84..ab6309d55f 100644
--- a/source4/torture/rpc/spoolss_notify.c
+++ b/source4/torture/rpc/spoolss_notify.c
@@ -21,7 +21,6 @@
#include "includes.h"
#include "torture/torture.h"
-#include "torture/ui.h"
#include "torture/rpc/rpc.h"
#include "librpc/gen_ndr/ndr_spoolss_c.h"
#include "rpc_server/dcerpc_server.h"
diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c
index 9e2921d406..9ce9fb7526 100644
--- a/source4/torture/rpc/spoolss_win.c
+++ b/source4/torture/rpc/spoolss_win.c
@@ -20,7 +20,6 @@
#include "includes.h"
#include "torture/torture.h"
-#include "torture/ui.h"
#include "torture/rpc/rpc.h"
#include "librpc/gen_ndr/ndr_spoolss_c.h"
#include "rpc_server/dcerpc_server.h"
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
index 100e7cead2..51efd99bd8 100644
--- a/source4/torture/rpc/testjoin.c
+++ b/source4/torture/rpc/testjoin.c
@@ -508,9 +508,11 @@ _PUBLIC_ void torture_leave_domain(struct test_join *join)
/* Delete machine account */
status = dcerpc_samr_DeleteUser(join->p, join, &d);
if (!NT_STATUS_IS_OK(status)) {
- printf("Delete of machine account failed\n");
+ printf("Delete of machine account %s failed\n",
+ join->netbios_name);
} else {
- printf("Delete of machine account was successful.\n");
+ printf("Delete of machine account %s was successful.\n",
+ join->netbios_name);
}
if (join->libnet_r) {
diff --git a/source4/torture/smb2/config.mk b/source4/torture/smb2/config.mk
index 379632f0e7..11c4e1fa2c 100644
--- a/source4/torture/smb2/config.mk
+++ b/source4/torture/smb2/config.mk
@@ -2,16 +2,14 @@
#################################
# Start SUBSYSTEM TORTURE_SMB2
[MODULE::TORTURE_SMB2]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_smb2_init
-PRIVATE_PROTO_HEADER = \
- proto.h
PRIVATE_DEPENDENCIES = \
LIBCLI_SMB2 POPT_CREDENTIALS
# End SUBSYSTEM TORTURE_SMB2
#################################
-TORTURE_SMB2_OBJ_FILES = $(addprefix torture/smb2/, \
+TORTURE_SMB2_OBJ_FILES = $(addprefix $(torturesrcdir)/smb2/, \
connect.o \
scan.o \
util.o \
@@ -20,5 +18,9 @@ TORTURE_SMB2_OBJ_FILES = $(addprefix torture/smb2/, \
find.o \
lock.o \
notify.o \
- smb2.o)
+ smb2.o \
+ persistent_handles.o \
+ oplocks.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/smb2/proto.h,$(TORTURE_SMB2_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c
index c47a26277c..906d6e4f8d 100644
--- a/source4/torture/smb2/getinfo.c
+++ b/source4/torture/smb2/getinfo.c
@@ -51,9 +51,9 @@ static struct {
{ LEVEL(RAW_FILEINFO_COMPRESSION_INFORMATION) },
{ LEVEL(RAW_FILEINFO_NETWORK_OPEN_INFORMATION) },
{ LEVEL(RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION) },
-/*
-disabled until we know how the alignment now works
-{ LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) }, */
+/*
+ { LEVEL(RAW_FILEINFO_SMB2_ALL_EAS) },
+*/
{ LEVEL(RAW_FILEINFO_SMB2_ALL_INFORMATION) },
{ LEVEL(RAW_FILEINFO_SEC_DESC) }
};
@@ -107,9 +107,6 @@ static bool torture_smb2_fileinfo(struct torture_context *tctx, struct smb2_tree
file_levels[i].dinfo.query_secdesc.in.secinfo_flags = 0x7;
}
if (file_levels[i].level == RAW_FILEINFO_SMB2_ALL_EAS) {
- if (torture_setting_bool(tctx, "samba4", false)) {
- continue;
- }
file_levels[i].finfo.all_eas.in.continue_flags =
SMB2_CONTINUE_FLAG_RESTART;
file_levels[i].dinfo.all_eas.in.continue_flags =
@@ -183,6 +180,9 @@ bool torture_smb2_getinfo(struct torture_context *torture)
return false;
}
+ smb2_deltree(tree, FNAME);
+ smb2_deltree(tree, DNAME);
+
status = torture_setup_complex_file(tree, FNAME);
if (!NT_STATUS_IS_OK(status)) {
return false;
diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c
index 3cf2e93ee0..1a56cb9cad 100644
--- a/source4/torture/smb2/lock.c
+++ b/source4/torture/smb2/lock.c
@@ -51,6 +51,7 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
struct smb2_handle h;
uint8_t buf[200];
struct smb2_lock lck;
+ struct smb2_lock_element el[1];
ZERO_STRUCT(buf);
@@ -60,126 +61,132 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree
status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
CHECK_STATUS(status, NT_STATUS_OK);
- lck.in.unknown1 = 0x0000;
- lck.in.unknown2 = 0x00000000;
+ lck.in.locks = el;
+
+ lck.in.lock_count = 0x0000;
+ lck.in.reserved = 0x00000000;
lck.in.file.handle = h;
- lck.in.offset = 0x0000000000000000;
- lck.in.count = 0x0000000000000000;
- lck.in.unknown5 = 0x0000000000000000;
- lck.in.flags = 0x00000000;
+ el[0].offset = 0x0000000000000000;
+ el[0].length = 0x0000000000000000;
+ el[0].reserved = 0x0000000000000000;
+ el[0].flags = 0x00000000;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x00000000;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x00000000;
lck.in.file.handle = h;
- lck.in.offset = 0;
- lck.in.count = 0;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = SMB2_LOCK_FLAG_NONE;
+ el[0].offset = 0;
+ el[0].length = 0;
+ el[0].reserved = 0x00000000;
+ el[0].flags = SMB2_LOCK_FLAG_NONE;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
lck.in.file.handle.data[0] +=1;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
lck.in.file.handle.data[0] -=1;
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0xFFFFFFFF;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x123ab1;
lck.in.file.handle = h;
- lck.in.offset = UINT64_MAX;
- lck.in.count = UINT64_MAX;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = SMB2_LOCK_FLAG_EXCLUSIV|SMB2_LOCK_FLAG_NO_PENDING;
+ el[0].offset = UINT64_MAX;
+ el[0].length = UINT64_MAX;
+ el[0].reserved = 0x00000000;
+ el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
+ lck.in.reserved = 0x123ab2;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
+ lck.in.reserved = 0x123ab3;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
+ lck.in.reserved = 0x123ab4;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
+ lck.in.reserved = 0x123ab5;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x12345678;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x12345678;
lck.in.file.handle = h;
- lck.in.offset = UINT32_MAX;
- lck.in.count = UINT32_MAX;
- lck.in.unknown5 = 0x87654321;
- lck.in.flags = SMB2_LOCK_FLAG_EXCLUSIV|SMB2_LOCK_FLAG_NO_PENDING;
+ el[0].offset = UINT32_MAX;
+ el[0].length = UINT32_MAX;
+ el[0].reserved = 0x87654321;
+ el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
- lck.in.flags = 0x00000000;
+ el[0].flags = 0x00000000;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
- lck.in.flags = 0x00000001;
+ el[0].flags = 0x00000001;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x87654321;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x87654321;
lck.in.file.handle = h;
- lck.in.offset = 0x00000000FFFFFFFF;
- lck.in.count = 0x00000000FFFFFFFF;
- lck.in.unknown5 = 0x12345678;
- lck.in.flags = SMB2_LOCK_FLAG_UNLOCK;
+ el[0].offset = 0x00000000FFFFFFFF;
+ el[0].length = 0x00000000FFFFFFFF;
+ el[0].reserved = 0x1234567;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x12345678;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x1234567;
lck.in.file.handle = h;
- lck.in.offset = 0x00000000FFFFFFFF;
- lck.in.count = 0x00000000FFFFFFFF;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = SMB2_LOCK_FLAG_UNLOCK;
+ el[0].offset = 0x00000000FFFFFFFF;
+ el[0].length = 0x00000000FFFFFFFF;
+ el[0].reserved = 0x00000000;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
status = smb2_lock(tree, &lck);
- CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
+ CHECK_STATUS(status, NT_STATUS_OK);
done:
return ret;
@@ -206,6 +213,9 @@ static bool test_lock_read_write(struct torture_context *torture,
struct smb2_create cr;
struct smb2_write wr;
struct smb2_read rd;
+ struct smb2_lock_element el[1];
+
+ lck.in.locks = el;
ZERO_STRUCT(buf);
@@ -215,27 +225,27 @@ static bool test_lock_read_write(struct torture_context *torture,
status = smb2_util_write(tree, h1, buf, 0, ARRAY_SIZE(buf));
CHECK_STATUS(status, NT_STATUS_OK);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x00000000;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x00000000;
lck.in.file.handle = h1;
- lck.in.offset = 0;
- lck.in.count = ARRAY_SIZE(buf)/2;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = s->lock_flags;
+ el[0].offset = 0;
+ el[0].length = ARRAY_SIZE(buf)/2;
+ el[0].reserved = 0x00000000;
+ el[0].flags = s->lock_flags;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x00000000;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x00000000;
lck.in.file.handle = h1;
- lck.in.offset = ARRAY_SIZE(buf)/2;
- lck.in.count = ARRAY_SIZE(buf)/2;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = s->lock_flags;
+ el[0].offset = ARRAY_SIZE(buf)/2;
+ el[0].length = ARRAY_SIZE(buf)/2;
+ el[0].reserved = 0x00000000;
+ el[0].flags = s->lock_flags;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
ZERO_STRUCT(cr);
cr.in.oplock_level = 0;
@@ -286,16 +296,16 @@ static bool test_lock_read_write(struct torture_context *torture,
status = smb2_read(tree, tree, &rd);
CHECK_STATUS(status, s->read_h2_status);
- lck.in.unknown1 = 0x0001;
- lck.in.unknown2 = 0x00000000;
+ lck.in.lock_count = 0x0001;
+ lck.in.reserved = 0x00000000;
lck.in.file.handle = h1;
- lck.in.offset = ARRAY_SIZE(buf)/2;
- lck.in.count = ARRAY_SIZE(buf)/2;
- lck.in.unknown5 = 0x00000000;
- lck.in.flags = SMB2_LOCK_FLAG_UNLOCK;
+ el[0].offset = ARRAY_SIZE(buf)/2;
+ el[0].length = ARRAY_SIZE(buf)/2;
+ el[0].reserved = 0x00000000;
+ el[0].flags = SMB2_LOCK_FLAG_UNLOCK;
status = smb2_lock(tree, &lck);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(lck.out.unknown1, 0);
+ CHECK_VALUE(lck.out.reserved, 0);
ZERO_STRUCT(wr);
wr.in.file.handle = h2;
@@ -349,7 +359,7 @@ static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_t
{
struct test_lock_read_write_state s = {
.fname = "lock_rw_exclusiv.dat",
- .lock_flags = SMB2_LOCK_FLAG_EXCLUSIV,
+ .lock_flags = SMB2_LOCK_FLAG_EXCLUSIVE,
.write_h1_status = NT_STATUS_OK,
.read_h1_status = NT_STATUS_OK,
.write_h2_status = NT_STATUS_FILE_LOCK_CONFLICT,
diff --git a/source4/torture/smb2/oplocks.c b/source4/torture/smb2/oplocks.c
new file mode 100644
index 0000000000..9a06ae1f19
--- /dev/null
+++ b/source4/torture/smb2/oplocks.c
@@ -0,0 +1,178 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ test suite for SMB2 oplocks
+
+ Copyright (C) Stefan Metzmacher 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/security.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "torture/torture.h"
+#include "torture/smb2/proto.h"
+#include "param/param.h"
+
+#define CHECK_VAL(v, correct) do { \
+ if ((v) != (correct)) { \
+ torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
+ __location__, #v, (int)v, (int)correct); \
+ ret = false; \
+ }} while (0)
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
+ nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+static struct {
+ struct smb2_handle handle;
+ uint8_t level;
+ struct smb2_break br;
+ int count;
+ int failures;
+} break_info;
+
+static void torture_oplock_break_callback(struct smb2_request *req)
+{
+ NTSTATUS status;
+ struct smb2_break br;
+
+ ZERO_STRUCT(br);
+ status = smb2_break_recv(req, &break_info.br);
+ if (!NT_STATUS_IS_OK(status)) {
+ break_info.failures++;
+ }
+
+ return;
+}
+
+/* a oplock break request handler */
+static bool torture_oplock_handler(struct smb2_transport *transport,
+ const struct smb2_handle *handle,
+ uint8_t level, void *private_data)
+{
+ struct smb2_tree *tree = private_data;
+ const char *name;
+ struct smb2_request *req;
+
+ break_info.handle = *handle;
+ break_info.level = level;
+ break_info.count++;
+
+ switch (level) {
+ case SMB2_OPLOCK_LEVEL_II:
+ name = "level II";
+ break;
+ case SMB2_OPLOCK_LEVEL_NONE:
+ name = "none";
+ break;
+ default:
+ name = "unknown";
+ break_info.failures++;
+ }
+ printf("Acking to %s [0x%02X] in oplock handler\n",
+ name, level);
+
+ ZERO_STRUCT(break_info.br);
+ break_info.br.in.file.handle = *handle;
+ break_info.br.in.oplock_level = level;
+ break_info.br.in.reserved = 0;
+ break_info.br.in.reserved2 = 0;
+
+ req = smb2_break_send(tree, &break_info.br);
+ req->async.fn = torture_oplock_break_callback;
+ req->async.private_data = NULL;
+
+ return true;
+}
+
+bool torture_smb2_oplock_batch1(struct torture_context *tctx,
+ struct smb2_tree *tree)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ struct smb2_handle h1, h2;
+ struct smb2_create io;
+ NTSTATUS status;
+ const char *fname = "oplock.dat";
+ bool ret = true;
+
+ tree->session->transport->oplock.handler = torture_oplock_handler;
+ tree->session->transport->oplock.private_data = tree;
+
+ smb2_util_unlink(tree, fname);
+
+ ZERO_STRUCT(break_info);
+
+ ZERO_STRUCT(io);
+ io.in.security_flags = 0x00;
+ io.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
+ io.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ io.in.create_flags = 0x00000000;
+ io.in.reserved = 0x00000000;
+ io.in.desired_access = SEC_RIGHTS_FILE_ALL;
+ io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
+ NTCREATEX_OPTIONS_ASYNC_ALERT |
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
+ 0x00200000;
+ io.in.fname = fname;
+
+ status = smb2_create(tree, mem_ctx, &io);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
+ /*CHECK_VAL(io.out.reserved, 0);*/
+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_CREATED);
+ CHECK_VAL(io.out.alloc_size, 0);
+ CHECK_VAL(io.out.size, 0);
+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(io.out.reserved2, 0);
+ CHECK_VAL(break_info.count, 0);
+
+ h1 = io.out.file.handle;
+
+ ZERO_STRUCT(io.in.blobs);
+ status = smb2_create(tree, mem_ctx, &io);
+ CHECK_VAL(break_info.count, 1);
+ CHECK_VAL(break_info.failures, 0);
+ CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_II);
+ /*CHECK_VAL(io.out.reserved, 0);*/
+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED);
+ CHECK_VAL(io.out.alloc_size, 0);
+ CHECK_VAL(io.out.size, 0);
+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(io.out.reserved2, 0);
+
+ h2 = io.out.file.handle;
+
+done:
+ talloc_free(mem_ctx);
+
+ smb2_util_close(tree, h1);
+ smb2_util_close(tree, h2);
+ smb2_util_unlink(tree, fname);
+ return ret;
+}
diff --git a/source4/torture/smb2/persistent_handles.c b/source4/torture/smb2/persistent_handles.c
new file mode 100644
index 0000000000..249ddd1733
--- /dev/null
+++ b/source4/torture/smb2/persistent_handles.c
@@ -0,0 +1,184 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ test suite for SMB2 persistent file handles
+
+ Copyright (C) Stefan Metzmacher 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/security.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
+#include "torture/torture.h"
+#include "torture/smb2/proto.h"
+#include "param/param.h"
+
+#define CHECK_VAL(v, correct) do { \
+ if ((v) != (correct)) { \
+ torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
+ __location__, #v, (int)v, (int)correct); \
+ ret = false; \
+ }} while (0)
+
+#define CHECK_STATUS(status, correct) do { \
+ if (!NT_STATUS_EQUAL(status, correct)) { \
+ torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
+ nt_errstr(status), nt_errstr(correct)); \
+ ret = false; \
+ goto done; \
+ }} while (0)
+
+/*
+ basic testing of SMB2 persistent file handles
+ regarding the position information on the handle
+*/
+bool torture_smb2_persistent_handles1(struct torture_context *tctx,
+ struct smb2_tree *tree1,
+ struct smb2_tree *tree2)
+{
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ struct smb2_handle h1, h2;
+ struct smb2_create io1, io2;
+ NTSTATUS status;
+ const char *fname = "persistent_handles.dat";
+ DATA_BLOB b;
+ union smb_fileinfo qfinfo;
+ union smb_setfileinfo sfinfo;
+ bool ret = true;
+ uint64_t pos;
+
+ smb2_util_unlink(tree1, fname);
+
+ ZERO_STRUCT(io1);
+ io1.in.security_flags = 0x00;
+ io1.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
+ io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+ io1.in.create_flags = 0x00000000;
+ io1.in.reserved = 0x00000000;
+ io1.in.desired_access = SEC_RIGHTS_FILE_ALL;
+ io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+ io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+ NTCREATEX_SHARE_ACCESS_WRITE |
+ NTCREATEX_SHARE_ACCESS_DELETE;
+ io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+ io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
+ NTCREATEX_OPTIONS_ASYNC_ALERT |
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
+ 0x00200000;
+ io1.in.fname = fname;
+
+ b = data_blob_talloc(mem_ctx, NULL, 16);
+ SBVAL(b.data, 0, 0);
+ SBVAL(b.data, 8, 0);
+
+ status = smb2_create_blob_add(tree1, &io1.in.blobs,
+ SMB2_CREATE_TAG_DHNQ,
+ b);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_create(tree1, mem_ctx, &io1);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
+ /*CHECK_VAL(io1.out.reserved, 0);*/
+ CHECK_VAL(io1.out.create_action, NTCREATEX_ACTION_CREATED);
+ CHECK_VAL(io1.out.alloc_size, 0);
+ CHECK_VAL(io1.out.size, 0);
+ CHECK_VAL(io1.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(io1.out.reserved2, 0);
+
+ /* TODO: check extra blob content */
+
+ h1 = io1.out.file.handle;
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(qfinfo.position_information.out.position, 0);
+ pos = qfinfo.position_information.out.position;
+ torture_comment(tctx, "position: %llu\n",
+ (unsigned long long)pos);
+
+ ZERO_STRUCT(sfinfo);
+ sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION;
+ sfinfo.generic.in.file.handle = h1;
+ sfinfo.position_information.in.position = 0x1000;
+ status = smb2_setinfo_file(tree1, &sfinfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
+ pos = qfinfo.position_information.out.position;
+ torture_comment(tctx, "position: %llu\n",
+ (unsigned long long)pos);
+
+ talloc_free(tree1);
+ tree1 = NULL;
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = h1;
+ status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
+ CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
+
+ ZERO_STRUCT(io2);
+ io2.in.fname = fname;
+
+ b = data_blob_talloc(tctx, NULL, 16);
+ SBVAL(b.data, 0, h1.data[0]);
+ SBVAL(b.data, 8, h1.data[1]);
+
+ status = smb2_create_blob_add(tree2, &io2.in.blobs,
+ SMB2_CREATE_TAG_DHNC,
+ b);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ status = smb2_create(tree2, mem_ctx, &io2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH);
+ CHECK_VAL(io2.out.reserved, 0x00);
+ CHECK_VAL(io2.out.create_action, NTCREATEX_ACTION_EXISTED);
+ CHECK_VAL(io2.out.alloc_size, 0);
+ CHECK_VAL(io2.out.size, 0);
+ CHECK_VAL(io2.out.file_attr, FILE_ATTRIBUTE_ARCHIVE);
+ CHECK_VAL(io2.out.reserved2, 0);
+
+ h2 = io2.out.file.handle;
+
+ ZERO_STRUCT(qfinfo);
+ qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
+ qfinfo.generic.in.file.handle = h2;
+ status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VAL(qfinfo.position_information.out.position, 0x1000);
+ pos = qfinfo.position_information.out.position;
+ torture_comment(tctx, "position: %llu\n",
+ (unsigned long long)pos);
+
+ smb2_util_close(tree2, h2);
+
+ talloc_free(mem_ctx);
+
+ smb2_util_unlink(tree2, fname);
+done:
+ return ret;
+}
diff --git a/source4/torture/smb2/scan.c b/source4/torture/smb2/scan.c
index 0f4c9fefdf..889d343a49 100644
--- a/source4/torture/smb2/scan.c
+++ b/source4/torture/smb2/scan.c
@@ -207,7 +207,7 @@ bool torture_smb2_scan(struct torture_context *torture)
status = smb2_connect(mem_ctx, host, share,
lp_resolve_context(torture->lp_ctx),
credentials, &tree,
- event_context_find(mem_ctx));
+ torture->ev);
if (!NT_STATUS_IS_OK(status)) {
printf("Connection failed - %s\n", nt_errstr(status));
return false;
@@ -224,7 +224,7 @@ bool torture_smb2_scan(struct torture_context *torture)
status = smb2_connect(mem_ctx, host, share,
lp_resolve_context(torture->lp_ctx),
credentials, &tree,
- event_context_find(mem_ctx));
+ torture->ev);
if (!NT_STATUS_IS_OK(status)) {
printf("Connection failed - %s\n", nt_errstr(status));
return false;
diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c
index d07611264b..37eadcf7fd 100644
--- a/source4/torture/smb2/smb2.c
+++ b/source4/torture/smb2/smb2.c
@@ -21,7 +21,7 @@
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/smb2/proto.h"
#include "lib/util/dlinklist.h"
@@ -47,9 +47,9 @@ static bool wrap_simple_1smb2_test(struct torture_context *torture_ctx,
}
struct torture_test *torture_suite_add_1smb2_test(struct torture_suite *suite,
- const char *name,
- bool (*run) (struct torture_context *,
- struct smb2_tree *))
+ const char *name,
+ bool (*run)(struct torture_context *,
+ struct smb2_tree *))
{
struct torture_test *test;
struct torture_tcase *tcase;
@@ -69,6 +69,61 @@ struct torture_test *torture_suite_add_1smb2_test(struct torture_suite *suite,
return test;
}
+
+static bool wrap_simple_2smb2_test(struct torture_context *torture_ctx,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
+{
+ bool (*fn) (struct torture_context *, struct smb2_tree *, struct smb2_tree *);
+ bool ret;
+
+ struct smb2_tree *tree1;
+ struct smb2_tree *tree2;
+ TALLOC_CTX *mem_ctx = talloc_new(torture_ctx);
+
+ if (!torture_smb2_connection(torture_ctx, &tree1) ||
+ !torture_smb2_connection(torture_ctx, &tree2)) {
+ return false;
+ }
+
+ talloc_steal(mem_ctx, tree1);
+ talloc_steal(mem_ctx, tree2);
+
+ fn = test->fn;
+
+ ret = fn(torture_ctx, tree1, tree2);
+
+ /* the test may already closed some of the connections */
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+
+_PUBLIC_ struct torture_test *torture_suite_add_2smb2_test(struct torture_suite *suite,
+ const char *name,
+ bool (*run)(struct torture_context *,
+ struct smb2_tree *,
+ struct smb2_tree *))
+{
+ struct torture_test *test;
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, name);
+
+ test = talloc(tcase, struct torture_test);
+
+ test->name = talloc_strdup(test, name);
+ test->description = NULL;
+ test->run = wrap_simple_2smb2_test;
+ test->fn = run;
+ test->dangerous = false;
+
+ DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+
+ return test;
+}
+
NTSTATUS torture_smb2_init(void)
{
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "SMB2");
@@ -82,6 +137,8 @@ NTSTATUS torture_smb2_init(void)
torture_suite_add_simple_test(suite, "FIND", torture_smb2_find);
torture_suite_add_suite(suite, torture_smb2_lock_init());
torture_suite_add_simple_test(suite, "NOTIFY", torture_smb2_notify);
+ torture_suite_add_2smb2_test(suite, "PERSISTENT-HANDLES1", torture_smb2_persistent_handles1);
+ torture_suite_add_1smb2_test(suite, "OPLOCK-BATCH1", torture_smb2_oplock_batch1);
suite->description = talloc_strdup(suite, "SMB2-specific tests");
diff --git a/source4/torture/smb2/util.c b/source4/torture/smb2/util.c
index f85b1c42ff..af4f345104 100644
--- a/source4/torture/smb2/util.c
+++ b/source4/torture/smb2/util.c
@@ -22,6 +22,7 @@
#include "includes.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
+#include "libcli/smb_composite/smb_composite.h"
#include "lib/cmdline/popt_common.h"
#include "lib/events/events.h"
#include "system/time.h"
@@ -34,47 +35,6 @@
/*
- close a handle with SMB2
-*/
-NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
-{
- struct smb2_close c;
-
- ZERO_STRUCT(c);
- c.in.file.handle = h;
-
- return smb2_close(tree, &c);
-}
-
-/*
- unlink a file with SMB2
-*/
-NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
-{
- struct smb2_create io;
- NTSTATUS status;
-
- ZERO_STRUCT(io);
- io.in.desired_access = SEC_RIGHTS_FILE_ALL;
- io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
- io.in.create_disposition = NTCREATEX_DISP_OPEN;
- io.in.share_access =
- NTCREATEX_SHARE_ACCESS_DELETE|
- NTCREATEX_SHARE_ACCESS_READ|
- NTCREATEX_SHARE_ACCESS_WRITE;
- io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
- io.in.fname = fname;
-
- status = smb2_create(tree, tree, &io);
- if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- return NT_STATUS_OK;
- }
- NT_STATUS_NOT_OK_RETURN(status);
-
- return smb2_util_close(tree, io.out.file.handle);
-}
-
-/*
write to a file on SMB2
*/
NTSTATUS smb2_util_write(struct smb2_tree *tree,
@@ -314,7 +274,7 @@ bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tr
status = smb2_connect(tctx, host, share,
lp_resolve_context(tctx->lp_ctx),
credentials, tree,
- event_context_find(tctx));
+ tctx->ev);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
host, share, nt_errstr(status));
diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c
index faae784e4b..418f933993 100644
--- a/source4/torture/smbtorture.c
+++ b/source4/torture/smbtorture.c
@@ -30,8 +30,7 @@
#include "lib/events/events.h"
#include "dynconfig.h"
-#include "torture/torture.h"
-#include "build.h"
+#include "torture/smbtorture.h"
#include "lib/util/dlinklist.h"
#include "librpc/rpc/dcerpc.h"
#include "param/param.h"
@@ -675,7 +674,7 @@ int main(int argc,char *argv[])
exit(1);
}
- torture = torture_context_init(cli_credentials_get_event_context(cmdline_credentials), ui_ops);
+ torture = torture_context_init(event_context_init(NULL), ui_ops);
if (basedir != NULL) {
if (basedir[0] != '/') {
fprintf(stderr, "Please specify an absolute path to --basedir\n");
diff --git a/source4/torture/torture.h b/source4/torture/smbtorture.h
index 26ecdb567b..3b5a573d83 100644
--- a/source4/torture/torture.h
+++ b/source4/torture/smbtorture.h
@@ -18,10 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __TORTURE_H__
-#define __TORTURE_H__
+#ifndef __SMBTORTURE_H__
+#define __SMBTORTURE_H__
-#include "torture/ui.h"
+#include "torture/torture.h"
struct smbcli_state;
@@ -37,5 +37,4 @@ struct torture_test;
int torture_init(void);
bool torture_register_suite(struct torture_suite *suite);
-
-#endif /* __TORTURE_H__ */
+#endif /* __SMBTORTURE_H__ */
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index 8a41b72249..54fe0ead27 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -21,7 +21,6 @@
#include "includes.h"
#include "system/time.h"
#include "torture/torture.h"
-#include "build.h"
#include "lib/util/dlinklist.h"
#include "param/param.h"
#include "lib/cmdline/popt_common.h"
@@ -60,7 +59,7 @@ _PUBLIC_ int torture_init(void)
extern NTSTATUS torture_raw_init(void);
extern NTSTATUS torture_unix_init(void);
extern NTSTATUS torture_winbind_init(void);
- init_module_fn static_init[] = { STATIC_torture_MODULES };
+ init_module_fn static_init[] = { STATIC_smbtorture_MODULES };
init_module_fn *shared_init = load_samba_modules(NULL, cmdline_lp_ctx, "torture");
run_init_functions(static_init);
diff --git a/source4/torture/torture.pc.in b/source4/torture/torture.pc.in
deleted file mode 100644
index 6582816cb5..0000000000
--- a/source4/torture/torture.pc.in
+++ /dev/null
@@ -1,12 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-modulesdir=${prefix}/modules/torture
-
-Name: torture
-Description: Samba torture (test) suite
-Requires: talloc
-Version: 0.0.1
-Libs: -L${libdir} -ltorture
-Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1
diff --git a/source4/torture/ui.c b/source4/torture/ui.c
deleted file mode 100644
index efa584ebea..0000000000
--- a/source4/torture/ui.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB torture UI functions
-
- Copyright (C) Jelmer Vernooij 2006
-
- 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 "includes.h"
-#include "torture/ui.h"
-#include "torture/torture.h"
-#include "lib/util/dlinklist.h"
-#include "param/param.h"
-#include "system/filesys.h"
-#include "auth/credentials/credentials.h"
-#include "lib/cmdline/popt_common.h"
-
-struct torture_context *torture_context_init(struct event_context *event_ctx,
- const struct torture_ui_ops *ui_ops)
-{
- struct torture_context *torture = talloc_zero(event_ctx,
- struct torture_context);
- torture->ui_ops = ui_ops;
- torture->returncode = true;
- torture->ev = event_ctx;
-
- if (ui_ops->init)
- ui_ops->init(torture);
-
- return torture;
-}
-
-/**
- create a temporary directory.
-*/
-_PUBLIC_ NTSTATUS torture_temp_dir(struct torture_context *tctx,
- const char *prefix,
- char **tempdir)
-{
- SMB_ASSERT(tctx->outputdir != NULL);
-
- *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir,
- prefix);
- NT_STATUS_HAVE_NO_MEMORY(*tempdir);
-
- if (mkdtemp(*tempdir) == NULL) {
- return map_nt_error_from_unix(errno);
- }
-
- return NT_STATUS_OK;
-}
-
-void torture_comment(struct torture_context *context, const char *comment, ...)
-{
- va_list ap;
- char *tmp;
-
- if (!context->ui_ops->comment)
- return;
-
- va_start(ap, comment);
- tmp = talloc_vasprintf(context, comment, ap);
-
- context->ui_ops->comment(context, tmp);
-
- talloc_free(tmp);
-}
-
-void torture_warning(struct torture_context *context, const char *comment, ...)
-{
- va_list ap;
- char *tmp;
-
- if (!context->ui_ops->warning)
- return;
-
- va_start(ap, comment);
- tmp = talloc_vasprintf(context, comment, ap);
-
- context->ui_ops->warning(context, tmp);
-
- talloc_free(tmp);
-}
-
-void torture_result(struct torture_context *context,
- enum torture_result result, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
-
- if (context->last_reason) {
- torture_warning(context, "%s", context->last_reason);
- talloc_free(context->last_reason);
- }
-
- context->last_result = result;
- context->last_reason = talloc_vasprintf(context, fmt, ap);
- va_end(ap);
-}
-
-struct torture_suite *torture_suite_create(TALLOC_CTX *ctx, const char *name)
-{
- struct torture_suite *suite = talloc_zero(ctx, struct torture_suite);
-
- suite->name = talloc_strdup(suite, name);
- suite->testcases = NULL;
- suite->children = NULL;
-
- return suite;
-}
-
-void torture_tcase_set_fixture(struct torture_tcase *tcase,
- bool (*setup) (struct torture_context *, void **),
- bool (*teardown) (struct torture_context *, void *))
-{
- tcase->setup = setup;
- tcase->teardown = teardown;
-}
-
-static bool wrap_test_with_testcase_const(struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- bool (*fn) (struct torture_context *,
- const void *tcase_data,
- const void *test_data);
-
- fn = test->fn;
-
- return fn(torture_ctx, tcase->data, test->data);
-}
-
-struct torture_test *torture_tcase_add_test_const(struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *, const void *tcase_data,
- const void *test_data),
- const void *data)
-{
- struct torture_test *test = talloc(tcase, struct torture_test);
-
- test->name = talloc_strdup(test, name);
- test->description = NULL;
- test->run = wrap_test_with_testcase_const;
- test->fn = run;
- test->dangerous = false;
- test->data = data;
-
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
-
- return test;
-}
-
-
-bool torture_suite_init_tcase(struct torture_suite *suite,
- struct torture_tcase *tcase,
- const char *name)
-{
- tcase->name = talloc_strdup(tcase, name);
- tcase->description = NULL;
- tcase->setup = NULL;
- tcase->teardown = NULL;
- tcase->fixture_persistent = true;
- tcase->tests = NULL;
-
- DLIST_ADD_END(suite->testcases, tcase, struct torture_tcase *);
-
- return true;
-}
-
-
-struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite,
- const char *name)
-{
- struct torture_tcase *tcase = talloc(suite, struct torture_tcase);
-
- if (!torture_suite_init_tcase(suite, tcase, name))
- return NULL;
-
- return tcase;
-}
-
-bool torture_run_suite(struct torture_context *context,
- struct torture_suite *suite)
-{
- bool ret = true;
- struct torture_tcase *tcase;
- struct torture_suite *tsuite;
- char *old_testname;
-
- context->level++;
- if (context->ui_ops->suite_start)
- context->ui_ops->suite_start(context, suite);
-
- old_testname = context->active_testname;
- if (old_testname != NULL)
- context->active_testname = talloc_asprintf(context, "%s-%s",
- old_testname, suite->name);
- else
- context->active_testname = talloc_strdup(context, suite->name);
-
- for (tcase = suite->testcases; tcase; tcase = tcase->next) {
- ret &= torture_run_tcase(context, tcase);
- }
-
- for (tsuite = suite->children; tsuite; tsuite = tsuite->next) {
- ret &= torture_run_suite(context, tsuite);
- }
-
- talloc_free(context->active_testname);
- context->active_testname = old_testname;
-
- if (context->ui_ops->suite_finish)
- context->ui_ops->suite_finish(context, suite);
-
- context->level--;
-
- return ret;
-}
-
-void torture_ui_test_start(struct torture_context *context,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- if (context->ui_ops->test_start)
- context->ui_ops->test_start(context, tcase, test);
-}
-
-int str_list_match(const char *name, char **list)
-{
- int i, ret = 0;
- if (list == NULL)
- return 0;
-
- for (i = 0; list[i]; i++) {
- if (gen_fnmatch(list[i], name) == 0)
- ret++;
- }
- return ret;
-}
-
-void torture_ui_test_result(struct torture_context *context,
- enum torture_result result,
- const char *comment)
-{
- if (context->ui_ops->test_result)
- context->ui_ops->test_result(context, result, comment);
-
- if (result == TORTURE_ERROR || result == TORTURE_FAIL)
- context->returncode = false;
-}
-
-static bool internal_torture_run_test(struct torture_context *context,
- struct torture_tcase *tcase,
- struct torture_test *test,
- bool already_setup)
-{
- bool success;
- char *old_testname;
-
- if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {
- old_testname = context->active_testname;
- context->active_testname = talloc_asprintf(context, "%s-%s", old_testname, test->name);
- }
-
- context->active_tcase = tcase;
- context->active_test = test;
-
- torture_ui_test_start(context, tcase, test);
-
- context->last_reason = NULL;
- context->last_result = TORTURE_OK;
-
- if (!already_setup && tcase->setup &&
- !tcase->setup(context, &(tcase->data))) {
- if (context->last_reason == NULL)
- context->last_reason = talloc_strdup(context, "Setup failure");
- context->last_result = TORTURE_ERROR;
- success = false;
- } else if (test->dangerous &&
- !torture_setting_bool(context, "dangerous", false)) {
- context->last_result = TORTURE_SKIP;
- context->last_reason = talloc_asprintf(context,
- "disabled %s - enable dangerous tests to use", test->name);
- success = true;
- } else {
- success = test->run(context, tcase, test);
-
- if (!success && context->last_result == TORTURE_OK) {
- if (context->last_reason == NULL)
- context->last_reason = talloc_strdup(context, "Unknown error/failure");
- context->last_result = TORTURE_ERROR;
- }
- }
-
- if (!already_setup && tcase->teardown && !tcase->teardown(context, tcase->data)) {
- if (context->last_reason == NULL)
- context->last_reason = talloc_strdup(context, "Setup failure");
- context->last_result = TORTURE_ERROR;
- success = false;
- }
-
- torture_ui_test_result(context, context->last_result,
- context->last_reason);
-
- talloc_free(context->last_reason);
-
- if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {
- talloc_free(context->active_testname);
- context->active_testname = old_testname;
- }
- context->active_test = NULL;
- context->active_tcase = NULL;
-
- return success;
-}
-
-bool torture_run_tcase(struct torture_context *context,
- struct torture_tcase *tcase)
-{
- bool ret = true;
- char *old_testname;
- struct torture_test *test;
-
- context->level++;
-
- context->active_tcase = tcase;
- if (context->ui_ops->tcase_start)
- context->ui_ops->tcase_start(context, tcase);
-
- if (tcase->fixture_persistent && tcase->setup
- && !tcase->setup(context, &tcase->data)) {
- /* FIXME: Use torture ui ops for reporting this error */
- fprintf(stderr, "Setup failed: ");
- if (context->last_reason != NULL)
- fprintf(stderr, "%s", context->last_reason);
- fprintf(stderr, "\n");
- ret = false;
- goto done;
- }
-
- old_testname = context->active_testname;
- context->active_testname = talloc_asprintf(context, "%s-%s",
- old_testname, tcase->name);
- for (test = tcase->tests; test; test = test->next) {
- ret &= internal_torture_run_test(context, tcase, test,
- tcase->fixture_persistent);
- }
- talloc_free(context->active_testname);
- context->active_testname = old_testname;
-
- if (tcase->fixture_persistent && tcase->teardown &&
- !tcase->teardown(context, tcase->data))
- ret = false;
-
-done:
- context->active_tcase = NULL;
-
- if (context->ui_ops->tcase_finish)
- context->ui_ops->tcase_finish(context, tcase);
-
- context->level--;
-
- return ret;
-}
-
-bool torture_run_test(struct torture_context *context,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- return internal_torture_run_test(context, tcase, test, false);
-}
-
-int torture_setting_int(struct torture_context *test, const char *name,
- int default_value)
-{
- return lp_parm_int(test->lp_ctx, NULL, "torture", name, default_value);
-}
-
-double torture_setting_double(struct torture_context *test, const char *name,
- double default_value)
-{
- return lp_parm_double(test->lp_ctx, NULL, "torture", name, default_value);
-}
-
-bool torture_setting_bool(struct torture_context *test, const char *name,
- bool default_value)
-{
- return lp_parm_bool(test->lp_ctx, NULL, "torture", name, default_value);
-}
-
-const char *torture_setting_string(struct torture_context *test,
- const char *name,
- const char *default_value)
-{
- const char *ret;
-
- SMB_ASSERT(test != NULL);
- SMB_ASSERT(test->lp_ctx != NULL);
-
- ret = lp_parm_string(test->lp_ctx, NULL, "torture", name);
-
- if (ret == NULL)
- return default_value;
-
- return ret;
-}
-
-static bool wrap_test_with_simple_tcase_const (
- struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- bool (*fn) (struct torture_context *, const void *tcase_data);
-
- fn = test->fn;
-
- return fn(torture_ctx, test->data);
-}
-
-struct torture_tcase *torture_suite_add_simple_tcase_const(
- struct torture_suite *suite, const char *name,
- bool (*run) (struct torture_context *test, const void *),
- const void *data)
-{
- struct torture_tcase *tcase;
- struct torture_test *test;
-
- tcase = torture_suite_add_tcase(suite, name);
-
- test = talloc(tcase, struct torture_test);
-
- test->name = talloc_strdup(test, name);
- test->description = NULL;
- test->run = wrap_test_with_simple_tcase_const;
- test->fn = run;
- test->data = data;
- test->dangerous = false;
-
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
-
- return tcase;
-}
-
-static bool wrap_simple_test(struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- bool (*fn) (struct torture_context *);
-
- fn = test->fn;
-
- return fn(torture_ctx);
-}
-
-struct torture_tcase *torture_suite_add_simple_test(
- struct torture_suite *suite,
- const char *name,
- bool (*run) (struct torture_context *test))
-{
- struct torture_test *test;
- struct torture_tcase *tcase;
-
- tcase = torture_suite_add_tcase(suite, name);
-
- test = talloc(tcase, struct torture_test);
-
- test->name = talloc_strdup(test, name);
- test->description = NULL;
- test->run = wrap_simple_test;
- test->fn = run;
- test->dangerous = false;
-
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
-
- return tcase;
-}
-
-bool torture_suite_add_suite(struct torture_suite *suite,
- struct torture_suite *child)
-{
- if (child == NULL)
- return false;
-
- DLIST_ADD_END(suite->children, child, struct torture_suite *);
-
- /* FIXME: Check for duplicates and return false if the
- * added suite already exists as a child */
-
- return true;
-}
-
-
-struct torture_suite *torture_find_suite(struct torture_suite *parent,
- const char *name)
-{
- struct torture_suite *child;
-
- for (child = parent->children; child; child = child->next)
- if (!strcmp(child->name, name))
- return child;
-
- return NULL;
-}
-
-static bool wrap_test_with_simple_test_const(struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- bool (*fn) (struct torture_context *, const void *tcase_data);
-
- fn = test->fn;
-
- return fn(torture_ctx, tcase->data);
-}
-
-struct torture_test *torture_tcase_add_simple_test_const(
- struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *test,
- const void *tcase_data))
-{
- struct torture_test *test;
-
- test = talloc(tcase, struct torture_test);
-
- test->name = talloc_strdup(test, name);
- test->description = NULL;
- test->run = wrap_test_with_simple_test_const;
- test->fn = run;
- test->data = NULL;
- test->dangerous = false;
-
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
-
- return test;
-}
-
-static bool wrap_test_with_simple_test(struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test)
-{
- bool (*fn) (struct torture_context *, void *tcase_data);
-
- fn = test->fn;
-
- return fn(torture_ctx, tcase->data);
-}
-
-struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *test, void *tcase_data))
-{
- struct torture_test *test;
-
- test = talloc(tcase, struct torture_test);
-
- test->name = talloc_strdup(test, name);
- test->description = NULL;
- test->run = wrap_test_with_simple_test;
- test->fn = run;
- test->data = NULL;
- test->dangerous = false;
-
- DLIST_ADD_END(tcase->tests, test, struct torture_test *);
-
- return test;
-}
-
-
-
diff --git a/source4/torture/ui.h b/source4/torture/ui.h
deleted file mode 100644
index 15b04c2397..0000000000
--- a/source4/torture/ui.h
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB torture UI functions
-
- Copyright (C) Jelmer Vernooij 2006
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __TORTURE_UI_H__
-#define __TORTURE_UI_H__
-
-struct torture_test;
-struct torture_context;
-struct torture_suite;
-struct torture_tcase;
-
-enum torture_result {
- TORTURE_OK=0,
- TORTURE_FAIL=1,
- TORTURE_ERROR=2,
- TORTURE_SKIP=3
-};
-
-/*
- * These callbacks should be implemented by any backend that wishes
- * to listen to reports from the torture tests.
- */
-struct torture_ui_ops
-{
- void (*init) (struct torture_context *);
- void (*comment) (struct torture_context *, const char *);
- void (*warning) (struct torture_context *, const char *);
- void (*suite_start) (struct torture_context *, struct torture_suite *);
- void (*suite_finish) (struct torture_context *, struct torture_suite *);
- void (*tcase_start) (struct torture_context *, struct torture_tcase *);
- void (*tcase_finish) (struct torture_context *, struct torture_tcase *);
- void (*test_start) (struct torture_context *,
- struct torture_tcase *,
- struct torture_test *);
- void (*test_result) (struct torture_context *,
- enum torture_result, const char *reason);
-};
-
-void torture_ui_test_start(struct torture_context *context,
- struct torture_tcase *tcase,
- struct torture_test *test);
-
-void torture_ui_test_result(struct torture_context *context,
- enum torture_result result,
- const char *comment);
-
-/*
- * Holds information about a specific run of the testsuite.
- * The data in this structure should be considered private to
- * the torture tests and should only be used directly by the torture
- * code and the ui backends.
- *
- * Torture tests should instead call the torture_*() macros and functions
- * specified below.
- */
-
-struct torture_context
-{
- const struct torture_ui_ops *ui_ops;
- void *ui_data;
-
- char *active_testname;
- struct torture_test *active_test;
- struct torture_tcase *active_tcase;
-
- bool quiet; /* Whether tests should avoid writing output to stdout */
-
- enum torture_result last_result;
- char *last_reason;
-
- bool returncode;
-
- const char *outputdir;
- int level;
- struct event_context *ev;
-
- struct loadparm_context *lp_ctx;
-};
-
-/*
- * Describes a particular torture test
- */
-struct torture_test {
- const char *name;
- const char *description;
- bool dangerous;
- /* Function to call to run this test */
- bool (*run) (struct torture_context *torture_ctx,
- struct torture_tcase *tcase,
- struct torture_test *test);
-
- struct torture_test *prev, *next;
-
- /* Pointer to the actual test function. This is run by the
- * run() function above. */
- void *fn;
- const void *data;
-};
-
-/*
- * Describes a particular test case.
- */
-struct torture_tcase {
- const char *name;
- const char *description;
- bool (*setup) (struct torture_context *tcase, void **data);
- bool (*teardown) (struct torture_context *tcase, void *data);
- bool fixture_persistent;
- void *data;
- struct torture_test *tests;
- struct torture_tcase *prev, *next;
-};
-
-struct torture_suite
-{
- const char *name;
- const char *description;
- struct torture_tcase *testcases;
- struct torture_suite *children;
-
- /* Pointers to siblings of this torture suite */
- struct torture_suite *prev, *next;
-};
-
-/** Create a new torture suite */
-struct torture_suite *torture_suite_create(TALLOC_CTX *mem_ctx,
- const char *name);
-
-/** Change the setup and teardown functions for a testcase */
-void torture_tcase_set_fixture(struct torture_tcase *tcase,
- bool (*setup) (struct torture_context *, void **),
- bool (*teardown) (struct torture_context *, void *));
-
-/* Add another test to run for a particular testcase */
-struct torture_test *torture_tcase_add_test_const(struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *test,
- const void *tcase_data, const void *test_data),
- const void *test_data);
-
-/* Add a testcase to a testsuite */
-struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite,
- const char *name);
-
-/* Convenience wrapper that adds a testcase against only one
- * test will be run */
-struct torture_tcase *torture_suite_add_simple_tcase_const(
- struct torture_suite *suite,
- const char *name,
- bool (*run) (struct torture_context *test,
- const void *test_data),
- const void *data);
-
-/* Convenience function that adds a test which only
- * gets the test case data */
-struct torture_test *torture_tcase_add_simple_test_const(
- struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *test,
- const void *tcase_data));
-
-/* Convenience wrapper that adds a test that doesn't need any
- * testcase data */
-struct torture_tcase *torture_suite_add_simple_test(
- struct torture_suite *suite,
- const char *name,
- bool (*run) (struct torture_context *test));
-
-/* Add a child testsuite to an existing testsuite */
-bool torture_suite_add_suite(struct torture_suite *suite,
- struct torture_suite *child);
-
-/* Run the specified testsuite recursively */
-bool torture_run_suite(struct torture_context *context,
- struct torture_suite *suite);
-
-/* Run the specified testcase */
-bool torture_run_tcase(struct torture_context *context,
- struct torture_tcase *tcase);
-
-/* Run the specified test */
-bool torture_run_test(struct torture_context *context,
- struct torture_tcase *tcase,
- struct torture_test *test);
-
-void torture_comment(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
-void torture_warning(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
-void torture_result(struct torture_context *test,
- enum torture_result, const char *reason, ...) PRINTF_ATTRIBUTE(3,4);
-
-#define torture_assert(torture_ctx,expr,cmt) \
- if (!(expr)) { \
- torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \
- return false; \
- }
-
-#define torture_assert_werr_equal(torture_ctx, got, expected, cmt) \
- do { WERROR __got = got, __expected = expected; \
- if (!W_ERROR_EQUAL(__got, __expected)) { \
- torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", win_errstr(__got), win_errstr(__expected), cmt); \
- return false; \
- } \
- } while (0)
-
-#define torture_assert_ntstatus_equal(torture_ctx,got,expected,cmt) \
- do { NTSTATUS __got = got, __expected = expected; \
- if (!NT_STATUS_EQUAL(__got, __expected)) { \
- torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", nt_errstr(__got), nt_errstr(__expected), cmt); \
- return false; \
- }\
- } while(0)
-
-#define torture_assert_ndr_err_equal(torture_ctx,got,expected,cmt) \
- do { enum ndr_err_code __got = got, __expected = expected; \
- if (__got != __expected) { \
- torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %d, expected %d (%s): %s", __got, __expected, __STRING(expected), cmt); \
- return false; \
- }\
- } while(0)
-
-#define torture_assert_casestr_equal(torture_ctx,got,expected,cmt) \
- do { const char *__got = (got), *__expected = (expected); \
- if (!strequal(__got, __expected)) { \
- torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", __got, __expected, cmt); \
- return false; \
- } \
- } while(0)
-
-#define torture_assert_str_equal(torture_ctx,got,expected,cmt)\
- do { const char *__got = (got), *__expected = (expected); \
- if (strcmp_safe(__got, __expected) != 0) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": "#got" was %s, expected %s: %s", \
- __got, __expected, cmt); \
- return false; \
- } \
- } while(0)
-
-#define torture_assert_mem_equal(torture_ctx,got,expected,len,cmt)\
- do { const void *__got = (got), *__expected = (expected); \
- if (memcmp(__got, __expected, len) != 0) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": "#got" of len %d did not match"#expected": %s", len, cmt); \
- return false; \
- } \
- } while(0)
-
-#define torture_assert_file_contains_text(torture_ctx,filename,expected,cmt)\
- do { \
- char *__got; \
- const char *__expected = (expected); \
- size_t __size; \
- __got = file_load(filename, &__size, torture_ctx); \
- if (__got == NULL) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": unable to open %s: %s\n", \
- filename, cmt); \
- return false; \
- } \
- \
- if (strcmp_safe(__got, __expected) != 0) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": %s contained:\n%sExpected: %s%s\n", \
- filename, __got, __expected, cmt); \
- talloc_free(__got); \
- return false; \
- } \
- talloc_free(__got); \
- } while(0)
-
-#define torture_assert_file_contains(torture_ctx,filename,expected,cmt)\
- do { const char *__got, *__expected = (expected); \
- size_t __size; \
- __got = file_load(filename, *size, torture_ctx); \
- if (strcmp_safe(__got, __expected) != 0) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": %s contained:\n%sExpected: %s%s\n", \
- __got, __expected, cmt); \
- talloc_free(__got); \
- return false; \
- } \
- talloc_free(__got); \
- } while(0)
-
-#define torture_assert_int_equal(torture_ctx,got,expected,cmt)\
- do { int __got = (got), __expected = (expected); \
- if (__got != __expected) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": "#got" was %d, expected %d: %s", \
- __got, __expected, cmt); \
- return false; \
- } \
- } while(0)
-
-#define torture_assert_u64_equal(torture_ctx,got,expected,cmt)\
- do { uint64_t __got = (got), __expected = (expected); \
- if (__got != __expected) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": "#got" was %llu, expected %llu: %s", \
- (unsigned long long)__got, (unsigned long long)__expected, cmt); \
- return false; \
- } \
- } while(0)
-
-#define torture_assert_errno_equal(torture_ctx,expected,cmt)\
- do { int __expected = (expected); \
- if (errno != __expected) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": errno was %d (%s), expected %d: %s: %s", \
- errno, strerror(errno), __expected, \
- strerror(__expected), cmt); \
- return false; \
- } \
- } while(0)
-
-
-
-#define torture_skip(torture_ctx,cmt) do {\
- torture_result(torture_ctx, TORTURE_SKIP, __location__": %s", cmt);\
- return true; \
- } while(0)
-#define torture_fail(torture_ctx,cmt) do {\
- torture_result(torture_ctx, TORTURE_FAIL, __location__": %s", cmt);\
- return false; \
- } while (0)
-#define torture_fail_goto(torture_ctx,label,cmt) do {\
- torture_result(torture_ctx, TORTURE_FAIL, __location__": %s", cmt);\
- goto label; \
- } while (0)
-
-#define torture_out stderr
-
-/* Convenience macros */
-#define torture_assert_ntstatus_ok(torture_ctx,expr,cmt) \
- torture_assert_ntstatus_equal(torture_ctx,expr,NT_STATUS_OK,cmt)
-
-#define torture_assert_werr_ok(torture_ctx,expr,cmt) \
- torture_assert_werr_equal(torture_ctx,expr,WERR_OK,cmt)
-
-#define torture_assert_ndr_success(torture_ctx,expr,cmt) \
- torture_assert_ndr_err_equal(torture_ctx,expr,NDR_ERR_SUCCESS,cmt)
-
-/* Getting settings */
-const char *torture_setting_string(struct torture_context *test, \
- const char *name,
- const char *default_value);
-
-int torture_setting_int(struct torture_context *test,
- const char *name,
- int default_value);
-
-double torture_setting_double(struct torture_context *test,
- const char *name,
- double default_value);
-
-bool torture_setting_bool(struct torture_context *test,
- const char *name,
- bool default_value);
-
-struct torture_suite *torture_find_suite(struct torture_suite *parent,
- const char *name);
-
-NTSTATUS torture_temp_dir(struct torture_context *tctx,
- const char *prefix,
- char **tempdir);
-
-struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase,
- const char *name,
- bool (*run) (struct torture_context *test, void *tcase_data));
-
-
-bool torture_suite_init_tcase(struct torture_suite *suite,
- struct torture_tcase *tcase,
- const char *name);
-
-struct torture_context *torture_context_init(struct event_context *event_ctx,
- const struct torture_ui_ops *ui_ops);
-
-#endif /* __TORTURE_UI_H__ */
diff --git a/source4/torture/unix/unix.c b/source4/torture/unix/unix.c
index 05ea27db02..661e337270 100644
--- a/source4/torture/unix/unix.c
+++ b/source4/torture/unix/unix.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/unix/proto.h"
NTSTATUS torture_unix_init(void)
diff --git a/source4/torture/unix/unix_info2.c b/source4/torture/unix/unix_info2.c
index c14be9e2d0..d7482ddcf1 100644
--- a/source4/torture/unix/unix_info2.c
+++ b/source4/torture/unix/unix_info2.c
@@ -63,8 +63,8 @@ static struct smbcli_state *connect_to_server(struct torture_context *tctx)
lp_smb_ports(tctx->lp_ctx),
share, NULL,
cmdline_credentials,
- lp_resolve_context(tctx->lp_ctx), NULL,
- &options);
+ lp_resolve_context(tctx->lp_ctx),
+ tctx->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
printf("failed to connect to //%s/%s: %s\n",
diff --git a/source4/torture/unix/whoami.c b/source4/torture/unix/whoami.c
index a1333ac5bd..d4f19bb57a 100644
--- a/source4/torture/unix/whoami.c
+++ b/source4/torture/unix/whoami.c
@@ -84,7 +84,7 @@ static struct smbcli_state *connect_to_server(struct torture_context *tctx,
lp_smb_ports(tctx->lp_ctx),
share, NULL,
creds, lp_resolve_context(tctx->lp_ctx),
- NULL, &options);
+ tctx->ev, &options);
if (!NT_STATUS_IS_OK(status)) {
printf("failed to connect to //%s/%s: %s\n",
diff --git a/source4/torture/util.h b/source4/torture/util.h
index 1009fcf9f1..9dc948ade5 100644
--- a/source4/torture/util.h
+++ b/source4/torture/util.h
@@ -20,6 +20,11 @@
#ifndef _TORTURE_PROVISION_H_
#define _TORTURE_PROVISION_H_
+#include "torture/torture.h"
+
+struct smbcli_state;
+struct smbcli_tree;
+
/**
setup a directory ready for a test
*/
diff --git a/source4/torture/util_smb.c b/source4/torture/util_smb.c
index c1a20094f3..938e7d6c03 100644
--- a/source4/torture/util_smb.c
+++ b/source4/torture/util_smb.c
@@ -28,7 +28,6 @@
#include "system/shmem.h"
#include "system/wait.h"
#include "system/time.h"
-#include "torture/ui.h"
#include "torture/torture.h"
#include "util/dlinklist.h"
#include "auth/credentials/credentials.h"
diff --git a/source4/torture/winbind/config.mk b/source4/torture/winbind/config.mk
index 155766a677..15bc51daba 100644
--- a/source4/torture/winbind/config.mk
+++ b/source4/torture/winbind/config.mk
@@ -2,14 +2,14 @@
#################################
# Start SUBSYSTEM TORTURE_WINBIND
[MODULE::TORTURE_WINBIND]
-SUBSYSTEM = torture
+SUBSYSTEM = smbtorture
INIT_FUNCTION = torture_winbind_init
-PRIVATE_PROTO_HEADER = \
- proto.h
PRIVATE_DEPENDENCIES = \
LIBWINBIND-CLIENT
# End SUBSYSTEM TORTURE_WINBIND
#################################
-TORTURE_WINBIND_OBJ_FILES = $(addprefix torture/winbind/, winbind.o struct_based.o)
+TORTURE_WINBIND_OBJ_FILES = $(addprefix $(torturesrcdir)/winbind/, winbind.o struct_based.o)
+
+$(eval $(call proto_header_template,$(torturesrcdir)/winbind/proto.h,$(TORTURE_WINBIND_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/winbind/struct_based.c b/source4/torture/winbind/struct_based.c
index 51ac0e622a..31c5b8cf96 100644
--- a/source4/torture/winbind/struct_based.c
+++ b/source4/torture/winbind/struct_based.c
@@ -26,7 +26,7 @@
#include "libcli/security/security.h"
#include "librpc/gen_ndr/netlogon.h"
#include "param/param.h"
-#include "auth/pam_errors.h"
+#include "auth/ntlm/pam_errors.h"
#define DO_STRUCT_REQ_REP_EXT(op,req,rep,expected,strict,warnaction,cmt) do { \
NSS_STATUS __got, __expected = (expected); \
@@ -262,7 +262,7 @@ static bool torture_winbind_struct_check_machacc(struct torture_context *torture
torture_assert_str_equal(torture,
rep.data.auth.error_string,
- nt_errstr(NT_STATUS_OK),
+ get_friendly_nt_error_msg(NT_STATUS_OK),
"WINBINDD_CHECK_MACHACC ok: error_string");
torture_assert_int_equal(torture,
@@ -295,6 +295,10 @@ static bool get_trusted_domains(struct torture_context *torture,
DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
extra_data = (char *)rep.extra_data.data;
+ if (!extra_data) {
+ return true;
+ }
+
torture_assert(torture, extra_data, "NULL trust list");
while (next_token(&extra_data, line, "\n", sizeof(fstring))) {
@@ -356,7 +360,6 @@ static bool torture_winbind_struct_list_trustdom(struct torture_context *torture
DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
list1 = (char *)rep.extra_data.data;
- torture_assert(torture, list1, "NULL trust list");
torture_comment(torture, "%s\n", list1);
@@ -368,7 +371,6 @@ static bool torture_winbind_struct_list_trustdom(struct torture_context *torture
DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
list2 = (char *)rep.extra_data.data;
- torture_assert(torture, list2, "NULL trust list");
/*
* The list_all_domains parameter should be ignored
@@ -381,7 +383,7 @@ static bool torture_winbind_struct_list_trustdom(struct torture_context *torture
ok = get_trusted_domains(torture, &listd);
torture_assert(torture, ok, "failed to get trust list");
- for (i=0; listd[i].netbios_name; i++) {
+ for (i=0; listd && listd[i].netbios_name; i++) {
if (i == 0) {
struct dom_sid *builtin_sid;
@@ -424,7 +426,7 @@ static bool torture_winbind_struct_domain_info(struct torture_context *torture)
ok = get_trusted_domains(torture, &listd);
torture_assert(torture, ok, "failed to get trust list");
- for (i=0; listd[i].netbios_name; i++) {
+ for (i=0; listd && listd[i].netbios_name; i++) {
struct winbindd_request req;
struct winbindd_response rep;
struct dom_sid *sid;
@@ -485,14 +487,14 @@ static bool torture_winbind_struct_getdcname(struct torture_context *torture)
bool ok;
bool strict = torture_setting_bool(torture, "strict mode", false);
struct torture_trust_domain *listd = NULL;
- uint32_t i;
+ uint32_t i, count = 0;
torture_comment(torture, "Running WINBINDD_GETDCNAME (struct based)\n");
ok = get_trusted_domains(torture, &listd);
torture_assert(torture, ok, "failed to get trust list");
- for (i=0; listd[i].netbios_name; i++) {
+ for (i=0; listd && listd[i].netbios_name; i++) {
struct winbindd_request req;
struct winbindd_response rep;
@@ -512,8 +514,13 @@ static bool torture_winbind_struct_getdcname(struct torture_context *torture)
/* TODO: check rep.data.dc_name; */
torture_comment(torture, "DOMAIN '%s' => DCNAME '%s'\n",
req.domain_name, rep.data.dc_name);
+ count++;
}
+ if (strict) {
+ torture_assert(torture, count > 0,
+ "WiNBINDD_GETDCNAME was not tested");
+ }
return true;
}
@@ -530,7 +537,7 @@ static bool torture_winbind_struct_dsgetdcname(struct torture_context *torture)
ok = get_trusted_domains(torture, &listd);
torture_assert(torture, ok, "failed to get trust list");
- for (i=0; listd[i].netbios_name; i++) {
+ for (i=0; listd && listd[i].netbios_name; i++) {
struct winbindd_request req;
struct winbindd_response rep;
diff --git a/source4/torture/winbind/winbind.c b/source4/torture/winbind/winbind.c
index e283602337..b12e92552e 100644
--- a/source4/torture/winbind/winbind.c
+++ b/source4/torture/winbind/winbind.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
#include "torture/winbind/proto.h"
NTSTATUS torture_winbind_init(void)