s3:smbd: fix NULL dereference in case of readlink failure
[Samba.git] / source4 / torture / rpc / remote_pac.c
blob8f4ee2bbc445be430206611d885f327f2559c530
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for netlogon PAC operations
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "auth/auth_sam_reply.h"
25 #include "auth/gensec/gensec.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/credentials/credentials_krb5.h"
30 #include "lib/cmdline/cmdline.h"
31 #include "torture/rpc/torture_rpc.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "libcli/security/security.h"
34 #include "librpc/gen_ndr/ndr_netlogon_c.h"
35 #include "librpc/gen_ndr/ndr_krb5pac.h"
36 #include "librpc/gen_ndr/ndr_samr_c.h"
37 #include "param/param.h"
38 #include <ldb.h>
39 #include "ldb_wrap.h"
40 #include "dsdb/samdb/samdb.h"
42 #define TEST_MACHINE_NAME_BDC "torturepacbdc"
43 #define TEST_MACHINE_NAME_WKSTA "torturepacwksta"
44 #define TEST_MACHINE_NAME_S4U2SELF_BDC "tests4u2selfbdc"
45 #define TEST_MACHINE_NAME_S4U2SELF_WKSTA "tests4u2selfwk"
46 #define TEST_MACHINE_NAME_S4U2PROXY_WKSTA "tests4u2proxywk"
48 struct pac_data {
49 DATA_BLOB pac_blob;
50 struct PAC_SIGNATURE_DATA *pac_srv_sig;
51 struct PAC_SIGNATURE_DATA *pac_kdc_sig;
54 /* A helper function which avoids touching the local databases to
55 * generate the session info, as we just want to verify the PAC
56 * details, not the full local token */
57 static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx,
58 TALLOC_CTX *mem_ctx,
59 struct smb_krb5_context *smb_krb5_context,
60 DATA_BLOB *pac_blob,
61 const char *principal_name,
62 const struct tsocket_address *remote_address,
63 uint32_t session_info_flags,
64 struct auth_session_info **session_info)
66 NTSTATUS nt_status;
67 struct auth_user_info_dc *user_info_dc;
68 TALLOC_CTX *tmp_ctx;
69 struct pac_data *pac_data;
71 if (pac_blob == NULL) {
72 DBG_ERR("pac_blob missing\n");
73 return NT_STATUS_NO_IMPERSONATION_TOKEN;
76 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
77 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
79 auth_ctx->private_data = pac_data = talloc_zero(auth_ctx, struct pac_data);
81 pac_data->pac_blob = data_blob_dup_talloc(pac_data, *pac_blob);
82 if (pac_data->pac_blob.length != pac_blob->length) {
83 talloc_free(tmp_ctx);
84 return NT_STATUS_NO_MEMORY;
87 pac_data->pac_srv_sig = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
88 if (!pac_data->pac_srv_sig) {
89 talloc_free(tmp_ctx);
90 return NT_STATUS_NO_MEMORY;
92 pac_data->pac_kdc_sig = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA);
93 if (!pac_data->pac_kdc_sig) {
94 talloc_free(tmp_ctx);
95 return NT_STATUS_NO_MEMORY;
98 nt_status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
99 *pac_blob,
100 smb_krb5_context->krb5_context,
101 &user_info_dc,
102 pac_data->pac_srv_sig,
103 pac_data->pac_kdc_sig);
104 if (!NT_STATUS_IS_OK(nt_status)) {
105 talloc_free(tmp_ctx);
106 return nt_status;
109 talloc_steal(pac_data, pac_data->pac_srv_sig);
110 talloc_steal(pac_data, pac_data->pac_kdc_sig);
112 if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
113 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
116 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
117 nt_status = auth_generate_session_info(mem_ctx,
118 NULL,
119 NULL,
120 user_info_dc, session_info_flags,
121 session_info);
122 if (!NT_STATUS_IS_OK(nt_status)) {
123 talloc_free(tmp_ctx);
124 return nt_status;
127 talloc_free(tmp_ctx);
128 return nt_status;
131 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
133 static const struct PAC_BUFFER *get_pac_buffer(const struct PAC_DATA *pac_data,
134 enum PAC_TYPE type)
136 const struct PAC_BUFFER *pac_buf = NULL;
137 uint32_t i;
139 for (i = 0; i < pac_data->num_buffers; ++i) {
140 pac_buf = &pac_data->buffers[i];
142 if (pac_buf->type == type) {
143 break;
147 return pac_buf;
150 /* Also happens to be a really good one-step verification of our Kerberos stack */
152 static bool netlogon_validate_pac(struct torture_context *tctx,
153 struct dcerpc_pipe *p1,
154 struct cli_credentials *server_creds,
155 enum netr_SchannelType secure_channel_type,
156 const char *test_machine_name,
157 uint32_t negotiate_flags,
158 struct pac_data *pac_data,
159 struct auth_session_info *session_info);
161 static bool test_PACVerify(struct torture_context *tctx,
162 struct dcerpc_pipe *p,
163 struct cli_credentials *credentials,
164 enum netr_SchannelType secure_channel_type,
165 const char *test_machine_name,
166 uint32_t negotiate_flags)
168 NTSTATUS status;
169 bool ok;
170 const char *pkinit_ccache = torture_setting_string(tctx, "pkinit_ccache", NULL);
171 bool pkinit_in_use = pkinit_ccache != NULL;
172 bool expect_pac_upn_dns_info = torture_setting_bool(tctx, "expect_pac_upn_dns_info", true);
173 size_t num_pac_buffers;
174 struct gensec_security *gensec_client_context;
175 struct gensec_security *gensec_server_context;
176 struct cli_credentials *client_creds;
177 struct cli_credentials *server_creds;
179 DATA_BLOB client_to_server, server_to_client;
180 struct PAC_DATA pac_data_struct;
181 enum ndr_err_code ndr_err;
183 struct auth4_context *auth_context;
184 struct auth_session_info *session_info;
185 struct pac_data *pac_data;
186 const struct PAC_BUFFER *pac_buf = NULL;
188 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
189 torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
191 torture_comment(tctx,
192 "Testing PAC Verify (secure_channel_type: %d, machine: %s, negotiate_flags: 0x%08x\n",
193 secure_channel_type, test_machine_name, negotiate_flags);
195 if (pkinit_in_use) {
196 struct cli_credentials *tmp_creds = NULL;
197 const char *error_string = NULL;
198 int rc;
200 torture_comment(tctx,
201 "Using pkinit_ccache=%s\n",
202 pkinit_ccache);
204 tmp_creds = cli_credentials_init(tctx);
205 torture_assert(tctx, tmp_creds, "Failed to create credentials");
207 rc = cli_credentials_set_ccache(tmp_creds,
208 tctx->lp_ctx,
209 pkinit_ccache,
210 CRED_SPECIFIED,
211 &error_string);
212 torture_assert_int_equal(tctx,
215 "cli_credentials_set_ccache failed");
216 cli_credentials_set_kerberos_state(tmp_creds,
217 CRED_USE_KERBEROS_REQUIRED,
218 CRED_SPECIFIED);
221 * Copy the credentials in order to use a different MEMORY krb5
222 * ccache for each client/server setup. The MEMORY cache
223 * identifier is a pointer to the creds container. If we copy
224 * it the pointer changes and we will get a new clean memory
225 * cache.
227 client_creds =
228 cli_credentials_shallow_copy(tmp_ctx, tmp_creds);
229 torture_assert(tctx,
230 client_creds,
231 "Failed to copy of credentials");
232 } else {
234 * Copy the credentials in order to use a different MEMORY krb5
235 * ccache for each client/server setup. The MEMORY cache
236 * identifier is a pointer to the creds container. If we copy
237 * it the pointer changes and we will get a new clean memory
238 * cache.
240 client_creds =
241 cli_credentials_shallow_copy(tmp_ctx,
242 samba_cmdline_get_creds());
243 torture_assert(tctx,
244 client_creds,
245 "Failed to copy of credentials");
246 cli_credentials_invalidate_ccache(client_creds, CRED_SPECIFIED);
250 server_creds = cli_credentials_shallow_copy(tmp_ctx,
251 credentials);
252 torture_assert(tctx, server_creds, "Failed to copy of credentials");
254 auth_context = talloc_zero(tmp_ctx, struct auth4_context);
255 torture_assert(tctx, auth_context != NULL, "talloc_new() failed");
257 auth_context->generate_session_info_pac = test_generate_session_info_pac;
259 status = gensec_client_start(tctx, &gensec_client_context,
260 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
261 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
263 status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
265 status = gensec_set_credentials(gensec_client_context, client_creds);
266 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
268 status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
269 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
271 status = gensec_server_start(tctx,
272 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
273 auth_context, &gensec_server_context);
274 torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
276 status = gensec_set_credentials(gensec_server_context, server_creds);
277 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
279 status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
280 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
282 server_to_client = data_blob(NULL, 0);
284 do {
285 /* Do a client-server update dance */
286 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
287 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
288 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
291 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
292 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
293 torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
296 if (NT_STATUS_IS_OK(status)) {
297 break;
299 } while (1);
301 /* Extract the PAC using Samba's code */
303 status = gensec_session_info(gensec_server_context, gensec_server_context, &session_info);
304 torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
306 pac_data = talloc_get_type(auth_context->private_data, struct pac_data);
308 torture_assert(tctx, pac_data != NULL, "gensec_update failed to fill in pac_data in auth_context");
309 torture_assert(tctx, pac_data->pac_srv_sig != NULL, "pac_srv_sig not present");
310 torture_assert(tctx, pac_data->pac_kdc_sig != NULL, "pac_kdc_sig not present");
312 ndr_err = ndr_pull_struct_blob(&pac_data->pac_blob, tmp_ctx, &pac_data_struct,
313 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
314 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed");
316 num_pac_buffers = 7;
317 if (expect_pac_upn_dns_info) {
318 num_pac_buffers += 1;
320 if (pkinit_in_use) {
321 num_pac_buffers += 1;
324 torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version");
325 torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers");
327 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_INFO);
328 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_INFO");
329 torture_assert(tctx,
330 pac_buf->info != NULL,
331 "PAC_TYPE_LOGON_INFO info");
333 if (pkinit_in_use) {
334 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_CREDENTIAL_INFO);
335 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_CREDENTIAL_INFO");
336 torture_assert(tctx,
337 pac_buf->info != NULL,
338 "PAC_TYPE_CREDENTIAL_INFO info");
341 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_NAME);
342 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_NAME");
343 torture_assert(tctx,
344 pac_buf->info != NULL,
345 "PAC_TYPE_LOGON_NAME info");
347 if (expect_pac_upn_dns_info) {
348 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_UPN_DNS_INFO);
349 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_UPN_DNS_INFO");
350 torture_assert(tctx,
351 pac_buf->info != NULL,
352 "PAC_TYPE_UPN_DNS_INFO info");
355 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_SRV_CHECKSUM);
356 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_SRV_CHECKSUM");
357 torture_assert(tctx,
358 pac_buf->info != NULL,
359 "PAC_TYPE_SRV_CHECKSUM info");
361 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_KDC_CHECKSUM);
362 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_KDC_CHECKSUM");
363 torture_assert(tctx,
364 pac_buf->info != NULL,
365 "PAC_TYPE_KDC_CHECKSUM info");
367 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_TICKET_CHECKSUM);
368 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_TICKET_CHECKSUM");
369 torture_assert(tctx,
370 pac_buf->info != NULL,
371 "PAC_TYPE_TICKET_CHECKSUM info");
373 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_FULL_CHECKSUM);
374 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_FULL_CHECKSUM");
375 torture_assert(tctx,
376 pac_buf->info != NULL,
377 "PAC_TYPE_FULL_CHECKSUM info");
379 ok = netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name,
380 negotiate_flags, pac_data, session_info);
382 talloc_free(tmp_ctx);
384 return ok;
387 static bool netlogon_validate_pac(struct torture_context *tctx,
388 struct dcerpc_pipe *p1,
389 struct cli_credentials *server_creds,
390 enum netr_SchannelType secure_channel_type,
391 const char *test_machine_name,
392 uint32_t negotiate_flags,
393 struct pac_data *pac_data,
394 struct auth_session_info *session_info)
396 struct PAC_Validate pac_wrapped_struct;
397 struct netlogon_creds_CredentialState *creds = NULL;
398 struct netr_Authenticator return_authenticator;
399 struct netr_Authenticator auth, auth2;
400 struct netr_GenericInfo generic;
401 struct netr_LogonSamLogon r;
402 union netr_Validation validation;
403 union netr_LogonLevel logon;
404 uint8_t authoritative;
405 struct dcerpc_pipe *p = NULL;
406 struct dcerpc_binding_handle *b = NULL;
407 enum ndr_err_code ndr_err;
408 DATA_BLOB payload, pac_wrapped;
410 if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
411 server_creds, secure_channel_type,
412 &creds)) {
413 return false;
415 if (!test_SetupCredentialsPipe(p1, tctx, server_creds, creds,
416 DCERPC_SIGN | DCERPC_SEAL, &p)) {
417 return false;
419 b = p->binding_handle;
421 pac_wrapped_struct.ChecksumLength = pac_data->pac_srv_sig->signature.length;
422 pac_wrapped_struct.SignatureType = pac_data->pac_kdc_sig->type;
423 pac_wrapped_struct.SignatureLength = pac_data->pac_kdc_sig->signature.length;
424 pac_wrapped_struct.ChecksumAndSignature = payload
425 = data_blob_talloc(tctx, NULL,
426 pac_wrapped_struct.ChecksumLength
427 + pac_wrapped_struct.SignatureLength);
428 memcpy(&payload.data[0],
429 pac_data->pac_srv_sig->signature.data,
430 pac_wrapped_struct.ChecksumLength);
431 memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
432 pac_data->pac_kdc_sig->signature.data,
433 pac_wrapped_struct.SignatureLength);
435 ndr_err = ndr_push_struct_blob(&pac_wrapped, tctx, &pac_wrapped_struct,
436 (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
437 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
439 torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
440 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
441 netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length);
442 } else {
443 netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
446 generic.length = pac_wrapped.length;
447 generic.data = pac_wrapped.data;
449 /* Validate it over the netlogon pipe */
451 generic.identity_info.parameter_control = 0;
452 generic.identity_info.logon_id = 0;
453 generic.identity_info.domain_name.string = session_info->info->domain_name;
454 generic.identity_info.account_name.string = session_info->info->account_name;
455 generic.identity_info.workstation.string = test_machine_name;
457 generic.package_name.string = "Kerberos";
459 logon.generic = &generic;
461 ZERO_STRUCT(auth2);
462 netlogon_creds_client_authenticator(creds, &auth);
463 r.in.credential = &auth;
464 r.in.return_authenticator = &auth2;
465 r.in.logon = &logon;
466 r.in.logon_level = NetlogonGenericInformation;
467 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
468 r.in.computer_name = cli_credentials_get_workstation(server_creds);
469 r.in.validation_level = NetlogonValidationGenericInfo2;
470 r.out.validation = &validation;
471 r.out.authoritative = &authoritative;
472 r.out.return_authenticator = &return_authenticator;
474 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
475 "LogonSamLogon failed");
477 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogon failed");
479 /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
480 generic.data[generic.length-1]++;
482 logon.generic = &generic;
484 ZERO_STRUCT(auth2);
485 netlogon_creds_client_authenticator(creds, &auth);
486 r.in.credential = &auth;
487 r.in.return_authenticator = &auth2;
488 r.in.logon_level = NetlogonGenericInformation;
489 r.in.logon = &logon;
490 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
491 r.in.computer_name = cli_credentials_get_workstation(server_creds);
492 r.in.validation_level = NetlogonValidationGenericInfo2;
494 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
495 "LogonSamLogon failed");
497 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
499 torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
500 "Credential chaining failed");
502 /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
503 generic.length--;
505 logon.generic = &generic;
507 ZERO_STRUCT(auth2);
508 netlogon_creds_client_authenticator(creds, &auth);
509 r.in.credential = &auth;
510 r.in.return_authenticator = &auth2;
511 r.in.logon_level = NetlogonGenericInformation;
512 r.in.logon = &logon;
513 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
514 r.in.computer_name = cli_credentials_get_workstation(server_creds);
515 r.in.validation_level = NetlogonValidationGenericInfo2;
517 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
518 "LogonSamLogon failed");
520 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
522 torture_assert(tctx, netlogon_creds_client_check(creds,
523 &r.out.return_authenticator->cred),
524 "Credential chaining failed");
526 pac_wrapped_struct.ChecksumLength = pac_data->pac_srv_sig->signature.length;
527 pac_wrapped_struct.SignatureType = pac_data->pac_kdc_sig->type;
529 /* Break the SignatureType */
530 pac_wrapped_struct.SignatureType++;
532 pac_wrapped_struct.SignatureLength = pac_data->pac_kdc_sig->signature.length;
533 pac_wrapped_struct.ChecksumAndSignature = payload
534 = data_blob_talloc(tctx, NULL,
535 pac_wrapped_struct.ChecksumLength
536 + pac_wrapped_struct.SignatureLength);
537 memcpy(&payload.data[0],
538 pac_data->pac_srv_sig->signature.data,
539 pac_wrapped_struct.ChecksumLength);
540 memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
541 pac_data->pac_kdc_sig->signature.data,
542 pac_wrapped_struct.SignatureLength);
544 ndr_err = ndr_push_struct_blob(&pac_wrapped, tctx, &pac_wrapped_struct,
545 (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
546 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
548 torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
549 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
550 netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length);
551 } else {
552 netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
555 generic.length = pac_wrapped.length;
556 generic.data = pac_wrapped.data;
558 logon.generic = &generic;
560 ZERO_STRUCT(auth2);
561 netlogon_creds_client_authenticator(creds, &auth);
562 r.in.credential = &auth;
563 r.in.return_authenticator = &auth2;
564 r.in.logon_level = NetlogonGenericInformation;
565 r.in.logon = &logon;
566 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
567 r.in.computer_name = cli_credentials_get_workstation(server_creds);
568 r.in.validation_level = NetlogonValidationGenericInfo2;
570 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
571 "LogonSamLogon failed");
573 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");
575 torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
576 "Credential chaining failed");
578 pac_wrapped_struct.ChecksumLength = pac_data->pac_srv_sig->signature.length;
579 pac_wrapped_struct.SignatureType = pac_data->pac_kdc_sig->type;
580 pac_wrapped_struct.SignatureLength = pac_data->pac_kdc_sig->signature.length;
582 pac_wrapped_struct.ChecksumAndSignature = payload
583 = data_blob_talloc(tctx, NULL,
584 pac_wrapped_struct.ChecksumLength
585 + pac_wrapped_struct.SignatureLength);
586 memcpy(&payload.data[0],
587 pac_data->pac_srv_sig->signature.data,
588 pac_wrapped_struct.ChecksumLength);
589 memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
590 pac_data->pac_kdc_sig->signature.data,
591 pac_wrapped_struct.SignatureLength);
593 /* Break the signature length */
594 pac_wrapped_struct.SignatureLength++;
596 ndr_err = ndr_push_struct_blob(&pac_wrapped, tctx, &pac_wrapped_struct,
597 (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
598 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");
600 torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
601 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
602 netlogon_creds_aes_encrypt(creds, pac_wrapped.data, pac_wrapped.length);
603 } else {
604 netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);
607 generic.length = pac_wrapped.length;
608 generic.data = pac_wrapped.data;
610 logon.generic = &generic;
612 ZERO_STRUCT(auth2);
613 netlogon_creds_client_authenticator(creds, &auth);
614 r.in.credential = &auth;
615 r.in.return_authenticator = &auth2;
616 r.in.logon_level = NetlogonGenericInformation;
617 r.in.logon = &logon;
618 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
619 r.in.computer_name = cli_credentials_get_workstation(server_creds);
620 r.in.validation_level = NetlogonValidationGenericInfo2;
622 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogon_r(b, tctx, &r),
623 "LogonSamLogon failed");
625 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");
627 torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
628 "Credential chaining failed");
630 return true;
633 static bool test_PACVerify_bdc_arcfour(struct torture_context *tctx,
634 struct dcerpc_pipe *p,
635 struct cli_credentials *credentials)
637 return test_PACVerify(tctx, p, credentials, SEC_CHAN_BDC,
638 TEST_MACHINE_NAME_BDC,
639 NETLOGON_NEG_AUTH2_ADS_FLAGS);
642 static bool test_PACVerify_bdc_aes(struct torture_context *tctx,
643 struct dcerpc_pipe *p,
644 struct cli_credentials *credentials)
646 return test_PACVerify(tctx, p, credentials, SEC_CHAN_BDC,
647 TEST_MACHINE_NAME_BDC,
648 NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
651 static bool test_PACVerify_workstation_arcfour(struct torture_context *tctx,
652 struct dcerpc_pipe *p,
653 struct cli_credentials *credentials)
655 return test_PACVerify(tctx, p, credentials, SEC_CHAN_WKSTA,
656 TEST_MACHINE_NAME_WKSTA,
657 NETLOGON_NEG_AUTH2_ADS_FLAGS);
660 static bool test_PACVerify_workstation_aes(struct torture_context *tctx,
661 struct dcerpc_pipe *p,
662 struct cli_credentials *credentials)
664 return test_PACVerify(tctx, p, credentials, SEC_CHAN_WKSTA,
665 TEST_MACHINE_NAME_WKSTA,
666 NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
669 #ifdef SAMBA4_USES_HEIMDAL
670 static NTSTATUS check_primary_group_in_validation(TALLOC_CTX *mem_ctx,
671 uint16_t validation_level,
672 const union netr_Validation *validation)
674 const struct netr_SamBaseInfo *base = NULL;
675 int i;
676 switch (validation_level) {
677 case 2:
678 if (!validation || !validation->sam2) {
679 return NT_STATUS_INVALID_PARAMETER;
681 base = &validation->sam2->base;
682 break;
683 case 3:
684 if (!validation || !validation->sam3) {
685 return NT_STATUS_INVALID_PARAMETER;
687 base = &validation->sam3->base;
688 break;
689 case 6:
690 if (!validation || !validation->sam6) {
691 return NT_STATUS_INVALID_PARAMETER;
693 base = &validation->sam6->base;
694 break;
695 default:
696 return NT_STATUS_INVALID_LEVEL;
699 for (i = 0; i < base->groups.count; i++) {
700 if (base->groups.rids[i].rid == base->primary_gid) {
701 return NT_STATUS_OK;
704 return NT_STATUS_INVALID_PARAMETER;
707 /* Check various ways to get the PAC, in particular check the group membership and
708 * other details between the PAC from a normal kinit, S4U2Self and a SamLogon */
709 static bool test_S4U2Self(struct torture_context *tctx,
710 struct dcerpc_pipe *p1,
711 struct cli_credentials *credentials,
712 enum netr_SchannelType secure_channel_type,
713 const char *test_machine_name,
714 uint32_t negotiate_flags)
716 NTSTATUS status;
717 struct dcerpc_pipe *p = NULL;
718 struct dcerpc_binding_handle *b = NULL;
720 struct netr_LogonSamLogon r;
722 union netr_LogonLevel logon;
723 union netr_Validation validation;
724 uint8_t authoritative;
726 struct netr_Authenticator auth, auth2;
728 DATA_BLOB client_to_server, server_to_client;
730 struct netlogon_creds_CredentialState *creds;
731 struct gensec_security *gensec_client_context;
732 struct gensec_security *gensec_server_context;
733 struct cli_credentials *client_creds;
734 struct cli_credentials *server_creds;
736 struct auth4_context *auth_context;
737 struct auth_session_info *kinit_session_info;
738 struct auth_session_info *s4u2self_session_info;
739 struct auth_user_info_dc *netlogon_user_info_dc;
741 struct netr_NetworkInfo ninfo = {};
742 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
743 size_t i;
744 size_t j;
745 size_t k;
746 int flags = CLI_CRED_NTLMv2_AUTH;
748 struct dom_sid *builtin_domain;
750 struct dom_sid *ai_auth_authority = NULL;
751 struct dom_sid *ai_service = NULL;
752 struct dom_sid *ai_claims_valid = NULL;
753 size_t ai_auth_authority_count = 0;
754 size_t ai_service_count = 0;
755 size_t ai_claims_valid_count = 0;
756 size_t kinit_asserted_identity_index = 0;
757 size_t kinit_claims_valid_index = 0;
758 size_t s4u2self_asserted_identity_index = 0;
759 size_t s4u2self_claims_valid_index = 0;
760 bool ok;
762 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
764 torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
766 torture_comment(tctx,
767 "Testing S4U2SELF (secure_channel_type: %d, machine: %s, negotiate_flags: 0x%08x\n",
768 secure_channel_type, test_machine_name, negotiate_flags);
771 * Copy the credentials in order to use a different MEMORY krb5 ccache
772 * for each client/server setup. The MEMORY cache identifier is a
773 * pointer to the creds container. If we copy it the pointer changes and
774 * we will get a new clean memory cache.
776 client_creds = cli_credentials_shallow_copy(tmp_ctx,
777 samba_cmdline_get_creds());
778 torture_assert(tctx, client_creds, "Failed to copy of credentials");
779 /* We use cli_credentials_get_ntlm_response(), so relax krb5 requirements. */
780 cli_credentials_set_kerberos_state(client_creds,
781 CRED_USE_KERBEROS_DESIRED,
782 CRED_SPECIFIED);
784 server_creds = cli_credentials_shallow_copy(tmp_ctx,
785 credentials);
786 torture_assert(tctx, server_creds, "Failed to copy of credentials");
788 if (!test_SetupCredentials2(p1, tctx, negotiate_flags,
789 server_creds, secure_channel_type,
790 &creds)) {
791 return false;
793 if (!test_SetupCredentialsPipe(p1, tctx, server_creds, creds,
794 DCERPC_SIGN | DCERPC_SEAL, &p)) {
795 return false;
797 b = p->binding_handle;
799 auth_context = talloc_zero(tmp_ctx, struct auth4_context);
800 torture_assert(tctx, auth_context != NULL, "talloc_new() failed");
802 auth_context->generate_session_info_pac = test_generate_session_info_pac;
804 /* First, do a normal Kerberos connection */
806 status = gensec_client_start(tctx, &gensec_client_context,
807 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
808 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
810 status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
812 status = gensec_set_credentials(gensec_client_context, client_creds);
813 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
815 status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
816 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
818 status = gensec_server_start(tctx,
819 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
820 auth_context, &gensec_server_context);
821 torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
823 status = gensec_set_credentials(gensec_server_context, server_creds);
824 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
826 status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
827 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
829 server_to_client = data_blob(NULL, 0);
831 do {
832 /* Do a client-server update dance */
833 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
834 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
835 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
838 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
839 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
840 torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
843 if (NT_STATUS_IS_OK(status)) {
844 break;
846 } while (1);
848 /* Extract the PAC using Samba's code */
850 status = gensec_session_info(gensec_server_context, gensec_server_context, &kinit_session_info);
851 torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
854 /* Now do the dance with S4U2Self */
856 /* Wipe out any existing ccache */
857 cli_credentials_invalidate_ccache(client_creds, CRED_SPECIFIED);
858 cli_credentials_invalidate_ccache(server_creds, CRED_SPECIFIED);
859 cli_credentials_set_impersonate_principal(server_creds,
860 cli_credentials_get_principal(client_creds, tmp_ctx),
861 talloc_asprintf(tmp_ctx, "host/%s", test_machine_name));
863 status = gensec_client_start(tctx, &gensec_client_context,
864 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
865 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
867 status = gensec_set_target_hostname(gensec_client_context, test_machine_name);
869 /* We now set the same credentials on both client and server contexts */
870 status = gensec_set_credentials(gensec_client_context, server_creds);
871 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
873 status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
874 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
876 status = gensec_server_start(tctx,
877 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
878 auth_context, &gensec_server_context);
879 torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
881 status = gensec_set_credentials(gensec_server_context, server_creds);
882 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
884 status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
885 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
887 server_to_client = data_blob(NULL, 0);
889 do {
890 /* Do a client-server update dance */
891 status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
892 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
893 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
896 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
897 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
898 torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
901 if (NT_STATUS_IS_OK(status)) {
902 break;
904 } while (1);
906 /* Don't pollute the remaining tests with the changed credentials */
907 cli_credentials_invalidate_ccache(server_creds, CRED_SPECIFIED);
908 cli_credentials_set_target_service(server_creds, NULL);
909 cli_credentials_set_impersonate_principal(server_creds, NULL, NULL);
911 /* Extract the PAC using Samba's code */
913 status = gensec_session_info(gensec_server_context, gensec_server_context, &s4u2self_session_info);
914 torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
916 cli_credentials_get_ntlm_username_domain(client_creds, tctx,
917 &ninfo.identity_info.account_name.string,
918 &ninfo.identity_info.domain_name.string);
920 /* Now try with SamLogon */
921 generate_random_buffer(ninfo.challenge,
922 sizeof(ninfo.challenge));
923 chal = data_blob_const(ninfo.challenge,
924 sizeof(ninfo.challenge));
926 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(server_creds),
927 cli_credentials_get_domain(server_creds));
929 status = cli_credentials_get_ntlm_response(client_creds, tctx,
930 &flags,
931 chal,
932 NULL, /* server_timestamp */
933 names_blob,
934 &lm_resp, &nt_resp,
935 NULL, NULL);
936 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
938 ninfo.lm.data = lm_resp.data;
939 ninfo.lm.length = lm_resp.length;
941 ninfo.nt.data = nt_resp.data;
942 ninfo.nt.length = nt_resp.length;
944 ninfo.identity_info.parameter_control = 0;
945 ninfo.identity_info.logon_id = 0;
946 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(server_creds);
948 logon.network = &ninfo;
950 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
951 r.in.computer_name = cli_credentials_get_workstation(server_creds);
952 r.in.credential = &auth;
953 r.in.return_authenticator = &auth2;
954 r.in.logon_level = NetlogonNetworkInformation;
955 r.in.logon = &logon;
956 r.out.validation = &validation;
957 r.out.authoritative = &authoritative;
959 ZERO_STRUCT(auth2);
960 netlogon_creds_client_authenticator(creds, &auth);
962 r.in.validation_level = 3;
964 status = dcerpc_netr_LogonSamLogon_r(b, tctx, &r);
965 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
967 torture_assert(tctx, netlogon_creds_client_check(creds,
968 &r.out.return_authenticator->cred),
969 "Credential chaining failed");
971 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogon failed");
973 status = make_user_info_dc_netlogon_validation(tmp_ctx,
974 ninfo.identity_info.account_name.string,
975 r.in.validation_level,
976 r.out.validation,
977 true, /* This user was authenticated */
978 &netlogon_user_info_dc);
980 torture_assert_ntstatus_ok(tctx, status, "make_user_info_dc_netlogon_validation failed");
982 /* Check that the primary group is present in validation's RID array */
983 status = check_primary_group_in_validation(tmp_ctx, r.in.validation_level, r.out.validation);
984 torture_assert_ntstatus_ok(tctx, status, "check_primary_group_in_validation failed");
986 torture_assert_str_equal(tctx, netlogon_user_info_dc->info->account_name == NULL ? "" : netlogon_user_info_dc->info->account_name,
987 kinit_session_info->info->account_name, "Account name differs for kinit-based PAC");
988 torture_assert_str_equal(tctx,netlogon_user_info_dc->info->account_name == NULL ? "" : netlogon_user_info_dc->info->account_name,
989 s4u2self_session_info->info->account_name, "Account name differs for S4U2Self");
990 torture_assert_str_equal(tctx, netlogon_user_info_dc->info->full_name == NULL ? "" : netlogon_user_info_dc->info->full_name, kinit_session_info->info->full_name, "Full name differs for kinit-based PAC");
991 torture_assert_str_equal(tctx, netlogon_user_info_dc->info->full_name == NULL ? "" : netlogon_user_info_dc->info->full_name, s4u2self_session_info->info->full_name, "Full name differs for S4U2Self");
993 builtin_domain = dom_sid_parse_talloc(tmp_ctx, SID_BUILTIN);
994 torture_assert_not_null(tctx, builtin_domain, "failed to parse SID");
996 /* KRB5 might have an additional sid, the asserted identity */
997 ai_auth_authority = dom_sid_parse_talloc(
998 tmp_ctx,
999 SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY);
1000 torture_assert_not_null(tctx, ai_auth_authority, "failed to parse SID");
1002 ai_service = dom_sid_parse_talloc(
1003 tmp_ctx,
1004 SID_SERVICE_ASSERTED_IDENTITY);
1005 torture_assert_not_null(tctx, ai_service, "failed to parse SID");
1007 /* ...and the Claims Valid SID. */
1008 ai_claims_valid = dom_sid_parse_talloc(
1009 tmp_ctx,
1010 SID_CLAIMS_VALID);
1011 torture_assert_not_null(tctx, ai_claims_valid, "failed to parse SID");
1013 ai_auth_authority_count = 0;
1014 ai_service_count = 0;
1015 ai_claims_valid_count = 0;
1016 for (i = 0; i < kinit_session_info->torture->num_dc_sids; i++) {
1017 ok = dom_sid_equal(&kinit_session_info->torture->dc_sids[i].sid,
1018 ai_auth_authority);
1019 if (ok) {
1020 ai_auth_authority_count++;
1021 kinit_asserted_identity_index = i;
1024 ok = dom_sid_equal(&kinit_session_info->torture->dc_sids[i].sid,
1025 ai_service);
1026 if (ok) {
1027 ai_service_count++;
1028 kinit_asserted_identity_index = i;
1031 ok = dom_sid_equal(&kinit_session_info->torture->dc_sids[i].sid,
1032 ai_claims_valid);
1033 if (ok) {
1034 ai_claims_valid_count++;
1035 kinit_claims_valid_index = i;
1039 torture_assert_int_equal(tctx, ai_auth_authority_count, 1,
1040 "Kinit authority asserted identity should be (1)");
1041 torture_assert_int_equal(tctx, ai_service_count, 0,
1042 "Kinit service asserted identity should be (0)");
1043 torture_assert_int_equal(tctx, ai_claims_valid_count, 1,
1044 "Kinit Claims Valid should be (1)");
1046 ai_auth_authority_count = 0;
1047 ai_service_count = 0;
1048 ai_claims_valid_count = 0;
1049 for (i = 0; i < s4u2self_session_info->torture->num_dc_sids; i++) {
1050 ok = dom_sid_equal(&s4u2self_session_info->torture->dc_sids[i].sid,
1051 ai_auth_authority);
1052 if (ok) {
1053 ai_auth_authority_count++;
1054 s4u2self_asserted_identity_index = i;
1057 ok = dom_sid_equal(&s4u2self_session_info->torture->dc_sids[i].sid,
1058 ai_service);
1059 if (ok) {
1060 ai_service_count++;
1061 s4u2self_asserted_identity_index = i;
1064 ok = dom_sid_equal(&s4u2self_session_info->torture->dc_sids[i].sid,
1065 ai_claims_valid);
1066 if (ok) {
1067 ai_claims_valid_count++;
1068 s4u2self_claims_valid_index = i;
1072 torture_assert_int_equal(tctx, ai_auth_authority_count, 0,
1073 "S4U2Self authority asserted identity should be (0)");
1074 torture_assert_int_equal(tctx, ai_service_count, 1,
1075 "S4U2Self service asserted identity should be (1)");
1076 torture_assert_int_equal(tctx, ai_claims_valid_count, 1,
1077 "S4U2Self Claims Valid should be (1)");
1080 * Subtract 2 to account for the Asserted Identity and Claims Valid
1081 * SIDs.
1083 torture_assert_int_equal(tctx, netlogon_user_info_dc->num_sids, kinit_session_info->torture->num_dc_sids - 2, "Different numbers of domain groups for kinit-based PAC");
1084 torture_assert_int_equal(tctx, netlogon_user_info_dc->num_sids, s4u2self_session_info->torture->num_dc_sids - 2, "Different numbers of domain groups for S4U2Self");
1086 /* Loop over all three SID arrays. */
1087 for (i = 0, j = 0, k = 0; i < netlogon_user_info_dc->num_sids; i++, j++, k++) {
1088 while (j == kinit_asserted_identity_index || j == kinit_claims_valid_index) {
1089 /* Skip over the asserted identity and Claims Valid SIDs. */
1090 ++j;
1092 while (k == s4u2self_asserted_identity_index || k == s4u2self_claims_valid_index) {
1093 /* Skip over the asserted identity and Claims Valid SIDs. */
1094 ++k;
1096 torture_assert_sid_equal(tctx, &netlogon_user_info_dc->sids[i].sid, &kinit_session_info->torture->dc_sids[j].sid, "Different domain groups for kinit-based PAC");
1097 torture_assert_u32_equal(tctx, netlogon_user_info_dc->sids[i].attrs, kinit_session_info->torture->dc_sids[j].attrs, "Different domain group attrs for kinit-based PAC");
1098 torture_assert_sid_equal(tctx, &netlogon_user_info_dc->sids[i].sid, &s4u2self_session_info->torture->dc_sids[k].sid, "Different domain groups for S4U2Self");
1099 torture_assert_u32_equal(tctx, netlogon_user_info_dc->sids[i].attrs, s4u2self_session_info->torture->dc_sids[k].attrs, "Different domain group attrs for S4U2Self");
1100 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, &s4u2self_session_info->torture->dc_sids[k].sid), "Returned BUILTIN domain in groups for S4U2Self");
1101 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, &kinit_session_info->torture->dc_sids[j].sid), "Returned BUILTIN domain in groups kinit-based PAC");
1102 torture_assert(tctx, !dom_sid_in_domain(builtin_domain, &netlogon_user_info_dc->sids[i].sid), "Returned BUILTIN domain in groups from NETLOGON SamLogon reply");
1105 return true;
1108 static bool test_S4U2Self_bdc_arcfour(struct torture_context *tctx,
1109 struct dcerpc_pipe *p,
1110 struct cli_credentials *credentials)
1112 return test_S4U2Self(tctx, p, credentials, SEC_CHAN_BDC,
1113 TEST_MACHINE_NAME_S4U2SELF_BDC,
1114 NETLOGON_NEG_AUTH2_ADS_FLAGS);
1117 static bool test_S4U2Self_bdc_aes(struct torture_context *tctx,
1118 struct dcerpc_pipe *p,
1119 struct cli_credentials *credentials)
1121 return test_S4U2Self(tctx, p, credentials, SEC_CHAN_BDC,
1122 TEST_MACHINE_NAME_S4U2SELF_BDC,
1123 NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
1126 static bool test_S4U2Self_workstation_arcfour(struct torture_context *tctx,
1127 struct dcerpc_pipe *p,
1128 struct cli_credentials *credentials)
1130 return test_S4U2Self(tctx, p, credentials, SEC_CHAN_WKSTA,
1131 TEST_MACHINE_NAME_S4U2SELF_WKSTA,
1132 NETLOGON_NEG_AUTH2_ADS_FLAGS);
1135 static bool test_S4U2Self_workstation_aes(struct torture_context *tctx,
1136 struct dcerpc_pipe *p,
1137 struct cli_credentials *credentials)
1139 return test_S4U2Self(tctx, p, credentials, SEC_CHAN_WKSTA,
1140 TEST_MACHINE_NAME_S4U2SELF_WKSTA,
1141 NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
1144 static bool test_S4U2Proxy(struct torture_context *tctx,
1145 struct dcerpc_pipe *p,
1146 struct cli_credentials *credentials,
1147 enum netr_SchannelType secure_channel_type,
1148 const char *test_machine_name,
1149 uint32_t negotiate_flags)
1151 NTSTATUS status;
1152 struct gensec_security *gensec_client_context = NULL;
1153 struct gensec_security *gensec_server_context = NULL;
1154 struct cli_credentials *server_creds = NULL;
1155 size_t num_pac_buffers;
1156 struct auth4_context *auth_context = NULL;
1157 struct auth_session_info *session_info = NULL;
1158 struct pac_data *pac_data = NULL;
1159 const struct PAC_BUFFER *pac_buf = NULL;
1160 char *impersonate_princ = NULL, *self_princ = NULL, *target_princ = NULL;
1161 enum ndr_err_code ndr_err;
1162 struct PAC_DATA pac_data_struct;
1163 struct PAC_CONSTRAINED_DELEGATION *deleg = NULL;
1165 DATA_BLOB client_to_server, server_to_client;
1167 auth_context = talloc_zero(tctx, struct auth4_context);
1168 torture_assert_not_null(tctx, auth_context, "talloc_new() failed");
1170 auth_context->generate_session_info_pac = test_generate_session_info_pac;
1172 torture_comment(tctx,
1173 "Testing S4U2Proxy (secure_channel_type: %d, machine: %s, negotiate_flags: 0x%08x\n",
1174 secure_channel_type, test_machine_name, negotiate_flags);
1176 impersonate_princ = cli_credentials_get_principal(samba_cmdline_get_creds(), tctx);
1177 torture_assert_not_null(tctx, impersonate_princ, "Failed to get impersonate client name");
1179 server_creds = cli_credentials_shallow_copy(tctx, credentials);
1180 torture_assert_not_null(tctx, server_creds, "Failed to copy of credentials");
1182 self_princ = talloc_asprintf(tctx, "host/%s", test_machine_name);
1183 cli_credentials_invalidate_ccache(server_creds, CRED_SPECIFIED);
1184 cli_credentials_set_impersonate_principal(server_creds, impersonate_princ, self_princ);
1186 /* Trigger S4U2Proxy by setting a target_service different than self_principal */
1187 target_princ = talloc_asprintf(tctx, "%s$", test_machine_name);
1188 cli_credentials_set_target_service(server_creds, target_princ);
1190 status = gensec_client_start(tctx, &gensec_client_context,
1191 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
1192 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
1194 status = gensec_set_target_principal(gensec_client_context, target_princ);
1195 torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
1197 /* We now set the same credentials on both client and server contexts */
1198 status = gensec_set_credentials(gensec_client_context, server_creds);
1199 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
1201 status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
1202 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
1204 status = gensec_server_start(tctx,
1205 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
1206 auth_context, &gensec_server_context);
1207 torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
1209 status = gensec_set_credentials(gensec_server_context, server_creds);
1210 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
1212 status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
1213 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");
1215 server_to_client = data_blob(NULL, 0);
1217 do {
1218 /* Do a client-server update dance */
1219 status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
1220 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
1221 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
1224 status = gensec_update(gensec_server_context, tctx, client_to_server, &server_to_client);
1225 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
1226 torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
1229 if (NT_STATUS_IS_OK(status)) {
1230 break;
1232 } while (1);
1234 /* Extract the PAC using Samba's code */
1236 status = gensec_session_info(gensec_server_context, gensec_server_context, &session_info);
1237 torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
1239 pac_data = talloc_get_type(auth_context->private_data, struct pac_data);
1241 torture_assert_not_null(tctx, pac_data, "gensec_update failed to fill in pac_data in auth_context");
1242 torture_assert_not_null(tctx, pac_data->pac_srv_sig, "pac_srv_sig not present");
1243 torture_assert_not_null(tctx, pac_data->pac_kdc_sig, "pac_kdc_sig not present");
1245 ndr_err = ndr_pull_struct_blob(&pac_data->pac_blob, tctx, &pac_data_struct,
1246 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
1247 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed");
1249 num_pac_buffers = 9;
1251 torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version");
1252 torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers");
1254 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_INFO);
1255 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_INFO");
1256 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_LOGON_INFO info");
1258 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_LOGON_NAME);
1259 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_LOGON_NAME");
1260 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_LOGON_NAME info");
1262 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_UPN_DNS_INFO);
1263 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_UPN_DNS_INFO");
1264 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_UPN_DNS_INFO info");
1266 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_SRV_CHECKSUM);
1267 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_SRV_CHECKSUM");
1268 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_SRV_CHECKSUM info");
1270 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_KDC_CHECKSUM);
1271 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_KDC_CHECKSUM");
1272 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_KDC_CHECKSUM info");
1274 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_TICKET_CHECKSUM);
1275 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_TICKET_CHECKSUM");
1276 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_TICKET_CHECKSUM info");
1278 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_FULL_CHECKSUM);
1279 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_FULL_CHECKSUM");
1280 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_FULL_CHECKSUM info");
1282 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_CLIENT_CLAIMS_INFO);
1283 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_CLIENT_CLAIMS_INFO");
1284 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_CLIENT_CLAIMS_INFO info");
1286 pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_CONSTRAINED_DELEGATION);
1287 torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_CONSTRAINED_DELEGATION");
1288 torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_CONSTRAINED_DELEGATION info");
1290 deleg = pac_buf->info->constrained_delegation.info;
1291 torture_assert_str_equal(tctx, deleg->proxy_target.string, target_princ, "wrong proxy_target");
1292 torture_assert_int_equal(tctx, deleg->num_transited_services, 1, "wrong transited_services number");
1293 torture_assert_str_equal(tctx, deleg->transited_services[0].string,
1294 talloc_asprintf(tctx, "%s@%s", self_princ, cli_credentials_get_realm(credentials)),
1295 "wrong transited_services[0]");
1297 return netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name,
1298 negotiate_flags, pac_data, session_info);
1301 static bool setup_constrained_delegation(struct torture_context *tctx,
1302 struct dcerpc_pipe *p,
1303 struct test_join *join_ctx,
1304 const char *machine_name)
1306 struct samr_SetUserInfo r;
1307 union samr_UserInfo user_info;
1308 struct dcerpc_pipe *samr_pipe = torture_join_samr_pipe(join_ctx);
1309 const char *server_dn_str = NULL;
1310 struct ldb_context *sam_ctx = NULL;
1311 struct ldb_dn *server_dn = NULL;
1312 struct ldb_message *msg = NULL;
1313 char *url = NULL;
1314 int ret;
1316 url = talloc_asprintf(tctx, "ldap://%s", dcerpc_server_name(p));
1317 sam_ctx = ldb_wrap_connect(tctx, tctx->ev, tctx->lp_ctx, url, NULL, samba_cmdline_get_creds(), 0);
1318 torture_assert_not_null(tctx, sam_ctx, "Connection to the SAMDB on DC failed!");
1320 server_dn_str = samdb_search_string(sam_ctx, tctx, ldb_get_default_basedn(sam_ctx), "distinguishedName",
1321 "samaccountname=%s$", machine_name);
1322 torture_assert_not_null(tctx, server_dn_str, "samdb_search_string()");
1324 server_dn = ldb_dn_new(tctx, sam_ctx, server_dn_str);
1325 torture_assert_not_null(tctx, server_dn, "ldb_dn_new()");
1327 msg = ldb_msg_new(tctx);
1328 torture_assert_not_null(tctx, msg, "ldb_msg_new()");
1330 msg->dn = server_dn;
1331 ret = ldb_msg_add_string(msg, "msDS-AllowedToDelegateTo", talloc_asprintf(tctx, "%s$", machine_name));
1332 torture_assert_int_equal(tctx, ret, 0, "ldb_msg_add_string())");
1334 ret = ldb_modify(sam_ctx, msg);
1335 torture_assert_int_equal(tctx, ret, 0, "ldb_modify()");
1337 /* Allow forwardable flag in S4U2Self */
1338 user_info.info16.acct_flags = ACB_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | ACB_WSTRUST;
1339 r.in.user_handle = torture_join_samr_user_policy(join_ctx);
1340 r.in.level = 16;
1341 r.in.info = &user_info;
1343 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(samr_pipe->binding_handle, tctx, &r),
1344 "failed to set ACB_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION info account flags");
1345 torture_assert_ntstatus_ok(tctx, r.out.result,
1346 "failed to set ACB_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION into account flags");
1348 return true;
1351 static bool test_S4U2Proxy_workstation_arcfour(struct torture_context *tctx,
1352 struct dcerpc_pipe *p,
1353 struct cli_credentials *credentials,
1354 struct test_join *join_ctx)
1356 torture_assert(tctx, setup_constrained_delegation(tctx, p, join_ctx,
1357 TEST_MACHINE_NAME_S4U2PROXY_WKSTA),
1358 "setup_constrained_delegation() failed");
1359 return test_S4U2Proxy(tctx, p, credentials, SEC_CHAN_WKSTA,
1360 TEST_MACHINE_NAME_S4U2PROXY_WKSTA,
1361 NETLOGON_NEG_AUTH2_ADS_FLAGS);
1364 static bool test_S4U2Proxy_workstation_aes(struct torture_context *tctx,
1365 struct dcerpc_pipe *p,
1366 struct cli_credentials *credentials,
1367 struct test_join *join_ctx)
1369 torture_assert(tctx, setup_constrained_delegation(tctx, p, join_ctx,
1370 TEST_MACHINE_NAME_S4U2PROXY_WKSTA),
1371 "setup_constrained_delegation() failed");
1372 return test_S4U2Proxy(tctx, p, credentials, SEC_CHAN_WKSTA,
1373 TEST_MACHINE_NAME_S4U2PROXY_WKSTA,
1374 NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES);
1376 #endif
1378 struct torture_suite *torture_rpc_remote_pac(TALLOC_CTX *mem_ctx)
1380 struct torture_suite *suite = torture_suite_create(mem_ctx, "pac");
1381 struct torture_rpc_tcase *tcase;
1383 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netr-bdc-arcfour",
1384 &ndr_table_netlogon, TEST_MACHINE_NAME_BDC);
1385 torture_rpc_tcase_add_test_creds(tcase, "verify-sig-arcfour", test_PACVerify_bdc_arcfour);
1387 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netr-bdc-aes",
1388 &ndr_table_netlogon, TEST_MACHINE_NAME_BDC);
1389 torture_rpc_tcase_add_test_creds(tcase, "verify-sig-aes", test_PACVerify_bdc_aes);
1391 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-arcfour",
1392 &ndr_table_netlogon, TEST_MACHINE_NAME_WKSTA);
1393 torture_rpc_tcase_add_test_creds(tcase, "verify-sig-arcfour", test_PACVerify_workstation_arcfour);
1395 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-aes",
1396 &ndr_table_netlogon, TEST_MACHINE_NAME_WKSTA);
1397 torture_rpc_tcase_add_test_creds(tcase, "verify-sig-aes", test_PACVerify_workstation_aes);
1399 #ifdef SAMBA4_USES_HEIMDAL
1400 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netr-bdc-arcfour",
1401 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2SELF_BDC);
1402 torture_rpc_tcase_add_test_creds(tcase, "s4u2self-arcfour", test_S4U2Self_bdc_arcfour);
1404 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "netr-bcd-aes",
1405 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2SELF_BDC);
1406 torture_rpc_tcase_add_test_creds(tcase, "s4u2self-aes", test_S4U2Self_bdc_aes);
1408 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-arcfour",
1409 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2SELF_WKSTA);
1410 torture_rpc_tcase_add_test_creds(tcase, "s4u2self-arcfour", test_S4U2Self_workstation_arcfour);
1412 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-aes",
1413 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2SELF_WKSTA);
1414 torture_rpc_tcase_add_test_creds(tcase, "s4u2self-aes", test_S4U2Self_workstation_aes);
1416 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-arcfour",
1417 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2PROXY_WKSTA);
1418 torture_rpc_tcase_add_test_join(tcase, "s4u2proxy-arcfour", test_S4U2Proxy_workstation_arcfour);
1420 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "netr-mem-aes",
1421 &ndr_table_netlogon, TEST_MACHINE_NAME_S4U2PROXY_WKSTA);
1422 torture_rpc_tcase_add_test_join(tcase, "s4u2proxy-aes", test_S4U2Proxy_workstation_aes);
1423 #endif
1424 return suite;