torture krb5.kdc.canon: Correct principal being checked in TEST_AS_REQ_SELF stage
[Samba.git] / source4 / torture / krb5 / kdc-canon-heimdal.c
blob30eca87cb52ae1eb4d378d8fdbd1a09a3c00e131
1 /*
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/>.
23 #include "includes.h"
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_REMOVEDOLLAR 0x0000100
46 #define TEST_AS_REQ_SPN 0x0000200
47 #define TEST_ALL 0x00003FF
49 struct test_data {
50 const char *test_name;
51 const char *realm;
52 const char *real_realm;
53 const char *real_domain;
54 const char *username;
55 const char *real_username;
56 bool canonicalize;
57 bool enterprise;
58 bool upper_realm;
59 bool upper_username;
60 bool netbios_realm;
61 bool win2k;
62 bool upn;
63 bool other_upn_suffix;
64 bool s4u2self;
65 bool removedollar;
66 bool as_req_spn;
67 bool spn_is_upn;
68 const char *krb5_service;
69 const char *krb5_hostname;
72 enum test_stage {
73 TEST_AS_REQ = 0,
74 TEST_TGS_REQ_KRBTGT_CANON = 1,
75 TEST_TGS_REQ_CANON = 2,
76 TEST_SELF_TRUST_TGS_REQ = 3,
77 TEST_TGS_REQ = 4,
78 TEST_TGS_REQ_KRBTGT = 5,
79 TEST_TGS_REQ_HOST = 6,
80 TEST_TGS_REQ_HOST_SRV_INST = 7,
81 TEST_TGS_REQ_HOST_SRV_HST = 8,
82 TEST_AS_REQ_SELF = 9,
83 TEST_DONE = 10
86 struct torture_krb5_context {
87 struct smb_krb5_context *smb_krb5_context;
88 struct torture_context *tctx;
89 struct addrinfo *server;
90 struct test_data *test_data;
91 int packet_count;
92 enum test_stage test_stage;
93 AS_REQ as_req;
94 AS_REP as_rep;
95 TGS_REQ tgs_req;
96 TGS_REP tgs_rep;
99 struct pac_data {
100 const char *principal_name;
104 * A helper function which avoids touching the local databases to
105 * generate the session info, as we just want to verify the principal
106 * name that we found in the ticket not the full local token
108 static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx,
109 TALLOC_CTX *mem_ctx,
110 struct smb_krb5_context *smb_krb5_context,
111 DATA_BLOB *pac_blob,
112 const char *principal_name,
113 const struct tsocket_address *remote_address,
114 uint32_t session_info_flags,
115 struct auth_session_info **session_info)
117 NTSTATUS nt_status;
118 struct auth_user_info_dc *user_info_dc;
119 TALLOC_CTX *tmp_ctx;
120 struct pac_data *pac_data;
122 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
123 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
125 auth_ctx->private_data = pac_data = talloc_zero(auth_ctx, struct pac_data);
127 pac_data->principal_name = talloc_strdup(pac_data, principal_name);
128 if (!pac_data->principal_name) {
129 talloc_free(tmp_ctx);
130 return NT_STATUS_NO_MEMORY;
133 nt_status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
134 *pac_blob,
135 smb_krb5_context->krb5_context,
136 &user_info_dc, NULL, NULL);
137 if (!NT_STATUS_IS_OK(nt_status)) {
138 talloc_free(tmp_ctx);
139 return nt_status;
142 if (user_info_dc->info->authenticated) {
143 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
146 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
147 nt_status = auth_generate_session_info(mem_ctx,
148 NULL,
149 NULL,
150 user_info_dc, session_info_flags,
151 session_info);
152 if (!NT_STATUS_IS_OK(nt_status)) {
153 talloc_free(tmp_ctx);
154 return nt_status;
157 talloc_free(tmp_ctx);
158 return NT_STATUS_OK;
161 /* Check to see if we can pass the PAC across to the NETLOGON server for validation */
163 /* Also happens to be a really good one-step verfication of our Kerberos stack */
165 static bool test_accept_ticket(struct torture_context *tctx,
166 struct cli_credentials *credentials,
167 const char *principal,
168 DATA_BLOB client_to_server)
170 NTSTATUS status;
171 struct gensec_security *gensec_server_context;
172 DATA_BLOB server_to_client;
173 struct auth4_context *auth_context;
174 struct auth_session_info *session_info;
175 struct pac_data *pac_data;
176 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
178 torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");
180 auth_context = talloc_zero(tmp_ctx, struct auth4_context);
181 torture_assert(tctx, auth_context != NULL, "talloc_new() failed");
183 auth_context->generate_session_info_pac = test_generate_session_info_pac;
185 status = gensec_server_start(tctx,
186 lpcfg_gensec_settings(tctx, tctx->lp_ctx),
187 auth_context, &gensec_server_context);
188 torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");
190 status = gensec_set_credentials(gensec_server_context, credentials);
191 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");
193 status = gensec_start_mech_by_name(gensec_server_context, "krb5");
194 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_name (server) failed");
196 server_to_client = data_blob(NULL, 0);
198 /* Do a client-server update dance */
199 status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
200 torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
202 /* Extract the PAC using Samba's code */
204 status = gensec_session_info(gensec_server_context, gensec_server_context, &session_info);
205 torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");
207 pac_data = talloc_get_type(auth_context->private_data, struct pac_data);
209 torture_assert(tctx, pac_data != NULL, "gensec_update failed to fill in pac_data in auth_context");
210 torture_assert(tctx, pac_data->principal_name != NULL, "principal_name not present");
211 torture_assert_str_equal(tctx, pac_data->principal_name, principal, "wrong principal name");
212 return true;
216 * TEST_AS_REQ and TEST_AS_REQ_SELF - SEND
218 * Confirm that the outgoing packet meets certain expectations. This
219 * should be extended to further assert the correct and expected
220 * behaviour of the krb5 libs, so we know what we are sending to the
221 * server.
223 * Additionally, this CHANGES the request to remove the canonicalize
224 * flag automatically added by the krb5 libs when an enterprise
225 * principal is used, so we can test what the server does in this
226 * combination.
230 static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_context,
231 const krb5_data *send_buf,
232 krb5_data *modified_send_buf)
234 AS_REQ mod_as_req;
235 krb5_error_code k5ret;
236 size_t used;
237 torture_assert_int_equal(test_context->tctx, decode_AS_REQ(send_buf->data, send_buf->length,
238 &test_context->as_req, &used),
239 0, "decode_AS_REQ for TEST_AS_REQ failed");
240 mod_as_req = test_context->as_req;
241 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
242 torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno,
243 5, "Got wrong as_req->pvno");
244 if (test_context->test_data->canonicalize
245 || test_context->test_data->enterprise) {
246 torture_assert(test_context->tctx,
247 test_context->as_req.req_body.kdc_options.canonicalize,
248 "krb5 libs did not set canonicalize!");
249 } else {
250 torture_assert_int_equal(test_context->tctx,
251 test_context->as_req.req_body.kdc_options.canonicalize,
252 false,
253 "krb5 libs unexpectedly set canonicalize!");
256 if (test_context->test_data->as_req_spn) {
257 if (test_context->test_data->upn) {
258 torture_assert_int_equal(test_context->tctx,
259 test_context->as_req.req_body.cname->name_type,
260 KRB5_NT_PRINCIPAL,
261 "krb5 libs unexpectedly "
262 "did not set principal "
263 "as NT_SRV_HST!");
264 } else {
265 torture_assert_int_equal(test_context->tctx,
266 test_context->as_req.req_body.cname->name_type,
267 KRB5_NT_SRV_HST,
268 "krb5 libs unexpectedly "
269 "did not set principal "
270 "as NT_SRV_HST!");
272 } else if (test_context->test_data->enterprise) {
273 torture_assert_int_equal(test_context->tctx,
274 test_context->as_req.req_body.cname->name_type,
275 KRB5_NT_ENTERPRISE_PRINCIPAL,
276 "krb5 libs did not pass principal as enterprise!");
277 } else {
278 torture_assert_int_equal(test_context->tctx,
279 test_context->as_req.req_body.cname->name_type,
280 KRB5_NT_PRINCIPAL,
281 "krb5 libs unexpectedly set principal as enterprise!");
284 /* Force off canonicalize that was forced on by the krb5 libs */
285 if (test_context->test_data->canonicalize == false && test_context->test_data->enterprise) {
286 mod_as_req.req_body.kdc_options.canonicalize = false;
289 if (test_context->test_stage == TEST_AS_REQ_SELF) {
291 * Force the server name to match the client name,
292 * including the name type. This isn't possible with
293 * the krb5 client libs alone
295 mod_as_req.req_body.sname = test_context->as_req.req_body.cname;
298 ASN1_MALLOC_ENCODE(AS_REQ, modified_send_buf->data, modified_send_buf->length,
299 &mod_as_req, &used, k5ret);
300 torture_assert_int_equal(test_context->tctx,
301 k5ret, 0,
302 "encode_AS_REQ failed");
304 if (test_context->test_stage != TEST_AS_REQ_SELF) {
305 torture_assert_int_equal(test_context->tctx, used, send_buf->length,
306 "re-encode length mismatch");
308 return true;
312 * TEST_AS_REQ - RECV
314 * Confirm that the reply packet from the KDC meets certain
315 * expectations as part of TEST_AS_REQ. This uses a packet count to
316 * work out what packet we are up to in the multiple exchanged
317 * triggerd by krb5_get_init_creds_password().
321 static bool torture_krb5_post_recv_as_req_test(struct torture_krb5_context *test_context,
322 const krb5_data *recv_buf)
324 KRB_ERROR error;
325 size_t used;
326 if (test_context->packet_count == 0) {
327 krb5_error_code k5ret;
329 * The client libs obtain the salt by attempting to
330 * authenticate without pre-authentication and getting
331 * the correct salt with the
332 * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in
333 * the test (netbios_realm && upn) that deliberatly
334 * has an incorrect principal, we check we get the
335 * correct error.
337 k5ret = decode_KRB_ERROR(recv_buf->data, recv_buf->length,
338 &error, &used);
339 if (k5ret != 0) {
340 AS_REP as_rep;
341 k5ret = decode_AS_REP(recv_buf->data, recv_buf->length,
342 &as_rep, &used);
343 if (k5ret == 0) {
344 if (test_context->test_data->netbios_realm && test_context->test_data->upn) {
345 torture_assert(test_context->tctx, false,
346 "expected to get a KRB_ERROR packet with "
347 "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, got valid AS-REP");
348 } else {
349 torture_assert(test_context->tctx, false,
350 "expected to get a KRB_ERROR packet with "
351 "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
353 } else {
354 if (test_context->test_data->netbios_realm && test_context->test_data->upn) {
355 torture_assert(test_context->tctx, false,
356 "unable to decode as KRB-ERROR or AS-REP, "
357 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN");
358 } else {
359 torture_assert(test_context->tctx, false,
360 "unable to decode as KRB-ERROR or AS-REP, "
361 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED");
365 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
366 "length mismatch");
367 torture_assert_int_equal(test_context->tctx, error.pvno, 5,
368 "Got wrong error.pvno");
369 if (test_context->test_data->netbios_realm && test_context->test_data->upn) {
370 torture_assert_int_equal(test_context->tctx,
371 error.error_code,
372 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE,
373 "Got wrong error.error_code");
374 } else if (test_context->test_data->as_req_spn && !test_context->test_data->spn_is_upn) {
375 torture_assert_int_equal(test_context->tctx,
376 error.error_code,
377 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE,
378 "Got wrong error.error_code");
379 } else {
380 torture_assert_int_equal(test_context->tctx,
381 error.error_code,
382 KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE,
383 "Got wrong error.error_code");
386 free_KRB_ERROR(&error);
387 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
388 && (test_context->packet_count == 1)) {
390 * The Windows 2012R2 KDC will always respond with
391 * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket
392 * won't fit, because of the PAC. (It appears to do
393 * this always, even if it will). This triggers the
394 * client to try again over TCP.
396 torture_assert_int_equal(test_context->tctx,
397 used, recv_buf->length,
398 "length mismatch");
399 torture_assert_int_equal(test_context->tctx,
400 error.pvno, 5,
401 "Got wrong error.pvno");
402 torture_assert_int_equal(test_context->tctx,
403 error.error_code,
404 KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
405 "Got wrong error.error_code");
406 free_KRB_ERROR(&error);
407 } else {
409 * Finally the successful packet.
411 torture_assert_int_equal(test_context->tctx,
412 decode_AS_REP(recv_buf->data, recv_buf->length,
413 &test_context->as_rep, &used), 0,
414 "decode_AS_REP failed");
415 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
416 "length mismatch");
417 torture_assert_int_equal(test_context->tctx,
418 test_context->as_rep.pvno, 5,
419 "Got wrong as_rep->pvno");
420 torture_assert_int_equal(test_context->tctx,
421 test_context->as_rep.ticket.tkt_vno, 5,
422 "Got wrong as_rep->ticket.tkt_vno");
423 torture_assert(test_context->tctx,
424 test_context->as_rep.ticket.enc_part.kvno,
425 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
428 * We can confirm that the correct proxy behaviour is
429 * in use on the KDC by checking the KVNO of the
430 * krbtgt account returned in the reply.
432 * A packet passed to the full RW DC will not have a
433 * KVNO in the upper bits, while a packet processed
434 * locally on the RODC will have these bits filled in
435 * the msDS-SecondaryKrbTgtNumber
437 if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
438 torture_assert_int_not_equal(test_context->tctx,
439 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
440 0, "Did not get a RODC number in the KVNO");
441 } else {
442 torture_assert_int_equal(test_context->tctx,
443 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
444 0, "Unexpecedly got a RODC number in the KVNO");
446 free_AS_REP(&test_context->as_rep);
448 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
449 free_AS_REQ(&test_context->as_req);
450 return true;
454 * TEST_TGS_REQ_KRBTGT_CANON
457 * Confirm that the outgoing TGS-REQ packet from krb5_get_creds()
458 * for the krbtgt/realm principal meets certain expectations, like
459 * that the canonicalize bit is not set
463 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)
465 size_t used;
466 torture_assert_int_equal(test_context->tctx,
467 decode_TGS_REQ(send_buf->data, send_buf->length,
468 &test_context->tgs_req, &used),
469 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
470 torture_assert_int_equal(test_context->tctx,
471 used, send_buf->length,
472 "length mismatch");
473 torture_assert_int_equal(test_context->tctx,
474 test_context->tgs_req.pvno, 5,
475 "Got wrong as_req->pvno");
476 torture_assert_int_equal(test_context->tctx,
477 test_context->tgs_req.req_body.kdc_options.canonicalize,
478 true,
479 "krb5 libs unexpectedly did not set canonicalize!");
481 torture_assert_int_equal(test_context->tctx,
482 test_context->tgs_req.req_body.sname->name_type,
483 KRB5_NT_PRINCIPAL,
484 "Mismatch in name_type between request and expected request");
486 torture_assert_str_equal(test_context->tctx,
487 test_context->tgs_req.req_body.realm,
488 test_context->test_data->real_realm,
489 "Mismatch in realm between request and expected request");
491 *modified_send_buf = *send_buf;
492 return true;
496 * TEST_TGS_REQ_KRBTGT_CANON
498 * Confirm that the reply TGS-REP packet for krb5_get_creds()
499 * where the client is behaving as if this is a cross-realm trust due
500 * to case or netbios vs dns name differences meets certain
501 * expectations, while canonicalize is set
505 static bool torture_krb5_post_recv_tgs_req_krbtgt_canon_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
507 size_t used;
508 torture_assert_int_equal(test_context->tctx,
509 decode_TGS_REP(recv_buf->data, recv_buf->length,
510 &test_context->tgs_rep, &used),
512 "decode_TGS_REP failed");
513 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
514 torture_assert_int_equal(test_context->tctx,
515 test_context->tgs_rep.pvno, 5,
516 "Got wrong as_rep->pvno");
517 torture_assert_int_equal(test_context->tctx,
518 test_context->tgs_rep.ticket.tkt_vno, 5,
519 "Got wrong as_rep->ticket.tkt_vno");
520 torture_assert(test_context->tctx,
521 test_context->tgs_rep.ticket.enc_part.kvno,
522 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
523 torture_assert_str_equal(test_context->tctx,
524 test_context->tgs_req.req_body.realm,
525 test_context->tgs_rep.ticket.realm,
526 "Mismatch in realm between request and ticket response");
527 torture_assert_str_equal(test_context->tctx,
528 test_context->tgs_rep.ticket.realm,
529 test_context->test_data->real_realm,
530 "Mismatch in realm between ticket response and expected ticket response");
531 torture_assert_int_equal(test_context->tctx,
532 test_context->tgs_rep.ticket.sname.name_type,
533 KRB5_NT_SRV_INST,
534 "Mismatch in name_type between ticket response and expected value of KRB5_NT_SRV_INST");
536 torture_assert_int_equal(test_context->tctx,
537 test_context->tgs_rep.ticket.sname.name_string.len,
539 "Mismatch in name_type between ticket response and expected value, expected krbtgt/REALM@REALM");
541 torture_assert_str_equal(test_context->tctx,
542 test_context->tgs_rep.ticket.sname.name_string.val[0], "krbtgt",
543 "Mismatch in name between response and expected response, expected krbtgt");
544 torture_assert_str_equal(test_context->tctx,
545 test_context->tgs_rep.ticket.sname.name_string.val[1], test_context->test_data->real_realm,
546 "Mismatch in realm part of krbtgt/ in expected response, expected krbtgt/REALM@REALM");
549 * We can confirm that the correct proxy behaviour is
550 * in use on the KDC by checking the KVNO of the
551 * krbtgt account returned in the reply.
553 * A packet passed to the full RW DC will not have a
554 * KVNO in the upper bits, while a packet processed
555 * locally on the RODC will have these bits filled in
556 * the msDS-SecondaryKrbTgtNumber
558 if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
559 torture_assert_int_not_equal(test_context->tctx,
560 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
561 0, "Did not get a RODC number in the KVNO");
562 } else {
563 torture_assert_int_equal(test_context->tctx,
564 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
565 0, "Unexpecedly got a RODC number in the KVNO");
567 free_TGS_REP(&test_context->tgs_rep);
568 torture_assert(test_context->tctx,
569 test_context->packet_count < 2,
570 "too many packets");
571 free_TGS_REQ(&test_context->tgs_req);
572 return true;
576 * TEST_TGS_REQ_CANON
578 * Confirm that the outgoing TGS-REQ packet from krb5_get_creds
579 * certain expectations, like that the canonicalize bit is set (this
580 * test is to force that handling) and that if an enterprise name was
581 * requested, that it was sent.
585 static bool torture_krb5_pre_send_tgs_req_canon_test(struct torture_krb5_context *test_context,
586 const krb5_data *send_buf,
587 krb5_data *modified_send_buf)
589 size_t used;
590 torture_assert_int_equal(test_context->tctx,
591 decode_TGS_REQ(send_buf->data, send_buf->length,
592 &test_context->tgs_req, &used),
593 0, "decode_TGS_REQ for TEST_TGS_REQ_CANON test failed");
594 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
595 torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno");
596 torture_assert_int_equal(test_context->tctx,
597 test_context->tgs_req.req_body.kdc_options.canonicalize,
598 true, "krb5 libs unexpectedly did not set canonicalize!");
600 if (test_context->test_data->enterprise) {
601 torture_assert_int_equal(test_context->tctx,
602 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_ENTERPRISE_PRINCIPAL,
603 "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL");
604 torture_assert_str_equal(test_context->tctx,
605 test_context->tgs_req.req_body.realm, test_context->test_data->real_realm,
606 "Mismatch in realm between request and expected request");
608 } else if (test_context->test_data->as_req_spn) {
609 torture_assert_int_equal(test_context->tctx,
610 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_SRV_HST,
611 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_HST");
612 torture_assert_str_equal(test_context->tctx,
613 test_context->tgs_req.req_body.realm, test_context->test_data->real_realm,
614 "Mismatch in realm between request and expected request");
616 } else if (test_context->test_data->canonicalize) {
617 torture_assert_int_equal(test_context->tctx,
618 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL,
619 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
620 torture_assert_str_equal(test_context->tctx,
621 test_context->tgs_req.req_body.realm, test_context->test_data->real_realm,
622 "Mismatch in realm between request and expected request");
624 } else {
625 torture_assert_int_equal(test_context->tctx,
626 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL,
627 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
628 torture_assert_str_equal(test_context->tctx,
629 test_context->tgs_req.req_body.realm, test_context->test_data->realm,
630 "Mismatch in realm between request and expected request");
634 *modified_send_buf = *send_buf;
636 return true;
640 * TEST_TGS_REQ_CANON - RECV
642 * Confirm that the reply TGS-REP or error packet from the KDC meets
643 * certain expectations as part of TEST_TGS_REQ_CANON.
645 * This is triggered by krb5_get_creds()
649 static bool torture_krb5_post_recv_tgs_req_canon_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
651 KRB_ERROR error;
652 size_t used;
655 * If this account did not have a servicePrincipalName, then
656 * we expect a errro packet, not a TGS-REQ
658 if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) {
659 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
660 torture_assert_int_equal(test_context->tctx,
661 error.pvno, 5,
662 "Got wrong error.pvno");
663 torture_assert_int_equal(test_context->tctx,
664 error.error_code,
665 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE,
666 "Got wrong error.error_code");
667 } else {
668 torture_assert_int_equal(test_context->tctx,
669 decode_TGS_REP(recv_buf->data, recv_buf->length,
670 &test_context->tgs_rep,
671 &used),
673 "decode_TGS_REP failed");
674 torture_assert_int_equal(test_context->tctx,
675 used, recv_buf->length,
676 "length mismatch");
677 torture_assert_int_equal(test_context->tctx,
678 test_context->tgs_rep.pvno, 5,
679 "Got wrong as_rep->pvno");
680 torture_assert_int_equal(test_context->tctx,
681 test_context->tgs_rep.ticket.tkt_vno, 5,
682 "Got wrong as_rep->ticket.tkt_vno");
683 torture_assert(test_context->tctx,
684 test_context->tgs_rep.ticket.enc_part.kvno,
685 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
686 torture_assert_str_equal(test_context->tctx,
687 test_context->tgs_rep.ticket.realm,
688 test_context->test_data->real_realm,
689 "Mismatch in realm between ticket response and expected upper case REALM");
690 torture_assert_int_equal(test_context->tctx,
691 test_context->tgs_rep.ticket.sname.name_type,
692 test_context->tgs_req.req_body.sname->name_type,
693 "Mismatch in name_type between request and ticket response");
694 torture_assert_int_equal(test_context->tctx,
695 test_context->tgs_rep.ticket.sname.name_string.len,
696 test_context->tgs_req.req_body.sname->name_string.len,
697 "Mismatch in name_string.len between request and ticket response");
698 torture_assert(test_context->tctx,
699 test_context->tgs_rep.ticket.sname.name_string.len >= 1,
700 "name_string.len should be >=1 in ticket response");
701 torture_assert_str_equal(test_context->tctx,
702 test_context->tgs_rep.ticket.sname.name_string.val[0],
703 test_context->tgs_req.req_body.sname->name_string.val[0],
704 "Mismatch in name between request and expected request");
705 torture_assert_int_equal(test_context->tctx,
706 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
707 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
708 free_TGS_REP(&test_context->tgs_rep);
710 torture_assert(test_context->tctx, test_context->packet_count == 0, "too many packets");
711 free_TGS_REQ(&test_context->tgs_req);
713 return true;
717 * TEST_SELF_TRUST_TGS_REQ
719 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
720 * certain expectations, like that the canonicalize bit is set (this
721 * test is to force that handling).
723 * This test is for the case where the name we ask for, while a valid
724 * alternate name for our own realm is used. The client acts as if
725 * this is cross-realm trust.
729 static bool torture_krb5_pre_send_self_trust_tgs_req_test(struct torture_krb5_context *test_context,
730 const krb5_data *send_buf,
731 krb5_data *modified_send_buf)
733 size_t used;
734 torture_assert_int_equal(test_context->tctx,
735 decode_TGS_REQ(send_buf->data, send_buf->length,
736 &test_context->tgs_req, &used),
737 0, "decode_TGS_REQ for TEST_SELF_TRUST_TGS_REQ test failed");
738 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
739 torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5, "Got wrong as_req->pvno");
741 if (test_context->test_data->enterprise
742 || (test_context->test_data->spn_is_upn && test_context->test_data->upn)) {
743 torture_assert_int_equal(test_context->tctx,
744 test_context->tgs_req.req_body.kdc_options.canonicalize,
745 true,
746 "krb5 libs unexpectedly"
747 " did not set canonicalize!");
748 } else {
749 torture_assert_int_equal(test_context->tctx,
750 test_context->tgs_req.req_body.kdc_options.canonicalize,
751 false,
752 "krb5 libs unexpectedly"
753 " set canonicalize!");
757 if (test_context->test_data->canonicalize) {
758 torture_assert_str_equal(test_context->tctx,
759 test_context->tgs_req.req_body.realm,
760 test_context->test_data->real_realm,
761 "Mismatch in realm between request and expected request");
762 } else {
763 torture_assert_str_equal(test_context->tctx,
764 test_context->tgs_req.req_body.realm,
765 test_context->test_data->realm,
766 "Mismatch in realm between request and expected request");
768 torture_assert_int_equal(test_context->tctx,
769 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL,
770 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
771 torture_assert_int_equal(test_context->tctx,
772 test_context->tgs_req.req_body.sname->name_string.len, 2,
773 "Mismatch in name between request and expected request, expected krbtgt/realm");
774 torture_assert_str_equal(test_context->tctx,
775 test_context->tgs_req.req_body.sname->name_string.val[0], "krbtgt",
776 "Mismatch in name between request and expected request, expected krbtgt");
777 torture_assert_str_equal(test_context->tctx,
778 test_context->tgs_req.req_body.sname->name_string.val[1], test_context->test_data->realm,
779 "Mismatch in realm part of cross-realm request principal between request and expected request");
780 *modified_send_buf = *send_buf;
782 return true;
786 * TEST_SELF_TRUST_TGS_REQ and TEST_TGS_REQ_KRBTGT - RECV
788 * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(),
789 * where the client is behaving as if this is a cross-realm trust due
790 * to case or netbios vs dns name differences meets certain
791 * expectations.
795 static bool torture_krb5_post_recv_self_trust_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
797 size_t used;
798 torture_assert_int_equal(test_context->tctx,
799 decode_TGS_REP(recv_buf->data, recv_buf->length,
800 &test_context->tgs_rep, &used),
802 "decode_TGS_REP failed");
803 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
804 torture_assert_int_equal(test_context->tctx,
805 test_context->tgs_rep.pvno, 5,
806 "Got wrong as_rep->pvno");
807 torture_assert_int_equal(test_context->tctx,
808 test_context->tgs_rep.ticket.tkt_vno, 5,
809 "Got wrong as_rep->ticket.tkt_vno");
810 torture_assert(test_context->tctx,
811 test_context->tgs_rep.ticket.enc_part.kvno,
812 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
813 torture_assert_str_equal(test_context->tctx,
814 test_context->tgs_req.req_body.realm,
815 test_context->tgs_rep.ticket.realm,
816 "Mismatch in realm between request and ticket response");
817 torture_assert_int_equal(test_context->tctx,
818 test_context->tgs_rep.ticket.sname.name_type,
819 test_context->tgs_req.req_body.sname->name_type,
820 "Mismatch in name_type between request and ticket response");
822 torture_assert_int_equal(test_context->tctx,
823 test_context->tgs_rep.ticket.sname.name_string.len, 2,
824 "Mismatch in name between request and expected request, expected krbtgt/realm");
825 torture_assert_str_equal(test_context->tctx,
826 test_context->tgs_rep.ticket.sname.name_string.val[0], "krbtgt",
827 "Mismatch in name between request and expected request, expected krbtgt");
828 torture_assert_str_equal(test_context->tctx,
829 test_context->tgs_rep.ticket.sname.name_string.val[1], test_context->test_data->realm,
830 "Mismatch in realm part of cross-realm request principal between response and expected request");
832 * We can confirm that the correct proxy behaviour is
833 * in use on the KDC by checking the KVNO of the
834 * krbtgt account returned in the reply.
836 * A packet passed to the full RW DC will not have a
837 * KVNO in the upper bits, while a packet processed
838 * locally on the RODC will have these bits filled in
839 * the msDS-SecondaryKrbTgtNumber
841 if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
842 torture_assert_int_not_equal(test_context->tctx,
843 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
844 0, "Did not get a RODC number in the KVNO");
845 } else {
846 torture_assert_int_equal(test_context->tctx,
847 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
848 0, "Unexpecedly got a RODC number in the KVNO");
850 free_TGS_REP(&test_context->tgs_rep);
851 torture_assert_int_equal(test_context->tctx,
852 test_context->packet_count, 0,
853 "too many packets");
854 test_context->packet_count = 0;
855 test_context->test_stage = TEST_TGS_REQ;
856 free_TGS_REQ(&test_context->tgs_req);
857 return true;
861 * TEST_TGS_REQ
863 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
864 * certain expectations, like that the canonicalize bit is set (this
865 * test is to force that handling) and that if an enterprise name was
866 * requested, that it was sent.
870 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)
872 size_t used;
873 torture_assert_int_equal(test_context->tctx,
874 decode_TGS_REQ(send_buf->data, send_buf->length,
875 &test_context->tgs_req, &used),
876 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
877 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
878 torture_assert_int_equal(test_context->tctx, test_context->tgs_req.pvno, 5,
879 "Got wrong as_req->pvno");
881 if (test_context->test_data->enterprise
882 && test_context->test_data->s4u2self == false
883 && test_context->test_data->spn_is_upn) {
884 torture_assert_int_equal(test_context->tctx,
885 test_context->tgs_req.req_body.kdc_options.canonicalize,
886 true,
887 "krb5 libs unexpectedly"
888 " did not set canonicalize!");
889 } else {
890 torture_assert_int_equal(test_context->tctx,
891 test_context->tgs_req.req_body.kdc_options.canonicalize,
892 false,
893 "krb5 libs unexpectedly"
894 " set canonicalize!");
897 if (test_context->test_data->enterprise) {
898 torture_assert_int_equal(test_context->tctx,
899 test_context->tgs_req.req_body.sname->name_type,
900 KRB5_NT_ENTERPRISE_PRINCIPAL,
901 "Mismatch in name type between request and expected request, expected KRB5_NT_ENTERPRISE_PRINCIPAL");
902 torture_assert_str_equal(test_context->tctx,
903 test_context->tgs_req.req_body.realm,
904 test_context->test_data->real_realm,
905 "Mismatch in realm between request and expected request");
907 } else if (test_context->test_data->spn_is_upn && test_context->test_data->upn && test_context->test_data->canonicalize) {
908 torture_assert_int_equal(test_context->tctx,
909 test_context->tgs_req.req_body.sname->name_type,
910 KRB5_NT_PRINCIPAL,
911 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
912 torture_assert_str_equal(test_context->tctx,
913 test_context->tgs_req.req_body.realm,
914 test_context->test_data->real_realm,
915 "Mismatch in realm between request and expected request");
917 } else if (test_context->test_data->spn_is_upn
918 && test_context->test_data->as_req_spn
919 && test_context->test_data->canonicalize == false) {
920 torture_assert_int_equal(test_context->tctx,
921 test_context->tgs_req.req_body.sname->name_type,
922 KRB5_NT_SRV_HST,
923 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_HST");
924 torture_assert_str_equal(test_context->tctx,
925 test_context->tgs_req.req_body.realm,
926 test_context->test_data->realm,
927 "Mismatch in realm between request and expected request");
929 } else {
930 torture_assert_int_equal(test_context->tctx,
931 test_context->tgs_req.req_body.sname->name_type,
932 KRB5_NT_PRINCIPAL,
933 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
934 torture_assert_str_equal(test_context->tctx,
935 test_context->tgs_req.req_body.realm,
936 test_context->test_data->realm,
937 "Mismatch in realm between request and expected request");
941 *modified_send_buf = *send_buf;
943 return true;
947 * TEST_TGS_REQ - RECV
949 * Confirm that the reply TGS-REP packet for krb5_mk_req_exact(), for
950 * the actual target service.
954 static bool torture_krb5_post_recv_tgs_req_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
956 KRB_ERROR error;
957 size_t used;
959 * If this account did not have a servicePrincipalName, then
960 * we expect a errro packet, not a TGS-REQ
962 if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) {
963 torture_assert_int_equal(test_context->tctx,
964 used, recv_buf->length,
965 "length mismatch");
966 torture_assert_int_equal(test_context->tctx,
967 error.pvno, 5,
968 "Got wrong error.pvno");
969 torture_assert_int_equal(test_context->tctx,
970 error.error_code,
971 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE,
972 "Got wrong error.error_code");
973 } else {
974 torture_assert_int_equal(test_context->tctx,
975 decode_TGS_REP(recv_buf->data, recv_buf->length,
976 &test_context->tgs_rep, &used),
978 "decode_TGS_REP failed");
979 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
980 "length mismatch");
981 torture_assert_int_equal(test_context->tctx,
982 test_context->tgs_rep.pvno, 5,
983 "Got wrong as_rep->pvno");
984 torture_assert_int_equal(test_context->tctx,
985 test_context->tgs_rep.ticket.tkt_vno, 5,
986 "Got wrong as_rep->ticket.tkt_vno");
987 torture_assert(test_context->tctx,
988 test_context->tgs_rep.ticket.enc_part.kvno,
989 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
990 torture_assert_str_equal(test_context->tctx,
991 test_context->tgs_rep.ticket.realm,
992 test_context->test_data->real_realm,
993 "Mismatch in realm between ticket response and expected upper case REALM");
994 torture_assert_int_equal(test_context->tctx,
995 test_context->tgs_req.req_body.sname->name_type,
996 test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response");
997 torture_assert_int_equal(test_context->tctx,
998 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
999 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
1000 free_TGS_REP(&test_context->tgs_rep);
1002 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
1003 free_TGS_REQ(&test_context->tgs_req);
1004 test_context->test_stage = TEST_DONE;
1005 return true;
1009 * TEST_TGS_REQ_KRBTGT
1012 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
1013 * for the krbtgt/realm principal meets certain expectations, like
1014 * that the canonicalize bit is not set
1018 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)
1020 size_t used;
1021 torture_assert_int_equal(test_context->tctx,
1022 decode_TGS_REQ(send_buf->data, send_buf->length,
1023 &test_context->tgs_req, &used),
1024 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
1025 torture_assert_int_equal(test_context->tctx,
1026 used, send_buf->length,
1027 "length mismatch");
1028 torture_assert_int_equal(test_context->tctx,
1029 test_context->tgs_req.pvno, 5,
1030 "Got wrong as_req->pvno");
1031 torture_assert_int_equal(test_context->tctx,
1032 test_context->tgs_req.req_body.kdc_options.canonicalize,
1033 false,
1034 "krb5 libs unexpectedly set canonicalize!");
1036 torture_assert_str_equal(test_context->tctx,
1037 test_context->tgs_req.req_body.realm,
1038 test_context->test_data->realm,
1039 "Mismatch in realm between request and expected request");
1041 *modified_send_buf = *send_buf;
1042 test_context->test_stage = TEST_DONE;
1043 return true;
1047 * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST and TEST_TGS_REQ_HOST_SRV_HST
1050 * Confirm that the outgoing TGS-REQ packet from krb5_mk_req_exact()
1051 * for the krbtgt/realm principal meets certain expectations, like
1052 * that the canonicalize bit is not set
1056 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)
1058 size_t used;
1059 torture_assert_int_equal(test_context->tctx,
1060 decode_TGS_REQ(send_buf->data, send_buf->length,
1061 &test_context->tgs_req, &used),
1062 0, "decode_TGS_REQ for TEST_TGS_REQ test failed");
1063 torture_assert_int_equal(test_context->tctx,
1064 used, send_buf->length,
1065 "length mismatch");
1066 torture_assert_int_equal(test_context->tctx,
1067 test_context->tgs_req.pvno, 5,
1068 "Got wrong as_req->pvno");
1069 torture_assert_int_equal(test_context->tctx,
1070 test_context->tgs_req.req_body.sname->name_string.len, 2,
1071 "Mismatch in name between request and expected request, expected krbtgt/realm");
1072 torture_assert_int_equal(test_context->tctx,
1073 test_context->tgs_req.req_body.kdc_options.canonicalize,
1074 true,
1075 "krb5 libs unexpectedly did not set canonicalize!");
1077 if (test_context->test_stage == TEST_TGS_REQ_HOST_SRV_INST) {
1078 torture_assert_int_equal(test_context->tctx,
1079 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_SRV_INST,
1080 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_INST");
1081 torture_assert_str_equal(test_context->tctx,
1082 test_context->tgs_req.req_body.sname->name_string.val[0],
1083 strupper_talloc(test_context, test_context->test_data->krb5_service),
1084 "Mismatch in name between request and expected request, expected service");
1085 torture_assert_str_equal(test_context->tctx,
1086 test_context->tgs_req.req_body.sname->name_string.val[1],
1087 test_context->test_data->krb5_hostname,
1088 "Mismatch in hostname part between request and expected request");
1090 } else if (test_context->test_stage == TEST_TGS_REQ_HOST_SRV_HST) {
1092 torture_assert_int_equal(test_context->tctx,
1093 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_SRV_HST,
1094 "Mismatch in name type between request and expected request, expected KRB5_NT_SRV_HST");
1095 torture_assert_str_equal(test_context->tctx,
1096 test_context->tgs_req.req_body.sname->name_string.val[0],
1097 test_context->test_data->krb5_service,
1098 "Mismatch in name between request and expected request, expected service");
1099 torture_assert_str_equal(test_context->tctx,
1100 test_context->tgs_req.req_body.sname->name_string.val[1],
1101 strupper_talloc(test_context, test_context->test_data->krb5_hostname),
1102 "Mismatch in hostname part between request and expected request");
1104 } else {
1105 torture_assert_int_equal(test_context->tctx,
1106 test_context->tgs_req.req_body.sname->name_type, KRB5_NT_PRINCIPAL,
1107 "Mismatch in name type between request and expected request, expected KRB5_NT_PRINCIPAL");
1108 torture_assert_str_equal(test_context->tctx,
1109 test_context->tgs_req.req_body.sname->name_string.val[0],
1110 test_context->test_data->krb5_service,
1111 "Mismatch in name between request and expected request, expected service");
1112 torture_assert_str_equal(test_context->tctx,
1113 test_context->tgs_req.req_body.sname->name_string.val[1],
1114 test_context->test_data->krb5_hostname,
1115 "Mismatch in hostname part between request and expected request");
1118 torture_assert_str_equal(test_context->tctx,
1119 test_context->tgs_req.req_body.realm,
1120 test_context->test_data->real_realm,
1121 "Mismatch in realm between request and expected request");
1123 *modified_send_buf = *send_buf;
1124 return true;
1128 * TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST - RECV
1130 * Confirm that the reply TGS-REP packet for krb5_mk_req(), for
1131 * the actual target service, as a SPN, not a any other name type.
1135 static bool torture_krb5_post_recv_tgs_req_host_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
1137 size_t used;
1138 torture_assert_int_equal(test_context->tctx,
1139 decode_TGS_REP(recv_buf->data, recv_buf->length,
1140 &test_context->tgs_rep, &used),
1142 "decode_TGS_REP failed");
1143 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
1144 "length mismatch");
1145 torture_assert_int_equal(test_context->tctx,
1146 test_context->tgs_rep.pvno, 5,
1147 "Got wrong as_rep->pvno");
1148 torture_assert_int_equal(test_context->tctx,
1149 test_context->tgs_rep.ticket.tkt_vno, 5,
1150 "Got wrong as_rep->ticket.tkt_vno");
1151 torture_assert(test_context->tctx,
1152 test_context->tgs_rep.ticket.enc_part.kvno,
1153 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
1154 torture_assert_str_equal(test_context->tctx,
1155 test_context->tgs_rep.ticket.realm,
1156 test_context->test_data->real_realm,
1157 "Mismatch in realm between ticket response and expected upper case REALM");
1158 torture_assert_int_equal(test_context->tctx,
1159 test_context->tgs_req.req_body.sname->name_type,
1160 test_context->tgs_rep.ticket.sname.name_type, "Mismatch in name_type between request and ticket response");
1161 torture_assert_int_equal(test_context->tctx,
1162 test_context->tgs_rep.ticket.sname.name_string.len, 2,
1163 "Mismatch in name between request and expected request, expected service/hostname");
1164 torture_assert_str_equal(test_context->tctx,
1165 test_context->tgs_rep.ticket.sname.name_string.val[0],
1166 test_context->tgs_req.req_body.sname->name_string.val[0],
1167 "Mismatch in name between request and expected request, expected service/hostname");
1168 torture_assert_str_equal(test_context->tctx,
1169 test_context->tgs_rep.ticket.sname.name_string.val[1],
1170 test_context->tgs_req.req_body.sname->name_string.val[1],
1171 "Mismatch in name between request and expected request, expected service/hostname");
1173 torture_assert_int_equal(test_context->tctx,
1174 *test_context->tgs_rep.ticket.enc_part.kvno & 0xFFFF0000,
1175 0, "Unexpecedly got a RODC number in the KVNO, should just be principal KVNO");
1176 free_TGS_REP(&test_context->tgs_rep);
1178 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
1179 return true;
1183 * TEST_AS_REQ_SELF - RECV
1185 * Confirm that the reply packet from the KDC meets certain
1186 * expectations as part of TEST_AS_REQ. This uses a packet count to
1187 * work out what packet we are up to in the multiple exchanged
1188 * triggerd by krb5_get_init_creds_password().
1192 static bool torture_krb5_post_recv_as_req_self_test(struct torture_krb5_context *test_context,
1193 const krb5_data *recv_buf)
1195 KRB_ERROR error;
1196 size_t used;
1197 if (test_context->packet_count == 0) {
1198 krb5_error_code k5ret;
1200 * The client libs obtain the salt by attempting to
1201 * authenticate without pre-authentication and getting
1202 * the correct salt with the
1203 * KRB5KDC_ERR_PREAUTH_REQUIRED error. If we are in
1204 * the test (netbios_realm && upn) that deliberatly
1205 * has an incorrect principal, we check we get the
1206 * correct error.
1208 k5ret = decode_KRB_ERROR(recv_buf->data, recv_buf->length,
1209 &error, &used);
1210 if (k5ret != 0) {
1211 AS_REP as_rep;
1212 k5ret = decode_AS_REP(recv_buf->data, recv_buf->length,
1213 &as_rep, &used);
1214 if (k5ret == 0) {
1215 if (torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false
1216 || (test_context->test_data->upn == true)) {
1217 torture_assert(test_context->tctx, false,
1218 "expected to get a KRB_ERROR packet with "
1219 "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
1220 } else {
1221 torture_assert(test_context->tctx, false,
1222 "expected to get a KRB_ERROR packet with "
1223 "KRB5KDC_ERR_PREAUTH_REQUIRED, got valid AS-REP");
1225 } else {
1226 if (torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false
1227 || (test_context->test_data->upn == true)) {
1228 torture_assert(test_context->tctx, false,
1229 "unable to decode as KRB-ERROR or AS-REP, "
1230 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN or KRB5KDC_ERR_PREAUTH_REQUIRED");
1231 } else {
1232 torture_assert(test_context->tctx, false,
1233 "unable to decode as KRB-ERROR or AS-REP, "
1234 "expected to get a KRB_ERROR packet with KRB5KDC_ERR_PREAUTH_REQUIRED");
1238 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
1239 "length mismatch");
1240 torture_assert_int_equal(test_context->tctx, error.pvno, 5,
1241 "Got wrong error.pvno");
1242 if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false) == false
1243 || (test_context->test_data->upn == true))
1244 && error.error_code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE) {
1246 * IGNORE
1248 * This case is because Samba's Heimdal KDC
1249 * checks server and client accounts before
1250 * checking for pre-authentication.
1252 } else {
1253 torture_assert_int_equal(test_context->tctx,
1254 error.error_code,
1255 KRB5KDC_ERR_PREAUTH_REQUIRED - KRB5KDC_ERR_NONE,
1256 "Got wrong error.error_code");
1259 free_KRB_ERROR(&error);
1260 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
1261 && (test_context->packet_count == 1)) {
1263 * The Windows 2012R2 KDC will always respond with
1264 * KRB5KRB_ERR_RESPONSE_TOO_BIG over UDP as the ticket
1265 * won't fit, because of the PAC. (It appears to do
1266 * this always, even if it will). This triggers the
1267 * client to try again over TCP.
1269 torture_assert_int_equal(test_context->tctx,
1270 used, recv_buf->length,
1271 "length mismatch");
1272 torture_assert_int_equal(test_context->tctx,
1273 error.pvno, 5,
1274 "Got wrong error.pvno");
1275 if ((torture_setting_bool(test_context->tctx, "expect_machine_account", false)
1276 && ((test_context->test_data->upn == false)
1277 || (test_context->test_data->as_req_spn &&
1278 test_context->test_data->spn_is_upn)
1279 || (test_context->test_data->enterprise == false &&
1280 test_context->test_data->upn &&
1281 test_context->test_data->spn_is_upn)))) {
1282 torture_assert_int_equal(test_context->tctx,
1283 error.error_code,
1284 KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
1285 "Got wrong error.error_code");
1286 } else {
1287 torture_assert_int_equal(test_context->tctx,
1288 error.error_code,
1289 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN - KRB5KDC_ERR_NONE,
1290 "Got wrong error.error_code");
1292 free_KRB_ERROR(&error);
1293 } else {
1295 * Finally the successful packet.
1297 torture_assert_int_equal(test_context->tctx,
1298 decode_AS_REP(recv_buf->data, recv_buf->length,
1299 &test_context->as_rep, &used), 0,
1300 "decode_AS_REP failed");
1301 torture_assert_int_equal(test_context->tctx, used, recv_buf->length,
1302 "length mismatch");
1303 torture_assert_int_equal(test_context->tctx,
1304 test_context->as_rep.pvno, 5,
1305 "Got wrong as_rep->pvno");
1306 torture_assert_int_equal(test_context->tctx,
1307 test_context->as_rep.ticket.tkt_vno, 5,
1308 "Got wrong as_rep->ticket.tkt_vno");
1309 torture_assert(test_context->tctx,
1310 test_context->as_rep.ticket.enc_part.kvno,
1311 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
1314 * We do not expect an RODC number here in the KVNO,
1315 * as this is a ticket to the user's own account.
1317 torture_assert_int_equal(test_context->tctx,
1318 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
1319 0, "Unexpecedly got a RODC number in the KVNO");
1320 free_AS_REP(&test_context->as_rep);
1322 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
1323 free_AS_REQ(&test_context->as_req);
1324 return true;
1328 * This function is set in torture_krb5_init_context_canon as krb5
1329 * send_and_recv function. This allows us to override what server the
1330 * test is aimed at, and to inspect the packets just before they are
1331 * sent to the network, and before they are processed on the recv
1332 * side.
1334 * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test()
1335 * functions are implement the actual tests.
1337 * When this asserts, the caller will get a spurious 'cannot contact
1338 * any KDC' message.
1341 static krb5_error_code smb_krb5_send_and_recv_func_canon_override(krb5_context context,
1342 void *data, /* struct torture_krb5_context */
1343 krb5_krbhst_info *hi,
1344 time_t timeout,
1345 const krb5_data *send_buf,
1346 krb5_data *recv_buf)
1348 krb5_error_code k5ret;
1349 bool ok = false;
1350 krb5_data modified_send_buf;
1352 struct torture_krb5_context *test_context
1353 = talloc_get_type_abort(data, struct torture_krb5_context);
1355 switch (test_context->test_stage) {
1356 case TEST_DONE:
1357 torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs");
1358 return EINVAL;
1359 case TEST_AS_REQ:
1360 ok = torture_krb5_pre_send_as_req_test(test_context, send_buf,
1361 &modified_send_buf);
1362 break;
1363 case TEST_TGS_REQ_KRBTGT_CANON:
1364 ok = torture_krb5_pre_send_tgs_req_krbtgt_canon_test(test_context, send_buf,
1365 &modified_send_buf);
1366 break;
1367 case TEST_TGS_REQ_CANON:
1368 ok = torture_krb5_pre_send_tgs_req_canon_test(test_context, send_buf,
1369 &modified_send_buf);
1370 break;
1371 case TEST_SELF_TRUST_TGS_REQ:
1372 ok = torture_krb5_pre_send_self_trust_tgs_req_test(test_context, send_buf,
1373 &modified_send_buf);
1374 break;
1375 case TEST_TGS_REQ:
1376 ok = torture_krb5_pre_send_tgs_req_test(test_context, send_buf,
1377 &modified_send_buf);
1378 break;
1379 case TEST_TGS_REQ_KRBTGT:
1380 ok = torture_krb5_pre_send_tgs_req_krbtgt_test(test_context, send_buf,
1381 &modified_send_buf);
1382 break;
1383 case TEST_TGS_REQ_HOST:
1384 case TEST_TGS_REQ_HOST_SRV_INST:
1385 case TEST_TGS_REQ_HOST_SRV_HST:
1386 ok = torture_krb5_pre_send_tgs_req_host_test(test_context, send_buf,
1387 &modified_send_buf);
1388 break;
1389 case TEST_AS_REQ_SELF:
1390 ok = torture_krb5_pre_send_as_req_test(test_context, send_buf,
1391 &modified_send_buf);
1392 break;
1394 if (ok == false) {
1395 return EINVAL;
1398 k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server,
1399 hi, timeout, &modified_send_buf,
1400 recv_buf);
1401 if (k5ret != 0) {
1402 return k5ret;
1405 switch (test_context->test_stage) {
1406 case TEST_DONE:
1407 torture_warning(test_context->tctx, "Unexpected outgoing packet from krb5 libs");
1408 return EINVAL;
1409 case TEST_AS_REQ:
1410 ok = torture_krb5_post_recv_as_req_test(test_context, recv_buf);
1411 break;
1412 case TEST_TGS_REQ_KRBTGT_CANON:
1413 ok = torture_krb5_post_recv_tgs_req_krbtgt_canon_test(test_context, recv_buf);
1414 break;
1415 case TEST_TGS_REQ_CANON:
1416 ok = torture_krb5_post_recv_tgs_req_canon_test(test_context, recv_buf);
1417 break;
1418 case TEST_SELF_TRUST_TGS_REQ:
1419 ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf);
1420 break;
1421 case TEST_TGS_REQ:
1422 ok = torture_krb5_post_recv_tgs_req_test(test_context, recv_buf);
1423 break;
1424 case TEST_TGS_REQ_KRBTGT:
1425 ok = torture_krb5_post_recv_self_trust_tgs_req_test(test_context, recv_buf);
1426 break;
1427 case TEST_TGS_REQ_HOST:
1428 case TEST_TGS_REQ_HOST_SRV_INST:
1429 case TEST_TGS_REQ_HOST_SRV_HST:
1430 ok = torture_krb5_post_recv_tgs_req_host_test(test_context, recv_buf);
1431 break;
1432 case TEST_AS_REQ_SELF:
1433 ok = torture_krb5_post_recv_as_req_self_test(test_context, recv_buf);
1434 break;
1436 if (ok == false) {
1437 KRB_ERROR error;
1438 size_t used;
1439 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);
1440 if (decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0) {
1441 torture_warning(test_context->tctx,
1442 "STAGE: %d Unexpectedly got a KRB-ERROR packet "
1443 "with error code %d (%s)",
1444 test_context->test_stage,
1445 error.error_code,
1446 error_message(error.error_code + KRB5KDC_ERR_NONE));
1447 free_KRB_ERROR(&error);
1449 return EINVAL;
1452 test_context->packet_count++;
1454 return k5ret;
1457 static int test_context_destructor(struct torture_krb5_context *test_context)
1459 freeaddrinfo(test_context->server);
1460 return 0;
1464 static bool torture_krb5_init_context_canon(struct torture_context *tctx,
1465 struct test_data *test_data,
1466 struct torture_krb5_context **torture_krb5_context)
1468 const char *host = torture_setting_string(tctx, "host", NULL);
1469 krb5_error_code k5ret;
1470 bool ok;
1472 struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context);
1473 torture_assert(tctx, test_context != NULL, "Failed to allocate");
1475 test_context->test_data = test_data;
1476 test_context->tctx = tctx;
1478 k5ret = smb_krb5_init_context(test_context, tctx->lp_ctx, &test_context->smb_krb5_context);
1479 torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
1481 ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST);
1482 torture_assert(tctx, ok, "Failed to parse target server");
1484 talloc_set_destructor(test_context, test_context_destructor);
1486 set_sockaddr_port(test_context->server->ai_addr, 88);
1488 k5ret = krb5_set_send_to_kdc_func(test_context->smb_krb5_context->krb5_context,
1489 smb_krb5_send_and_recv_func_canon_override,
1490 test_context);
1491 torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed");
1492 *torture_krb5_context = test_context;
1493 return true;
1497 static bool torture_krb5_as_req_canon(struct torture_context *tctx, const void *tcase_data)
1499 krb5_error_code k5ret;
1500 krb5_get_init_creds_opt *krb_options = NULL;
1501 struct test_data *test_data = talloc_get_type_abort(tcase_data, struct test_data);
1502 krb5_principal principal;
1503 krb5_principal krbtgt_other;
1504 krb5_principal expected_principal;
1505 const char *principal_string = NULL;
1506 char *krbtgt_other_string;
1507 int principal_flags;
1508 const char *expected_principal_string = NULL;
1509 char *expected_unparse_principal_string;
1510 int expected_principal_flags;
1511 char *got_principal_string;
1512 char *assertion_message;
1513 const char *password = cli_credentials_get_password(
1514 popt_get_cmdline_credentials());
1515 krb5_context k5_context;
1516 struct torture_krb5_context *test_context;
1517 bool ok;
1518 krb5_creds my_creds;
1519 krb5_creds *server_creds;
1520 krb5_ccache ccache;
1521 krb5_auth_context auth_context;
1522 char *cc_name;
1523 krb5_data in_data, enc_ticket;
1524 krb5_get_creds_opt opt;
1526 const char *spn = NULL;
1527 const char *spn_real_realm = NULL;
1528 const char *upn = torture_setting_string(tctx, "krb5-upn", "");
1529 test_data->krb5_service = torture_setting_string(tctx, "krb5-service", "host");
1530 test_data->krb5_hostname = torture_setting_string(tctx, "krb5-hostname", "");
1533 * If we have not passed a UPN on the command line,
1534 * then skip the UPN tests.
1536 if (test_data->upn && upn[0] == '\0') {
1537 torture_skip(tctx, "This test needs a UPN specified as --option=torture:krb5-upn=user@example.com to run");
1541 * If we have not passed a SPN on the command line,
1542 * then skip the SPN tests.
1544 if (test_data->as_req_spn && test_data->krb5_hostname[0] == '\0') {
1545 torture_skip(tctx, "This test needs a hostname specified as --option=torture:krb5-hostname=hostname.example.com and optinally --option=torture:krb5-service=service (defaults to host) to run");
1548 if (test_data->removedollar &&
1549 !torture_setting_bool(tctx, "run_removedollar_test", false))
1551 torture_skip(tctx, "--option=torture:run_removedollar_test=true not specified");
1554 if (test_data->netbios_realm) {
1555 test_data->realm = test_data->real_domain;
1556 } else {
1557 test_data->realm = test_data->real_realm;
1560 if (test_data->upn) {
1561 char *p;
1562 test_data->username = talloc_strdup(test_data, upn);
1563 p = strchr(test_data->username, '@');
1564 if (p) {
1565 *p = '\0';
1566 p++;
1569 * Test the UPN behaviour carefully. We can
1570 * test in two different modes, depending on
1571 * what UPN has been set up for us.
1573 * If the UPN is in our realm, then we do all the tests with this name also.
1575 * If the UPN is not in our realm, then we
1576 * expect the tests that replace the realm to
1577 * fail (as it won't match)
1579 if (strcasecmp(p, test_data->real_realm) != 0) {
1580 test_data->other_upn_suffix = true;
1581 } else {
1582 test_data->other_upn_suffix = false;
1586 * This lets us test the combination of the UPN prefix
1587 * with a valid domain, without adding even more
1588 * combinations
1590 if (test_data->netbios_realm == false) {
1591 test_data->realm = p;
1595 ok = torture_krb5_init_context_canon(tctx, test_data, &test_context);
1596 torture_assert(tctx, ok, "torture_krb5_init_context failed");
1597 k5_context = test_context->smb_krb5_context->krb5_context;
1599 if (test_data->upper_realm) {
1600 test_data->realm = strupper_talloc(test_data, test_data->realm);
1601 } else {
1602 test_data->realm = strlower_talloc(test_data, test_data->realm);
1604 if (test_data->upper_username) {
1605 test_data->username = strupper_talloc(test_data, test_data->username);
1606 } else {
1607 test_data->username = talloc_strdup(test_data, test_data->username);
1610 if (test_data->removedollar) {
1611 char *p;
1613 p = strchr_m(test_data->username, '$');
1614 torture_assert(tctx, p != NULL, talloc_asprintf(tctx,
1615 "username[%s] contains no '$'\n",
1616 test_data->username));
1617 *p = '\0';
1620 spn = talloc_asprintf(test_data, "%s/%s@%s",
1621 test_data->krb5_service,
1622 test_data->krb5_hostname,
1623 test_data->realm);
1625 spn_real_realm = talloc_asprintf(test_data, "%s/%s@%s",
1626 test_data->krb5_service,
1627 test_data->krb5_hostname,
1628 test_data->real_realm);
1630 if (test_data->as_req_spn) {
1631 if (test_data->enterprise) {
1632 torture_skip(tctx,
1633 "This test combination "
1634 "is skipped intentionally");
1636 principal_string = spn;
1637 } else {
1638 principal_string = talloc_asprintf(test_data,
1639 "%s@%s",
1640 test_data->username,
1641 test_data->realm);
1645 test_data->spn_is_upn
1646 = (strcasecmp(upn, spn) == 0);
1649 * If we are set to canonicalize, we get back the fixed UPPER
1650 * case realm, and the real username (ie matching LDAP
1651 * samAccountName)
1653 * Otherwise, if we are set to enterprise, we
1654 * get back the whole principal as-sent
1656 * Finally, if we are not set to canonicalize, we get back the
1657 * fixed UPPER case realm, but the as-sent username
1659 if (test_data->as_req_spn && !test_data->spn_is_upn) {
1660 expected_principal_string = spn;
1661 } else if (test_data->canonicalize) {
1662 expected_principal_string = talloc_asprintf(test_data,
1663 "%s@%s",
1664 test_data->real_username,
1665 test_data->real_realm);
1666 } else if (test_data->enterprise) {
1667 expected_principal_string = principal_string;
1668 } else if (test_data->as_req_spn && test_data->spn_is_upn) {
1669 expected_principal_string = spn_real_realm;
1670 } else {
1671 expected_principal_string = talloc_asprintf(test_data,
1672 "%s@%s",
1673 test_data->username,
1674 test_data->real_realm);
1677 if (test_data->enterprise) {
1678 principal_flags = KRB5_PRINCIPAL_PARSE_ENTERPRISE;
1679 } else {
1680 if (test_data->upn && test_data->other_upn_suffix) {
1681 torture_skip(tctx, "UPN test for UPN with other UPN suffix only runs with enterprise principals");
1683 principal_flags = 0;
1686 if (test_data->canonicalize) {
1687 expected_principal_flags = 0;
1688 } else {
1689 expected_principal_flags = principal_flags;
1692 torture_assert_int_equal(tctx,
1693 krb5_parse_name_flags(k5_context,
1694 principal_string,
1695 principal_flags,
1696 &principal),
1697 0, "krb5_parse_name_flags failed");
1698 torture_assert_int_equal(tctx,
1699 krb5_parse_name_flags(k5_context,
1700 expected_principal_string,
1701 expected_principal_flags,
1702 &expected_principal),
1703 0, "krb5_parse_name_flags failed");
1705 if (test_data->as_req_spn) {
1706 if (test_data->upn) {
1707 krb5_principal_set_type(k5_context,
1708 principal,
1709 KRB5_NT_PRINCIPAL);
1710 krb5_principal_set_type(k5_context,
1711 expected_principal,
1712 KRB5_NT_PRINCIPAL);
1713 } else {
1714 krb5_principal_set_type(k5_context,
1715 principal,
1716 KRB5_NT_SRV_HST);
1717 krb5_principal_set_type(k5_context,
1718 expected_principal,
1719 KRB5_NT_SRV_HST);
1723 torture_assert_int_equal(tctx,
1724 krb5_unparse_name(k5_context,
1725 expected_principal,
1726 &expected_unparse_principal_string),
1727 0, "krb5_unparse_name failed");
1729 * Prepare a AS-REQ and run the TEST_AS_REQ tests
1733 test_context->test_stage = TEST_AS_REQ;
1734 test_context->packet_count = 0;
1737 * Set the canonicalize flag if this test requires it
1739 torture_assert_int_equal(tctx,
1740 krb5_get_init_creds_opt_alloc(k5_context, &krb_options),
1741 0, "krb5_get_init_creds_opt_alloc failed");
1743 torture_assert_int_equal(tctx,
1744 krb5_get_init_creds_opt_set_canonicalize(k5_context,
1745 krb_options,
1746 test_data->canonicalize),
1747 0, "krb5_get_init_creds_opt_set_canonicalize failed");
1749 torture_assert_int_equal(tctx,
1750 krb5_get_init_creds_opt_set_win2k(k5_context,
1751 krb_options,
1752 test_data->win2k),
1753 0, "krb5_get_init_creds_opt_set_win2k failed");
1755 k5ret = krb5_get_init_creds_password(k5_context, &my_creds, principal,
1756 password, NULL, NULL, 0,
1757 NULL, krb_options);
1759 if (test_data->netbios_realm && test_data->upn) {
1760 torture_assert_int_equal(tctx, k5ret,
1761 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN,
1762 "Got wrong error_code from krb5_get_init_creds_password");
1763 /* We can't proceed with more checks */
1764 return true;
1765 } else if (test_context->test_data->as_req_spn
1766 && !test_context->test_data->spn_is_upn) {
1767 torture_assert_int_equal(tctx, k5ret,
1768 KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN,
1769 "Got wrong error_code from "
1770 "krb5_get_init_creds_password");
1771 /* We can't proceed with more checks */
1772 return true;
1773 } else {
1774 assertion_message = talloc_asprintf(tctx,
1775 "krb5_get_init_creds_password for %s failed: %s",
1776 principal_string,
1777 smb_get_krb5_error_message(k5_context, k5ret, tctx));
1778 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
1781 torture_assert(tctx,
1782 test_context->packet_count > 1,
1783 "Expected krb5_get_init_creds_password to send more packets");
1786 * Assert that the reply was with the correct type of
1787 * principal, depending on the flags we set
1789 if (test_data->canonicalize == false && test_data->enterprise) {
1790 torture_assert_int_equal(tctx,
1791 krb5_principal_get_type(k5_context,
1792 my_creds.client),
1793 KRB5_NT_ENTERPRISE_PRINCIPAL,
1794 "smb_krb5_init_context gave incorrect client->name.name_type");
1795 } else if (test_data->canonicalize == false && test_data->as_req_spn) {
1796 torture_assert_int_equal(tctx,
1797 krb5_principal_get_type(k5_context,
1798 my_creds.client),
1799 KRB5_NT_SRV_HST,
1800 "smb_krb5_init_context gave incorrect client->name.name_type");
1801 } else {
1802 torture_assert_int_equal(tctx,
1803 krb5_principal_get_type(k5_context,
1804 my_creds.client),
1805 KRB5_NT_PRINCIPAL,
1806 "smb_krb5_init_context gave incorrect client->name.name_type");
1809 torture_assert_int_equal(tctx,
1810 krb5_unparse_name(k5_context,
1811 my_creds.client, &got_principal_string), 0,
1812 "krb5_unparse_name failed");
1814 assertion_message = talloc_asprintf(tctx,
1815 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
1816 got_principal_string, expected_principal_string);
1817 krb5_free_unparsed_name(k5_context, got_principal_string);
1819 torture_assert(tctx, krb5_principal_compare(k5_context,
1820 my_creds.client, expected_principal),
1821 assertion_message);
1824 torture_assert_int_equal(tctx,
1825 krb5_principal_get_type(k5_context,
1826 my_creds.server), KRB5_NT_SRV_INST,
1827 "smb_krb5_init_context gave incorrect server->name.name_type");
1829 torture_assert_int_equal(tctx,
1830 krb5_principal_get_num_comp(k5_context,
1831 my_creds.server), 2,
1832 "smb_krb5_init_context gave incorrect number of components in my_creds.server->name");
1834 torture_assert_str_equal(tctx,
1835 krb5_principal_get_comp_string(k5_context,
1836 my_creds.server, 0),
1837 "krbtgt",
1838 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[0]");
1840 if (test_data->canonicalize || test_data->enterprise) {
1841 torture_assert_str_equal(tctx,
1842 krb5_principal_get_comp_string(k5_context,
1843 my_creds.server, 1),
1844 test_data->real_realm,
1846 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]");
1847 } else {
1848 torture_assert_str_equal(tctx,
1849 krb5_principal_get_comp_string(k5_context,
1850 my_creds.server, 1),
1851 test_data->realm,
1853 "smb_krb5_init_context gave incorrect my_creds.server->name.name_string[1]");
1855 torture_assert_str_equal(tctx,
1856 krb5_principal_get_realm(k5_context,
1857 my_creds.server),
1858 test_data->real_realm,
1859 "smb_krb5_init_context gave incorrect my_creds.server->realm");
1861 /* Store the result of the 'kinit' above into a memory ccache */
1862 cc_name = talloc_asprintf(tctx, "MEMORY:%s", test_data->test_name);
1863 torture_assert_int_equal(tctx, krb5_cc_resolve(k5_context, cc_name,
1864 &ccache),
1865 0, "krb5_cc_resolve failed");
1867 torture_assert_int_equal(tctx, krb5_cc_initialize(k5_context,
1868 ccache, my_creds.client),
1869 0, "krb5_cc_initialize failed");
1871 torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context,
1872 ccache, &my_creds),
1873 0, "krb5_cc_store_cred failed");
1876 * Prepare a TGS-REQ and run the TEST_TGS_REQ_KRBTGT_CANON tests
1878 * This tests krb5_get_creds behaviour, which allows us to set
1879 * the KRB5_GC_CANONICALIZE option against the krbtgt/ principal
1882 krbtgt_other_string = talloc_asprintf(test_data, "krbtgt/%s@%s", test_data->real_domain, test_data->real_realm);
1883 torture_assert_int_equal(tctx,
1884 krb5_make_principal(k5_context, &krbtgt_other,
1885 test_data->real_realm, "krbtgt",
1886 test_data->real_domain, NULL),
1887 0, "krb5_make_principal failed");
1889 test_context->test_stage = TEST_TGS_REQ_KRBTGT_CANON;
1890 test_context->packet_count = 0;
1892 torture_assert_int_equal(tctx,
1893 krb5_get_creds_opt_alloc(k5_context, &opt),
1894 0, "krb5_get_creds_opt_alloc");
1896 krb5_get_creds_opt_add_options(k5_context,
1897 opt,
1898 KRB5_GC_CANONICALIZE);
1900 krb5_get_creds_opt_add_options(k5_context,
1901 opt,
1902 KRB5_GC_NO_STORE);
1904 /* Confirm if we can get a ticket krbtgt/realm that we got back with the initial kinit */
1905 k5ret = krb5_get_creds(k5_context, opt, ccache, krbtgt_other, &server_creds);
1907 if (test_data->canonicalize == false && test_data->enterprise == false
1908 && test_data->netbios_realm && test_data->upper_realm) {
1910 * In these situations, the code above does store a
1911 * principal in the credentials cache matching what
1912 * krb5_get_creds() needs, so the test succeds, with no packets.
1915 assertion_message = talloc_asprintf(tctx,
1916 "krb5_get_creds for %s failed with: %s",
1917 krbtgt_other_string,
1918 smb_get_krb5_error_message(k5_context, k5ret,
1919 tctx));
1921 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
1922 torture_assert_int_equal(tctx,
1923 test_context->packet_count,
1924 0, "Expected krb5_get_creds not to send packets");
1925 } else if (test_data->canonicalize == false && test_data->enterprise == false
1926 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
1927 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
1928 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
1929 } else {
1932 * In these situations, the code above does not store a
1933 * principal in the credentials cache matching what
1934 * krb5_get_creds() needs without talking to the KDC, so the
1935 * test fails with looping detected because when we set
1936 * canonicalize we confuse the client libs.
1939 assertion_message = talloc_asprintf(tctx,
1940 "krb5_get_creds for %s should have failed with looping detected: %s",
1941 krbtgt_other_string,
1942 smb_get_krb5_error_message(k5_context, k5ret,
1943 tctx));
1945 torture_assert_int_equal(tctx, k5ret, KRB5_GET_IN_TKT_LOOP, assertion_message);
1946 torture_assert_int_equal(tctx,
1947 test_context->packet_count,
1948 2, "Expected krb5_get_creds to send packets");
1952 * Prepare a TGS-REQ and run the TEST_TGS_REQ_CANON tests
1954 * This tests krb5_get_creds behaviour, which allows us to set
1955 * the KRB5_GC_CANONICALIZE option
1958 test_context->test_stage = TEST_TGS_REQ_CANON;
1959 test_context->packet_count = 0;
1961 torture_assert_int_equal(tctx,
1962 krb5_get_creds_opt_alloc(k5_context, &opt),
1963 0, "krb5_get_creds_opt_alloc");
1965 krb5_get_creds_opt_add_options(k5_context,
1966 opt,
1967 KRB5_GC_CANONICALIZE);
1969 krb5_get_creds_opt_add_options(k5_context,
1970 opt,
1971 KRB5_GC_NO_STORE);
1973 if (test_data->s4u2self) {
1974 torture_assert_int_equal(tctx,
1975 krb5_get_creds_opt_set_impersonate(k5_context,
1976 opt,
1977 principal),
1978 0, "krb5_get_creds_opt_set_impersonate failed");
1981 /* Confirm if we can get a ticket to our own name */
1982 k5ret = krb5_get_creds(k5_context, opt, ccache, principal, &server_creds);
1985 * In these situations, the code above does not store a
1986 * principal in the credentials cache matching what
1987 * krb5_get_creds() needs, so the test fails.
1990 if (test_data->canonicalize == false && test_data->enterprise == false
1991 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
1992 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
1993 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
1994 } else {
1995 assertion_message = talloc_asprintf(tctx,
1996 "krb5_get_creds for %s failed: %s",
1997 principal_string,
1998 smb_get_krb5_error_message(k5_context, k5ret,
1999 tctx));
2002 * Only machine accounts (strictly, accounts with a
2003 * servicePrincipalName) can expect this test to succeed
2005 if (torture_setting_bool(tctx, "expect_machine_account", false)
2006 && (test_data->enterprise
2007 || test_data->spn_is_upn
2008 || test_data->upn == false)) {
2009 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2010 torture_assert_int_equal(tctx, krb5_cc_store_cred(k5_context,
2011 ccache, server_creds),
2012 0, "krb5_cc_store_cred failed");
2014 torture_assert_int_equal(tctx,
2015 krb5_free_creds(k5_context,
2016 server_creds),
2017 0, "krb5_free_cred_contents failed");
2019 } else {
2020 torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN,
2021 assertion_message);
2024 torture_assert_int_equal(tctx,
2025 test_context->packet_count,
2026 1, "Expected krb5_get_creds to send packets");
2030 * Confirm gettting a ticket to pass to the server, running
2031 * either the TEST_TGS_REQ or TEST_SELF_TRUST_TGS_REQ stage.
2033 * This triggers the client to attempt to get a
2034 * cross-realm ticket between the alternate names of
2035 * the server, and we need to confirm that behaviour.
2040 * This tries to guess when the krb5 libs will ask for a
2041 * cross-realm ticket, and when they will just ask the KDC
2042 * directly.
2044 if (test_context->test_data->canonicalize == false
2045 || test_context->test_data->enterprise
2046 || (test_context->test_data->spn_is_upn && test_context->test_data->upn)
2047 || (test_context->test_data->upper_realm
2048 && test_context->test_data->netbios_realm == false)) {
2049 test_context->test_stage = TEST_TGS_REQ;
2050 } else {
2051 test_context->test_stage = TEST_SELF_TRUST_TGS_REQ;
2054 test_context->packet_count = 0;
2055 torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context),
2056 0, "krb5_auth_con_init failed");
2058 in_data.length = 0;
2059 k5ret = krb5_mk_req_exact(k5_context,
2060 &auth_context,
2061 AP_OPTS_USE_SUBKEY,
2062 principal,
2063 &in_data, ccache,
2064 &enc_ticket);
2065 assertion_message = talloc_asprintf(tctx,
2066 "krb5_mk_req_exact for %s failed: %s",
2067 principal_string,
2068 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2071 * Only machine accounts (strictly, accounts with a
2072 * servicePrincipalName) can expect this test to succeed
2074 if (torture_setting_bool(tctx, "expect_machine_account", false)
2075 && (test_data->enterprise ||
2076 (test_context->test_data->as_req_spn
2077 || test_context->test_data->spn_is_upn)
2078 || test_data->upn == false)) {
2079 DATA_BLOB client_to_server;
2080 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2081 client_to_server = data_blob_const(enc_ticket.data, enc_ticket.length);
2083 /* This is very weird */
2084 if (test_data->canonicalize == false
2085 && test_context->test_data->as_req_spn
2086 && test_context->test_data->spn_is_upn
2087 && test_context->test_data->s4u2self) {
2089 torture_assert(tctx,
2090 test_accept_ticket(tctx,
2091 popt_get_cmdline_credentials(),
2092 spn_real_realm,
2093 client_to_server),
2094 "test_accept_ticket failed - failed to accept the ticket we just created");
2095 } else if (test_data->canonicalize == true
2096 && test_context->test_data->as_req_spn
2097 && test_context->test_data->spn_is_upn
2098 && test_context->test_data->s4u2self) {
2100 torture_assert(tctx,
2101 test_accept_ticket(tctx,
2102 popt_get_cmdline_credentials(),
2103 spn,
2104 client_to_server),
2105 "test_accept_ticket failed - failed to accept the ticket we just created");
2106 } else if (test_data->canonicalize == true
2107 && test_data->enterprise == false
2108 && test_context->test_data->upn
2109 && test_context->test_data->spn_is_upn
2110 && test_context->test_data->s4u2self) {
2112 torture_assert(tctx,
2113 test_accept_ticket(tctx,
2114 popt_get_cmdline_credentials(),
2115 principal_string,
2116 client_to_server),
2117 "test_accept_ticket failed - failed to accept the ticket we just created");
2118 } else if (test_data->canonicalize == false
2119 && test_data->enterprise == false
2120 && test_context->test_data->upn
2121 && test_context->test_data->spn_is_upn
2122 && test_context->test_data->s4u2self) {
2124 const char *accept_expected_principal_string
2125 = talloc_asprintf(test_data,
2126 "%s@%s",
2127 test_data->username,
2128 test_data->real_realm);
2130 torture_assert(tctx,
2131 test_accept_ticket(tctx,
2132 popt_get_cmdline_credentials(),
2133 accept_expected_principal_string,
2134 client_to_server),
2135 "test_accept_ticket failed - failed to accept the ticket we just created");
2136 } else {
2138 torture_assert(tctx,
2139 test_accept_ticket(tctx,
2140 popt_get_cmdline_credentials(),
2141 expected_unparse_principal_string,
2142 client_to_server),
2143 "test_accept_ticket failed - failed to accept the ticket we just created");
2145 krb5_data_free(&enc_ticket);
2146 } else {
2147 torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN,
2148 assertion_message);
2152 * Only in these cases would the above code have needed to
2153 * send packets to the network
2155 if (test_data->canonicalize == false && test_data->enterprise == false
2156 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
2157 torture_assert(tctx,
2158 test_context->packet_count > 0,
2159 "Expected krb5_mk_req_exact to send packets");
2163 * Confirm gettting a ticket to pass to the server, running
2164 * the TEST_TGS_REQ_HOST, TEST_TGS_REQ_HOST_SRV_INST, TEST_TGS_REQ_HOST_SRV_HST stage
2166 * This triggers the client to attempt to get a
2167 * cross-realm ticket between the alternate names of
2168 * the server, and we need to confirm that behaviour.
2172 if (*test_data->krb5_service && *test_data->krb5_hostname) {
2173 bool implied_canonicalize;
2174 krb5_principal host_principal_srv_inst;
2176 * This tries to guess when the krb5 libs will ask for a
2177 * cross-realm ticket, and when they will just ask the KDC
2178 * directly.
2180 test_context->test_stage = TEST_TGS_REQ_HOST;
2181 test_context->packet_count = 0;
2182 torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context),
2183 0, "krb5_auth_con_init failed");
2185 in_data.length = 0;
2186 k5ret = krb5_mk_req(k5_context,
2187 &auth_context,
2189 test_data->krb5_service,
2190 test_data->krb5_hostname,
2191 &in_data, ccache,
2192 &enc_ticket);
2194 implied_canonicalize = test_data->canonicalize;
2195 if (test_data->spn_is_upn && (test_data->upn || test_data->as_req_spn)) {
2196 implied_canonicalize = true;
2198 if (test_data->enterprise) {
2199 implied_canonicalize = true;
2202 if (implied_canonicalize == false
2203 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
2204 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
2205 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2206 } else if (test_data->spn_is_upn
2207 && test_data->canonicalize == false
2208 && test_data->enterprise == false
2209 && test_data->upper_realm == false
2210 && test_data->upper_username == true
2211 && test_data->upn) {
2212 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
2213 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2214 } else {
2215 assertion_message = talloc_asprintf(tctx,
2216 "krb5_mk_req for %s/%s failed: %s",
2217 test_data->krb5_service,
2218 test_data->krb5_hostname,
2219 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2221 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2223 if (test_data->spn_is_upn == false) {
2225 * Only in these cases would the above
2226 * code have needed to send packets to
2227 * the network
2229 torture_assert(tctx,
2230 test_context->packet_count > 0,
2231 "Expected krb5_get_creds to send packets");
2236 test_context->test_stage = TEST_TGS_REQ_HOST_SRV_INST;
2237 test_context->packet_count = 0;
2239 torture_assert_int_equal(tctx,
2240 krb5_make_principal(k5_context, &host_principal_srv_inst,
2241 test_data->real_realm,
2242 strupper_talloc(tctx, test_data->krb5_service),
2243 test_data->krb5_hostname,
2244 NULL),
2245 0, "krb5_make_principal failed");
2247 krb5_principal_set_type(k5_context, host_principal_srv_inst, KRB5_NT_SRV_INST);
2249 torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context),
2250 0, "krb5_auth_con_init failed");
2252 in_data.length = 0;
2253 k5ret = krb5_mk_req_exact(k5_context,
2254 &auth_context,
2256 host_principal_srv_inst,
2257 &in_data, ccache,
2258 &enc_ticket);
2259 krb5_free_principal(k5_context, host_principal_srv_inst);
2260 if (test_data->canonicalize == false && test_data->enterprise == false
2261 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
2262 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
2263 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2264 } else {
2265 assertion_message = talloc_asprintf(tctx,
2266 "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s",
2267 test_data->krb5_service,
2268 test_data->krb5_hostname,
2269 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2271 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2273 * Only in these cases would the above code have needed to
2274 * send packets to the network
2276 torture_assert(tctx,
2277 test_context->packet_count > 0,
2278 "Expected krb5_get_creds to send packets");
2282 test_context->test_stage = TEST_TGS_REQ_HOST_SRV_HST;
2283 test_context->packet_count = 0;
2285 torture_assert_int_equal(tctx,
2286 krb5_make_principal(k5_context, &host_principal_srv_inst,
2287 test_data->real_realm,
2288 test_data->krb5_service,
2289 strupper_talloc(tctx, test_data->krb5_hostname),
2290 NULL),
2291 0, "krb5_make_principal failed");
2293 krb5_principal_set_type(k5_context, host_principal_srv_inst, KRB5_NT_SRV_HST);
2295 torture_assert_int_equal(tctx, krb5_auth_con_init(k5_context, &auth_context),
2296 0, "krb5_auth_con_init failed");
2298 in_data.length = 0;
2299 k5ret = krb5_mk_req_exact(k5_context,
2300 &auth_context,
2302 host_principal_srv_inst,
2303 &in_data, ccache,
2304 &enc_ticket);
2305 krb5_free_principal(k5_context, host_principal_srv_inst);
2306 if (test_data->canonicalize == false && test_data->enterprise == false
2307 && (test_data->upper_realm == false || test_data->netbios_realm == true)) {
2308 torture_assert_int_equal(tctx, k5ret, KRB5_CC_NOTFOUND,
2309 "krb5_get_creds should have failed with KRB5_CC_NOTFOUND");
2310 } else {
2311 assertion_message = talloc_asprintf(tctx,
2312 "krb5_mk_req for %s/%s KRB5_NT_SRV_INST failed: %s",
2313 test_data->krb5_service,
2314 test_data->krb5_hostname,
2315 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2317 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2319 * Only in these cases would the above code have needed to
2320 * send packets to the network
2322 torture_assert(tctx,
2323 test_context->packet_count > 0,
2324 "Expected krb5_get_creds to send packets");
2329 * Confirm gettting a ticket for the same krbtgt/realm that we
2330 * got back with the initial ticket, running the
2331 * TEST_TGS_REQ_KRBTGT stage.
2335 test_context->test_stage = TEST_TGS_REQ_KRBTGT;
2336 test_context->packet_count = 0;
2338 in_data.length = 0;
2339 k5ret = krb5_mk_req_exact(k5_context,
2340 &auth_context,
2342 my_creds.server,
2343 &in_data, ccache,
2344 &enc_ticket);
2346 assertion_message = talloc_asprintf(tctx,
2347 "krb5_mk_req_exact for %s failed: %s",
2348 principal_string,
2349 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2350 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2353 * Confirm gettting a ticket for our own principal that we
2354 * got back with the initial ticket, running the
2355 * TEST_AS_REQ_SELF stage.
2358 test_context->test_stage = TEST_AS_REQ_SELF;
2359 test_context->packet_count = 0;
2361 k5ret = krb5_get_init_creds_password(k5_context, &my_creds, principal,
2362 password, NULL, NULL, 0,
2363 principal_string, krb_options);
2365 if (torture_setting_bool(test_context->tctx, "expect_machine_account", false)
2366 && (test_data->upn == false || (test_data->enterprise == false && test_data->upn == true && test_data->spn_is_upn))) {
2367 assertion_message = talloc_asprintf(tctx,
2368 "krb5_get_init_creds_password for %s failed: %s",
2369 principal_string,
2370 smb_get_krb5_error_message(k5_context, k5ret, tctx));
2371 torture_assert_int_equal(tctx, k5ret, 0, assertion_message);
2372 torture_assert(tctx,
2373 test_context->packet_count >= 2,
2374 "Expected krb5_get_init_creds_password to send more packets");
2376 } else {
2377 assertion_message = talloc_asprintf(tctx,
2378 "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);
2379 torture_assert_int_equal(tctx, k5ret,
2380 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN,
2381 assertion_message);
2382 torture_assert(tctx,
2383 test_context->packet_count >= 1,
2384 "Expected krb5_get_init_creds_password to send more packets");
2386 /* We can't proceed with more checks */
2387 return true;
2391 * Assert that the reply was with the correct type of
2392 * principal, depending on the flags we set
2394 if (test_data->as_req_spn && test_data->spn_is_upn && test_data->canonicalize == false) {
2395 torture_assert_int_equal(tctx,
2396 krb5_principal_get_type(k5_context,
2397 my_creds.client),
2398 KRB5_NT_SRV_HST,
2399 "smb_krb5_init_context gave incorrect client->name.name_type");
2400 torture_assert_int_equal(tctx,
2401 krb5_principal_get_type(k5_context,
2402 my_creds.server),
2403 KRB5_NT_SRV_HST,
2404 "smb_krb5_init_context gave incorrect server->name.name_type");
2405 } else if (test_data->canonicalize == false && test_data->enterprise) {
2406 torture_assert_int_equal(tctx,
2407 krb5_principal_get_type(k5_context,
2408 my_creds.client),
2409 KRB5_NT_ENTERPRISE_PRINCIPAL,
2410 "smb_krb5_init_context gave incorrect client->name.name_type");
2411 torture_assert_int_equal(tctx,
2412 krb5_principal_get_type(k5_context,
2413 my_creds.server),
2414 KRB5_NT_ENTERPRISE_PRINCIPAL,
2415 "smb_krb5_init_context gave incorrect server->name.name_type");
2416 } else {
2417 torture_assert_int_equal(tctx,
2418 krb5_principal_get_type(k5_context,
2419 my_creds.client),
2420 KRB5_NT_PRINCIPAL,
2421 "smb_krb5_init_context gave incorrect client->name.name_type");
2422 torture_assert_int_equal(tctx,
2423 krb5_principal_get_type(k5_context,
2424 my_creds.server),
2425 KRB5_NT_PRINCIPAL,
2426 "smb_krb5_init_context gave incorrect server->name.name_type");
2429 torture_assert_int_equal(tctx,
2430 krb5_unparse_name(k5_context,
2431 my_creds.client, &got_principal_string), 0,
2432 "krb5_unparse_name failed");
2434 assertion_message = talloc_asprintf(tctx,
2435 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
2436 got_principal_string, expected_principal_string);
2437 krb5_free_unparsed_name(k5_context, got_principal_string);
2439 torture_assert(tctx, krb5_principal_compare(k5_context,
2440 my_creds.client, expected_principal),
2441 assertion_message);
2443 torture_assert_int_equal(tctx,
2444 krb5_unparse_name(k5_context,
2445 my_creds.client, &got_principal_string), 0,
2446 "krb5_unparse_name failed");
2448 assertion_message = talloc_asprintf(tctx,
2449 "krb5_get_init_creds_password returned a different server principal %s to what was expected %s",
2450 got_principal_string, expected_principal_string);
2451 krb5_free_unparsed_name(k5_context, got_principal_string);
2453 torture_assert(tctx, krb5_principal_compare(k5_context,
2454 my_creds.server, expected_principal),
2455 assertion_message);
2457 krb5_free_principal(k5_context, principal);
2458 krb5_get_init_creds_opt_free(k5_context, krb_options);
2460 torture_assert_int_equal(tctx, krb5_free_cred_contents(k5_context, &my_creds),
2461 0, "krb5_free_cred_contents failed");
2463 return true;
2466 struct torture_suite *torture_krb5_canon(TALLOC_CTX *mem_ctx)
2468 unsigned int i;
2469 struct torture_suite *suite = torture_suite_create(mem_ctx, "canon");
2470 suite->description = talloc_strdup(suite, "Kerberos Canonicalisation tests");
2472 for (i = 0; i < TEST_ALL; i++) {
2473 char *name = talloc_asprintf(suite, "%s.%s.%s.%s.%s.%s.%s.%s",
2474 (i & TEST_CANONICALIZE) ? "canon" : "no-canon",
2475 (i & TEST_ENTERPRISE) ? "enterprise" : "no-enterprise",
2476 (i & TEST_UPPER_REALM) ? "uc-realm" : "lc-realm",
2477 (i & TEST_UPPER_USERNAME) ? "uc-user" : "lc-user",
2478 (i & TEST_NETBIOS_REALM) ? "netbios-realm" : "krb5-realm",
2479 (i & TEST_WIN2K) ? "win2k" : "no-win2k",
2480 (i & TEST_UPN) ? "upn" :
2481 ((i & TEST_AS_REQ_SPN) ? "spn" :
2482 ((i & TEST_REMOVEDOLLAR) ? "removedollar" : "samaccountname")),
2483 (i & TEST_S4U2SELF) ? "s4u2self" : "normal");
2484 struct torture_suite *sub_suite = torture_suite_create(mem_ctx, name);
2486 struct test_data *test_data = talloc_zero(suite, struct test_data);
2487 if (i & TEST_UPN) {
2488 if (i & TEST_AS_REQ_SPN) {
2489 continue;
2492 if ((i & TEST_UPN) || (i & TEST_AS_REQ_SPN)) {
2493 if (i & TEST_REMOVEDOLLAR) {
2494 continue;
2498 test_data->test_name = name;
2499 test_data->real_realm
2500 = strupper_talloc(test_data,
2501 cli_credentials_get_realm(
2502 popt_get_cmdline_credentials()));
2503 test_data->real_domain = cli_credentials_get_domain(
2504 popt_get_cmdline_credentials());
2505 test_data->username = cli_credentials_get_username(
2506 popt_get_cmdline_credentials());
2507 test_data->real_username = cli_credentials_get_username(
2508 popt_get_cmdline_credentials());
2509 test_data->canonicalize = (i & TEST_CANONICALIZE) != 0;
2510 test_data->enterprise = (i & TEST_ENTERPRISE) != 0;
2511 test_data->upper_realm = (i & TEST_UPPER_REALM) != 0;
2512 test_data->upper_username = (i & TEST_UPPER_USERNAME) != 0;
2513 test_data->netbios_realm = (i & TEST_NETBIOS_REALM) != 0;
2514 test_data->win2k = (i & TEST_WIN2K) != 0;
2515 test_data->upn = (i & TEST_UPN) != 0;
2516 test_data->s4u2self = (i & TEST_S4U2SELF) != 0;
2517 test_data->removedollar = (i & TEST_REMOVEDOLLAR) != 0;
2518 test_data->as_req_spn = (i & TEST_AS_REQ_SPN) != 0;
2519 torture_suite_add_simple_tcase_const(sub_suite, name, torture_krb5_as_req_canon,
2520 test_data);
2521 torture_suite_add_suite(suite, sub_suite);
2524 return suite;