summaryrefslogtreecommitdiff
path: root/source4/torture
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture')
-rw-r--r--source4/torture/auth/pac.c69
-rw-r--r--source4/torture/config.mk2
-rw-r--r--source4/torture/nbt/dgram.c4
-rw-r--r--source4/torture/rpc/lsa.c151
-rw-r--r--source4/torture/rpc/netlogon.c15
-rw-r--r--source4/torture/rpc/netlogon.h6
-rw-r--r--source4/torture/rpc/remote_pac.c203
-rw-r--r--source4/torture/rpc/rpc.c1
-rw-r--r--source4/torture/rpc/session_key.c5
-rw-r--r--source4/torture/rpc/testjoin.c1
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);