diff options
-rw-r--r-- | source4/libcli/auth/schannel.c | 2 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 25 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_schannel.c | 36 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 84 | ||||
-rw-r--r-- | source4/torture/config.mk | 2 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.c | 185 | ||||
-rw-r--r-- | source4/torture/rpc/schannel.c | 130 | ||||
-rw-r--r-- | source4/torture/rpc/spoolss.c | 8 | ||||
-rw-r--r-- | source4/torture/rpc/testjoin.c | 277 | ||||
-rw-r--r-- | source4/torture/torture.c | 3 |
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}, |