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;
65 const char *krb5_service;
66 const char *krb5_hostname;
70 * Confirm that the outgoing packet meets certain expectations. This
71 * should be extended to further assert the correct and expected
72 * behaviour of the krb5 libs, so we know what we are sending to the
77 static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, krb5_data *send_buf)
80 switch (test_context->test)
82 case TORTURE_KRB5_TEST_PLAIN:
83 case TORTURE_KRB5_TEST_PAC_REQUEST:
84 case TORTURE_KRB5_TEST_BREAK_PW:
85 case TORTURE_KRB5_TEST_CLOCK_SKEW:
86 case TORTURE_KRB5_TEST_AES:
87 case TORTURE_KRB5_TEST_RC4:
88 case TORTURE_KRB5_TEST_AES_RC4:
89 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
90 torture_assert_int_equal(test_context->tctx,
91 decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0,
92 "decode_AS_REQ failed");
93 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
94 torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno");
96 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
97 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
100 krb5_error_code k5ret;
101 krb5_data modified_send_buf;
102 torture_assert_int_equal(test_context->tctx,
103 decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0,
104 "decode_AS_REQ failed");
105 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
106 torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno");
108 /* Only change it if configured with --option=torture:krb5-hostname= */
109 if (test_context->krb5_hostname[0] == '\0') {
113 mod_as_req = test_context->as_req;
115 torture_assert_int_equal(test_context->tctx,
116 mod_as_req.req_body.sname->name_string.len, 2,
117 "Sending wrong mod_as_req.req_body->sname.name_string.len");
118 free(mod_as_req.req_body.sname->name_string.val[0]);
119 free(mod_as_req.req_body.sname->name_string.val[1]);
120 mod_as_req.req_body.sname->name_string.val[0] = strdup(test_context->krb5_service);
121 mod_as_req.req_body.sname->name_string.val[1] = strdup(test_context->krb5_hostname);
123 ASN1_MALLOC_ENCODE(AS_REQ, modified_send_buf.data, modified_send_buf.length,
124 &mod_as_req, &used, k5ret);
125 torture_assert_int_equal(test_context->tctx,
127 "encode_AS_REQ failed");
129 *send_buf = modified_send_buf;
136 static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
137 const krb5_data *reply,
138 krb5_error_code expected_error,
141 KRB_ERROR error = { 0 };
145 rc = decode_KRB_ERROR(reply->data, reply->length, &error, &used);
146 torture_assert_int_equal(test_context->tctx,
148 "decode_AS_REP failed");
150 torture_assert_int_equal(test_context->tctx,
153 torture_assert_int_equal(test_context->tctx,
155 "Got wrong error.pvno");
156 torture_assert_int_equal(test_context->tctx,
157 error.error_code, expected_error - KRB5KDC_ERR_NONE,
158 "Got wrong error.error_code");
165 torture_assert(test_context->tctx,
166 error.e_data != NULL,
167 "No e-data returned");
169 rc = decode_METHOD_DATA(error.e_data->data,
170 error.e_data->length,
173 torture_assert_int_equal(test_context->tctx,
175 "Got invalid method data");
177 torture_assert(test_context->tctx,
180 for (i = 0; i < m.len; i++) {
181 if (m.val[i].padata_type == KRB5_PADATA_ENC_TIMESTAMP) {
186 torture_assert(test_context->tctx,
188 "Encrypted timestamp not found");
191 free_KRB_ERROR(&error);
196 static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context,
197 const krb5_data *reply,
198 krb5_enctype expected_enctype)
200 ENCTYPE reply_enctype = { 0 };
204 rc = decode_AS_REP(reply->data,
206 &test_context->as_rep,
208 torture_assert_int_equal(test_context->tctx,
210 "decode_AS_REP failed");
211 torture_assert_int_equal(test_context->tctx,
214 torture_assert_int_equal(test_context->tctx,
215 test_context->as_rep.pvno, 5,
216 "Got wrong as_rep->pvno");
217 torture_assert_int_equal(test_context->tctx,
218 test_context->as_rep.ticket.tkt_vno, 5,
219 "Got wrong as_rep->ticket.tkt_vno");
220 torture_assert(test_context->tctx,
221 test_context->as_rep.ticket.enc_part.kvno,
222 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
224 reply_enctype = test_context->as_rep.enc_part.etype;
226 torture_assert_int_equal(test_context->tctx,
227 reply_enctype, expected_enctype,
228 "Ticket encrypted with invalid algorithm");
234 * Confirm that the incoming packet from the KDC meets certain
235 * expectations. This uses a switch and the packet count to work out
236 * what test we are in, and where in the test we are, so we can assert
237 * on the expected reply packets from the KDC.
241 static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, krb5_data *recv_buf)
247 switch (test_context->test)
249 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
250 case TORTURE_KRB5_TEST_PLAIN:
251 if (test_context->packet_count == 0) {
252 ok = torture_check_krb5_error(test_context,
254 KRB5KDC_ERR_PREAUTH_REQUIRED,
256 torture_assert(test_context->tctx,
258 "torture_check_krb5_error failed");
259 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
260 && (test_context->packet_count == 1)) {
261 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
262 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
263 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
264 "Got wrong error.error_code");
265 free_KRB_ERROR(&error);
267 torture_assert_int_equal(test_context->tctx,
268 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
269 "decode_AS_REP failed");
270 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
271 torture_assert_int_equal(test_context->tctx,
272 test_context->as_rep.pvno, 5,
273 "Got wrong as_rep->pvno");
274 torture_assert_int_equal(test_context->tctx,
275 test_context->as_rep.ticket.tkt_vno, 5,
276 "Got wrong as_rep->ticket.tkt_vno");
277 torture_assert(test_context->tctx,
278 test_context->as_rep.ticket.enc_part.kvno,
279 "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
280 if (test_context->test == TORTURE_KRB5_TEST_PLAIN) {
281 if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
282 torture_assert_int_not_equal(test_context->tctx,
283 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
284 0, "Did not get a RODC number in the KVNO");
286 torture_assert_int_equal(test_context->tctx,
287 *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
288 0, "Unexpecedly got a RODC number in the KVNO");
291 free_AS_REP(&test_context->as_rep);
293 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
294 free_AS_REQ(&test_context->as_req);
298 * Confirm correct error codes when we ask for the PAC. This behaviour is rather odd...
300 case TORTURE_KRB5_TEST_PAC_REQUEST:
301 if (test_context->packet_count == 0) {
302 ok = torture_check_krb5_error(test_context,
304 KRB5KRB_ERR_RESPONSE_TOO_BIG,
306 torture_assert(test_context->tctx,
308 "torture_check_krb5_error failed");
309 } else if (test_context->packet_count == 1) {
310 ok = torture_check_krb5_error(test_context,
312 KRB5KDC_ERR_PREAUTH_REQUIRED,
314 torture_assert(test_context->tctx,
316 "torture_check_krb5_error failed");
317 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
318 && (test_context->packet_count == 2)) {
319 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
320 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
321 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
322 "Got wrong error.error_code");
323 free_KRB_ERROR(&error);
325 torture_assert_int_equal(test_context->tctx,
326 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
327 "decode_AS_REP failed");
328 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
329 torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno");
330 free_AS_REP(&test_context->as_rep);
332 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
333 free_AS_REQ(&test_context->as_req);
337 * Confirm correct error codes when we deliberatly send the wrong password
339 case TORTURE_KRB5_TEST_BREAK_PW:
340 if (test_context->packet_count == 0) {
341 ok = torture_check_krb5_error(test_context,
343 KRB5KDC_ERR_PREAUTH_REQUIRED,
345 torture_assert(test_context->tctx,
347 "torture_check_krb5_error failed");
348 } else if (test_context->packet_count == 1) {
349 ok = torture_check_krb5_error(test_context,
351 KRB5KDC_ERR_PREAUTH_FAILED,
353 torture_assert(test_context->tctx,
355 "torture_check_krb5_error failed");
357 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
358 free_AS_REQ(&test_context->as_req);
362 * Confirm correct error codes when we deliberatly skew the client clock
364 case TORTURE_KRB5_TEST_CLOCK_SKEW:
365 if (test_context->packet_count == 0) {
366 ok = torture_check_krb5_error(test_context,
368 KRB5KDC_ERR_PREAUTH_REQUIRED,
370 torture_assert(test_context->tctx,
372 "torture_check_krb5_error failed");
373 } else if (test_context->packet_count == 1) {
374 ok = torture_check_krb5_error(test_context,
378 torture_assert(test_context->tctx,
380 "torture_check_krb5_error failed");
382 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
383 free_AS_REQ(&test_context->as_req);
385 case TORTURE_KRB5_TEST_AES:
386 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES\n");
388 if (test_context->packet_count == 0) {
389 ok = torture_check_krb5_error(test_context,
391 KRB5KDC_ERR_PREAUTH_REQUIRED,
393 torture_assert(test_context->tctx,
395 "torture_check_krb5_error failed");
396 } else if (krb5_is_krb_error(recv_buf)) {
397 ok = torture_check_krb5_error(test_context,
399 KRB5KRB_ERR_RESPONSE_TOO_BIG,
401 torture_assert(test_context->tctx,
403 "torture_check_krb5_error failed");
405 ok = torture_check_krb5_as_rep_enctype(test_context,
407 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
408 torture_assert(test_context->tctx,
410 "torture_check_krb5_as_rep_enctype failed");
413 torture_assert(test_context->tctx,
414 test_context->packet_count < 3,
417 case TORTURE_KRB5_TEST_RC4:
418 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_RC4\n");
420 if (test_context->packet_count == 0) {
421 ok = torture_check_krb5_error(test_context,
423 KRB5KDC_ERR_PREAUTH_REQUIRED,
425 torture_assert(test_context->tctx,
427 "torture_check_krb5_error failed");
428 } else if (krb5_is_krb_error(recv_buf)) {
429 ok = torture_check_krb5_error(test_context,
431 KRB5KRB_ERR_RESPONSE_TOO_BIG,
433 torture_assert(test_context->tctx,
435 "torture_check_krb5_error failed");
437 ok = torture_check_krb5_as_rep_enctype(test_context,
439 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5);
440 torture_assert(test_context->tctx,
442 "torture_check_krb5_as_rep_enctype failed");
445 torture_assert(test_context->tctx,
446 test_context->packet_count < 3,
449 case TORTURE_KRB5_TEST_AES_RC4:
450 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES_RC4\n");
452 if (test_context->packet_count == 0) {
453 ok = torture_check_krb5_error(test_context,
455 KRB5KDC_ERR_PREAUTH_REQUIRED,
457 torture_assert(test_context->tctx,
459 "torture_check_krb5_error failed");
460 } else if (krb5_is_krb_error(recv_buf)) {
461 ok = torture_check_krb5_error(test_context,
463 KRB5KRB_ERR_RESPONSE_TOO_BIG,
465 torture_assert(test_context->tctx,
467 "torture_check_krb5_error failed");
469 ok = torture_check_krb5_as_rep_enctype(test_context,
471 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
472 torture_assert(test_context->tctx,
474 "torture_check_krb5_as_rep_enctype failed");
477 torture_assert(test_context->tctx,
478 test_context->packet_count < 3,
481 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
482 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
485 krb5_error_code k5ret;
486 krb5_data modified_recv_buf;
487 if (test_context->packet_count == 0) {
488 ok = torture_check_krb5_error(test_context,
490 KRB5KDC_ERR_PREAUTH_REQUIRED,
492 torture_assert(test_context->tctx,
494 "torture_check_krb5_error failed");
495 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
496 && (test_context->packet_count == 1)) {
497 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
498 torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
499 torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
500 "Got wrong error.error_code");
501 free_KRB_ERROR(&error);
503 torture_assert_int_equal(test_context->tctx,
504 decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
505 "decode_AS_REP failed");
506 torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
507 torture_assert_int_equal(test_context->tctx,
508 test_context->as_rep.pvno, 5,
509 "Got wrong as_rep->pvno");
510 torture_assert_int_equal(test_context->tctx,
511 test_context->as_rep.ticket.tkt_vno, 5,
512 "Got wrong as_rep->ticket.tkt_vno");
513 torture_assert_int_equal(test_context->tctx,
514 test_context->as_rep.ticket.sname.name_string.len, 2,
515 "Got wrong as_rep->ticket.sname.name_string.len");
516 free(test_context->as_rep.ticket.sname.name_string.val[0]);
517 free(test_context->as_rep.ticket.sname.name_string.val[1]);
518 test_context->as_rep.ticket.sname.name_string.val[0] = strdup("bad");
519 test_context->as_rep.ticket.sname.name_string.val[1] = strdup("mallory");
521 mod_as_rep = test_context->as_rep;
523 ASN1_MALLOC_ENCODE(AS_REP, modified_recv_buf.data, modified_recv_buf.length,
524 &mod_as_rep, &used, k5ret);
525 torture_assert_int_equal(test_context->tctx,
527 "encode_AS_REQ failed");
528 krb5_data_free(recv_buf);
530 *recv_buf = modified_recv_buf;
531 free_AS_REQ(&test_context->as_req);
533 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
545 * This function is set in torture_krb5_init_context as krb5
546 * send_and_recv function. This allows us to override what server the
547 * test is aimed at, and to inspect the packets just before they are
548 * sent to the network, and before they are processed on the recv
551 * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test()
552 * functions are implement the actual tests.
554 * When this asserts, the caller will get a spurious 'cannot contact
558 static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context,
559 void *data, /* struct torture_krb5_context */
560 krb5_krbhst_info *hi,
562 const krb5_data *send_buf,
565 krb5_error_code k5ret;
567 krb5_data modified_send_buf = *send_buf;
569 struct torture_krb5_context *test_context
570 = talloc_get_type_abort(data, struct torture_krb5_context);
572 ok = torture_krb5_pre_send_test(test_context, &modified_send_buf);
577 k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server,
578 hi, timeout, &modified_send_buf, recv_buf);
582 ok = torture_krb5_post_recv_test(test_context, recv_buf);
587 test_context->packet_count++;
592 static int test_context_destructor(struct torture_krb5_context *test_context)
594 freeaddrinfo(test_context->server);
599 static bool torture_krb5_init_context(struct torture_context *tctx,
600 enum torture_krb5_test test,
601 struct smb_krb5_context **smb_krb5_context)
603 const char *host = torture_setting_string(tctx, "host", NULL);
604 krb5_error_code k5ret;
607 struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context);
608 torture_assert(tctx, test_context != NULL, "Failed to allocate");
610 test_context->test = test;
611 test_context->tctx = tctx;
613 test_context->krb5_service = torture_setting_string(tctx, "krb5-service", "host");
614 test_context->krb5_hostname = torture_setting_string(tctx, "krb5-hostname", "");
616 k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context);
617 torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
619 ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST);
620 torture_assert(tctx, ok, "Failed to parse target server");
622 talloc_set_destructor(test_context, test_context_destructor);
624 set_sockaddr_port(test_context->server->ai_addr, 88);
626 k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
627 smb_krb5_send_and_recv_func_override,
629 torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed");
633 static bool torture_krb5_as_req_creds(struct torture_context *tctx,
634 struct cli_credentials *credentials,
635 enum torture_krb5_test test)
637 krb5_error_code k5ret;
640 krb5_principal principal;
641 struct smb_krb5_context *smb_krb5_context;
642 krb5_context k5_context;
643 enum credentials_obtained obtained;
644 const char *error_string;
645 const char *password = cli_credentials_get_password(credentials);
646 const char *expected_principal_string;
647 krb5_get_init_creds_opt *krb_options = NULL;
649 const char *krb5_service = torture_setting_string(tctx, "krb5-service", "host");
650 const char *krb5_hostname = torture_setting_string(tctx, "krb5-hostname", "");
653 ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
654 torture_assert(tctx, ok, "torture_krb5_init_context failed");
655 k5_context = smb_krb5_context->krb5_context;
657 expected_principal_string
658 = cli_credentials_get_principal(credentials,
661 realm = strupper_talloc(tctx, cli_credentials_get_realm(credentials));
662 k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context,
663 &principal, &obtained, &error_string);
664 torture_assert_int_equal(tctx, k5ret, 0, error_string);
668 case TORTURE_KRB5_TEST_PLAIN:
669 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
670 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
671 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
674 case TORTURE_KRB5_TEST_PAC_REQUEST:
675 torture_assert_int_equal(tctx,
676 krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options),
677 0, "krb5_get_init_creds_opt_alloc failed");
679 torture_assert_int_equal(tctx,
680 krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context, krb_options, true),
681 0, "krb5_get_init_creds_opt_set_pac_request failed");
684 case TORTURE_KRB5_TEST_BREAK_PW:
685 password = "NOT the password";
688 case TORTURE_KRB5_TEST_CLOCK_SKEW:
689 torture_assert_int_equal(tctx,
690 krb5_set_real_time(smb_krb5_context->krb5_context, time(NULL) + 3600, 0),
691 0, "krb5_set_real_time failed");
694 case TORTURE_KRB5_TEST_AES: {
695 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96 };
697 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
699 torture_assert_int_equal(tctx,
701 "krb5_get_init_creds_opt_alloc failed");
703 krb5_get_init_creds_opt_set_etype_list(krb_options,
708 case TORTURE_KRB5_TEST_RC4: {
709 krb5_enctype etype_list[] = { KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
711 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
713 torture_assert_int_equal(tctx,
715 "krb5_get_init_creds_opt_alloc failed");
717 krb5_get_init_creds_opt_set_etype_list(krb_options,
722 case TORTURE_KRB5_TEST_AES_RC4: {
723 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
724 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
726 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
728 torture_assert_int_equal(tctx,
730 "krb5_get_init_creds_opt_alloc failed");
732 krb5_get_init_creds_opt_set_etype_list(krb_options,
740 k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal,
741 password, NULL, NULL, 0,
743 krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
747 case TORTURE_KRB5_TEST_PLAIN:
748 case TORTURE_KRB5_TEST_CHANGE_SERVER_IN:
749 case TORTURE_KRB5_TEST_PAC_REQUEST:
750 case TORTURE_KRB5_TEST_AES:
751 case TORTURE_KRB5_TEST_RC4:
752 case TORTURE_KRB5_TEST_AES_RC4:
754 char *got_principal_string;
755 char *assertion_message;
756 torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
758 torture_assert_int_equal(tctx,
759 krb5_principal_get_type(k5_context,
762 "smb_krb5_init_context gave incorrect client->name.name_type");
764 torture_assert_int_equal(tctx,
765 krb5_unparse_name(k5_context,
767 &got_principal_string), 0,
768 "krb5_unparse_name failed");
770 assertion_message = talloc_asprintf(tctx,
771 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
772 got_principal_string, expected_principal_string);
773 krb5_free_unparsed_name(k5_context, got_principal_string);
775 torture_assert(tctx, krb5_principal_compare(k5_context,
781 torture_assert_str_equal(tctx,
782 my_creds.server->name.name_string.val[0],
784 "Mismatch in name between AS_REP and expected response, expected krbtgt");
785 torture_assert_str_equal(tctx,
786 my_creds.server->name.name_string.val[1],
788 "Mismatch in realm part of krbtgt/ in AS_REP, expected krbtgt/REALM@REALM");
790 torture_assert_str_equal(tctx,
791 my_creds.server->realm,
793 "Mismatch in server realm in AS_REP, expected krbtgt/REALM@REALM");
797 case TORTURE_KRB5_TEST_BREAK_PW:
798 torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed");
801 case TORTURE_KRB5_TEST_CLOCK_SKEW:
802 torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_SKEW, "krb5_get_init_creds_password should have failed");
805 case TORTURE_KRB5_TEST_CHANGE_SERVER_OUT:
806 case TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH:
808 char *got_principal_string;
809 char *assertion_message;
810 torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
812 torture_assert_int_equal(tctx,
813 krb5_principal_get_type(k5_context,
816 "smb_krb5_init_context gave incorrect client->name.name_type");
818 torture_assert_int_equal(tctx,
819 krb5_unparse_name(k5_context,
821 &got_principal_string), 0,
822 "krb5_unparse_name failed");
824 assertion_message = talloc_asprintf(tctx,
825 "krb5_get_init_creds_password returned a different principal %s to what was expected %s",
826 got_principal_string, expected_principal_string);
827 krb5_free_unparsed_name(k5_context, got_principal_string);
829 torture_assert(tctx, krb5_principal_compare(k5_context,
834 if (krb5_hostname[0] == '\0') {
838 torture_assert_str_equal(tctx,
839 my_creds.server->name.name_string.val[0],
841 "Mismatch in name[0] between AS_REP and expected response");
842 torture_assert_str_equal(tctx,
843 my_creds.server->name.name_string.val[1],
845 "Mismatch in name[1] between AS_REP and expected response");
847 torture_assert_str_equal(tctx,
848 my_creds.server->realm,
850 "Mismatch in server realm in AS_REP, expected krbtgt/REALM@REALM");
856 k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds);
857 torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed");
862 static bool torture_krb5_as_req_cmdline(struct torture_context *tctx)
864 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
865 TORTURE_KRB5_TEST_PLAIN);
868 static bool torture_krb5_as_req_pac_request(struct torture_context *tctx)
870 if (torture_setting_bool(tctx, "expect_rodc", false)) {
871 torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users");
873 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
874 TORTURE_KRB5_TEST_PAC_REQUEST);
877 static bool torture_krb5_as_req_break_pw(struct torture_context *tctx)
879 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
880 TORTURE_KRB5_TEST_BREAK_PW);
883 static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx)
885 return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
886 TORTURE_KRB5_TEST_CLOCK_SKEW);
889 static bool torture_krb5_as_req_aes(struct torture_context *tctx)
891 return torture_krb5_as_req_creds(tctx,
892 popt_get_cmdline_credentials(),
893 TORTURE_KRB5_TEST_AES);
896 static bool torture_krb5_as_req_rc4(struct torture_context *tctx)
898 return torture_krb5_as_req_creds(tctx,
899 popt_get_cmdline_credentials(),
900 TORTURE_KRB5_TEST_RC4);
903 static bool torture_krb5_as_req_aes_rc4(struct torture_context *tctx)
905 return torture_krb5_as_req_creds(tctx,
906 popt_get_cmdline_credentials(),
907 TORTURE_KRB5_TEST_AES_RC4);
910 /* Checking for the "Orpheus' Lyre" attack */
911 static bool torture_krb5_as_req_change_server_out(struct torture_context *tctx)
913 return torture_krb5_as_req_creds(tctx,
914 popt_get_cmdline_credentials(),
915 TORTURE_KRB5_TEST_CHANGE_SERVER_OUT);
918 static bool torture_krb5_as_req_change_server_in(struct torture_context *tctx)
920 return torture_krb5_as_req_creds(tctx,
921 popt_get_cmdline_credentials(),
922 TORTURE_KRB5_TEST_CHANGE_SERVER_IN);
925 static bool torture_krb5_as_req_change_server_both(struct torture_context *tctx)
927 return torture_krb5_as_req_creds(tctx,
928 popt_get_cmdline_credentials(),
929 TORTURE_KRB5_TEST_CHANGE_SERVER_BOTH);
932 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
934 struct torture_suite *suite = torture_suite_create(ctx, "krb5");
935 struct torture_suite *kdc_suite = torture_suite_create(suite, "kdc");
936 suite->description = talloc_strdup(suite, "Kerberos tests");
937 kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests");
939 torture_suite_add_simple_test(kdc_suite, "as-req-cmdline",
940 torture_krb5_as_req_cmdline);
942 torture_suite_add_simple_test(kdc_suite, "as-req-pac-request",
943 torture_krb5_as_req_pac_request);
945 torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
946 torture_krb5_as_req_break_pw);
948 torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
949 torture_krb5_as_req_clock_skew);
951 torture_suite_add_simple_test(kdc_suite,
953 torture_krb5_as_req_aes);
955 torture_suite_add_simple_test(kdc_suite,
957 torture_krb5_as_req_rc4);
959 torture_suite_add_simple_test(kdc_suite,
961 torture_krb5_as_req_aes_rc4);
964 * This is in and out of the client.
965 * Out refers to requests, in refers to replies
967 torture_suite_add_simple_test(kdc_suite,
968 "as-req-change-server-in",
969 torture_krb5_as_req_change_server_in);
971 torture_suite_add_simple_test(kdc_suite,
972 "as-req-change-server-out",
973 torture_krb5_as_req_change_server_out);
975 torture_suite_add_simple_test(kdc_suite,
976 "as-req-change-server-both",
977 torture_krb5_as_req_change_server_both);
979 torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
980 torture_suite_add_suite(suite, kdc_suite);
982 torture_register_suite(ctx, suite);