summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/auth/schannel.c2
-rw-r--r--source4/librpc/rpc/dcerpc.h25
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c36
-rw-r--r--source4/librpc/rpc/dcerpc_util.c84
-rw-r--r--source4/torture/config.mk2
-rw-r--r--source4/torture/rpc/netlogon.c185
-rw-r--r--source4/torture/rpc/schannel.c130
-rw-r--r--source4/torture/rpc/spoolss.c8
-rw-r--r--source4/torture/rpc/testjoin.c277
-rw-r--r--source4/torture/torture.c3
10 files changed, 515 insertions, 237 deletions
diff --git a/source4/libcli/auth/schannel.c b/source4/libcli/auth/schannel.c
index 294873feffb..95e881d32af 100644
--- a/source4/libcli/auth/schannel.c
+++ b/source4/libcli/auth/schannel.c
@@ -286,7 +286,7 @@ void schannel_end(struct schannel_state **state)
create an schannel context state
*/
NTSTATUS schannel_start(struct schannel_state **state,
- uint8_t session_key[16],
+ const uint8_t session_key[16],
BOOL initiator)
{
TALLOC_CTX *mem_ctx;
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 74bdaf878e6..d81f0ab9650 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -71,21 +71,28 @@ struct dcerpc_pipe {
};
/* dcerpc pipe flags */
-#define DCERPC_DEBUG_PRINT_IN (1<<0)
-#define DCERPC_DEBUG_PRINT_OUT (1<<1)
+#define DCERPC_DEBUG_PRINT_IN (1<<0)
+#define DCERPC_DEBUG_PRINT_OUT (1<<1)
#define DCERPC_DEBUG_PRINT_BOTH (DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT)
-#define DCERPC_DEBUG_VALIDATE_IN 4
-#define DCERPC_DEBUG_VALIDATE_OUT 8
+#define DCERPC_DEBUG_VALIDATE_IN (1<<2)
+#define DCERPC_DEBUG_VALIDATE_OUT (1<<3)
#define DCERPC_DEBUG_VALIDATE_BOTH (DCERPC_DEBUG_VALIDATE_IN | DCERPC_DEBUG_VALIDATE_OUT)
-#define DCERPC_SIGN 16
-#define DCERPC_SEAL 32
+#define DCERPC_SIGN (1<<4)
+#define DCERPC_SEAL (1<<5)
-#define DCERPC_PUSH_BIGENDIAN 64
-#define DCERPC_PULL_BIGENDIAN 128
+#define DCERPC_PUSH_BIGENDIAN (1<<6)
+#define DCERPC_PULL_BIGENDIAN (1<<7)
-#define DCERPC_SCHANNEL 256
+#define DCERPC_SCHANNEL_BDC (1<<8)
+#define DCERPC_SCHANNEL_WORKSTATION (1<<9)
+#define DCERPC_SCHANNEL_DOMAIN (1<<10)
+#define DCERPC_SCHANNEL_ANY (DCERPC_SCHANNEL_BDC| \
+ DCERPC_SCHANNEL_DOMAIN| \
+ DCERPC_SCHANNEL_WORKSTATION)
+
+#define DCERPC_AUTH_OPTIONS (DCERPC_SEAL|DCERPC_SIGN|DCERPC_SCHANNEL_ANY)
/*
this is used to find pointers to calls
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c
index 61db90d1e3f..f81429c1f3b 100644
--- a/source4/librpc/rpc/dcerpc_schannel.c
+++ b/source4/librpc/rpc/dcerpc_schannel.c
@@ -81,7 +81,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
const char *username,
const char *password,
int chan_type,
- uint8_t new_session_key[8])
+ uint8_t new_session_key[16])
{
NTSTATUS status;
struct dcerpc_pipe *p2;
@@ -91,7 +91,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
struct samr_Password mach_pwd;
struct creds_CredentialState creds;
const char *workgroup, *workstation;
- uint32_t negotiate_flags = 0;
+ uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
workstation = username;
workgroup = domain;
@@ -99,10 +99,10 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
/*
step 1 - establish a netlogon connection, with no authentication
*/
- status = dcerpc_secondary_smb(p, &p2,
- DCERPC_NETLOGON_NAME,
- DCERPC_NETLOGON_UUID,
- DCERPC_NETLOGON_VERSION);
+ status = dcerpc_secondary_connection(p, &p2,
+ DCERPC_NETLOGON_NAME,
+ DCERPC_NETLOGON_UUID,
+ DCERPC_NETLOGON_VERSION);
/*
@@ -152,7 +152,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
*/
dcerpc_pipe_close(p2);
- memcpy(new_session_key, creds.session_key, 8);
+ memcpy(new_session_key, creds.session_key, 16);
return NT_STATUS_OK;
}
@@ -167,17 +167,13 @@ NTSTATUS dcerpc_bind_auth_schannel_key(struct dcerpc_pipe *p,
const char *uuid, uint_t version,
const char *domain,
const char *username,
- const uint8_t session_key[8])
+ const uint8_t session_key[16])
{
NTSTATUS status;
- uint8_t full_session_key[16];
struct schannel_state *schannel_state;
const char *workgroup, *workstation;
struct dcerpc_bind_schannel bind_schannel;
- memcpy(full_session_key, session_key, 8);
- memset(full_session_key+8, 0, 8);
-
workstation = username;
workgroup = domain;
@@ -234,7 +230,7 @@ NTSTATUS dcerpc_bind_auth_schannel_key(struct dcerpc_pipe *p,
goto done;
}
- status = schannel_start(&schannel_state, full_session_key, True);
+ status = schannel_start(&schannel_state, session_key, True);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -265,11 +261,19 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
const char *password)
{
NTSTATUS status;
- uint8_t session_key[8];
+ uint8_t session_key[16];
+ int chan_type = 0;
+
+ if (p->flags & DCERPC_SCHANNEL_BDC) {
+ chan_type = SEC_CHAN_BDC;
+ } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) {
+ chan_type = SEC_CHAN_WKSTA;
+ } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) {
+ chan_type = SEC_CHAN_DOMAIN;
+ }
status = dcerpc_schannel_key(p, domain, username, password,
- lp_server_role() == ROLE_DOMAIN_BDC? SEC_CHAN_BDC:SEC_CHAN_WKSTA,
- session_key);
+ chan_type, session_key);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 623d5ec24a7..c7edf043ece 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -275,7 +275,6 @@ static const struct {
} ncacn_options[] = {
{"sign", DCERPC_SIGN},
{"seal", DCERPC_SEAL},
- {"schannel", DCERPC_SCHANNEL},
{"validate", DCERPC_DEBUG_VALIDATE_BOTH},
{"print", DCERPC_DEBUG_PRINT_BOTH},
{"bigendian", DCERPC_PUSH_BIGENDIAN}
@@ -458,11 +457,18 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
pipe_name += 6;
}
- status = cli_full_connection(&cli, lp_netbios_name(),
- binding->host, NULL,
- "ipc$", "?????",
- username, username[0]?domain:"",
- password, 0, &retry);
+ if ((binding->flags & DCERPC_SCHANNEL_ANY) || !username || !username[0]) {
+ status = cli_full_connection(&cli, lp_netbios_name(),
+ binding->host, NULL,
+ "ipc$", "?????",
+ "", "", NULL, 0, &retry);
+ } else {
+ status = cli_full_connection(&cli, lp_netbios_name(),
+ binding->host, NULL,
+ "ipc$", "?????",
+ username, domain,
+ password, 0, &retry);
+ }
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to connect to %s - %s\n", binding->host, nt_errstr(status)));
return status;
@@ -482,23 +488,15 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
(*p)->flags = binding->flags;
- if (binding->flags & DCERPC_SCHANNEL) {
- const char *trust_password = NULL; // samdb_fetch_member_password();
- if (!trust_password) {
- DEBUG(0,("Unable to fetch machine password\n"));
- goto done;
- }
+ if (binding->flags & DCERPC_SCHANNEL_ANY) {
status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version,
- lp_workgroup(),
- lp_netbios_name(),
- trust_password);
+ domain, username, password);
} else if (binding->flags & (DCERPC_SIGN | DCERPC_SEAL)) {
status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password);
} else {
status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version);
}
-done:
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
dcerpc_pipe_close(*p);
@@ -552,7 +550,10 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
(*p)->flags = binding->flags;
- if (!(binding->flags & (DCERPC_SIGN|DCERPC_SEAL)) && !username[0]) {
+ if (binding->flags & DCERPC_SCHANNEL_ANY) {
+ status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version,
+ domain, username, password);
+ } else if (!(binding->flags & (DCERPC_SIGN|DCERPC_SEAL)) && !username[0]) {
status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version);
} else {
status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version,
@@ -560,7 +561,8 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
}
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
+ DEBUG(0,("Failed to bind to uuid %s - %s\n",
+ pipe_uuid, nt_errstr(status)));
dcerpc_pipe_close(*p);
return status;
}
@@ -635,28 +637,46 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p,
/*
- create a secondary dcerpc connection from a primary SMB connection
+ create a secondary dcerpc connection from a primary connection
- the secondary connection will be on the same SMB connection, but use a new fnum
+ if the primary is a SMB connection then the secondary connection
+ will be on the same SMB connection, but use a new fnum
*/
-NTSTATUS dcerpc_secondary_smb(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
- const char *pipe_name,
- const char *pipe_uuid,
- uint32_t pipe_version)
+NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
+ const char *pipe_name,
+ const char *pipe_uuid,
+ uint32_t pipe_version)
{
- NTSTATUS status;
struct cli_tree *tree;
+ NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+ struct dcerpc_binding b;
- tree = dcerpc_smb_tree(p);
- if (!tree) {
- return NT_STATUS_INVALID_PARAMETER;
+ switch (p->transport.transport) {
+ case NCACN_NP:
+ tree = dcerpc_smb_tree(p);
+ if (!tree) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = dcerpc_pipe_open_smb(p2, tree, pipe_name);
+ break;
+
+ case NCACN_IP_TCP:
+ status = dcerpc_parse_binding(p->mem_ctx, p->binding_string, &b);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ b.flags &= ~DCERPC_AUTH_OPTIONS;
+ status = dcerpc_pipe_connect_ncacn_ip_tcp(p2, &b, pipe_uuid,
+ pipe_version, NULL,
+ NULL, NULL);
+ break;
}
- status = dcerpc_pipe_open_smb(p2, tree, pipe_name);
if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
+ return status;
+ }
+
(*p2)->flags = p->flags;
status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version);
diff --git a/source4/torture/config.mk b/source4/torture/config.mk
index 4bbcf21b58c..a4ec4b40764 100644
--- a/source4/torture/config.mk
+++ b/source4/torture/config.mk
@@ -61,6 +61,8 @@ ADD_OBJ_FILES = \
torture/rpc/mgmt.o \
torture/rpc/scanner.o \
torture/rpc/autoidl.o \
+ torture/rpc/testjoin.o \
+ torture/rpc/schannel.o \
torture/rpc/netlogon.o
REQUIRED_SUBSYSTEMS = \
LIBSMB
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 04741d8b907..68571a2f6c3 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -25,172 +25,9 @@
#include "includes.h"
-#define TEST_MACHINE_NAME "torturetest"
-
-static struct {
- struct dcerpc_pipe *p;
- const char *machine_password;
- struct policy_handle acct_handle;
-} join;
-
-/*
- join the domain as a BDC
-*/
-static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
-{
- NTSTATUS status;
- struct samr_Connect c;
- struct samr_CreateUser2 r;
- struct samr_OpenDomain o;
- struct samr_LookupDomain l;
- struct samr_GetUserPwInfo pwp;
- struct samr_SetUserInfo s;
- union samr_UserInfo u;
- struct policy_handle handle;
- struct policy_handle domain_handle;
- uint32_t access_granted;
- uint32_t rid;
- BOOL ret = True;
- DATA_BLOB session_key;
- struct samr_Name name;
- int policy_min_pw_len = 0;
-
- printf("Connecting to SAMR\n");
-
- status = torture_rpc_connection(&join.p,
- DCERPC_SAMR_NAME,
- DCERPC_SAMR_UUID,
- DCERPC_SAMR_VERSION);
- if (!NT_STATUS_IS_OK(status)) {
- return False;
- }
-
- c.in.system_name = NULL;
- c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
- c.out.handle = &handle;
-
- status = dcerpc_samr_Connect(join.p, mem_ctx, &c);
- if (!NT_STATUS_IS_OK(status)) {
- printf("samr_Connect failed - %s\n", nt_errstr(status));
- return False;
- }
-
- printf("Opening domain %s\n", lp_workgroup());
-
- name.name = lp_workgroup();
- l.in.handle = &handle;
- l.in.domain = &name;
-
- status = dcerpc_samr_LookupDomain(join.p, mem_ctx, &l);
- if (!NT_STATUS_IS_OK(status)) {
- printf("LookupDomain failed - %s\n", nt_errstr(status));
- return False;
- }
-
- o.in.handle = &handle;
- o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
- o.in.sid = l.out.sid;
- o.out.domain_handle = &domain_handle;
-
- status = dcerpc_samr_OpenDomain(join.p, mem_ctx, &o);
- if (!NT_STATUS_IS_OK(status)) {
- printf("OpenDomain failed - %s\n", nt_errstr(status));
- return False;
- }
-
- printf("Creating machine account %s\n", TEST_MACHINE_NAME);
-
-again:
- name.name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
- r.in.handle = &domain_handle;
- r.in.account_name = &name;
- r.in.acct_flags = ACB_SVRTRUST;
- r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
- r.out.acct_handle = &join.acct_handle;
- r.out.access_granted = &access_granted;
- r.out.rid = &rid;
-
- status = dcerpc_samr_CreateUser2(join.p, mem_ctx, &r);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS) &&
- test_DeleteUser_byname(join.p, mem_ctx, &domain_handle, name.name)) {
- goto again;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- printf("CreateUser2 failed - %s\n", nt_errstr(status));
- return False;
- }
-
- pwp.in.handle = &join.acct_handle;
+static const char *machine_password;
- status = dcerpc_samr_GetUserPwInfo(join.p, mem_ctx, &pwp);
- if (NT_STATUS_IS_OK(status)) {
- policy_min_pw_len = pwp.out.info.min_password_len;
- }
-
- join.machine_password = generate_random_str(mem_ctx, MAX(8, policy_min_pw_len));
-
- printf("Setting machine account password '%s'\n", join.machine_password);
-
- s.in.handle = &join.acct_handle;
- s.in.info = &u;
- s.in.level = 24;
-
- encode_pw_buffer(u.info24.password.data, join.machine_password, STR_UNICODE);
- u.info24.pw_len = strlen(join.machine_password);
-
- status = dcerpc_fetch_session_key(join.p, &session_key);
- if (!NT_STATUS_IS_OK(status)) {
- printf("SetUserInfo level %u - no session key - %s\n",
- s.in.level, nt_errstr(status));
- return False;
- }
-
- arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
-
- status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
- if (!NT_STATUS_IS_OK(status)) {
- printf("SetUserInfo failed - %s\n", nt_errstr(status));
- return False;
- }
-
- s.in.handle = &join.acct_handle;
- s.in.info = &u;
- s.in.level = 16;
-
- u.info16.acct_flags = ACB_SVRTRUST;
-
- printf("Resetting ACB flags\n");
-
- status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
- if (!NT_STATUS_IS_OK(status)) {
- printf("SetUserInfo failed - %s\n", nt_errstr(status));
- return False;
- }
-
- return ret;
-}
-
-/*
- leave the domain as a BDC
-*/
-static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
-{
- struct samr_DeleteUser d;
- NTSTATUS status;
-
- d.in.handle = &join.acct_handle;
- d.out.handle = &join.acct_handle;
-
- status = dcerpc_samr_DeleteUser(join.p, mem_ctx, &d);
- if (!NT_STATUS_IS_OK(status)) {
- printf("Delete of machine account failed\n");
- return False;
- }
-
- return True;
-}
+#define TEST_MACHINE_NAME "torturetest"
static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
{
@@ -259,7 +96,7 @@ static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
- plain_pass = join.machine_password;
+ plain_pass = machine_password;
if (!plain_pass) {
printf("Unable to fetch machine password!\n");
return False;
@@ -319,7 +156,7 @@ static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
- plain_pass = join.machine_password;
+ plain_pass = machine_password;
if (!plain_pass) {
printf("Unable to fetch machine password!\n");
return False;
@@ -385,7 +222,7 @@ static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
- plain_pass = join.machine_password;
+ plain_pass = machine_password;
if (!plain_pass) {
printf("Unable to fetch machine password!\n");
return False;
@@ -1157,7 +994,7 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
printf("Credential chaining failed\n");
}
- join.machine_password = password;
+ machine_password = password;
if (!test_SetupCredentials(p, mem_ctx, &creds)) {
printf("ServerPasswordSet failed to actually change the password\n");
@@ -1679,10 +1516,13 @@ BOOL torture_rpc_netlogon(int dummy)
struct dcerpc_pipe *p;
TALLOC_CTX *mem_ctx;
BOOL ret = True;
+ void *join_ctx;
mem_ctx = talloc_init("torture_rpc_netlogon");
- if (!join_domain_bdc(mem_ctx)) {
+ join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
+ &machine_password);
+ if (!join_ctx) {
printf("Failed to join as BDC\n");
return False;
}
@@ -1757,10 +1597,7 @@ BOOL torture_rpc_netlogon(int dummy)
torture_rpc_close(p);
- if (!leave_domain_bdc(mem_ctx)) {
- printf("Failed to delete BDC machine account\n");
- return False;
- }
+ torture_leave_domain(join_ctx);
return ret;
}
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
new file mode 100644
index 00000000000..8d30f16b06d
--- /dev/null
+++ b/source4/torture/rpc/schannel.c
@@ -0,0 +1,130 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ test suite for schannel operations
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#define TEST_MACHINE_NAME "schanneltest"
+
+static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+ NTSTATUS status;
+ struct samr_GetDomPwInfo r;
+ int i;
+ struct samr_Name name;
+
+ name.name = lp_workgroup();
+ r.in.name = &name;
+
+ printf("Testing GetDomPwInfo with name %s\n", r.in.name->name);
+
+ /* do several ops to test credential chaining */
+ for (i=0;i<5;i++) {
+ status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("GetDomPwInfo op %d failed - %s\n", i, nt_errstr(status));
+ return False;
+ }
+ }
+
+ return True;
+}
+
+
+static BOOL test_schannel(TALLOC_CTX *mem_ctx,
+ uint16 acct_flags, uint32 dcerpc_flags,
+ uint32 schannel_type)
+{
+ void *join_ctx;
+ const char *machine_password;
+ NTSTATUS status;
+ char *binding = lp_parm_string(-1, "torture", "binding");
+ struct dcerpc_binding b;
+ struct dcerpc_pipe *p;
+
+ join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), acct_flags,
+ &machine_password);
+ if (!join_ctx) {
+ printf("Failed to join domain with acct_flags=0x%x\n", acct_flags);
+ return False;
+ }
+
+ status = dcerpc_parse_binding(mem_ctx, binding, &b);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Bad binding string %s\n", binding);
+ goto failed;
+ }
+
+ b.flags &= ~DCERPC_AUTH_OPTIONS;
+ b.flags |= dcerpc_flags;
+
+ status = dcerpc_pipe_connect_b(&p, &b,
+ DCERPC_SAMR_UUID,
+ DCERPC_SAMR_VERSION,
+ lp_workgroup(),
+ TEST_MACHINE_NAME,
+ machine_password);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to connect with schannel\n");
+ goto failed;
+ }
+
+ test_samr_ops(p, mem_ctx);
+
+ torture_leave_domain(join_ctx);
+ return True;
+
+failed:
+ torture_leave_domain(join_ctx);
+ return False;
+}
+
+
+BOOL torture_rpc_schannel(int dummy)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = True;
+ struct {
+ uint16 acct_flags;
+ uint32 dcerpc_flags;
+ uint32 schannel_type;
+ } tests[] = {
+ { ACB_WSTRUST, DCERPC_SCHANNEL_WORKSTATION | DCERPC_SIGN, 3 },
+ { ACB_WSTRUST, DCERPC_SCHANNEL_WORKSTATION | DCERPC_SEAL, 3 },
+ { ACB_SVRTRUST, DCERPC_SCHANNEL_BDC | DCERPC_SIGN, 3 },
+ { ACB_SVRTRUST, DCERPC_SCHANNEL_BDC | DCERPC_SEAL, 3 }
+ };
+ int i;
+
+ mem_ctx = talloc_init("torture_rpc_schannel");
+
+ for (i=0;i<ARRAY_SIZE(tests);i++) {
+ if (!test_schannel(mem_ctx,
+ tests[i].acct_flags, tests[i].dcerpc_flags, tests[i].schannel_type)) {
+ printf("Failed with acct_flags=0x%x dcerpc_flags=0x%x schannel_type=%d\n",
+ tests[i].acct_flags, tests[i].dcerpc_flags, tests[i].schannel_type);
+ ret = False;
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c
index 74860cd369e..cbeaac8d9e6 100644
--- a/source4/torture/rpc/spoolss.c
+++ b/source4/torture/rpc/spoolss.c
@@ -587,10 +587,10 @@ static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
printf("testing close on secondary pipe\n");
- status = dcerpc_secondary_smb(p, &p2,
- DCERPC_SPOOLSS_NAME,
- DCERPC_SPOOLSS_UUID,
- DCERPC_SPOOLSS_VERSION);
+ status = dcerpc_secondary_connection(p, &p2,
+ DCERPC_SPOOLSS_NAME,
+ DCERPC_SPOOLSS_UUID,
+ DCERPC_SPOOLSS_VERSION);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to create secondary connection\n");
return False;
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
new file mode 100644
index 00000000000..aab08c3a560
--- /dev/null
+++ b/source4/torture/rpc/testjoin.c
@@ -0,0 +1,277 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ utility code to join/leave a domain
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ this code is used by other torture modules to join/leave a domain
+ as either a member, bdc or thru a trust relationship
+*/
+
+#include "includes.h"
+
+struct test_join {
+ TALLOC_CTX *mem_ctx;
+ struct dcerpc_pipe *p;
+ const char *machine_password;
+ struct policy_handle acct_handle;
+};
+
+
+static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle, const char *name)
+{
+ NTSTATUS status;
+ struct samr_DeleteUser d;
+ struct policy_handle acct_handle;
+ uint32_t rid;
+ struct samr_LookupNames n;
+ struct samr_Name sname;
+ struct samr_OpenUser r;
+
+ sname.name = name;
+
+ n.in.handle = handle;
+ n.in.num_names = 1;
+ n.in.names = &sname;
+
+ status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+ if (NT_STATUS_IS_OK(status)) {
+ rid = n.out.rids.ids[0];
+ } else {
+ return status;
+ }
+
+ r.in.handle = handle;
+ r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ r.in.rid = rid;
+ r.out.acct_handle = &acct_handle;
+
+ status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
+ return status;
+ }
+
+ d.in.handle = &acct_handle;
+ d.out.handle = &acct_handle;
+ status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ join the domain as a test machine
+ an opaque pointer is returned. Pass it to torture_leave_domain()
+ when finished
+*/
+void *torture_join_domain(const char *machine_name,
+ const char *domain,
+ uint16 acct_flags,
+ const char **machine_password)
+{
+ NTSTATUS status;
+ struct samr_Connect c;
+ struct samr_CreateUser2 r;
+ struct samr_OpenDomain o;
+ struct samr_LookupDomain l;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ struct policy_handle handle;
+ struct policy_handle domain_handle;
+ uint32_t access_granted;
+ uint32_t rid;
+ DATA_BLOB session_key;
+ struct samr_Name name;
+ int policy_min_pw_len = 0;
+ struct test_join *join;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_init("torture_join_domain");
+ if (!mem_ctx) {
+ return NULL;
+ }
+
+ join = talloc_p(mem_ctx, struct test_join);
+ if (join == NULL) {
+ talloc_destroy(mem_ctx);
+ return NULL;
+ }
+
+ ZERO_STRUCTP(join);
+
+ join->mem_ctx = mem_ctx;
+
+ printf("Connecting to SAMR\n");
+
+ status = torture_rpc_connection(&join->p,
+ DCERPC_SAMR_NAME,
+ DCERPC_SAMR_UUID,
+ DCERPC_SAMR_VERSION);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
+ }
+
+ c.in.system_name = NULL;
+ c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ c.out.handle = &handle;
+
+ status = dcerpc_samr_Connect(join->p, mem_ctx, &c);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("samr_Connect failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ printf("Opening domain %s\n", domain);
+
+ name.name = domain;
+ l.in.handle = &handle;
+ l.in.domain = &name;
+
+ status = dcerpc_samr_LookupDomain(join->p, mem_ctx, &l);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("LookupDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ o.in.handle = &handle;
+ o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ o.in.sid = l.out.sid;
+ o.out.domain_handle = &domain_handle;
+
+ status = dcerpc_samr_OpenDomain(join->p, mem_ctx, &o);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ printf("Creating machine account %s\n", machine_name);
+
+again:
+ name.name = talloc_asprintf(mem_ctx, "%s$", machine_name);
+ r.in.handle = &domain_handle;
+ r.in.account_name = &name;
+ r.in.acct_flags = acct_flags;
+ r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ r.out.acct_handle = &join->acct_handle;
+ r.out.access_granted = &access_granted;
+ r.out.rid = &rid;
+
+ status = dcerpc_samr_CreateUser2(join->p, mem_ctx, &r);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+ status = DeleteUser_byname(join->p, mem_ctx, &domain_handle, name.name);
+ if (NT_STATUS_IS_OK(status)) {
+ goto again;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("CreateUser2 failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ pwp.in.handle = &join->acct_handle;
+
+ status = dcerpc_samr_GetUserPwInfo(join->p, mem_ctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info.min_password_len;
+ }
+
+ join->machine_password = generate_random_str(mem_ctx, MAX(8, policy_min_pw_len));
+
+ printf("Setting machine account password '%s'\n", join->machine_password);
+
+ s.in.handle = &join->acct_handle;
+ s.in.info = &u;
+ s.in.level = 24;
+
+ encode_pw_buffer(u.info24.password.data, join->machine_password, STR_UNICODE);
+ u.info24.pw_len = strlen(join->machine_password);
+
+ status = dcerpc_fetch_session_key(join->p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ torture_leave_domain(&join);
+ goto failed;
+ }
+
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+
+ status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ s.in.handle = &join->acct_handle;
+ s.in.info = &u;
+ s.in.level = 16;
+
+ u.info16.acct_flags = acct_flags;
+
+ printf("Resetting ACB flags\n");
+
+ status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ *machine_password = join->machine_password;
+
+ return join;
+
+failed:
+ torture_leave_domain(join);
+ return NULL;
+}
+
+
+/*
+ leave the domain, deleting the machine acct
+*/
+void torture_leave_domain(void *join_ctx)
+{
+ struct test_join *join = join_ctx;
+ struct samr_DeleteUser d;
+ NTSTATUS status;
+
+ if (!uuid_all_zero(&join->acct_handle.uuid)) {
+ d.in.handle = &join->acct_handle;
+ d.out.handle = &join->acct_handle;
+
+ status = dcerpc_samr_DeleteUser(join->p, join->mem_ctx, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Delete of machine account failed\n");
+ }
+ }
+
+ if (join->p) {
+ torture_rpc_close(join->p);
+ }
+
+ talloc_destroy(join->mem_ctx);
+}
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index 2dcacf23881..4ff340bdd0a 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -2795,7 +2795,7 @@ static BOOL run_vuidtest(int dummy)
const char *fname = "\\vuid.tst";
int fnum;
size_t size;
- time_t c_time, a_time, m_time, w_time, m_time2;
+ time_t c_time, a_time, m_time;
BOOL correct = True;
uint16_t orig_vuid;
@@ -4131,6 +4131,7 @@ static struct {
{"RPC-SPOOLSS", torture_rpc_spoolss, 0},
{"RPC-SAMR", torture_rpc_samr, 0},
{"RPC-NETLOGON", torture_rpc_netlogon, 0},
+ {"RPC-SCHANNEL", torture_rpc_schannel, 0},
{"RPC-WKSSVC", torture_rpc_wkssvc, 0},
{"RPC-SRVSVC", torture_rpc_srvsvc, 0},
{"RPC-ATSVC", torture_rpc_atsvc, 0},