diff options
Diffstat (limited to 'source4/torture')
-rw-r--r-- | source4/torture/auth/pac.c | 69 | ||||
-rw-r--r-- | source4/torture/config.mk | 2 | ||||
-rw-r--r-- | source4/torture/nbt/dgram.c | 4 | ||||
-rw-r--r-- | source4/torture/rpc/lsa.c | 151 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.c | 15 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.h | 6 | ||||
-rw-r--r-- | source4/torture/rpc/remote_pac.c | 203 | ||||
-rw-r--r-- | source4/torture/rpc/rpc.c | 1 | ||||
-rw-r--r-- | source4/torture/rpc/session_key.c | 5 | ||||
-rw-r--r-- | source4/torture/rpc/testjoin.c | 1 |
10 files changed, 391 insertions, 66 deletions
diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c index 4e51c66950..42901f1eff 100644 --- a/source4/torture/auth/pac.c +++ b/source4/torture/auth/pac.c @@ -139,7 +139,7 @@ static bool torture_pac_self_check(struct torture_context *tctx) dump_data(10,tmp_blob.data,tmp_blob.length); - /* Now check that we can read it back */ + /* Now check that we can read it back (using full decode and validate) */ nt_status = kerberos_decode_pac(mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_data, @@ -163,7 +163,31 @@ static bool torture_pac_self_check(struct torture_context *tctx) nt_errstr(nt_status))); } - /* Now check that we can read it back */ + /* Now check we can read it back (using Heimdal's pac parsing) */ + nt_status = kerberos_pac_blob_to_server_info(mem_ctx, + lp_iconv_convenience(tctx->lp_ctx), + tmp_blob, + smb_krb5_context->krb5_context, + &server_info_out); + + if (!dom_sid_equal(server_info->account_sid, + server_info_out->account_sid)) { + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &krbtgt_keyblock); + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &server_keyblock); + krb5_free_principal(smb_krb5_context->krb5_context, + client_principal); + + torture_fail(tctx, + talloc_asprintf(tctx, + "(self test) PAC Decode resulted in *different* domain SID: %s != %s", + dom_sid_string(mem_ctx, server_info->account_sid), + dom_sid_string(mem_ctx, server_info_out->account_sid))); + } + talloc_free(server_info_out); + + /* Now check that we can read it back (yet again) */ nt_status = kerberos_pac_logon_info(mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &logon_info, @@ -196,6 +220,7 @@ static bool torture_pac_self_check(struct torture_context *tctx) krb5_free_principal(smb_krb5_context->krb5_context, client_principal); + /* And make a server info from the samba-parsed PAC */ validation.sam3 = &logon_info->info3; nt_status = make_server_info_netlogon_validation(mem_ctx, "", @@ -403,7 +428,45 @@ static bool torture_pac_saved_check(struct torture_context *tctx) nt_errstr(nt_status))); } - /* Parse the PAC again, for the logon info this time */ + /* Now check we can read it back (using Heimdal's pac parsing) */ + nt_status = kerberos_pac_blob_to_server_info(mem_ctx, + lp_iconv_convenience(tctx->lp_ctx), + tmp_blob, + smb_krb5_context->krb5_context, + &server_info_out); + + if (!NT_STATUS_IS_OK(nt_status)) { + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + krbtgt_keyblock_p); + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &server_keyblock); + krb5_free_principal(smb_krb5_context->krb5_context, client_principal); + + torture_fail(tctx, talloc_asprintf(tctx, + "(saved test) Heimdal PAC decoding failed: %s", + nt_errstr(nt_status))); + } + + if (!pac_file && + !dom_sid_equal(dom_sid_parse_talloc(mem_ctx, + "S-1-5-21-3048156945-3961193616-3706469200-1005"), + server_info_out->account_sid)) { + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + krbtgt_keyblock_p); + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &server_keyblock); + krb5_free_principal(smb_krb5_context->krb5_context, client_principal); + + torture_fail(tctx, + talloc_asprintf(tctx, + "(saved test) Heimdal PAC Decode resulted in *different* domain SID: %s != %s", + "S-1-5-21-3048156945-3961193616-3706469200-1005", + dom_sid_string(mem_ctx, server_info_out->account_sid))); + } + + talloc_free(server_info_out); + + /* Parse the PAC again, for the logon info this time (using Samba4's parsing) */ nt_status = kerberos_pac_logon_info(mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &logon_info, diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 5a1746c215..96da10b5df 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -114,7 +114,7 @@ torture_rpc_OBJ_FILES = $(addprefix $(torturesrcdir)/rpc/, \ 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 \ eventlog.o epmapper.o winreg.o initshutdown.o oxidresolve.o remact.o mgmt.o \ - scanner.o autoidl.o countcalls.o testjoin.o schannel.o netlogon.o samlogon.o \ + scanner.o autoidl.o countcalls.o testjoin.o schannel.o netlogon.o remote_pac.o samlogon.o \ samsync.o bind.o dssetup.o alter_context.o bench.o samba3rpc.o rpc.o async_bind.o \ handles.o frsapi.o) diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c index 665a08bd5c..eac2b1fe30 100644 --- a/source4/torture/nbt/dgram.c +++ b/source4/torture/nbt/dgram.c @@ -291,6 +291,10 @@ static bool nbt_test_netlogon2(struct torture_context *tctx) join_ctx = torture_join_domain(tctx, TEST_NAME, ACB_WSTRUST, &machine_credentials); + 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 (another) temporary mailslot listener for replies */ diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index 4fb459ea25..ec74426ac6 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -28,7 +28,6 @@ #include "libcli/auth/libcli_auth.h" #include "torture/rpc/rpc.h" #include "param/param.h" - #define TEST_MACHINENAME "lsatestmach" static void init_lsa_String(struct lsa_String *name, const char *s) @@ -614,7 +613,8 @@ bool test_many_LookupSids(struct dcerpc_pipe *p, if (!test_LookupNames(p, mem_ctx, handle, &names)) { return false; } - } else { + } else if (p->conn->security_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && + p->conn->security_state.auth_info->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) { struct lsa_LookupSids3 r; struct lsa_TransNameArray2 names; @@ -779,6 +779,7 @@ static bool test_LookupPrivName(struct dcerpc_pipe *p, static bool test_RemovePrivilegesFromAccount(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle, struct policy_handle *acct_handle, struct lsa_LUID *luid) { @@ -801,7 +802,25 @@ static bool test_RemovePrivilegesFromAccount(struct dcerpc_pipe *p, status = dcerpc_lsa_RemovePrivilegesFromAccount(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { - printf("RemovePrivilegesFromAccount failed - %s\n", nt_errstr(status)); + + struct lsa_LookupPrivName r_name; + + r_name.in.handle = handle; + r_name.in.luid = luid; + + status = dcerpc_lsa_LookupPrivName(p, mem_ctx, &r_name); + if (!NT_STATUS_IS_OK(status)) { + printf("\nLookupPrivName failed - %s\n", nt_errstr(status)); + return false; + } + /* Windows 2008 does not allow this to be removed */ + if (strcmp("SeAuditPrivilege", r_name.out.name->string) == 0) { + return ret; + } + + printf("RemovePrivilegesFromAccount failed to remove %s - %s\n", + r_name.out.name->string, + nt_errstr(status)); return false; } @@ -864,7 +883,7 @@ static bool test_EnumPrivsAccount(struct dcerpc_pipe *p, &r.out.privs->set[i].luid); } - ret &= test_RemovePrivilegesFromAccount(p, mem_ctx, acct_handle, + ret &= test_RemovePrivilegesFromAccount(p, mem_ctx, handle, acct_handle, &r.out.privs->set[0].luid); ret &= test_AddPrivilegesToAccount(p, mem_ctx, acct_handle, &r.out.privs->set[0].luid); @@ -884,6 +903,26 @@ static bool test_Delete(struct dcerpc_pipe *p, r.in.handle = handle; status = dcerpc_lsa_Delete(p, mem_ctx, &r); + if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + printf("Delete should have failed NT_STATUS_NOT_SUPPORTED - %s\n", nt_errstr(status)); + return false; + } + + return true; +} + +static bool test_DeleteObject(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + NTSTATUS status; + struct lsa_DeleteObject r; + + printf("testing DeleteObject\n"); + + r.in.handle = handle; + r.out.handle = handle; + status = dcerpc_lsa_DeleteObject(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("Delete failed - %s\n", nt_errstr(status)); return false; @@ -912,7 +951,19 @@ static bool test_CreateAccount(struct dcerpc_pipe *p, r.out.acct_handle = &acct_handle; status = dcerpc_lsa_CreateAccount(p, mem_ctx, &r); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + struct lsa_OpenAccount r_o; + r_o.in.handle = handle; + r_o.in.sid = newsid; + r_o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r_o.out.acct_handle = &acct_handle; + + status = dcerpc_lsa_OpenAccount(p, mem_ctx, &r_o); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenAccount failed - %s\n", nt_errstr(status)); + return false; + } + } else if (!NT_STATUS_IS_OK(status)) { printf("CreateAccount failed - %s\n", nt_errstr(status)); return false; } @@ -921,6 +972,10 @@ static bool test_CreateAccount(struct dcerpc_pipe *p, return false; } + if (!test_DeleteObject(p, mem_ctx, &acct_handle)) { + return false; + } + return true; } @@ -948,6 +1003,10 @@ static bool test_DeleteTrustedDomain(struct dcerpc_pipe *p, return false; } + if (!test_DeleteObject(p, mem_ctx, &trustdom_handle)) { + return false; + } + return true; } @@ -986,7 +1045,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, struct lsa_SetSecret r7; struct lsa_QuerySecret r8; struct policy_handle sec_handle, sec_handle2, sec_handle3; - struct lsa_Delete d; + struct lsa_DeleteObject d_o; struct lsa_DATA_BUF buf1; struct lsa_DATA_BUF_PTR bufp1; struct lsa_DATA_BUF_PTR bufp2; @@ -1121,7 +1180,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, &blob1, &session_key); if (strcmp(secret1, secret2) != 0) { - printf("Returned secret '%s' doesn't match '%s'\n", + printf("Returned secret (r4) '%s' doesn't match '%s'\n", secret2, secret1); ret = false; } @@ -1136,7 +1195,9 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, r5.in.new_val->data = enc_key.data; r5.in.new_val->length = enc_key.length; r5.in.new_val->size = enc_key.length; - + + + msleep(200); printf("Testing SetSecret (existing value should move to old)\n"); status = dcerpc_lsa_SetSecret(p, mem_ctx, &r5); @@ -1200,8 +1261,10 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, } if (*r6.out.new_mtime == *r6.out.old_mtime) { - printf("Returned secret %s had same mtime for both secrets: %s\n", + printf("Returned secret (r6-%d) %s must not have same mtime for both secrets: %s != %s\n", + i, secname[i], + nt_time_string(mem_ctx, *r6.out.old_mtime), nt_time_string(mem_ctx, *r6.out.new_mtime)); ret = false; } @@ -1245,35 +1308,16 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, if (!r8.out.new_val || !r8.out.old_val) { printf("in/out pointers not returned, despite being set on in for QuerySecret\n"); ret = false; - } else if (r8.out.new_val->buf == NULL) { - if (i != LOCAL) { - printf("NEW secret buffer not returned after GLOBAL OLD set\n"); - ret = false; - } + } else if (r8.out.new_val->buf != NULL) { + printf("NEW secret buffer must not be returned after OLD set\n"); + ret = false; } else if (r8.out.old_val->buf == NULL) { - printf("OLD secret buffer not returned after OLD set\n"); + printf("OLD secret buffer was not returned after OLD set\n"); ret = false; } else if (r8.out.new_mtime == NULL || r8.out.old_mtime == NULL) { printf("Both times not returned after OLD set\n"); ret = false; } else { - if (i == LOCAL) { - printf("NEW secret buffer should not be returned after LOCAL OLD set\n"); - ret = false; - } - blob1.data = r8.out.new_val->buf->data; - blob1.length = r8.out.new_val->buf->length; - - blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length); - - secret6 = sess_decrypt_string(mem_ctx, - &blob1, &session_key); - - if (strcmp(secret3, secret4) != 0) { - printf("Returned NEW secret '%s' doesn't match '%s'\n", secret4, secret3); - ret = false; - } - blob1.data = r8.out.old_val->buf->data; blob1.length = r8.out.old_val->buf->size; @@ -1287,15 +1331,8 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, ret = false; } - if (*r8.out.new_mtime == *r8.out.old_mtime) { - if (i != GLOBAL) { - printf("Returned secret %s had same mtime for both secrets: %s\n", - secname[i], - nt_time_string(mem_ctx, *r8.out.new_mtime)); - ret = false; - } - } else { - printf("Returned secret %s should have had same mtime for both secrets: %s != %s\n", + if (*r8.out.new_mtime != *r8.out.old_mtime) { + printf("Returned secret (r8) %s did not had same mtime for both secrets: %s != %s\n", secname[i], nt_time_string(mem_ctx, *r8.out.old_mtime), nt_time_string(mem_ctx, *r8.out.new_mtime)); @@ -1308,8 +1345,13 @@ static bool test_CreateSecret(struct dcerpc_pipe *p, ret = false; } - d.in.handle = &sec_handle2; - status = dcerpc_lsa_Delete(p, mem_ctx, &d); + if (!test_DeleteObject(p, mem_ctx, &sec_handle)) { + return false; + } + + d_o.in.handle = &sec_handle2; + d_o.out.handle = &sec_handle2; + status = dcerpc_lsa_DeleteObject(p, mem_ctx, &d_o); if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { printf("Second delete expected INVALID_HANDLE - %s\n", nt_errstr(status)); ret = false; @@ -1454,9 +1496,9 @@ static bool test_EnumAccounts(struct dcerpc_pipe *p, return false; } - if (!test_LookupSids3(p, mem_ctx, &sids1)) { - return false; - } + /* Can't test lookupSids3 here, as clearly we must not + * be on schannel, or we would not be able to do the + * rest */ printf("testing all accounts\n"); for (i=0;i<sids1.num_sids;i++) { @@ -1667,8 +1709,8 @@ static bool test_query_each_TrustDom(struct dcerpc_pipe *p, struct policy_handle handle2; struct lsa_Close c; struct lsa_CloseTrustedDomainEx c_trust; - int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; - int ok[] = {1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1}; + int levels [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + int ok[] = {1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1}; if (domains->domains[i].sid) { trust.in.handle = handle; @@ -1912,8 +1954,6 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, r_ex.in.max_size, LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER, r_ex.in.max_size / LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER); - ret = false; - exit(1); } } else if (!NT_STATUS_IS_OK(enum_status)) { printf("EnumTrustedDomainEx failed - %s\n", nt_errstr(enum_status)); @@ -2015,10 +2055,6 @@ static bool test_QueryDomainInfoPolicy(struct dcerpc_pipe *p, NTSTATUS status; int i; bool ret = true; - if (torture_setting_bool(tctx, "samba4", false)) { - printf("skipping QueryDomainInformationPolicy test against Samba4\n"); - return true; - } printf("\nTesting QueryDomainInformationPolicy\n"); @@ -2030,7 +2066,10 @@ static bool test_QueryDomainInfoPolicy(struct dcerpc_pipe *p, status = dcerpc_lsa_QueryDomainInformationPolicy(p, tctx, &r); - if (!NT_STATUS_IS_OK(status)) { + /* If the server does not support EFS, then this is the correct return */ + if (i == LSA_DOMAIN_INFO_POLICY_EFS && NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + continue; + } else if (!NT_STATUS_IS_OK(status)) { printf("QueryDomainInformationPolicy failed - %s\n", nt_errstr(status)); ret = false; continue; @@ -2311,11 +2350,9 @@ bool torture_rpc_lsa(struct torture_context *tctx) ret = false; } -#if 0 if (!test_Delete(p, tctx, handle)) { ret = false; } -#endif if (!test_many_LookupSids(p, tctx, handle)) { ret = false; diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 5b92ce1382..5ec2c29a20 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -25,8 +25,10 @@ #include "torture/torture.h" #include "lib/events/events.h" #include "auth/auth.h" +#include "auth/gensec/gensec.h" #include "lib/cmdline/popt_common.h" #include "torture/rpc/rpc.h" +#include "torture/rpc/netlogon.h" #include "libcli/auth/libcli_auth.h" #include "librpc/gen_ndr/ndr_netlogon_c.h" #include "librpc/gen_ndr/ndr_lsa_c.h" @@ -67,8 +69,8 @@ static bool test_LogonUasLogoff(struct torture_context *tctx, } static bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, - struct cli_credentials *credentials, - struct creds_CredentialState **creds_out) + struct cli_credentials *credentials, + struct creds_CredentialState **creds_out) { NTSTATUS status; struct netr_ServerReqChallenge r; @@ -113,6 +115,13 @@ static bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context torture_comment(tctx, "Testing ServerAuthenticate\n"); status = dcerpc_netr_ServerAuthenticate(p, tctx, &a); + + /* This allows the tests to continue against the more fussy windows 2008 */ + if (NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED)) { + return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + credentials, SEC_CHAN_BDC, creds_out); + } + torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate"); torture_assert(tctx, creds_client_check(creds, &credentials3), @@ -122,7 +131,7 @@ static bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context return true; } -static bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, +bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t negotiate_flags, struct cli_credentials *machine_credentials, int sec_chan_type, diff --git a/source4/torture/rpc/netlogon.h b/source4/torture/rpc/netlogon.h new file mode 100644 index 0000000000..92d366b46a --- /dev/null +++ b/source4/torture/rpc/netlogon.h @@ -0,0 +1,6 @@ + +bool test_SetupCredentials2(struct dcerpc_pipe *p, struct torture_context *tctx, + uint32_t negotiate_flags, + struct cli_credentials *machine_credentials, + int sec_chan_type, + struct creds_CredentialState **creds_out); diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c new file mode 100644 index 0000000000..58c8ba0ee0 --- /dev/null +++ b/source4/torture/rpc/remote_pac.c @@ -0,0 +1,203 @@ +/* + Unix SMB/CIFS implementation. + + test suite for netlogon PAC operations + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 "torture/torture.h" +#include "lib/events/events.h" +#include "auth/auth.h" +#include "auth/gensec/gensec.h" +#include "lib/cmdline/popt_common.h" +#include "torture/rpc/rpc.h" +#include "torture/rpc/netlogon.h" +#include "libcli/auth/libcli_auth.h" +#include "librpc/gen_ndr/ndr_netlogon_c.h" +#include "librpc/gen_ndr/ndr_krb5pac.h" +#include "param/param.h" +#include "lib/messaging/irpc.h" +#include "cluster/cluster.h" + +#define TEST_MACHINE_NAME "torturepactest" + +/* Check to see if we can pass the PAC across to the NETLOGON server for validation */ + +/* Also happens to be a really good one-step verfication of our Kerberos stack */ + +static bool test_PACVerify(struct torture_context *tctx, + struct dcerpc_pipe *p, + struct cli_credentials *credentials) +{ + NTSTATUS status; + + struct netr_LogonSamLogon r; + + struct netr_GenericInfo generic; + struct netr_Authenticator auth, auth2; + + + struct creds_CredentialState *creds; + struct gensec_security *gensec_client_context; + struct gensec_security *gensec_server_context; + + struct messaging_context *msg_server_ctx; + DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload; + struct PAC_Validate pac_wrapped_struct; + + enum ndr_err_code ndr_err; + + struct auth_session_info *session_info; + + char *tmp_dir; + + TALLOC_CTX *tmp_ctx = talloc_new(tctx); + + torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed"); + + if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + credentials, SEC_CHAN_BDC, + &creds)) { + return false; + } + + status = torture_temp_dir(tctx, "PACVerify", &tmp_dir); + torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed"); + + msg_server_ctx = messaging_init(tctx, + tmp_dir, + cluster_id(0, 1), + lp_iconv_convenience(tctx->lp_ctx), + tctx->ev); + + torture_assert(tctx, msg_server_ctx != NULL, "Failed to init messaging context"); + + status = gensec_client_start(tctx, &gensec_client_context, tctx->ev, tctx->lp_ctx); + torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); + + status = gensec_set_target_hostname(gensec_client_context, TEST_MACHINE_NAME); + + status = gensec_set_credentials(gensec_client_context, cmdline_credentials); + torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); + + status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI"); + torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); + + status = gensec_server_start(tctx, tctx->ev, tctx->lp_ctx, msg_server_ctx, &gensec_server_context); + torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed"); + + status = gensec_set_credentials(gensec_server_context, credentials); + torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed"); + + status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI"); + torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed"); + + server_to_client = data_blob(NULL, 0); + + do { + /* Do a client-server update dance */ + status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; + torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); + } + + if (client_to_server.length == 0) { + break; + } + + status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; + torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed"); + } + + if (server_to_client.length == 0) { + break; + } + } while (1); + + /* Extract the PAC using Samba's code */ + + status = gensec_session_info(gensec_server_context, &session_info); + torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed"); + + pac_wrapped_struct.MessageType = 0x3; + pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; + pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; + pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; + pac_wrapped_struct.ChecksumAndSignature = payload + = data_blob_talloc(tmp_ctx, NULL, + pac_wrapped_struct.ChecksumLength + + pac_wrapped_struct.SignatureLength); + memcpy(&payload.data[0], + session_info->server_info->pac_srv_sig.signature.data, + pac_wrapped_struct.ChecksumLength); + memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], + session_info->server_info->pac_kdc_sig.signature.data, + pac_wrapped_struct.SignatureLength); + + ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, + (ndr_push_flags_fn_t)ndr_push_PAC_Validate); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); + + torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); + creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); + + /* Validate it over the netlogon pipe */ + + generic.identity_info.parameter_control = 0; + generic.identity_info.logon_id_high = 0; + generic.identity_info.logon_id_low = 0; + generic.identity_info.domain_name.string = session_info->server_info->domain_name; + generic.identity_info.account_name.string = session_info->server_info->account_name; + generic.identity_info.workstation.string = TEST_MACHINE_NAME; + + generic.package_name.string = "Kerberos"; + generic.length = pac_wrapped.length; + generic.data = pac_wrapped.data; + + ZERO_STRUCT(auth2); + creds_client_authenticator(creds, &auth); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = NetlogonGenericInformation; + r.in.logon.generic = &generic; + r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = cli_credentials_get_workstation(credentials); + r.in.validation_level = NetlogonValidationGenericInfo2; + + status = dcerpc_netr_LogonSamLogon(p, tctx, &r); + + torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); + + torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), + "Credential chaining failed"); + + return true; +} + +struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "PAC"); + struct torture_rpc_tcase *tcase; + + tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "netlogon", + &ndr_table_netlogon, TEST_MACHINE_NAME); + torture_rpc_tcase_add_test_creds(tcase, "verify", test_PACVerify); + + return suite; +} diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index 23867f2a77..85f7bde16c 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -395,6 +395,7 @@ NTSTATUS torture_rpc_init(void) torture_suite_add_simple_test(suite, "SAMR-USERS", torture_rpc_samr_users); torture_suite_add_simple_test(suite, "SAMR-PASSWORDS", torture_rpc_samr_passwords); torture_suite_add_suite(suite, torture_rpc_netlogon(suite)); + torture_suite_add_suite(suite, torture_rpc_remote_pac(suite)); torture_suite_add_simple_test(suite, "SAMLOGON", torture_rpc_samlogon); torture_suite_add_simple_test(suite, "SAMSYNC", torture_rpc_samsync); torture_suite_add_simple_test(suite, "SCHANNEL", torture_rpc_schannel); diff --git a/source4/torture/rpc/session_key.c b/source4/torture/rpc/session_key.c index 0df7e576ee..c069c62724 100644 --- a/source4/torture/rpc/session_key.c +++ b/source4/torture/rpc/session_key.c @@ -42,7 +42,7 @@ static bool test_CreateSecret_basic(struct dcerpc_pipe *p, struct lsa_SetSecret r3; struct lsa_QuerySecret r4; struct policy_handle sec_handle; - struct lsa_Delete d; + struct lsa_DeleteObject d; struct lsa_DATA_BUF buf1; struct lsa_DATA_BUF_PTR bufp1; DATA_BLOB enc_key; @@ -128,7 +128,8 @@ static bool test_CreateSecret_basic(struct dcerpc_pipe *p, torture_assert_str_equal(tctx, secret1, secret2, "Returned secret invalid"); d.in.handle = &sec_handle; - status = dcerpc_lsa_Delete(p, tctx, &d); + d.out.handle = &sec_handle; + status = dcerpc_lsa_DeleteObject(p, tctx, &d); torture_assert_ntstatus_ok(tctx, status, "delete should have returned OKINVALID_HANDLE"); return true; } diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c index 9fd9d2f0c6..2af8c4f872 100644 --- a/source4/torture/rpc/testjoin.c +++ b/source4/torture/rpc/testjoin.c @@ -400,6 +400,7 @@ _PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx, } cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED); cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED); + cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno); if (acct_flags & ACB_SVRTRUST) { cli_credentials_set_secure_channel_type(*machine_credentials, SEC_CHAN_BDC); |