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/winbind/proto.h"
27 #include "torture/krb5/proto.h"
28 #include "auth/credentials/credentials.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "source4/auth/kerberos/kerberos.h"
31 #include "source4/auth/kerberos/kerberos_util.h"
32 #include "lib/util/util_net.h"
34 #define krb5_is_app_tag(dat,tag) \
35 ((dat != NULL) && (dat)->length && \
36 (((((char *)(dat)->data)[0] & ~0x20) == ((tag) | 0x40))))
38 #define krb5_is_krb_error(dat) krb5_is_app_tag(dat, 30)
40 enum torture_krb5_test {
41 TORTURE_KRB5_TEST_PLAIN,
42 TORTURE_KRB5_TEST_PAC_REQUEST,
43 TORTURE_KRB5_TEST_BREAK_PW,
44 TORTURE_KRB5_TEST_CLOCK_SKEW,
45 TORTURE_KRB5_TEST_AES,
46 TORTURE_KRB5_TEST_RC4,
47 TORTURE_KRB5_TEST_AES_RC4,
50 * This is in and out of the client.
51 * Out refers to requests, in refers to replies
53 TORTURE_KRB5_TEST_CHANGE_SERVER_OUT,
54 TORTURE_KRB5_TEST_CHANGE_SERVER_IN,
55 TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH,
58 struct torture_krb5_context {
59 struct torture_context *tctx;
60 struct addrinfo *server;
61 enum torture_krb5_test test;
68 * Confirm that the outgoing packet meets certain expectations. This
69 * should be extended to further assert the correct and expected
70 * behaviour of the krb5 libs, so we know what we are sending to the
75 static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf)
78 switch (test_context->test)
80 case TORTURE_KRB5_TEST_PLAIN:
81 case TORTURE_KRB5_TEST_PAC_REQUEST:
82 case TORTURE_KRB5_TEST_BREAK_PW:
83 case TORTURE_KRB5_TEST_CLOCK_SKEW:
84 case TORTURE_KRB5_TEST_AES:
85 case TORTURE_KRB5_TEST_RC4:
86 case TORTURE_KRB5_TEST_AES_RC4:
87 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
88 torture_assert_int_equal(test_context->tctx,
89 decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0,
90 "decode_AS_REQ failed");
91 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
92 torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno");
94 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
95 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
101 static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
102 const krb5_data *reply,
103 krb5_error_code expected_error,
106 KRB_ERROR error = { 0 };
110 rc = decode_KRB_ERROR(reply->data, reply->length, &error, &used);
111 torture_assert_int_equal(test_context->tctx,
113 "decode_AS_REP failed");
115 torture_assert_int_equal(test_context->tctx,
118 torture_assert_int_equal(test_context->tctx,
120 "Got wrong error.pvno");
121 torture_assert_int_equal(test_context->tctx,
122 error.error_code, expected_error - KRB5KDC_ERR_NONE,
123 "Got wrong error.error_code");
130 torture_assert(test_context->tctx,
131 error.e_data != NULL,
132 "No e-data returned");
134 rc = decode_METHOD_DATA(error.e_data->data,
135 error.e_data->length,
138 torture_assert_int_equal(test_context->tctx,
140 "Got invalid method data");
142 torture_assert(test_context->tctx,
145 for (i = 0; i < m.len; i++) {
146 if (m.val[i].padata_type == KRB5_PADATA_ENC_TIMESTAMP) {
151 torture_assert(test_context->tctx,
153 "Encrypted timestamp not found");
156 free_KRB_ERROR(&error);
161 static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context,
162 const krb5_data *reply,
163 krb5_enctype expected_enctype)
165 ENCTYPE reply_enctype = { 0 };
169 rc = decode_AS_REP(reply->data,
171 &test_context->as_rep,
173 torture_assert_int_equal(test_context->tctx,
175 "decode_AS_REP failed");
176 torture_assert_int_equal(test_context->tctx,
179 torture_assert_int_equal(test_context->tctx,
180 test_context->as_rep.pvno, 5,
181 "Got wrong as_rep->pvno");
182 torture_assert_int_equal(test_context->tctx,
183 test_context->as_rep.ticket.tkt_vno, 5,
184 "Got wrong as_rep->ticket.tkt_vno");
185 torture_assert(test_context->tctx,
186 test_context->as_rep.ticket.enc_part.kvno,
187 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
189 reply_enctype = test_context->as_rep.enc_part.etype;
191 torture_assert_int_equal(test_context->tctx,
192 reply_enctype, expected_enctype,
193 "Ticket encrypted with invalid algorithm");
199 * Confirm that the incoming packet from the KDC meets certain
200 * expectations. This uses a switch and the packet count to work out
201 * what test we are in, and where in the test we are, so we can assert
202 * on the expected reply packets from the KDC.
206 static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, krb5_data *recv_buf)
212 switch (test_context->test)
214 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
215 case TORTURE_KRB5_TEST_PLAIN:
216 if (test_context->packet_count == 0) {
217 ok = torture_check_krb5_error(test_context,
219 KRB5KDC_ERR_PREAUTH_REQUIRED,
221 torture_assert(test_context->tctx,
223 "torture_check_krb5_error failed");
224 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
225 && (test_context->packet_count == 1)) {
226 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
227 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
228 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
229 "Got wrong error.error_code");
230 free_KRB_ERROR(&error);
232 torture_assert_int_equal(test_context->tctx,
233 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
234 "decode_AS_REP failed");
235 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
236 torture_assert_int_equal(test_context->tctx,
237 test_context->as_rep.pvno, 5,
238 "Got wrong as_rep->pvno");
239 torture_assert_int_equal(test_context->tctx,
240 test_context->as_rep.ticket.tkt_vno, 5,
241 "Got wrong as_rep->ticket.tkt_vno");
242 torture_assert(test_context->tctx,
243 test_context->as_rep.ticket.enc_part.kvno,
244 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
245 if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
246 torture_assert_int_not_equal(test_context->tctx,
247 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
248 0, "Did not get a RODC number in the KVNO");
250 torture_assert_int_equal(test_context->tctx,
251 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
252 0, "Unexpecedly got a RODC number in the KVNO");
254 free_AS_REP(&test_context->as_rep);
256 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
257 free_AS_REQ(&test_context->as_req);
261 * Confirm correct error codes when we ask for the PAC. This behaviour is rather odd...
263 case TORTURE_KRB5_TEST_PAC_REQUEST:
264 if (test_context->packet_count == 0) {
265 ok = torture_check_krb5_error(test_context,
267 KRB5KRB_ERR_RESPONSE_TOO_BIG,
269 torture_assert(test_context->tctx,
271 "torture_check_krb5_error failed");
272 } else if (test_context->packet_count == 1) {
273 ok = torture_check_krb5_error(test_context,
275 KRB5KDC_ERR_PREAUTH_REQUIRED,
277 torture_assert(test_context->tctx,
279 "torture_check_krb5_error failed");
280 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
281 && (test_context->packet_count == 2)) {
282 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
283 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
284 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
285 "Got wrong error.error_code");
286 free_KRB_ERROR(&error);
288 torture_assert_int_equal(test_context->tctx,
289 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
290 "decode_AS_REP failed");
291 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
292 torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno");
293 free_AS_REP(&test_context->as_rep);
295 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
296 free_AS_REQ(&test_context->as_req);
300 * Confirm correct error codes when we deliberatly send the wrong password
302 case TORTURE_KRB5_TEST_BREAK_PW:
303 if (test_context->packet_count == 0) {
304 ok = torture_check_krb5_error(test_context,
306 KRB5KDC_ERR_PREAUTH_REQUIRED,
308 torture_assert(test_context->tctx,
310 "torture_check_krb5_error failed");
311 } else if (test_context->packet_count == 1) {
312 ok = torture_check_krb5_error(test_context,
314 KRB5KDC_ERR_PREAUTH_FAILED,
316 torture_assert(test_context->tctx,
318 "torture_check_krb5_error failed");
320 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
321 free_AS_REQ(&test_context->as_req);
325 * Confirm correct error codes when we deliberatly skew the client clock
327 case TORTURE_KRB5_TEST_CLOCK_SKEW:
328 if (test_context->packet_count == 0) {
329 ok = torture_check_krb5_error(test_context,
331 KRB5KDC_ERR_PREAUTH_REQUIRED,
333 torture_assert(test_context->tctx,
335 "torture_check_krb5_error failed");
336 } else if (test_context->packet_count == 1) {
337 ok = torture_check_krb5_error(test_context,
341 torture_assert(test_context->tctx,
343 "torture_check_krb5_error failed");
345 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
346 free_AS_REQ(&test_context->as_req);
348 case TORTURE_KRB5_TEST_AES:
349 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES\n");
351 if (test_context->packet_count == 0) {
352 ok = torture_check_krb5_error(test_context,
354 KRB5KDC_ERR_PREAUTH_REQUIRED,
356 torture_assert(test_context->tctx,
358 "torture_check_krb5_error failed");
359 } else if (krb5_is_krb_error(recv_buf)) {
360 ok = torture_check_krb5_error(test_context,
362 KRB5KRB_ERR_RESPONSE_TOO_BIG,
364 torture_assert(test_context->tctx,
366 "torture_check_krb5_error failed");
368 ok = torture_check_krb5_as_rep_enctype(test_context,
370 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
371 torture_assert(test_context->tctx,
373 "torture_check_krb5_as_rep_enctype failed");
376 torture_assert(test_context->tctx,
377 test_context->packet_count < 3,
380 case TORTURE_KRB5_TEST_RC4:
381 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_RC4\n");
383 if (test_context->packet_count == 0) {
384 ok = torture_check_krb5_error(test_context,
386 KRB5KDC_ERR_PREAUTH_REQUIRED,
388 torture_assert(test_context->tctx,
390 "torture_check_krb5_error failed");
391 } else if (krb5_is_krb_error(recv_buf)) {
392 ok = torture_check_krb5_error(test_context,
394 KRB5KRB_ERR_RESPONSE_TOO_BIG,
396 torture_assert(test_context->tctx,
398 "torture_check_krb5_error failed");
400 ok = torture_check_krb5_as_rep_enctype(test_context,
402 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5);
403 torture_assert(test_context->tctx,
405 "torture_check_krb5_as_rep_enctype failed");
408 torture_assert(test_context->tctx,
409 test_context->packet_count < 3,
412 case TORTURE_KRB5_TEST_AES_RC4:
413 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES_RC4\n");
415 if (test_context->packet_count == 0) {
416 ok = torture_check_krb5_error(test_context,
418 KRB5KDC_ERR_PREAUTH_REQUIRED,
420 torture_assert(test_context->tctx,
422 "torture_check_krb5_error failed");
423 } else if (krb5_is_krb_error(recv_buf)) {
424 ok = torture_check_krb5_error(test_context,
426 KRB5KRB_ERR_RESPONSE_TOO_BIG,
428 torture_assert(test_context->tctx,
430 "torture_check_krb5_error failed");
432 ok = torture_check_krb5_as_rep_enctype(test_context,
434 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
435 torture_assert(test_context->tctx,
437 "torture_check_krb5_as_rep_enctype failed");
440 torture_assert(test_context->tctx,
441 test_context->packet_count < 3,
444 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
445 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
448 krb5_error_code k5ret;
449 krb5_data modified_recv_buf;
450 if (test_context->packet_count == 0) {
451 ok = torture_check_krb5_error(test_context,
453 KRB5KDC_ERR_PREAUTH_REQUIRED,
455 torture_assert(test_context->tctx,
457 "torture_check_krb5_error failed");
458 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
459 && (test_context->packet_count == 1)) {
460 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
461 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
462 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
463 "Got wrong error.error_code");
464 free_KRB_ERROR(&error);
466 torture_assert_int_equal(test_context->tctx,
467 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
468 "decode_AS_REP failed");
469 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
470 torture_assert_int_equal(test_context->tctx,
471 test_context->as_rep.pvno, 5,
472 "Got wrong as_rep->pvno");
473 torture_assert_int_equal(test_context->tctx,
474 test_context->as_rep.ticket.tkt_vno, 5,
475 "Got wrong as_rep->ticket.tkt_vno");
476 torture_assert_int_equal(test_context->tctx,
477 test_context->as_rep.ticket.sname.name_string.len, 2,
478 "Got wrong as_rep->ticket.sname.name_string.len");
479 free(test_context->as_rep.ticket.sname.name_string.val[0]);
480 free(test_context->as_rep.ticket.sname.name_string.val[1]);
481 test_context->as_rep.ticket.sname.name_string.val[0] = strdup("bad");
482 test_context->as_rep.ticket.sname.name_string.val[1] = strdup("mallory");
484 mod_as_rep = test_context->as_rep;
486 ASN1_MALLOC_ENCODE(AS_REP, modified_recv_buf.data, modified_recv_buf.length,
487 &mod_as_rep, &used, k5ret);
488 torture_assert_int_equal(test_context->tctx,
490 "encode_AS_REQ failed");
491 krb5_data_free(recv_buf);
493 *recv_buf = modified_recv_buf;
494 free_AS_REQ(&test_context->as_req);
496 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
508 * This function is set in torture_krb5_init_context as krb5
509 * send_and_recv function. This allows us to override what server the
510 * test is aimed at, and to inspect the packets just before they are
511 * sent to the network, and before they are processed on the recv
514 * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test()
515 * functions are implement the actual tests.
517 * When this asserts, the caller will get a spurious 'cannot contact
521 static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context,
522 void *data, /* struct torture_krb5_context */
523 krb5_krbhst_info *hi,
525 const krb5_data *send_buf,
528 krb5_error_code k5ret;
531 struct torture_krb5_context *test_context
532 = talloc_get_type_abort(data, struct torture_krb5_context);
534 ok = torture_krb5_pre_send_test(test_context, send_buf);
539 k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server,
540 hi, timeout, send_buf, recv_buf);
544 ok = torture_krb5_post_recv_test(test_context, recv_buf);
549 test_context->packet_count++;
554 static int test_context_destructor(struct torture_krb5_context *test_context)
556 freeaddrinfo(test_context->server);
561 static bool torture_krb5_init_context(struct torture_context *tctx,
562 enum torture_krb5_test test,
563 struct smb_krb5_context **smb_krb5_context)
565 const char *host = torture_setting_string(tctx, "host", NULL);
566 krb5_error_code k5ret;
569 struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context);
570 torture_assert(tctx, test_context != NULL, "Failed to allocate");
572 test_context->test = test;
573 test_context->tctx = tctx;
575 k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context);
576 torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
578 ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST);
579 torture_assert(tctx, ok, "Failed to parse target server");
581 talloc_set_destructor(test_context, test_context_destructor);
583 set_sockaddr_port(test_context->server->ai_addr, 88);
585 k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
586 smb_krb5_send_and_recv_func_override,
588 torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed");
592 static bool torture_krb5_as_req_creds(struct torture_context *tctx,
593 struct cli_credentials *credentials,
594 enum torture_krb5_test test)
596 krb5_error_code k5ret;
599 krb5_principal principal;
600 struct smb_krb5_context *smb_krb5_context;
601 krb5_context k5_context;
602 enum credentials_obtained obtained;
603 const char *error_string;
604 const char *password = cli_credentials_get_password(credentials);
605 const char *expected_principal_string;
606 krb5_get_init_creds_opt *krb_options = NULL;
609 ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
610 torture_assert(tctx, ok, "torture_krb5_init_context failed");
611 k5_context = smb_krb5_context->krb5_context;
613 expected_principal_string
614 = cli_credentials_get_principal(credentials,
617 realm = strupper_talloc(tctx, cli_credentials_get_realm(credentials));
618 k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context,
619 &principal, &obtained, &error_string);
620 torture_assert_int_equal(tctx, k5ret, 0, error_string);
624 case TORTURE_KRB5_TEST_PLAIN:
625 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
626 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
627 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
630 case TORTURE_KRB5_TEST_PAC_REQUEST:
631 torture_assert_int_equal(tctx,
632 krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options),
633 0, "krb5_get_init_creds_opt_alloc failed");
635 torture_assert_int_equal(tctx,
636 krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context, krb_options, true),
637 0, "krb5_get_init_creds_opt_set_pac_request failed");
640 case TORTURE_KRB5_TEST_BREAK_PW:
641 password = "NOT the password";
644 case TORTURE_KRB5_TEST_CLOCK_SKEW:
645 torture_assert_int_equal(tctx,
646 krb5_set_real_time(smb_krb5_context->krb5_context, time(NULL) + 3600, 0),
647 0, "krb5_set_real_time failed");
650 case TORTURE_KRB5_TEST_AES: {
651 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96 };
653 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
655 torture_assert_int_equal(tctx,
657 "krb5_get_init_creds_opt_alloc failed");
659 krb5_get_init_creds_opt_set_etype_list(krb_options,
664 case TORTURE_KRB5_TEST_RC4: {
665 krb5_enctype etype_list[] = { KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
667 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
669 torture_assert_int_equal(tctx,
671 "krb5_get_init_creds_opt_alloc failed");
673 krb5_get_init_creds_opt_set_etype_list(krb_options,
678 case TORTURE_KRB5_TEST_AES_RC4: {
679 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
680 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
682 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
684 torture_assert_int_equal(tctx,
686 "krb5_get_init_creds_opt_alloc failed");
688 krb5_get_init_creds_opt_set_etype_list(krb_options,
696 k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal,
697 password, NULL, NULL, 0,
699 krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
703 case TORTURE_KRB5_TEST_PLAIN:
704 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
705 case TORTURE_KRB5_TEST_PAC_REQUEST:
706 case TORTURE_KRB5_TEST_AES:
707 case TORTURE_KRB5_TEST_RC4:
708 case TORTURE_KRB5_TEST_AES_RC4:
710 char *got_principal_string;
711 char *assertion_message;
712 torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
714 torture_assert_int_equal(tctx,
715 krb5_principal_get_type(k5_context,
718 "smb_krb5_init_context gave incorrect client->name.name_type");
720 torture_assert_int_equal(tctx,
721 krb5_unparse_name(k5_context,
723 &got_principal_string), 0,
724 "krb5_unparse_name failed");
726 assertion_message = talloc_asprintf(tctx,
727 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
728 got_principal_string, expected_principal_string);
729 krb5_free_unparsed_name(k5_context, got_principal_string);
731 torture_assert(tctx, krb5_principal_compare(k5_context,
737 torture_assert_str_equal(tctx,
738 my_creds.server->name.name_string.val[0],
740 "Mismatch in name between AS_REP and expected response, expected krbtgt");
741 torture_assert_str_equal(tctx,
742 my_creds.server->name.name_string.val[1],
744 "Mismatch in realm part of krbtgt/ in AS_REP, expected krbtgt/REALM@REALM");
746 torture_assert_str_equal(tctx,
747 my_creds.server->realm,
749 "Mismatch in server realm in AS_REP, expected krbtgt/REALM@REALM");
753 case TORTURE_KRB5_TEST_BREAK_PW:
754 torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed");
757 case TORTURE_KRB5_TEST_CLOCK_SKEW:
758 torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_SKEW, "krb5_get_init_creds_password should have failed");
761 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
762 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
763 torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
767 k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds);
768 torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed");
773 static bool torture_krb5_as_req_cmdline(struct torture_context *tctx)
775 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
776 TORTURE_KRB5_TEST_PLAIN);
779 static bool torture_krb5_as_req_pac_request(struct torture_context *tctx)
781 if (torture_setting_bool(tctx, "expect_rodc", false)) {
782 torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users");
784 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
785 TORTURE_KRB5_TEST_PAC_REQUEST);
788 static bool torture_krb5_as_req_break_pw(struct torture_context *tctx)
790 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
791 TORTURE_KRB5_TEST_BREAK_PW);
794 static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx)
796 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
797 TORTURE_KRB5_TEST_CLOCK_SKEW);
800 static bool torture_krb5_as_req_aes(struct torture_context *tctx)
802 return torture_krb5_as_req_creds(tctx,
803 popt_get_cmdline_credentials(),
804 TORTURE_KRB5_TEST_AES);
807 static bool torture_krb5_as_req_rc4(struct torture_context *tctx)
809 return torture_krb5_as_req_creds(tctx,
810 popt_get_cmdline_credentials(),
811 TORTURE_KRB5_TEST_RC4);
814 static bool torture_krb5_as_req_aes_rc4(struct torture_context *tctx)
816 return torture_krb5_as_req_creds(tctx,
817 popt_get_cmdline_credentials(),
818 TORTURE_KRB5_TEST_AES_RC4);
821 /* Checking for the "Orpheus' Lyre" attack */
822 static bool torture_krb5_as_req_change_server_out(struct torture_context *tctx)
824 return torture_krb5_as_req_creds(tctx,
825 popt_get_cmdline_credentials(),
826 TORTURE_KRB5_TEST_CHANGE_SERVER_OUT);
829 static bool torture_krb5_as_req_change_server_in(struct torture_context *tctx)
831 return torture_krb5_as_req_creds(tctx,
832 popt_get_cmdline_credentials(),
833 TORTURE_KRB5_TEST_CHANGE_SERVER_IN);
836 static bool torture_krb5_as_req_change_server_both(struct torture_context *tctx)
838 return torture_krb5_as_req_creds(tctx,
839 popt_get_cmdline_credentials(),
840 TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH);
843 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
845 struct torture_suite *suite = torture_suite_create(ctx, "krb5");
846 struct torture_suite *kdc_suite = torture_suite_create(suite, "kdc");
847 suite->description = talloc_strdup(suite, "Kerberos tests");
848 kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests");
850 torture_suite_add_simple_test(kdc_suite, "as-req-cmdline",
851 torture_krb5_as_req_cmdline);
853 torture_suite_add_simple_test(kdc_suite, "as-req-pac-request",
854 torture_krb5_as_req_pac_request);
856 torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
857 torture_krb5_as_req_break_pw);
859 torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
860 torture_krb5_as_req_clock_skew);
862 torture_suite_add_simple_test(kdc_suite,
864 torture_krb5_as_req_aes);
866 torture_suite_add_simple_test(kdc_suite,
868 torture_krb5_as_req_rc4);
870 torture_suite_add_simple_test(kdc_suite,
872 torture_krb5_as_req_aes_rc4);
875 * This is in and out of the client.
876 * Out refers to requests, in refers to replies
878 torture_suite_add_simple_test(kdc_suite,
879 "as-req-change-server-in",
880 torture_krb5_as_req_change_server_in);
882 torture_suite_add_simple_test(kdc_suite,
883 "as-req-change-server-out",
884 torture_krb5_as_req_change_server_out);
886 torture_suite_add_simple_test(kdc_suite,
887 "as-req-change-server-both",
888 torture_krb5_as_req_change_server_both);
890 torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
891 torture_suite_add_suite(suite, kdc_suite);
893 torture_register_suite(ctx, suite);