2 Unix SMB/CIFS implementation.
4 Validate the krb5 pac generation routines
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2015
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/kerberos.h"
25 #include "torture/smbtorture.h"
26 #include "torture/krb5/proto.h"
27 #include "auth/credentials/credentials.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "source4/auth/kerberos/kerberos.h"
30 #include "source4/auth/kerberos/kerberos_util.h"
31 #include "lib/util/util_net.h"
32 #include "auth/auth.h"
33 #include "auth/auth_sam_reply.h"
34 #include "auth/gensec/gensec.h"
35 #include "param/param.h"
37 #define TEST_CANONICALIZE 0x0000001
38 #define TEST_ENTERPRISE 0x0000002
39 #define TEST_UPPER_REALM 0x0000004
40 #define TEST_UPPER_USERNAME 0x0000008
41 #define TEST_NETBIOS_REALM 0x0000010
42 #define TEST_WIN2K 0x0000020
43 #define TEST_UPN 0x0000040
44 #define TEST_S4U2SELF 0x0000080
45 #define TEST_ALL 0x00000FF
48 const char *test_name
;
50 const char *real_realm
;
51 const char *real_domain
;
53 const char *real_username
;
61 bool other_upn_suffix
;
63 const char *krb5_service
;
64 const char *krb5_hostname
;
69 TEST_TGS_REQ_KRBTGT_CANON
= 1,
70 TEST_TGS_REQ_CANON
= 2,
71 TEST_SELF_TRUST_TGS_REQ
= 3,
73 TEST_TGS_REQ_KRBTGT
= 5,
74 TEST_TGS_REQ_HOST
= 6,
75 TEST_TGS_REQ_HOST_SRV_INST
= 7,
76 TEST_TGS_REQ_HOST_SRV_HST
= 8,
81 struct torture_krb5_context
{
82 struct smb_krb5_context
*smb_krb5_context
;
83 struct torture_context
*tctx
;
84 struct addrinfo
*server
;
85 struct test_data
*test_data
;
87 enum test_stage test_stage
;
95 const char *principal_name
;
99 * A helper function which avoids touching the local databases to
100 * generate the session info, as we just want to verify the principal
101 * name that we found in the ticket not the full local token
103 static NTSTATUS
test_generate_session_info_pac(struct auth4_context
*auth_ctx
,
105 struct smb_krb5_context
*smb_krb5_context
,
107 const char *principal_name
,
108 const struct tsocket_address
*remote_address
,
109 uint32_t session_info_flags
,
110 struct auth_session_info
**session_info
)
113 struct auth_user_info_dc
*user_info_dc
;
115 struct pac_data
*pac_data
;
117 tmp_ctx
= talloc_named(mem_ctx
, 0, "gensec_gssapi_session_info context");
118 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
120 auth_ctx
->private_data
= pac_data
= talloc_zero(auth_ctx
, struct pac_data
);
122 pac_data
->principal_name
= talloc_strdup(pac_data
, principal_name
);
123 if (!pac_data
->principal_name
) {
124 talloc_free(tmp_ctx
);
125 return NT_STATUS_NO_MEMORY
;
128 nt_status
= kerberos_pac_blob_to_user_info_dc(tmp_ctx
,
130 smb_krb5_context
->krb5_context
,
131 &user_info_dc
, NULL
, NULL
);
132 if (!NT_STATUS_IS_OK(nt_status
)) {
133 talloc_free(tmp_ctx
);
137 if (user_info_dc
->info
->authenticated
) {
138 session_info_flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
141 session_info_flags
|= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
;
142 nt_status
= auth_generate_session_info(mem_ctx
,
145 user_info_dc
, session_info_flags
,
147 if (!NT_STATUS_IS_OK(nt_status
)) {
148 talloc_free(tmp_ctx
);
152 talloc_free(tmp_ctx
);
156 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
158 /* Also happens to be a really good one-step verfication of our Kerberos stack */
160 static bool test_accept_ticket(struct torture_context
*tctx
,
161 struct cli_credentials
*credentials
,
162 const char *principal
,
163 DATA_BLOB client_to_server
)
166 struct gensec_security
*gensec_server_context
;
167 DATA_BLOB server_to_client
;
168 struct auth4_context
*auth_context
;
169 struct auth_session_info
*session_info
;
170 struct pac_data
*pac_data
;
171 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
173 torture_assert(tctx
, tmp_ctx
!= NULL
, "talloc_new() failed");
175 auth_context
= talloc_zero(tmp_ctx
, struct auth4_context
);
176 torture_assert(tctx
, auth_context
!= NULL
, "talloc_new() failed");
178 auth_context
->generate_session_info_pac
= test_generate_session_info_pac
;
180 status
= gensec_server_start(tctx
,
181 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
),
182 auth_context
, &gensec_server_context
);
183 torture_assert_ntstatus_ok(tctx
, status
, "gensec_server_start (server) failed");
185 status
= gensec_set_credentials(gensec_server_context
, credentials
);
186 torture_assert_ntstatus_ok(tctx
, status
, "gensec_set_credentials (server) failed");
188 status
= gensec_start_mech_by_name(gensec_server_context
, "krb5");
189 torture_assert_ntstatus_ok(tctx
, status
, "gensec_start_mech_by_name (server) failed");
191 server_to_client
= data_blob(NULL
, 0);
193 /* Do a client-server update dance */
194 status
= gensec_update(gensec_server_context
, tmp_ctx
, client_to_server
, &server_to_client
);
195 torture_assert_ntstatus_ok(tctx
, status
, "gensec_update (server) failed");
197 /* Extract the PAC using Samba's code */
199 status
= gensec_session_info(gensec_server_context
, gensec_server_context
, &session_info
);
200 torture_assert_ntstatus_ok(tctx
, status
, "gensec_session_info failed");
202 pac_data
= talloc_get_type(auth_context
->private_data
, struct pac_data
);
204 torture_assert(tctx
, pac_data
!= NULL
, "gensec_update failed to fill in pac_data in auth_context");
205 torture_assert(tctx
, pac_data
->principal_name
!= NULL
, "principal_name not present");
206 torture_assert_str_equal(tctx
, pac_data
->principal_name
, principal
, "wrong principal name");
211 * TEST_AS_REQ and TEST_AS_REQ_SELF - SEND
213 * Confirm that the outgoing packet meets certain expectations. This
214 * should be extended to further assert the correct and expected
215 * behaviour of the krb5 libs, so we know what we are sending to the
218 * Additionally, this CHANGES the request to remove the canonicalize
219 * flag automatically added by the krb5 libs when an enterprise
220 * principal is used, so we can test what the server does in this
225 static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context
*test_context
,
226 const krb5_data
*send_buf
,
227 krb5_data
*modified_send_buf
)
230 krb5_error_code k5ret
;
232 torture_assert_int_equal(test_context
->tctx
, decode_AS_REQ(send_buf
->data
, send_buf
->length
,
233 &test_context
->as_req
, &used
),
234 0, "decode_AS_REQ for TEST_AS_REQ failed");
235 mod_as_req
= test_context
->as_req
;
236 torture_assert_int_equal(test_context
->tctx
, used
, send_buf
->length
, "length mismatch");
237 torture_assert_int_equal(test_context
->tctx
, test_context
->as_req
.pvno
,
238 5, "Got wrong as_req->pvno");
239 if (test_context
->test_data
->canonicalize
|| test_context
->test_data
->enterprise
) {
240 torture_assert(test_context
->tctx
,
241 test_context
->as_req
.req_body
.kdc_options
.canonicalize
,
242 "krb5 libs did not set canonicalize!");
244 torture_assert_int_equal(test_context
->tctx
,
245 test_context
->as_req
.req_body
.kdc_options
.canonicalize
,
247 "krb5 libs unexpectedly set canonicalize!");
250 if (test_context
->test_data
->enterprise
) {
251 torture_assert_int_equal(test_context
->tctx
,
252 test_context
->as_req
.req_body
.cname
->name_type
,
253 KRB5_NT_ENTERPRISE_PRINCIPAL
,
254 "krb5 libs did not pass principal as enterprise!");
256 torture_assert_int_equal(test_context
->tctx
,
257 test_context
->as_req
.req_body
.cname
->name_type
,
259 "krb5 libs unexpectedly set principal as enterprise!");
262 /* Force off canonicalize that was forced on by the krb5 libs */
263 if (test_context
->test_data
->canonicalize
== false && test_context
->test_data
->enterprise
) {
264 mod_as_req
.req_body
.kdc_options
.canonicalize
= false;
267 if (test_context
->test_stage
== TEST_AS_REQ_SELF
) {
269 * Force the server name to match the client name,
270 * including the name type. This isn't possible with
271 * the krb5 client libs alone
273 mod_as_req
.req_body
.sname
= test_context
->as_req
.req_body
.cname
;
276 ASN1_MALLOC_ENCODE(AS_REQ
, modified_send_buf
->data
, modified_send_buf
->length
,
277 &mod_as_req
, &used
, k5ret
);
278 torture_assert_int_equal(test_context
->tctx
,
280 "encode_AS_REQ failed");
282 if (test_context
->test_stage
!= TEST_AS_REQ_SELF
) {
283 torture_assert_int_equal(test_context
->tctx
, used
, send_buf
->length
,
284 "re-encode length mismatch");
292 * Confirm that the reply packet from the KDC meets certain
293 * expectations as part of TEST_AS_REQ. This uses a packet count to
294 * work out what packet we are up to in the multiple exchanged
295 * triggerd by krb5_get_init_creds_password().
299 static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context
*test_context
,
300 const krb5_data
*recv_buf
)
304 if (test_context
->packet_count
== 0) {
305 krb5_error_code k5ret
;
307 * The client libs obtain the salt by attempting to
308 * authenticate without pre-authentication and getting
309 * the correct salt with the
310 * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in
311 * the test (netbios_realm && upn) that deliberatly
312 * has an incorrect principal, we check we get the
315 k5ret
= decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
,
319 k5ret
= decode_AS_REP(recv_buf
->data
, recv_buf
->length
,
322 if (test_context
->test_data
->netbios_realm
&& test_context
->test_data
->upn
) {
323 torture_assert(test_context
->tctx
, false,
324 "expected to get a KRB_ERROR packet with "
325 "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, got valid AS-REP");
327 torture_assert(test_context
->tctx
, false,
328 "expected to get a KRB_ERROR packet with "
329 "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
332 if (test_context
->test_data
->netbios_realm
&& test_context
->test_data
->upn
) {
333 torture_assert(test_context
->tctx
, false,
334 "unable to decode as KRB-ERROR or AS-REP, "
335 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN");
337 torture_assert(test_context
->tctx
, false,
338 "unable to decode as KRB-ERROR or AS-REP, "
339 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED");
343 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
345 torture_assert_int_equal(test_context
->tctx
, error
.pvno
, 5,
346 "Got wrong error.pvno");
347 if (test_context
->test_data
->netbios_realm
&& test_context
->test_data
->upn
) {
348 torture_assert_int_equal(test_context
->tctx
,
350 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
- KRB5KDC_ERR_NONE
,
351 "Got wrong error.error_code");
353 torture_assert_int_equal(test_context
->tctx
,
355 KRB5KDC_ERR_PREAUTH_REQUIRED
- KRB5KDC_ERR_NONE
,
356 "Got wrong error.error_code");
359 free_KRB_ERROR(&error
);
360 } else if ((decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
, &error
, &used
) == 0)
361 && (test_context
->packet_count
== 1)) {
363 * The Windows 2012R2 KDC will always respond with
364 * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket
365 * won't fit, because of the PAC. (It appears to do
366 * this always, even if it will). This triggers the
367 * client to try again over TCP.
369 torture_assert_int_equal(test_context
->tctx
,
370 used
, recv_buf
->length
,
372 torture_assert_int_equal(test_context
->tctx
,
374 "Got wrong error.pvno");
375 torture_assert_int_equal(test_context
->tctx
,
377 KRB5KRB_ERR_RESPONSE_TOO_BIG
- KRB5KDC_ERR_NONE
,
378 "Got wrong error.error_code");
379 free_KRB_ERROR(&error
);
382 * Finally the successful packet.
384 torture_assert_int_equal(test_context
->tctx
,
385 decode_AS_REP(recv_buf
->data
, recv_buf
->length
,
386 &test_context
->as_rep
, &used
), 0,
387 "decode_AS_REP failed");
388 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
390 torture_assert_int_equal(test_context
->tctx
,
391 test_context
->as_rep
.pvno
, 5,
392 "Got wrong as_rep->pvno");
393 torture_assert_int_equal(test_context
->tctx
,
394 test_context
->as_rep
.ticket
.tkt_vno
, 5,
395 "Got wrong as_rep->ticket.tkt_vno");
396 torture_assert(test_context
->tctx
,
397 test_context
->as_rep
.ticket
.enc_part
.kvno
,
398 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
401 * We can confirm that the correct proxy behaviour is
402 * in use on the KDC by checking the KVNO of the
403 * krbtgt account returned in the reply.
405 * A packet passed to the full RW DC will not have a
406 * KVNO in the upper bits, while a packet processed
407 * locally on the RODC will have these bits filled in
408 * the msDS-SecondaryKrbTgtNumber
410 if (torture_setting_bool(test_context
->tctx
, "expect_cached_at_rodc", false)) {
411 torture_assert_int_not_equal(test_context
->tctx
,
412 *test_context
->as_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
413 0, "Did not get a RODC number in the KVNO");
415 torture_assert_int_equal(test_context
->tctx
,
416 *test_context
->as_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
417 0, "Unexpecedly got a RODC number in the KVNO");
419 free_AS_REP(&test_context
->as_rep
);
421 torture_assert(test_context
->tctx
, test_context
->packet_count
< 3, "too many packets");
422 free_AS_REQ(&test_context
->as_req
);
427 * TEST_TGS_REQ_KRBTGT_CANON
430 * Confirm that the outgoing TGS-REQ packet from krb5_get_creds()
431 * for the krbtgt/realm principal meets certain expectations, like
432 * that the canonicalize bit is not set
436 static bool torture_krb5_pre_send_tgs_req_krbtgt_canon_test(struct torture_krb5_context
*test_context
, const krb5_data
*send_buf
, krb5_data
*modified_send_buf
)
439 torture_assert_int_equal(test_context
->tctx
,
440 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
441 &test_context
->tgs_req
, &used
),
442 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
443 torture_assert_int_equal(test_context
->tctx
,
444 used
, send_buf
->length
,
446 torture_assert_int_equal(test_context
->tctx
,
447 test_context
->tgs_req
.pvno
, 5,
448 "Got wrong as_req->pvno");
449 torture_assert_int_equal(test_context
->tctx
,
450 test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
,
452 "krb5 libs unexpectedly did not set canonicalize!");
454 torture_assert_int_equal(test_context
->tctx
,
455 test_context
->tgs_req
.req_body
.sname
->name_type
,
457 "Mismatch in name_type between request and expected request");
459 torture_assert_str_equal(test_context
->tctx
,
460 test_context
->tgs_req
.req_body
.realm
,
461 test_context
->test_data
->real_realm
,
462 "Mismatch in realm between request and expected request");
464 *modified_send_buf
= *send_buf
;
469 * TEST_TGS_REQ_KRBTGT_CANON
471 * Confirm that the reply TGS-REP packet for krb5_get_creds()
472 * where the client is behaving as if this is a cross-realm trust due
473 * to case or netbios vs dns name differences meets certain
474 * expectations, while canonicalize is set
478 static bool torture_krb5_post_recv_tgs_req_krbtgt_canon_test(struct torture_krb5_context
*test_context
, const krb5_data
*recv_buf
)
481 torture_assert_int_equal(test_context
->tctx
,
482 decode_TGS_REP(recv_buf
->data
, recv_buf
->length
,
483 &test_context
->tgs_rep
, &used
),
485 "decode_TGS_REP failed");
486 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
, "length mismatch");
487 torture_assert_int_equal(test_context
->tctx
,
488 test_context
->tgs_rep
.pvno
, 5,
489 "Got wrong as_rep->pvno");
490 torture_assert_int_equal(test_context
->tctx
,
491 test_context
->tgs_rep
.ticket
.tkt_vno
, 5,
492 "Got wrong as_rep->ticket.tkt_vno");
493 torture_assert(test_context
->tctx
,
494 test_context
->tgs_rep
.ticket
.enc_part
.kvno
,
495 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
496 torture_assert_str_equal(test_context
->tctx
,
497 test_context
->tgs_req
.req_body
.realm
,
498 test_context
->tgs_rep
.ticket
.realm
,
499 "Mismatch in realm between request and ticket response");
500 torture_assert_str_equal(test_context
->tctx
,
501 test_context
->tgs_rep
.ticket
.realm
,
502 test_context
->test_data
->real_realm
,
503 "Mismatch in realm between ticket response and expected ticket response");
504 torture_assert_int_equal(test_context
->tctx
,
505 test_context
->tgs_rep
.ticket
.sname
.name_type
,
507 "Mismatch in name_type between ticket response and expected value of KRB5_NT_SRV_INST");
509 torture_assert_int_equal(test_context
->tctx
,
510 test_context
->tgs_rep
.ticket
.sname
.name_string
.len
,
512 "Mismatch in name_type between ticket response and expected value, expected krbtgt/REALM@REALM");
514 torture_assert_str_equal(test_context
->tctx
,
515 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[0], "krbtgt",
516 "Mismatch in name between reponse and expected response, expected krbtgt");
517 torture_assert_str_equal(test_context
->tctx
,
518 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[1], test_context
->test_data
->real_realm
,
519 "Mismatch in realm part of krbtgt/ in expected response, expected krbtgt/REALM@REALM");
522 * We can confirm that the correct proxy behaviour is
523 * in use on the KDC by checking the KVNO of the
524 * krbtgt account returned in the reply.
526 * A packet passed to the full RW DC will not have a
527 * KVNO in the upper bits, while a packet processed
528 * locally on the RODC will have these bits filled in
529 * the msDS-SecondaryKrbTgtNumber
531 if (torture_setting_bool(test_context
->tctx
, "expect_cached_at_rodc", false)) {
532 torture_assert_int_not_equal(test_context
->tctx
,
533 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
534 0, "Did not get a RODC number in the KVNO");
536 torture_assert_int_equal(test_context
->tctx
,
537 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
538 0, "Unexpecedly got a RODC number in the KVNO");
540 free_TGS_REP(&test_context
->tgs_rep
);
541 torture_assert(test_context
->tctx
,
542 test_context
->packet_count
< 2,
544 free_TGS_REQ(&test_context
->tgs_req
);
551 * Confirm that the outgoing TGS-REQ packet from krb5_get_creds
552 * certain expectations, like that the canonicalize bit is set (this
553 * test is to force that handling) and that if an enterprise name was
554 * requested, that it was sent.
558 static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context
*test_context
,
559 const krb5_data
*send_buf
,
560 krb5_data
*modified_send_buf
)
563 torture_assert_int_equal(test_context
->tctx
,
564 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
565 &test_context
->tgs_req
, &used
),
566 0, "decode_TGS_REQ for TEST_TGS_REQ_CANON test failed");
567 torture_assert_int_equal(test_context
->tctx
, used
, send_buf
->length
, "length mismatch");
568 torture_assert_int_equal(test_context
->tctx
, test_context
->tgs_req
.pvno
, 5, "Got wrong as_req->pvno");
569 torture_assert_int_equal(test_context
->tctx
,
570 test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
,
571 true, "krb5 libs unexpectedly did not set canonicalize!");
573 if (test_context
->test_data
->enterprise
) {
574 torture_assert_int_equal(test_context
->tctx
,
575 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_ENTERPRISE_PRINCIPAL
,
576 "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL");
577 torture_assert_str_equal(test_context
->tctx
,
578 test_context
->tgs_req
.req_body
.realm
, test_context
->test_data
->real_realm
,
579 "Mismatch in realm between request and expected request");
581 } else if (test_context
->test_data
->canonicalize
) {
582 torture_assert_int_equal(test_context
->tctx
,
583 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_PRINCIPAL
,
584 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
585 torture_assert_str_equal(test_context
->tctx
,
586 test_context
->tgs_req
.req_body
.realm
, test_context
->test_data
->real_realm
,
587 "Mismatch in realm between request and expected request");
590 torture_assert_int_equal(test_context
->tctx
,
591 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_PRINCIPAL
,
592 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
593 torture_assert_str_equal(test_context
->tctx
,
594 test_context
->tgs_req
.req_body
.realm
, test_context
->test_data
->realm
,
595 "Mismatch in realm between request and expected request");
599 *modified_send_buf
= *send_buf
;
605 * TEST_TGS_REQ_CANON - RECV
607 * Confirm that the reply TGS-REP or error packet from the KDC meets
608 * certain expectations as part of TEST_TGS_REQ_CANON.
610 * This is triggered by krb5_get_creds()
614 static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_context
*test_context
, const krb5_data
*recv_buf
)
620 * If this account did not have a servicePrincipalName, then
621 * we expect a errro packet, not a TGS-REQ
623 if (decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
, &error
, &used
) == 0) {
624 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
, "length mismatch");
625 torture_assert_int_equal(test_context
->tctx
,
627 "Got wrong error.pvno");
628 torture_assert_int_equal(test_context
->tctx
,
630 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
- KRB5KDC_ERR_NONE
,
631 "Got wrong error.error_code");
633 torture_assert_int_equal(test_context
->tctx
,
634 decode_TGS_REP(recv_buf
->data
, recv_buf
->length
,
635 &test_context
->tgs_rep
,
638 "decode_TGS_REP failed");
639 torture_assert_int_equal(test_context
->tctx
,
640 used
, recv_buf
->length
,
642 torture_assert_int_equal(test_context
->tctx
,
643 test_context
->tgs_rep
.pvno
, 5,
644 "Got wrong as_rep->pvno");
645 torture_assert_int_equal(test_context
->tctx
,
646 test_context
->tgs_rep
.ticket
.tkt_vno
, 5,
647 "Got wrong as_rep->ticket.tkt_vno");
648 torture_assert(test_context
->tctx
,
649 test_context
->tgs_rep
.ticket
.enc_part
.kvno
,
650 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
651 torture_assert_str_equal(test_context
->tctx
,
652 test_context
->tgs_rep
.ticket
.realm
,
653 test_context
->test_data
->real_realm
,
654 "Mismatch in realm between ticket response and expected upper case REALM");
655 torture_assert_int_equal(test_context
->tctx
,
656 test_context
->tgs_rep
.ticket
.sname
.name_type
,
657 test_context
->tgs_req
.req_body
.sname
->name_type
,
658 "Mismatch in name_type between request and ticket response");
659 torture_assert_int_equal(test_context
->tctx
,
660 test_context
->tgs_rep
.ticket
.sname
.name_string
.len
,
661 test_context
->tgs_req
.req_body
.sname
->name_string
.len
,
662 "Mismatch in name_string.len between request and ticket response");
663 torture_assert(test_context
->tctx
,
664 test_context
->tgs_rep
.ticket
.sname
.name_string
.len
>= 1,
665 "name_string.len should be >=1 in ticket response");
666 torture_assert_str_equal(test_context
->tctx
,
667 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[0],
668 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0],
669 "Mismatch in name between request and expected request");
670 torture_assert_int_equal(test_context
->tctx
,
671 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
672 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
673 free_TGS_REP(&test_context
->tgs_rep
);
675 torture_assert(test_context
->tctx
, test_context
->packet_count
== 0, "too many packets");
676 free_TGS_REQ(&test_context
->tgs_req
);
682 * TEST_SELF_TRUST_TGS_REQ
684 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
685 * certain expectations, like that the canonicalize bit is set (this
686 * test is to force that handling).
688 * This test is for the case where the name we ask for, while a valid
689 * alternate name for our own realm is used. The client acts as if
690 * this is cross-realm trust.
694 static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context
*test_context
,
695 const krb5_data
*send_buf
,
696 krb5_data
*modified_send_buf
)
699 torture_assert_int_equal(test_context
->tctx
,
700 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
701 &test_context
->tgs_req
, &used
),
702 0, "decode_TGS_REQ for TEST_SELF_TRUST_TGS_REQ test failed");
703 torture_assert_int_equal(test_context
->tctx
, used
, send_buf
->length
, "length mismatch");
704 torture_assert_int_equal(test_context
->tctx
, test_context
->tgs_req
.pvno
, 5, "Got wrong as_req->pvno");
705 torture_assert_int_equal(test_context
->tctx
, test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
, false, "krb5 libs unexpectedly set canonicalize!");
707 if (test_context
->test_data
->canonicalize
) {
708 torture_assert_str_equal(test_context
->tctx
,
709 test_context
->tgs_req
.req_body
.realm
,
710 test_context
->test_data
->real_realm
,
711 "Mismatch in realm between request and expected request");
713 torture_assert_str_equal(test_context
->tctx
,
714 test_context
->tgs_req
.req_body
.realm
,
715 test_context
->test_data
->realm
,
716 "Mismatch in realm between request and expected request");
718 torture_assert_int_equal(test_context
->tctx
,
719 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_PRINCIPAL
,
720 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
721 torture_assert_int_equal(test_context
->tctx
,
722 test_context
->tgs_req
.req_body
.sname
->name_string
.len
, 2,
723 "Mismatch in name between request and expected request, expected krbtgt/realm");
724 torture_assert_str_equal(test_context
->tctx
,
725 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0], "krbtgt",
726 "Mismatch in name between request and expected request, expected krbtgt");
727 torture_assert_str_equal(test_context
->tctx
,
728 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[1], test_context
->test_data
->realm
,
729 "Mismatch in realm part of cross-realm request principal between request and expected request");
730 *modified_send_buf
= *send_buf
;
736 * TEST_SELF_TRUST_TGS_REQ and TEST_TGS_REQ_KRBTGT - RECV
738 * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(),
739 * where the client is behaving as if this is a cross-realm trust due
740 * to case or netbios vs dns name differences meets certain
745 static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_context
*test_context
, const krb5_data
*recv_buf
)
748 torture_assert_int_equal(test_context
->tctx
,
749 decode_TGS_REP(recv_buf
->data
, recv_buf
->length
,
750 &test_context
->tgs_rep
, &used
),
752 "decode_TGS_REP failed");
753 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
, "length mismatch");
754 torture_assert_int_equal(test_context
->tctx
,
755 test_context
->tgs_rep
.pvno
, 5,
756 "Got wrong as_rep->pvno");
757 torture_assert_int_equal(test_context
->tctx
,
758 test_context
->tgs_rep
.ticket
.tkt_vno
, 5,
759 "Got wrong as_rep->ticket.tkt_vno");
760 torture_assert(test_context
->tctx
,
761 test_context
->tgs_rep
.ticket
.enc_part
.kvno
,
762 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
763 torture_assert_str_equal(test_context
->tctx
,
764 test_context
->tgs_req
.req_body
.realm
,
765 test_context
->tgs_rep
.ticket
.realm
,
766 "Mismatch in realm between request and ticket response");
767 torture_assert_int_equal(test_context
->tctx
,
768 test_context
->tgs_rep
.ticket
.sname
.name_type
,
769 test_context
->tgs_req
.req_body
.sname
->name_type
,
770 "Mismatch in name_type between request and ticket response");
772 torture_assert_int_equal(test_context
->tctx
,
773 test_context
->tgs_rep
.ticket
.sname
.name_string
.len
, 2,
774 "Mismatch in name between request and expected request, expected krbtgt/realm");
775 torture_assert_str_equal(test_context
->tctx
,
776 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[0], "krbtgt",
777 "Mismatch in name between request and expected request, expected krbtgt");
778 torture_assert_str_equal(test_context
->tctx
,
779 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[1], test_context
->test_data
->realm
,
780 "Mismatch in realm part of cross-realm request principal between response and expected request");
782 * We can confirm that the correct proxy behaviour is
783 * in use on the KDC by checking the KVNO of the
784 * krbtgt account returned in the reply.
786 * A packet passed to the full RW DC will not have a
787 * KVNO in the upper bits, while a packet processed
788 * locally on the RODC will have these bits filled in
789 * the msDS-SecondaryKrbTgtNumber
791 if (torture_setting_bool(test_context
->tctx
, "expect_cached_at_rodc", false)) {
792 torture_assert_int_not_equal(test_context
->tctx
,
793 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
794 0, "Did not get a RODC number in the KVNO");
796 torture_assert_int_equal(test_context
->tctx
,
797 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
798 0, "Unexpecedly got a RODC number in the KVNO");
800 free_TGS_REP(&test_context
->tgs_rep
);
801 torture_assert_int_equal(test_context
->tctx
,
802 test_context
->packet_count
, 0,
804 test_context
->packet_count
= 0;
805 test_context
->test_stage
= TEST_TGS_REQ
;
806 free_TGS_REQ(&test_context
->tgs_req
);
813 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
814 * certain expectations, like that the canonicalize bit is set (this
815 * test is to force that handling) and that if an enterprise name was
816 * requested, that it was sent.
820 static bool torture_krb5_pre_send_tgs_req_test(struct torture_krb5_context
*test_context
, const krb5_data
*send_buf
, krb5_data
*modified_send_buf
)
823 torture_assert_int_equal(test_context
->tctx
,
824 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
825 &test_context
->tgs_req
, &used
),
826 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
827 torture_assert_int_equal(test_context
->tctx
, used
, send_buf
->length
, "length mismatch");
828 torture_assert_int_equal(test_context
->tctx
, test_context
->tgs_req
.pvno
, 5,
829 "Got wrong as_req->pvno");
830 torture_assert_int_equal(test_context
->tctx
,
831 test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
,
833 "krb5 libs unexpectedly set canonicalize!");
835 if (test_context
->test_data
->enterprise
) {
836 torture_assert_int_equal(test_context
->tctx
,
837 test_context
->tgs_req
.req_body
.sname
->name_type
,
838 KRB5_NT_ENTERPRISE_PRINCIPAL
,
839 "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL");
840 torture_assert_str_equal(test_context
->tctx
,
841 test_context
->tgs_req
.req_body
.realm
,
842 test_context
->test_data
->real_realm
,
843 "Mismatch in realm between request and expected request");
846 torture_assert_int_equal(test_context
->tctx
,
847 test_context
->tgs_req
.req_body
.sname
->name_type
,
849 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
850 torture_assert_str_equal(test_context
->tctx
,
851 test_context
->tgs_req
.req_body
.realm
,
852 test_context
->test_data
->realm
,
853 "Mismatch in realm between request and expected request");
857 *modified_send_buf
= *send_buf
;
863 * TEST_TGS_REQ - RECV
865 * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(), for
866 * the actual target service.
870 static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context
*test_context
, const krb5_data
*recv_buf
)
875 * If this account did not have a servicePrincipalName, then
876 * we expect a errro packet, not a TGS-REQ
878 if (decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
, &error
, &used
) == 0) {
879 torture_assert_int_equal(test_context
->tctx
,
880 used
, recv_buf
->length
,
882 torture_assert_int_equal(test_context
->tctx
,
884 "Got wrong error.pvno");
885 torture_assert_int_equal(test_context
->tctx
,
887 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
- KRB5KDC_ERR_NONE
,
888 "Got wrong error.error_code");
890 torture_assert_int_equal(test_context
->tctx
,
891 decode_TGS_REP(recv_buf
->data
, recv_buf
->length
,
892 &test_context
->tgs_rep
, &used
),
894 "decode_TGS_REP failed");
895 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
897 torture_assert_int_equal(test_context
->tctx
,
898 test_context
->tgs_rep
.pvno
, 5,
899 "Got wrong as_rep->pvno");
900 torture_assert_int_equal(test_context
->tctx
,
901 test_context
->tgs_rep
.ticket
.tkt_vno
, 5,
902 "Got wrong as_rep->ticket.tkt_vno");
903 torture_assert(test_context
->tctx
,
904 test_context
->tgs_rep
.ticket
.enc_part
.kvno
,
905 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
906 torture_assert_str_equal(test_context
->tctx
,
907 test_context
->tgs_rep
.ticket
.realm
,
908 test_context
->test_data
->real_realm
,
909 "Mismatch in realm between ticket response and expected upper case REALM");
910 torture_assert_int_equal(test_context
->tctx
,
911 test_context
->tgs_req
.req_body
.sname
->name_type
,
912 test_context
->tgs_rep
.ticket
.sname
.name_type
, "Mismatch in name_type between request and ticket response");
913 torture_assert_int_equal(test_context
->tctx
,
914 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
915 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
916 free_TGS_REP(&test_context
->tgs_rep
);
918 torture_assert(test_context
->tctx
, test_context
->packet_count
< 3, "too many packets");
919 free_TGS_REQ(&test_context
->tgs_req
);
920 test_context
->test_stage
= TEST_DONE
;
925 * TEST_TGS_REQ_KRBTGT
928 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
929 * for the krbtgt/realm principal meets certain expectations, like
930 * that the canonicalize bit is not set
934 static bool torture_krb5_pre_send_tgs_req_krbtgt_test(struct torture_krb5_context
*test_context
, const krb5_data
*send_buf
, krb5_data
*modified_send_buf
)
937 torture_assert_int_equal(test_context
->tctx
,
938 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
939 &test_context
->tgs_req
, &used
),
940 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
941 torture_assert_int_equal(test_context
->tctx
,
942 used
, send_buf
->length
,
944 torture_assert_int_equal(test_context
->tctx
,
945 test_context
->tgs_req
.pvno
, 5,
946 "Got wrong as_req->pvno");
947 torture_assert_int_equal(test_context
->tctx
,
948 test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
,
950 "krb5 libs unexpectedly set canonicalize!");
952 torture_assert_str_equal(test_context
->tctx
,
953 test_context
->tgs_req
.req_body
.realm
,
954 test_context
->test_data
->realm
,
955 "Mismatch in realm between request and expected request");
957 *modified_send_buf
= *send_buf
;
958 test_context
->test_stage
= TEST_DONE
;
963 * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST and TEST_TGS_REQ_HOST_SRV_HST
966 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
967 * for the krbtgt/realm principal meets certain expectations, like
968 * that the canonicalize bit is not set
972 static bool torture_krb5_pre_send_tgs_req_host_test(struct torture_krb5_context
*test_context
, const krb5_data
*send_buf
, krb5_data
*modified_send_buf
)
975 torture_assert_int_equal(test_context
->tctx
,
976 decode_TGS_REQ(send_buf
->data
, send_buf
->length
,
977 &test_context
->tgs_req
, &used
),
978 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
979 torture_assert_int_equal(test_context
->tctx
,
980 used
, send_buf
->length
,
982 torture_assert_int_equal(test_context
->tctx
,
983 test_context
->tgs_req
.pvno
, 5,
984 "Got wrong as_req->pvno");
985 torture_assert_int_equal(test_context
->tctx
,
986 test_context
->tgs_req
.req_body
.sname
->name_string
.len
, 2,
987 "Mismatch in name between request and expected request, expected krbtgt/realm");
988 torture_assert_int_equal(test_context
->tctx
,
989 test_context
->tgs_req
.req_body
.kdc_options
.canonicalize
,
991 "krb5 libs unexpectedly did not set canonicalize!");
993 if (test_context
->test_stage
== TEST_TGS_REQ_HOST_SRV_INST
) {
994 torture_assert_int_equal(test_context
->tctx
,
995 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_SRV_INST
,
996 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_INST");
997 torture_assert_str_equal(test_context
->tctx
,
998 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0],
999 strupper_talloc(test_context
, test_context
->test_data
->krb5_service
),
1000 "Mismatch in name between request and expected request, expected service");
1001 torture_assert_str_equal(test_context
->tctx
,
1002 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[1],
1003 test_context
->test_data
->krb5_hostname
,
1004 "Mismatch in hostname part between request and expected request");
1006 } else if (test_context
->test_stage
== TEST_TGS_REQ_HOST_SRV_HST
) {
1008 torture_assert_int_equal(test_context
->tctx
,
1009 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_SRV_HST
,
1010 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_HST");
1011 torture_assert_str_equal(test_context
->tctx
,
1012 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0],
1013 test_context
->test_data
->krb5_service
,
1014 "Mismatch in name between request and expected request, expected service");
1015 torture_assert_str_equal(test_context
->tctx
,
1016 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[1],
1017 strupper_talloc(test_context
, test_context
->test_data
->krb5_hostname
),
1018 "Mismatch in hostname part between request and expected request");
1021 torture_assert_int_equal(test_context
->tctx
,
1022 test_context
->tgs_req
.req_body
.sname
->name_type
, KRB5_NT_PRINCIPAL
,
1023 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
1024 torture_assert_str_equal(test_context
->tctx
,
1025 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0],
1026 test_context
->test_data
->krb5_service
,
1027 "Mismatch in name between request and expected request, expected service");
1028 torture_assert_str_equal(test_context
->tctx
,
1029 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[1],
1030 test_context
->test_data
->krb5_hostname
,
1031 "Mismatch in hostname part between request and expected request");
1034 torture_assert_str_equal(test_context
->tctx
,
1035 test_context
->tgs_req
.req_body
.realm
,
1036 test_context
->test_data
->real_realm
,
1037 "Mismatch in realm between request and expected request");
1039 *modified_send_buf
= *send_buf
;
1044 * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST - RECV
1046 * Confirm that the reply TGS-REP packet for krb5_mk_req(), for
1047 * the actual target service, as a SPN, not a any other name type.
1051 static bool torture_krb5_post_recv_tgs_req_host_test(struct torture_krb5_context
*test_context
, const krb5_data
*recv_buf
)
1054 torture_assert_int_equal(test_context
->tctx
,
1055 decode_TGS_REP(recv_buf
->data
, recv_buf
->length
,
1056 &test_context
->tgs_rep
, &used
),
1058 "decode_TGS_REP failed");
1059 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
1061 torture_assert_int_equal(test_context
->tctx
,
1062 test_context
->tgs_rep
.pvno
, 5,
1063 "Got wrong as_rep->pvno");
1064 torture_assert_int_equal(test_context
->tctx
,
1065 test_context
->tgs_rep
.ticket
.tkt_vno
, 5,
1066 "Got wrong as_rep->ticket.tkt_vno");
1067 torture_assert(test_context
->tctx
,
1068 test_context
->tgs_rep
.ticket
.enc_part
.kvno
,
1069 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
1070 torture_assert_str_equal(test_context
->tctx
,
1071 test_context
->tgs_rep
.ticket
.realm
,
1072 test_context
->test_data
->real_realm
,
1073 "Mismatch in realm between ticket response and expected upper case REALM");
1074 torture_assert_int_equal(test_context
->tctx
,
1075 test_context
->tgs_req
.req_body
.sname
->name_type
,
1076 test_context
->tgs_rep
.ticket
.sname
.name_type
, "Mismatch in name_type between request and ticket response");
1077 torture_assert_int_equal(test_context
->tctx
,
1078 test_context
->tgs_rep
.ticket
.sname
.name_string
.len
, 2,
1079 "Mismatch in name between request and expected request, expected service/hostname");
1080 torture_assert_str_equal(test_context
->tctx
,
1081 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[0],
1082 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[0],
1083 "Mismatch in name between request and expected request, expected service/hostname");
1084 torture_assert_str_equal(test_context
->tctx
,
1085 test_context
->tgs_rep
.ticket
.sname
.name_string
.val
[1],
1086 test_context
->tgs_req
.req_body
.sname
->name_string
.val
[1],
1087 "Mismatch in name between request and expected request, expected service/hostname");
1089 torture_assert_int_equal(test_context
->tctx
,
1090 *test_context
->tgs_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
1091 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
1092 free_TGS_REP(&test_context
->tgs_rep
);
1094 torture_assert(test_context
->tctx
, test_context
->packet_count
< 2, "too many packets");
1099 * TEST_AS_REQ_SELF - RECV
1101 * Confirm that the reply packet from the KDC meets certain
1102 * expectations as part of TEST_AS_REQ. This uses a packet count to
1103 * work out what packet we are up to in the multiple exchanged
1104 * triggerd by krb5_get_init_creds_password().
1108 static bool torture_krb5_post_recv_as_req_self_test(struct torture_krb5_context
*test_context
,
1109 const krb5_data
*recv_buf
)
1113 if (test_context
->packet_count
== 0) {
1114 krb5_error_code k5ret
;
1116 * The client libs obtain the salt by attempting to
1117 * authenticate without pre-authentication and getting
1118 * the correct salt with the
1119 * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in
1120 * the test (netbios_realm && upn) that deliberatly
1121 * has an incorrect principal, we check we get the
1124 k5ret
= decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
,
1128 k5ret
= decode_AS_REP(recv_buf
->data
, recv_buf
->length
,
1131 if (torture_setting_bool(test_context
->tctx
, "expect_machine_account", false) == false
1132 || (test_context
->test_data
->upn
== true)) {
1133 torture_assert(test_context
->tctx
, false,
1134 "expected to get a KRB_ERROR packet with "
1135 "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
1137 torture_assert(test_context
->tctx
, false,
1138 "expected to get a KRB_ERROR packet with "
1139 "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
1142 if (torture_setting_bool(test_context
->tctx
, "expect_machine_account", false) == false
1143 || (test_context
->test_data
->upn
== true)) {
1144 torture_assert(test_context
->tctx
, false,
1145 "unable to decode as KRB-ERROR or AS-REP, "
1146 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED");
1148 torture_assert(test_context
->tctx
, false,
1149 "unable to decode as KRB-ERROR or AS-REP, "
1150 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED");
1154 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
1156 torture_assert_int_equal(test_context
->tctx
, error
.pvno
, 5,
1157 "Got wrong error.pvno");
1158 if ((torture_setting_bool(test_context
->tctx
, "expect_machine_account", false) == false
1159 || (test_context
->test_data
->upn
== true))
1160 && error
.error_code
== KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
- KRB5KDC_ERR_NONE
) {
1164 * This case is because Samba's Heimdal KDC
1165 * checks server and client accounts before
1166 * checking for pre-authentication.
1169 torture_assert_int_equal(test_context
->tctx
,
1171 KRB5KDC_ERR_PREAUTH_REQUIRED
- KRB5KDC_ERR_NONE
,
1172 "Got wrong error.error_code");
1175 free_KRB_ERROR(&error
);
1176 } else if ((decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
, &error
, &used
) == 0)
1177 && (test_context
->packet_count
== 1)) {
1179 * The Windows 2012R2 KDC will always respond with
1180 * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket
1181 * won't fit, because of the PAC. (It appears to do
1182 * this always, even if it will). This triggers the
1183 * client to try again over TCP.
1185 torture_assert_int_equal(test_context
->tctx
,
1186 used
, recv_buf
->length
,
1188 torture_assert_int_equal(test_context
->tctx
,
1190 "Got wrong error.pvno");
1191 if ((torture_setting_bool(test_context
->tctx
, "expect_machine_account", false)
1192 && (test_context
->test_data
->upn
== false))) {
1193 torture_assert_int_equal(test_context
->tctx
,
1195 KRB5KRB_ERR_RESPONSE_TOO_BIG
- KRB5KDC_ERR_NONE
,
1196 "Got wrong error.error_code");
1198 torture_assert_int_equal(test_context
->tctx
,
1200 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
- KRB5KDC_ERR_NONE
,
1201 "Got wrong error.error_code");
1203 free_KRB_ERROR(&error
);
1206 * Finally the successful packet.
1208 torture_assert_int_equal(test_context
->tctx
,
1209 decode_AS_REP(recv_buf
->data
, recv_buf
->length
,
1210 &test_context
->as_rep
, &used
), 0,
1211 "decode_AS_REP failed");
1212 torture_assert_int_equal(test_context
->tctx
, used
, recv_buf
->length
,
1214 torture_assert_int_equal(test_context
->tctx
,
1215 test_context
->as_rep
.pvno
, 5,
1216 "Got wrong as_rep->pvno");
1217 torture_assert_int_equal(test_context
->tctx
,
1218 test_context
->as_rep
.ticket
.tkt_vno
, 5,
1219 "Got wrong as_rep->ticket.tkt_vno");
1220 torture_assert(test_context
->tctx
,
1221 test_context
->as_rep
.ticket
.enc_part
.kvno
,
1222 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
1225 * We do not expect an RODC number here in the KVNO,
1226 * as this is a ticket to the user's own account.
1228 torture_assert_int_equal(test_context
->tctx
,
1229 *test_context
->as_rep
.ticket
.enc_part
.kvno
& 0xFFFF0000,
1230 0, "Unexpecedly got a RODC number in the KVNO");
1231 free_AS_REP(&test_context
->as_rep
);
1233 torture_assert(test_context
->tctx
, test_context
->packet_count
< 3, "too many packets");
1234 free_AS_REQ(&test_context
->as_req
);
1239 * This function is set in torture_krb5_init_context_canon as krb5
1240 * send_and_recv function. This allows us to override what server the
1241 * test is aimed at, and to inspect the packets just before they are
1242 * sent to the network, and before they are processed on the recv
1245 * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test()
1246 * functions are implement the actual tests.
1248 * When this asserts, the caller will get a spurious 'cannot contact
1252 static krb5_error_code
smb_krb5_send_and_recv_func_canon_override(krb5_context context
,
1253 void *data
, /* struct torture_krb5_context */
1254 krb5_krbhst_info
*hi
,
1256 const krb5_data
*send_buf
,
1257 krb5_data
*recv_buf
)
1259 krb5_error_code k5ret
;
1261 krb5_data modified_send_buf
;
1263 struct torture_krb5_context
*test_context
1264 = talloc_get_type_abort(data
, struct torture_krb5_context
);
1266 switch (test_context
->test_stage
) {
1268 torture_warning(test_context
->tctx
, "Unexpected outgoing packet from krb5 libs");
1271 ok
= torture_krb5_pre_send_as_req_test(test_context
, send_buf
,
1272 &modified_send_buf
);
1274 case TEST_TGS_REQ_KRBTGT_CANON
:
1275 ok
= torture_krb5_pre_send_tgs_req_krbtgt_canon_test(test_context
, send_buf
,
1276 &modified_send_buf
);
1278 case TEST_TGS_REQ_CANON
:
1279 ok
= torture_krb5_pre_send_tgs_req_canon_test(test_context
, send_buf
,
1280 &modified_send_buf
);
1282 case TEST_SELF_TRUST_TGS_REQ
:
1283 ok
= torture_krb5_pre_send_self_trust_tgs_req_test(test_context
, send_buf
,
1284 &modified_send_buf
);
1287 ok
= torture_krb5_pre_send_tgs_req_test(test_context
, send_buf
,
1288 &modified_send_buf
);
1290 case TEST_TGS_REQ_KRBTGT
:
1291 ok
= torture_krb5_pre_send_tgs_req_krbtgt_test(test_context
, send_buf
,
1292 &modified_send_buf
);
1294 case TEST_TGS_REQ_HOST
:
1295 case TEST_TGS_REQ_HOST_SRV_INST
:
1296 case TEST_TGS_REQ_HOST_SRV_HST
:
1297 ok
= torture_krb5_pre_send_tgs_req_host_test(test_context
, send_buf
,
1298 &modified_send_buf
);
1300 case TEST_AS_REQ_SELF
:
1301 ok
= torture_krb5_pre_send_as_req_test(test_context
, send_buf
,
1302 &modified_send_buf
);
1309 k5ret
= smb_krb5_send_and_recv_func_forced(context
, test_context
->server
,
1310 hi
, timeout
, &modified_send_buf
,
1316 switch (test_context
->test_stage
) {
1318 torture_warning(test_context
->tctx
, "Unexpected outgoing packet from krb5 libs");
1321 ok
= torture_krb5_post_recv_as_req_test(test_context
, recv_buf
);
1323 case TEST_TGS_REQ_KRBTGT_CANON
:
1324 ok
= torture_krb5_post_recv_tgs_req_krbtgt_canon_test(test_context
, recv_buf
);
1326 case TEST_TGS_REQ_CANON
:
1327 ok
= torture_krb5_post_recv_tgs_req_canon_test(test_context
, recv_buf
);
1329 case TEST_SELF_TRUST_TGS_REQ
:
1330 ok
= torture_krb5_post_recv_self_trust_tgs_req_test(test_context
, recv_buf
);
1333 ok
= torture_krb5_post_recv_tgs_req_test(test_context
, recv_buf
);
1335 case TEST_TGS_REQ_KRBTGT
:
1336 ok
= torture_krb5_post_recv_self_trust_tgs_req_test(test_context
, recv_buf
);
1338 case TEST_TGS_REQ_HOST
:
1339 case TEST_TGS_REQ_HOST_SRV_INST
:
1340 case TEST_TGS_REQ_HOST_SRV_HST
:
1341 ok
= torture_krb5_post_recv_tgs_req_host_test(test_context
, recv_buf
);
1343 case TEST_AS_REQ_SELF
:
1344 ok
= torture_krb5_post_recv_as_req_self_test(test_context
, recv_buf
);
1350 torture_warning(test_context
->tctx
, "Packet of length %llu failed post-recv checks in test stage %d", (unsigned long long)recv_buf
->length
, test_context
->test_stage
);
1351 if (decode_KRB_ERROR(recv_buf
->data
, recv_buf
->length
, &error
, &used
) == 0) {
1352 torture_warning(test_context
->tctx
,
1353 "STAGE: %d Unexpectedly got a KRB-ERROR packet "
1354 "with error code %d (%s)",
1355 test_context
->test_stage
,
1357 error_message(error
.error_code
+ KRB5KDC_ERR_NONE
));
1358 free_KRB_ERROR(&error
);
1363 test_context
->packet_count
++;
1368 static int test_context_destructor(struct torture_krb5_context
*test_context
)
1370 freeaddrinfo(test_context
->server
);
1375 static bool torture_krb5_init_context_canon(struct torture_context
*tctx
,
1376 struct test_data
*test_data
,
1377 struct torture_krb5_context
**torture_krb5_context
)
1379 const char *host
= torture_setting_string(tctx
, "host", NULL
);
1380 krb5_error_code k5ret
;
1383 struct torture_krb5_context
*test_context
= talloc_zero(tctx
, struct torture_krb5_context
);
1384 torture_assert(tctx
, test_context
!= NULL
, "Failed to allocate");
1386 test_context
->test_data
= test_data
;
1387 test_context
->tctx
= tctx
;
1389 k5ret
= smb_krb5_init_context(test_context
, tctx
->lp_ctx
, &test_context
->smb_krb5_context
);
1390 torture_assert_int_equal(tctx
, k5ret
, 0, "smb_krb5_init_context failed");
1392 ok
= interpret_string_addr_internal(&test_context
->server
, host
, AI_NUMERICHOST
);
1393 torture_assert(tctx
, ok
, "Failed to parse target server");
1395 talloc_set_destructor(test_context
, test_context_destructor
);
1397 set_sockaddr_port(test_context
->server
->ai_addr
, 88);
1399 k5ret
= krb5_set_send_to_kdc_func(test_context
->smb_krb5_context
->krb5_context
,
1400 smb_krb5_send_and_recv_func_canon_override
,
1402 torture_assert_int_equal(tctx
, k5ret
, 0, "krb5_set_send_to_kdc_func failed");
1403 *torture_krb5_context
= test_context
;
1408 static bool torture_krb5_as_req_canon(struct torture_context
*tctx
, const void *tcase_data
)
1410 krb5_error_code k5ret
;
1411 krb5_get_init_creds_opt
*krb_options
= NULL
;
1412 struct test_data
*test_data
= talloc_get_type_abort(tcase_data
, struct test_data
);
1413 krb5_principal principal
;
1414 krb5_principal krbtgt_other
;
1415 krb5_principal expected_principal
;
1416 char *principal_string
;
1417 char *krbtgt_other_string
;
1418 int principal_flags
;
1419 char *expected_principal_string
;
1420 char *expected_unparse_principal_string
;
1421 int expected_principal_flags
;
1422 char *got_principal_string
;
1423 char *assertion_message
;
1424 const char *password
= cli_credentials_get_password(cmdline_credentials
);
1425 krb5_context k5_context
;
1426 struct torture_krb5_context
*test_context
;
1428 krb5_creds my_creds
;
1429 krb5_creds
*server_creds
;
1431 krb5_auth_context auth_context
;
1433 krb5_data in_data
, enc_ticket
;
1434 krb5_get_creds_opt opt
;
1436 const char *upn
= torture_setting_string(tctx
, "krb5-upn", "");
1437 test_data
->krb5_service
= torture_setting_string(tctx
, "krb5-service", "host");
1438 test_data
->krb5_hostname
= torture_setting_string(tctx
, "krb5-hostname", "");
1441 * If we have not passed a UPN on the command line,
1442 * then skip the UPN tests.
1444 if (test_data
->upn
&& upn
[0] == '\0') {
1445 torture_skip(tctx
, "This test needs a UPN specified as --option=torture:krb5-upn=user@example.com to run");
1448 if (test_data
->netbios_realm
) {
1449 test_data
->realm
= test_data
->real_domain
;
1451 test_data
->realm
= test_data
->real_realm
;
1454 if (test_data
->upn
) {
1456 test_data
->username
= talloc_strdup(test_data
, upn
);
1457 p
= strchr(test_data
->username
, '@');
1463 * Test the UPN behaviour carefully. We can
1464 * test in two different modes, depending on
1465 * what UPN has been set up for us.
1467 * If the UPN is in our realm, then we do all the tests with this name also.
1469 * If the UPN is not in our realm, then we
1470 * expect the tests that replace the realm to
1471 * fail (as it won't match)
1473 if (strcasecmp(p
, test_data
->real_realm
) != 0) {
1474 test_data
->other_upn_suffix
= true;
1476 test_data
->other_upn_suffix
= false;
1480 * This lets us test the combination of the UPN prefix
1481 * with a valid domain, without adding even more
1484 if (test_data
->netbios_realm
== false) {
1485 test_data
->realm
= p
;
1489 ok
= torture_krb5_init_context_canon(tctx
, test_data
, &test_context
);
1490 torture_assert(tctx
, ok
, "torture_krb5_init_context failed");
1491 k5_context
= test_context
->smb_krb5_context
->krb5_context
;
1493 if (test_data
->upper_realm
) {
1494 test_data
->realm
= strupper_talloc(test_data
, test_data
->realm
);
1496 test_data
->realm
= strlower_talloc(test_data
, test_data
->realm
);
1498 if (test_data
->upper_username
) {
1499 test_data
->username
= strupper_talloc(test_data
, test_data
->username
);
1501 test_data
->username
= talloc_strdup(test_data
, test_data
->username
);
1504 principal_string
= talloc_asprintf(test_data
, "%s@%s", test_data
->username
, test_data
->realm
);
1507 * If we are set to canonicalize, we get back the fixed UPPER
1508 * case realm, and the real username (ie matching LDAP
1511 * Otherwise, if we are set to enterprise, we
1512 * get back the whole principal as-sent
1514 * Finally, if we are not set to canonicalize, we get back the
1515 * fixed UPPER case realm, but the as-sent username
1517 if (test_data
->canonicalize
) {
1518 expected_principal_string
= talloc_asprintf(test_data
,
1520 test_data
->real_username
,
1521 test_data
->real_realm
);
1522 } else if (test_data
->enterprise
) {
1523 expected_principal_string
= principal_string
;
1525 expected_principal_string
= talloc_asprintf(test_data
,
1527 test_data
->username
,
1528 test_data
->real_realm
);
1531 if (test_data
->enterprise
) {
1532 principal_flags
= KRB5_PRINCIPAL_PARSE_ENTERPRISE
;
1534 if (test_data
->upn
&& test_data
->other_upn_suffix
) {
1535 torture_skip(tctx
, "UPN test for UPN with other UPN suffix only runs with enterprise principals");
1537 principal_flags
= 0;
1540 if (test_data
->canonicalize
) {
1541 expected_principal_flags
= 0;
1543 expected_principal_flags
= principal_flags
;
1546 torture_assert_int_equal(tctx
,
1547 krb5_parse_name_flags(k5_context
,
1551 0, "krb5_parse_name_flags failed");
1552 torture_assert_int_equal(tctx
,
1553 krb5_parse_name_flags(k5_context
,
1554 expected_principal_string
,
1555 expected_principal_flags
,
1556 &expected_principal
),
1557 0, "krb5_parse_name_flags failed");
1559 torture_assert_int_equal(tctx
,
1560 krb5_unparse_name(k5_context
,
1562 &expected_unparse_principal_string
),
1563 0, "krb5_unparse_name failed");
1565 * Prepare a AS-REQ and run the TEST_AS_REQ tests
1569 test_context
->test_stage
= TEST_AS_REQ
;
1570 test_context
->packet_count
= 0;
1573 * Set the canonicalize flag if this test requires it
1575 torture_assert_int_equal(tctx
,
1576 krb5_get_init_creds_opt_alloc(k5_context
, &krb_options
),
1577 0, "krb5_get_init_creds_opt_alloc failed");
1579 torture_assert_int_equal(tctx
,
1580 krb5_get_init_creds_opt_set_canonicalize(k5_context
,
1582 test_data
->canonicalize
),
1583 0, "krb5_get_init_creds_opt_set_canonicalize failed");
1585 torture_assert_int_equal(tctx
,
1586 krb5_get_init_creds_opt_set_win2k(k5_context
,
1589 0, "krb5_get_init_creds_opt_set_win2k failed");
1591 k5ret
= krb5_get_init_creds_password(k5_context
, &my_creds
, principal
,
1592 password
, NULL
, NULL
, 0,
1595 if (test_data
->netbios_realm
&& test_data
->upn
) {
1596 torture_assert_int_equal(tctx
, k5ret
,
1597 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
,
1598 "Got wrong error_code from krb5_get_init_creds_password");
1599 /* We can't proceed with more checks */
1602 assertion_message
= talloc_asprintf(tctx
,
1603 "krb5_get_init_creds_password for %s failed: %s",
1605 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
1606 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
1609 torture_assert(tctx
,
1610 test_context
->packet_count
> 1,
1611 "Expected krb5_get_init_creds_password to send more packets");
1614 * Assert that the reply was with the correct type of
1615 * principal, depending on the flags we set
1617 if (test_data
->canonicalize
== false && test_data
->enterprise
) {
1618 torture_assert_int_equal(tctx
,
1619 krb5_principal_get_type(k5_context
,
1621 KRB5_NT_ENTERPRISE_PRINCIPAL
,
1622 "smb_krb5_init_context gave incorrect client->name.name_type");
1624 torture_assert_int_equal(tctx
,
1625 krb5_principal_get_type(k5_context
,
1628 "smb_krb5_init_context gave incorrect client->name.name_type");
1631 torture_assert_int_equal(tctx
,
1632 krb5_unparse_name(k5_context
,
1633 my_creds
.client
, &got_principal_string
), 0,
1634 "krb5_unparse_name failed");
1636 assertion_message
= talloc_asprintf(tctx
,
1637 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
1638 got_principal_string
, expected_principal_string
);
1639 krb5_free_unparsed_name(k5_context
, got_principal_string
);
1641 torture_assert(tctx
, krb5_principal_compare(k5_context
,
1642 my_creds
.client
, expected_principal
),
1646 torture_assert_int_equal(tctx
,
1647 krb5_principal_get_type(k5_context
,
1648 my_creds
.server
), KRB5_NT_SRV_INST
,
1649 "smb_krb5_init_context gave incorrect server->name.name_type");
1651 torture_assert_int_equal(tctx
,
1652 krb5_principal_get_num_comp(k5_context
,
1653 my_creds
.server
), 2,
1654 "smb_krb5_init_context gave incorrect number of components in my_creds.server->name");
1656 torture_assert_str_equal(tctx
,
1657 krb5_principal_get_comp_string(k5_context
,
1658 my_creds
.server
, 0),
1660 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]");
1662 if (test_data
->canonicalize
|| test_data
->enterprise
) {
1663 torture_assert_str_equal(tctx
,
1664 krb5_principal_get_comp_string(k5_context
,
1665 my_creds
.server
, 1),
1666 test_data
->real_realm
,
1668 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]");
1670 torture_assert_str_equal(tctx
,
1671 krb5_principal_get_comp_string(k5_context
,
1672 my_creds
.server
, 1),
1675 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]");
1677 torture_assert_str_equal(tctx
,
1678 krb5_principal_get_realm(k5_context
,
1680 test_data
->real_realm
,
1681 "smb_krb5_init_context gave incorrect my_creds.server->realm");
1683 /* Store the result of the 'kinit' above into a memory ccache */
1684 cc_name
= talloc_asprintf(tctx
, "MEMORY:%s", test_data
->test_name
);
1685 torture_assert_int_equal(tctx
, krb5_cc_resolve(k5_context
, cc_name
,
1687 0, "krb5_cc_resolve failed");
1689 torture_assert_int_equal(tctx
, krb5_cc_initialize(k5_context
,
1690 ccache
, my_creds
.client
),
1691 0, "krb5_cc_initialize failed");
1693 torture_assert_int_equal(tctx
, krb5_cc_store_cred(k5_context
,
1695 0, "krb5_cc_store_cred failed");
1698 * Prepare a TGS-REQ and run the TEST_TGS_REQ_KRBTGT_CANON tests
1700 * This tests krb5_get_creds behaviour, which allows us to set
1701 * the KRB5_GC_CANONICALIZE option against the krbtgt/ principal
1704 krbtgt_other_string
= talloc_asprintf(test_data
, "krbtgt/%s@%s", test_data
->real_domain
, test_data
->real_realm
);
1705 torture_assert_int_equal(tctx
,
1706 krb5_make_principal(k5_context
, &krbtgt_other
,
1707 test_data
->real_realm
, "krbtgt",
1708 test_data
->real_domain
, NULL
),
1709 0, "krb5_make_principal failed");
1711 test_context
->test_stage
= TEST_TGS_REQ_KRBTGT_CANON
;
1712 test_context
->packet_count
= 0;
1714 torture_assert_int_equal(tctx
,
1715 krb5_get_creds_opt_alloc(k5_context
, &opt
),
1716 0, "krb5_get_creds_opt_alloc");
1718 krb5_get_creds_opt_add_options(k5_context
,
1720 KRB5_GC_CANONICALIZE
);
1722 krb5_get_creds_opt_add_options(k5_context
,
1726 /* Confirm if we can get a ticket krbtgt/realm that we got back with the initial kinit */
1727 k5ret
= krb5_get_creds(k5_context
, opt
, ccache
, krbtgt_other
, &server_creds
);
1729 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1730 && test_data
->netbios_realm
&& test_data
->upper_realm
) {
1732 * In these situations, the code above does store a
1733 * principal in the credentials cache matching what
1734 * krb5_get_creds() needs, so the test succeds, with no packets.
1737 assertion_message
= talloc_asprintf(tctx
,
1738 "krb5_get_creds for %s failed with: %s",
1739 krbtgt_other_string
,
1740 smb_get_krb5_error_message(k5_context
, k5ret
,
1743 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
1744 torture_assert_int_equal(tctx
,
1745 test_context
->packet_count
,
1746 0, "Expected krb5_get_creds not to send packets");
1747 } else if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1748 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
1749 torture_assert_int_equal(tctx
, k5ret
, KRB5_CC_NOTFOUND
,
1750 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
1754 * In these situations, the code above does not store a
1755 * principal in the credentials cache matching what
1756 * krb5_get_creds() needs without talking to the KDC, so the
1757 * test fails with looping detected because when we set
1758 * canonicalize we confuse the client libs.
1761 assertion_message
= talloc_asprintf(tctx
,
1762 "krb5_get_creds for %s should have failed with looping detected: %s",
1763 krbtgt_other_string
,
1764 smb_get_krb5_error_message(k5_context
, k5ret
,
1767 torture_assert_int_equal(tctx
, k5ret
, KRB5_GET_IN_TKT_LOOP
, assertion_message
);
1768 torture_assert_int_equal(tctx
,
1769 test_context
->packet_count
,
1770 2, "Expected krb5_get_creds to send packets");
1774 * Prepare a TGS-REQ and run the TEST_TGS_REQ_CANON tests
1776 * This tests krb5_get_creds behaviour, which allows us to set
1777 * the KRB5_GC_CANONICALIZE option
1780 test_context
->test_stage
= TEST_TGS_REQ_CANON
;
1781 test_context
->packet_count
= 0;
1783 torture_assert_int_equal(tctx
,
1784 krb5_get_creds_opt_alloc(k5_context
, &opt
),
1785 0, "krb5_get_creds_opt_alloc");
1787 krb5_get_creds_opt_add_options(k5_context
,
1789 KRB5_GC_CANONICALIZE
);
1791 krb5_get_creds_opt_add_options(k5_context
,
1795 if (test_data
->s4u2self
) {
1796 torture_assert_int_equal(tctx
,
1797 krb5_get_creds_opt_set_impersonate(k5_context
,
1800 0, "krb5_get_creds_opt_set_impersonate failed");
1803 /* Confirm if we can get a ticket to our own name */
1804 k5ret
= krb5_get_creds(k5_context
, opt
, ccache
, principal
, &server_creds
);
1807 * In these situations, the code above does not store a
1808 * principal in the credentials cache matching what
1809 * krb5_get_creds() needs, so the test fails.
1812 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1813 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
1814 torture_assert_int_equal(tctx
, k5ret
, KRB5_CC_NOTFOUND
,
1815 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
1817 assertion_message
= talloc_asprintf(tctx
,
1818 "krb5_get_creds for %s failed: %s",
1820 smb_get_krb5_error_message(k5_context
, k5ret
,
1824 * Only machine accounts (strictly, accounts with a
1825 * servicePrincipalName) can expect this test to succeed
1827 if (torture_setting_bool(tctx
, "expect_machine_account", false)
1828 && (test_data
->enterprise
|| test_data
->upn
== false)) {
1829 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
1830 torture_assert_int_equal(tctx
, krb5_cc_store_cred(k5_context
,
1831 ccache
, server_creds
),
1832 0, "krb5_cc_store_cred failed");
1834 torture_assert_int_equal(tctx
,
1835 krb5_free_creds(k5_context
,
1837 0, "krb5_free_cred_contents failed");
1840 torture_assert_int_equal(tctx
, k5ret
, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
,
1844 torture_assert_int_equal(tctx
,
1845 test_context
->packet_count
,
1846 1, "Expected krb5_get_creds to send packets");
1850 * Confirm gettting a ticket to pass to the server, running
1851 * either the TEST_TGS_REQ or TEST_SELF_TRUST_TGS_REQ stage.
1853 * This triggers the client to attempt to get a
1854 * cross-realm ticket between the alternate names of
1855 * the server, and we need to confirm that behaviour.
1860 * This tries to guess when the krb5 libs will ask for a
1861 * cross-realm ticket, and when they will just ask the KDC
1864 if (test_context
->test_data
->canonicalize
== false
1865 || test_context
->test_data
->enterprise
1866 || (test_context
->test_data
->upper_realm
1867 && test_context
->test_data
->netbios_realm
== false)) {
1868 test_context
->test_stage
= TEST_TGS_REQ
;
1870 test_context
->test_stage
= TEST_SELF_TRUST_TGS_REQ
;
1873 test_context
->packet_count
= 0;
1874 torture_assert_int_equal(tctx
, krb5_auth_con_init(k5_context
, &auth_context
),
1875 0, "krb5_auth_con_init failed");
1878 k5ret
= krb5_mk_req_exact(k5_context
,
1884 assertion_message
= talloc_asprintf(tctx
,
1885 "krb5_mk_req_exact for %s failed: %s",
1887 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
1890 * Only machine accounts (strictly, accounts with a
1891 * servicePrincipalName) can expect this test to succeed
1893 if (torture_setting_bool(tctx
, "expect_machine_account", false) && (test_data
->enterprise
|| test_data
->upn
== false)) {
1894 DATA_BLOB client_to_server
;
1895 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
1896 client_to_server
= data_blob_const(enc_ticket
.data
, enc_ticket
.length
);
1897 torture_assert(tctx
,
1898 test_accept_ticket(tctx
, cmdline_credentials
,
1899 expected_unparse_principal_string
,
1901 "test_accept_ticket failed - failed to accept the ticket we just created");
1902 krb5_data_free(&enc_ticket
);
1904 torture_assert_int_equal(tctx
, k5ret
, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
,
1909 * Only in these cases would the above code have needed to
1910 * send packets to the network
1912 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1913 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
1914 torture_assert(tctx
,
1915 test_context
->packet_count
> 0,
1916 "Expected krb5_mk_req_exact to send packets");
1920 * Confirm gettting a ticket to pass to the server, running
1921 * the TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST stage
1923 * This triggers the client to attempt to get a
1924 * cross-realm ticket between the alternate names of
1925 * the server, and we need to confirm that behaviour.
1929 if (*test_data
->krb5_service
&& *test_data
->krb5_hostname
) {
1930 krb5_principal host_principal_srv_inst
;
1932 * This tries to guess when the krb5 libs will ask for a
1933 * cross-realm ticket, and when they will just ask the KDC
1936 test_context
->test_stage
= TEST_TGS_REQ_HOST
;
1937 test_context
->packet_count
= 0;
1938 torture_assert_int_equal(tctx
, krb5_auth_con_init(k5_context
, &auth_context
),
1939 0, "krb5_auth_con_init failed");
1942 k5ret
= krb5_mk_req(k5_context
,
1945 test_data
->krb5_service
,
1946 test_data
->krb5_hostname
,
1950 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1951 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
1952 torture_assert_int_equal(tctx
, k5ret
, KRB5_CC_NOTFOUND
,
1953 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
1955 assertion_message
= talloc_asprintf(tctx
,
1956 "krb5_mk_req for %s/%s failed: %s",
1957 test_data
->krb5_hostname
,
1958 test_data
->krb5_service
,
1959 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
1961 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
1963 * Only in these cases would the above code have needed to
1964 * send packets to the network
1966 torture_assert(tctx
,
1967 test_context
->packet_count
> 0,
1968 "Expected krb5_get_creds to send packets");
1972 test_context
->test_stage
= TEST_TGS_REQ_HOST_SRV_INST
;
1973 test_context
->packet_count
= 0;
1975 torture_assert_int_equal(tctx
,
1976 krb5_make_principal(k5_context
, &host_principal_srv_inst
,
1977 test_data
->real_realm
,
1978 strupper_talloc(tctx
, test_data
->krb5_service
),
1979 test_data
->krb5_hostname
,
1981 0, "krb5_make_principal failed");
1983 krb5_principal_set_type(k5_context
, host_principal_srv_inst
, KRB5_NT_SRV_INST
);
1985 torture_assert_int_equal(tctx
, krb5_auth_con_init(k5_context
, &auth_context
),
1986 0, "krb5_auth_con_init failed");
1989 k5ret
= krb5_mk_req_exact(k5_context
,
1992 host_principal_srv_inst
,
1995 krb5_free_principal(k5_context
, host_principal_srv_inst
);
1996 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
1997 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
1998 torture_assert_int_equal(tctx
, k5ret
, KRB5_CC_NOTFOUND
,
1999 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2001 assertion_message
= talloc_asprintf(tctx
,
2002 "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s",
2003 test_data
->krb5_service
,
2004 test_data
->krb5_hostname
,
2005 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
2007 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
2009 * Only in these cases would the above code have needed to
2010 * send packets to the network
2012 torture_assert(tctx
,
2013 test_context
->packet_count
> 0,
2014 "Expected krb5_get_creds to send packets");
2018 test_context
->test_stage
= TEST_TGS_REQ_HOST_SRV_HST
;
2019 test_context
->packet_count
= 0;
2021 torture_assert_int_equal(tctx
,
2022 krb5_make_principal(k5_context
, &host_principal_srv_inst
,
2023 test_data
->real_realm
,
2024 test_data
->krb5_service
,
2025 strupper_talloc(tctx
, test_data
->krb5_hostname
),
2027 0, "krb5_make_principal failed");
2029 krb5_principal_set_type(k5_context
, host_principal_srv_inst
, KRB5_NT_SRV_HST
);
2031 torture_assert_int_equal(tctx
, krb5_auth_con_init(k5_context
, &auth_context
),
2032 0, "krb5_auth_con_init failed");
2035 k5ret
= krb5_mk_req_exact(k5_context
,
2038 host_principal_srv_inst
,
2041 krb5_free_principal(k5_context
, host_principal_srv_inst
);
2042 if (test_data
->canonicalize
== false && test_data
->enterprise
== false
2043 && (test_data
->upper_realm
== false || test_data
->netbios_realm
== true)) {
2044 torture_assert_int_equal(tctx
, k5ret
, KRB5_CC_NOTFOUND
,
2045 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2047 assertion_message
= talloc_asprintf(tctx
,
2048 "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s",
2049 test_data
->krb5_service
,
2050 test_data
->krb5_hostname
,
2051 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
2053 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
2055 * Only in these cases would the above code have needed to
2056 * send packets to the network
2058 torture_assert(tctx
,
2059 test_context
->packet_count
> 0,
2060 "Expected krb5_get_creds to send packets");
2065 * Confirm gettting a ticket for the same krbtgt/realm that we
2066 * got back with the initial ticket, running the
2067 * TEST_TGS_REQ_KRBTGT stage.
2071 test_context
->test_stage
= TEST_TGS_REQ_KRBTGT
;
2072 test_context
->packet_count
= 0;
2075 k5ret
= krb5_mk_req_exact(k5_context
,
2082 assertion_message
= talloc_asprintf(tctx
,
2083 "krb5_mk_req_exact for %s failed: %s",
2085 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
2086 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
2089 * Confirm gettting a ticket for our own principal that we
2090 * got back with the initial ticket, running the
2091 * TEST_AS_REQ_SELF stage.
2094 test_context
->test_stage
= TEST_AS_REQ_SELF
;
2095 test_context
->packet_count
= 0;
2097 k5ret
= krb5_get_init_creds_password(k5_context
, &my_creds
, principal
,
2098 password
, NULL
, NULL
, 0,
2099 principal_string
, krb_options
);
2101 if (torture_setting_bool(test_context
->tctx
, "expect_machine_account", false) && (test_data
->upn
== false)) {
2102 assertion_message
= talloc_asprintf(tctx
,
2103 "krb5_get_init_creds_password for %s failed: %s",
2105 smb_get_krb5_error_message(k5_context
, k5ret
, tctx
));
2106 torture_assert_int_equal(tctx
, k5ret
, 0, assertion_message
);
2107 torture_assert(tctx
,
2108 test_context
->packet_count
>= 2,
2109 "Expected krb5_get_init_creds_password to send more packets");
2112 assertion_message
= talloc_asprintf(tctx
,
2113 "Got wrong error_code from krb5_get_init_creds_password, expected KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN trying to get a ticket to %s for %s", principal_string
, principal_string
);
2114 torture_assert_int_equal(tctx
, k5ret
,
2115 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
,
2117 torture_assert(tctx
,
2118 test_context
->packet_count
>= 1,
2119 "Expected krb5_get_init_creds_password to send more packets");
2121 /* We can't proceed with more checks */
2126 * Assert that the reply was with the correct type of
2127 * principal, depending on the flags we set
2129 if (test_data
->canonicalize
== false && test_data
->enterprise
) {
2130 torture_assert_int_equal(tctx
,
2131 krb5_principal_get_type(k5_context
,
2133 KRB5_NT_ENTERPRISE_PRINCIPAL
,
2134 "smb_krb5_init_context gave incorrect client->name.name_type");
2135 torture_assert_int_equal(tctx
,
2136 krb5_principal_get_type(k5_context
,
2138 KRB5_NT_ENTERPRISE_PRINCIPAL
,
2139 "smb_krb5_init_context gave incorrect server->name.name_type");
2141 torture_assert_int_equal(tctx
,
2142 krb5_principal_get_type(k5_context
,
2145 "smb_krb5_init_context gave incorrect client->name.name_type");
2146 torture_assert_int_equal(tctx
,
2147 krb5_principal_get_type(k5_context
,
2150 "smb_krb5_init_context gave incorrect server->name.name_type");
2153 torture_assert_int_equal(tctx
,
2154 krb5_unparse_name(k5_context
,
2155 my_creds
.client
, &got_principal_string
), 0,
2156 "krb5_unparse_name failed");
2158 assertion_message
= talloc_asprintf(tctx
,
2159 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
2160 got_principal_string
, expected_principal_string
);
2161 krb5_free_unparsed_name(k5_context
, got_principal_string
);
2163 torture_assert(tctx
, krb5_principal_compare(k5_context
,
2164 my_creds
.client
, expected_principal
),
2167 torture_assert_int_equal(tctx
,
2168 krb5_unparse_name(k5_context
,
2169 my_creds
.client
, &got_principal_string
), 0,
2170 "krb5_unparse_name failed");
2172 assertion_message
= talloc_asprintf(tctx
,
2173 "krb5_get_init_creds_password returned a different server principal %s to what was expected %s",
2174 got_principal_string
, expected_principal_string
);
2175 krb5_free_unparsed_name(k5_context
, got_principal_string
);
2177 torture_assert(tctx
, krb5_principal_compare(k5_context
,
2178 my_creds
.client
, expected_principal
),
2181 krb5_free_principal(k5_context
, principal
);
2182 krb5_get_init_creds_opt_free(k5_context
, krb_options
);
2184 torture_assert_int_equal(tctx
, krb5_free_cred_contents(k5_context
, &my_creds
),
2185 0, "krb5_free_cred_contents failed");
2190 struct torture_suite
*torture_krb5_canon(TALLOC_CTX
*mem_ctx
)
2193 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "canon");
2194 suite
->description
= talloc_strdup(suite
, "Kerberos Canonicalisation tests");
2196 for (i
= 0; i
< TEST_ALL
; i
++) {
2197 char *name
= talloc_asprintf(suite
, "%s.%s.%s.%s.%s.%s.%s.%s",
2198 (i
& TEST_CANONICALIZE
) ? "canon" : "no-canon",
2199 (i
& TEST_ENTERPRISE
) ? "enterprise" : "no-enterprise",
2200 (i
& TEST_UPPER_REALM
) ? "uc-realm" : "lc-realm",
2201 (i
& TEST_UPPER_USERNAME
) ? "uc-user" : "lc-user",
2202 (i
& TEST_NETBIOS_REALM
) ? "netbios-realm" : "krb5-realm",
2203 (i
& TEST_WIN2K
) ? "win2k" : "no-win2k",
2204 (i
& TEST_UPN
) ? "upn" : "no-upn",
2205 (i
& TEST_S4U2SELF
) ? "s4u2self" : "normal");
2207 struct test_data
*test_data
= talloc_zero(suite
, struct test_data
);
2209 test_data
->test_name
= name
;
2210 test_data
->real_realm
2211 = strupper_talloc(test_data
, cli_credentials_get_realm(cmdline_credentials
));
2212 test_data
->real_domain
= cli_credentials_get_domain(cmdline_credentials
);
2213 test_data
->username
= cli_credentials_get_username(cmdline_credentials
);
2214 test_data
->real_username
= cli_credentials_get_username(cmdline_credentials
);
2215 test_data
->canonicalize
= (i
& TEST_CANONICALIZE
) != 0;
2216 test_data
->enterprise
= (i
& TEST_ENTERPRISE
) != 0;
2217 test_data
->upper_realm
= (i
& TEST_UPPER_REALM
) != 0;
2218 test_data
->upper_username
= (i
& TEST_UPPER_USERNAME
) != 0;
2219 test_data
->netbios_realm
= (i
& TEST_NETBIOS_REALM
) != 0;
2220 test_data
->win2k
= (i
& TEST_WIN2K
) != 0;
2221 test_data
->upn
= (i
& TEST_UPN
) != 0;
2222 test_data
->s4u2self
= (i
& TEST_S4U2SELF
) != 0;
2223 torture_suite_add_simple_tcase_const(suite
, name
, torture_krb5_as_req_canon
,