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/>.
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"
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"
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
,
59 struct smb_krb5_context
*smb_krb5_context
,
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
)
67 struct auth_user_info_dc
*user_info_dc
;
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
) {
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
) {
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
) {
95 return NT_STATUS_NO_MEMORY
;
98 nt_status
= kerberos_pac_blob_to_user_info_dc(tmp_ctx
,
100 smb_krb5_context
->krb5_context
,
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
);
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
,
120 user_info_dc
, session_info_flags
,
122 if (!NT_STATUS_IS_OK(nt_status
)) {
123 talloc_free(tmp_ctx
);
127 talloc_free(tmp_ctx
);
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
,
136 const struct PAC_BUFFER
*pac_buf
= NULL
;
139 for (i
= 0; i
< pac_data
->num_buffers
; ++i
) {
140 pac_buf
= &pac_data
->buffers
[i
];
142 if (pac_buf
->type
== type
) {
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
)
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
);
196 struct cli_credentials
*tmp_creds
= NULL
;
197 const char *error_string
= NULL
;
200 torture_comment(tctx
,
201 "Using pkinit_ccache=%s\n",
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
,
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
,
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
228 cli_credentials_shallow_copy(tmp_ctx
, tmp_creds
);
231 "Failed to copy of credentials");
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
241 cli_credentials_shallow_copy(tmp_ctx
,
242 samba_cmdline_get_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
,
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);
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
)) {
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");
317 if (expect_pac_upn_dns_info
) {
318 num_pac_buffers
+= 1;
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");
330 pac_buf
->info
!= NULL
,
331 "PAC_TYPE_LOGON_INFO info");
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");
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");
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");
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");
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");
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");
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");
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
);
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
,
415 if (!test_SetupCredentialsPipe(p1
, tctx
, server_creds
, creds
,
416 DCERPC_SIGN
| DCERPC_SEAL
, &p
)) {
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
);
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
;
462 netlogon_creds_client_authenticator(creds
, &auth
);
463 r
.in
.credential
= &auth
;
464 r
.in
.return_authenticator
= &auth2
;
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
;
485 netlogon_creds_client_authenticator(creds
, &auth
);
486 r
.in
.credential
= &auth
;
487 r
.in
.return_authenticator
= &auth2
;
488 r
.in
.logon_level
= NetlogonGenericInformation
;
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 */
505 logon
.generic
= &generic
;
508 netlogon_creds_client_authenticator(creds
, &auth
);
509 r
.in
.credential
= &auth
;
510 r
.in
.return_authenticator
= &auth2
;
511 r
.in
.logon_level
= NetlogonGenericInformation
;
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
);
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
;
561 netlogon_creds_client_authenticator(creds
, &auth
);
562 r
.in
.credential
= &auth
;
563 r
.in
.return_authenticator
= &auth2
;
564 r
.in
.logon_level
= NetlogonGenericInformation
;
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
);
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
;
613 netlogon_creds_client_authenticator(creds
, &auth
);
614 r
.in
.credential
= &auth
;
615 r
.in
.return_authenticator
= &auth2
;
616 r
.in
.logon_level
= NetlogonGenericInformation
;
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");
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
;
676 switch (validation_level
) {
678 if (!validation
|| !validation
->sam2
) {
679 return NT_STATUS_INVALID_PARAMETER
;
681 base
= &validation
->sam2
->base
;
684 if (!validation
|| !validation
->sam3
) {
685 return NT_STATUS_INVALID_PARAMETER
;
687 base
= &validation
->sam3
->base
;
690 if (!validation
|| !validation
->sam6
) {
691 return NT_STATUS_INVALID_PARAMETER
;
693 base
= &validation
->sam6
->base
;
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
) {
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
)
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
;
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;
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
,
784 server_creds
= cli_credentials_shallow_copy(tmp_ctx
,
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
,
793 if (!test_SetupCredentialsPipe(p1
, tctx
, server_creds
, creds
,
794 DCERPC_SIGN
| DCERPC_SEAL
, &p
)) {
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);
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
)) {
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);
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
)) {
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
,
932 NULL
, /* server_timestamp */
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
;
956 r
.out
.validation
= &validation
;
957 r
.out
.authoritative
= &authoritative
;
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
,
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(
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(
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(
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
,
1020 ai_auth_authority_count
++;
1021 kinit_asserted_identity_index
= i
;
1024 ok
= dom_sid_equal(&kinit_session_info
->torture
->dc_sids
[i
].sid
,
1028 kinit_asserted_identity_index
= i
;
1031 ok
= dom_sid_equal(&kinit_session_info
->torture
->dc_sids
[i
].sid
,
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
,
1053 ai_auth_authority_count
++;
1054 s4u2self_asserted_identity_index
= i
;
1057 ok
= dom_sid_equal(&s4u2self_session_info
->torture
->dc_sids
[i
].sid
,
1061 s4u2self_asserted_identity_index
= i
;
1064 ok
= dom_sid_equal(&s4u2self_session_info
->torture
->dc_sids
[i
].sid
,
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
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. */
1092 while (k
== s4u2self_asserted_identity_index
|| k
== s4u2self_claims_valid_index
) {
1093 /* Skip over the asserted identity and Claims Valid SIDs. */
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");
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
)
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);
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
)) {
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
;
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
);
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");
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
);
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
);