mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r1041: - pulled the domain join code out of the netlogon test and made it a separate utility function, to allow
multiple torture tests to temporarily join a domain
- fixed a session key size problem
- added a schannel test suite
- allow schannel to work with ncacn_ip_tcp
(This used to be commit 36f05e4d57
)
This commit is contained in:
parent
7ea6a0b1fc
commit
a1318baa55
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -25,173 +25,10 @@
|
||||
#include "includes.h"
|
||||
|
||||
|
||||
static const char *machine_password;
|
||||
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
@ -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;
|
||||
}
|
||||
|
130
source4/torture/rpc/schannel.c
Normal file
130
source4/torture/rpc/schannel.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
277
source4/torture/rpc/testjoin.c
Normal file
277
source4/torture/rpc/testjoin.c
Normal file
@ -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);
|
||||
}
|
@ -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},
|
||||
|
Loading…
Reference in New Issue
Block a user