7d5a16702c3a184d9f6332590b27910a57ad9b58
[samba.git] / source4 / torture / krb5 / kdc-heimdal.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Validate the krb5 pac generation routines
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2015
7
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.
12
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.
17
18
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/>.
21 */
22
23 #include "includes.h"
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"
33
34 #define krb5_is_app_tag(dat,tag)                          \
35        ((dat != NULL) && (dat)->length &&                \
36         (((((char *)(dat)->data)[0] & ~0x20) == ((tag) | 0x40))))
37
38 #define krb5_is_krb_error(dat)                krb5_is_app_tag(dat, 30)
39
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,
48 };
49
50 struct torture_krb5_context {
51         struct torture_context *tctx;
52         struct addrinfo *server;
53         enum torture_krb5_test test;
54         int packet_count;
55         AS_REQ as_req;
56         AS_REP as_rep;
57 };
58
59 /*
60  * Confirm that the outgoing packet meets certain expectations.  This
61  * should be extended to further assert the correct and expected
62  * behaviour of the krb5 libs, so we know what we are sending to the
63  * server.
64  *
65  */
66
67 static bool torture_krb5_pre_send_test(struct torture_krb5_context *test_context, const krb5_data *send_buf)
68 {
69         size_t used;
70         switch (test_context->test)
71         {
72         case TORTURE_KRB5_TEST_PLAIN:
73         case TORTURE_KRB5_TEST_PAC_REQUEST:
74         case TORTURE_KRB5_TEST_BREAK_PW:
75         case TORTURE_KRB5_TEST_CLOCK_SKEW:
76         case TORTURE_KRB5_TEST_AES:
77         case TORTURE_KRB5_TEST_RC4:
78         case TORTURE_KRB5_TEST_AES_RC4:
79                 torture_assert_int_equal(test_context->tctx,
80                                          decode_AS_REQ(send_buf->data, send_buf->length, &test_context->as_req, &used), 0,
81                                          "decode_AS_REQ failed");
82                 torture_assert_int_equal(test_context->tctx, used, send_buf->length, "length mismatch");
83                 torture_assert_int_equal(test_context->tctx, test_context->as_req.pvno, 5, "Got wrong as_req->pvno");
84                 break;
85         }
86         return true;
87 }
88
89 static bool torture_check_krb5_error(struct torture_krb5_context *test_context,
90                                      const krb5_data *reply,
91                                      krb5_error_code expected_error,
92                                      bool check_pa_data)
93 {
94         KRB_ERROR error = { 0 };
95         size_t used = 0;
96         int rc;
97
98         rc = decode_KRB_ERROR(reply->data, reply->length, &error, &used);
99         torture_assert_int_equal(test_context->tctx,
100                                  rc, 0,
101                                  "decode_AS_REP failed");
102
103         torture_assert_int_equal(test_context->tctx,
104                                  used, reply->length,
105                                  "length mismatch");
106         torture_assert_int_equal(test_context->tctx,
107                                  error.pvno, 5,
108                                  "Got wrong error.pvno");
109         torture_assert_int_equal(test_context->tctx,
110                                  error.error_code, expected_error - KRB5KDC_ERR_NONE,
111                                  "Got wrong error.error_code");
112
113         if (check_pa_data) {
114                 METHOD_DATA m;
115                 size_t len;
116                 int i;
117                 bool found = false;
118                         torture_assert(test_context->tctx,
119                                        error.e_data != NULL,
120                                        "No e-data returned");
121
122                         rc = decode_METHOD_DATA(error.e_data->data,
123                                                 error.e_data->length,
124                                                 &m,
125                                                 &len);
126                         torture_assert_int_equal(test_context->tctx,
127                                                  rc, 0,
128                                                  "Got invalid method data");
129
130                         torture_assert(test_context->tctx,
131                                        m.len > 0,
132                                        "No PA_DATA given");
133                         for (i = 0; i < m.len; i++) {
134                                 if (m.val[i].padata_type == KRB5_PADATA_ENC_TIMESTAMP) {
135                                         found = true;
136                                         break;
137                                 }
138                         }
139                         torture_assert(test_context->tctx,
140                                        found,
141                                        "Encrypted timestamp not found");
142         }
143
144         free_KRB_ERROR(&error);
145
146         return true;
147 }
148
149 static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context,
150                                               const krb5_data *reply,
151                                               krb5_enctype expected_enctype)
152 {
153         ENCTYPE reply_enctype = { 0 };
154         size_t used = 0;
155         int rc;
156
157         rc = decode_AS_REP(reply->data,
158                            reply->length,
159                            &test_context->as_rep,
160                            &used);
161         torture_assert_int_equal(test_context->tctx,
162                                  rc, 0,
163                                  "decode_AS_REP failed");
164         torture_assert_int_equal(test_context->tctx,
165                                  used, reply->length,
166                                  "length mismatch");
167         torture_assert_int_equal(test_context->tctx,
168                                  test_context->as_rep.pvno, 5,
169                                  "Got wrong as_rep->pvno");
170         torture_assert_int_equal(test_context->tctx,
171                                  test_context->as_rep.ticket.tkt_vno, 5,
172                                  "Got wrong as_rep->ticket.tkt_vno");
173         torture_assert(test_context->tctx,
174                        test_context->as_rep.ticket.enc_part.kvno,
175                        "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
176
177         reply_enctype = test_context->as_rep.enc_part.etype;
178
179         torture_assert_int_equal(test_context->tctx,
180                                  reply_enctype, expected_enctype,
181                                  "Ticket encrypted with invalid algorithm");
182
183         return true;
184 }
185
186 /*
187  * Confirm that the incoming packet from the KDC meets certain
188  * expectations.  This uses a switch and the packet count to work out
189  * what test we are in, and where in the test we are, so we can assert
190  * on the expected reply packets from the KDC.
191  *
192  */
193
194 static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_context, const krb5_data *recv_buf)
195 {
196         KRB_ERROR error;
197         size_t used;
198         bool ok;
199
200         switch (test_context->test)
201         {
202         case TORTURE_KRB5_TEST_PLAIN:
203                 if (test_context->packet_count == 0) {
204                         ok = torture_check_krb5_error(test_context,
205                                                       recv_buf,
206                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
207                                                       false);
208                         torture_assert(test_context->tctx,
209                                        ok,
210                                        "torture_check_krb5_error failed");
211                 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
212                            && (test_context->packet_count == 1)) {
213                         torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
214                         torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
215                         torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
216                                                  "Got wrong error.error_code");
217                         free_KRB_ERROR(&error);
218                 } else {
219                         torture_assert_int_equal(test_context->tctx,
220                                                  decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
221                                                  "decode_AS_REP failed");
222                         torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
223                         torture_assert_int_equal(test_context->tctx,
224                                                  test_context->as_rep.pvno, 5,
225                                                  "Got wrong as_rep->pvno");
226                         torture_assert_int_equal(test_context->tctx,
227                                                  test_context->as_rep.ticket.tkt_vno, 5,
228                                                  "Got wrong as_rep->ticket.tkt_vno");
229                         torture_assert(test_context->tctx,
230                                        test_context->as_rep.ticket.enc_part.kvno,
231                                        "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno");
232                         if (torture_setting_bool(test_context->tctx, "expect_cached_at_rodc", false)) {
233                                 torture_assert_int_not_equal(test_context->tctx,
234                                                              *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
235                                                              0, "Did not get a RODC number in the KVNO");
236                         } else {
237                                 torture_assert_int_equal(test_context->tctx,
238                                                          *test_context->as_rep.ticket.enc_part.kvno & 0xFFFF0000,
239                                                          0, "Unexpecedly got a RODC number in the KVNO");
240                         }
241                         free_AS_REP(&test_context->as_rep);
242                 }
243                 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
244                 free_AS_REQ(&test_context->as_req);
245                 break;
246
247                 /*
248                  * Confirm correct error codes when we ask for the PAC.  This behaviour is rather odd...
249                  */
250         case TORTURE_KRB5_TEST_PAC_REQUEST:
251                 if (test_context->packet_count == 0) {
252                         ok = torture_check_krb5_error(test_context,
253                                                       recv_buf,
254                                                       KRB5KRB_ERR_RESPONSE_TOO_BIG,
255                                                       false);
256                         torture_assert(test_context->tctx,
257                                        ok,
258                                        "torture_check_krb5_error failed");
259                 } else if (test_context->packet_count == 1) {
260                         ok = torture_check_krb5_error(test_context,
261                                                       recv_buf,
262                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
263                                                       false);
264                         torture_assert(test_context->tctx,
265                                        ok,
266                                        "torture_check_krb5_error failed");
267                 } else if ((decode_KRB_ERROR(recv_buf->data, recv_buf->length, &error, &used) == 0)
268                            && (test_context->packet_count == 2)) {
269                         torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
270                         torture_assert_int_equal(test_context->tctx, error.pvno, 5, "Got wrong error.pvno");
271                         torture_assert_int_equal(test_context->tctx, error.error_code, KRB5KRB_ERR_RESPONSE_TOO_BIG - KRB5KDC_ERR_NONE,
272                                                  "Got wrong error.error_code");
273                         free_KRB_ERROR(&error);
274                 } else {
275                         torture_assert_int_equal(test_context->tctx,
276                                                  decode_AS_REP(recv_buf->data, recv_buf->length, &test_context->as_rep, &used), 0,
277                                                  "decode_AS_REP failed");
278                         torture_assert_int_equal(test_context->tctx, used, recv_buf->length, "length mismatch");
279                         torture_assert_int_equal(test_context->tctx, test_context->as_rep.pvno, 5, "Got wrong as_rep->pvno");
280                         free_AS_REP(&test_context->as_rep);
281                 }
282                 torture_assert(test_context->tctx, test_context->packet_count < 3, "too many packets");
283                 free_AS_REQ(&test_context->as_req);
284                 break;
285
286                 /*
287                  * Confirm correct error codes when we deliberatly send the wrong password
288                  */
289         case TORTURE_KRB5_TEST_BREAK_PW:
290                 if (test_context->packet_count == 0) {
291                         ok = torture_check_krb5_error(test_context,
292                                                       recv_buf,
293                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
294                                                       false);
295                         torture_assert(test_context->tctx,
296                                        ok,
297                                        "torture_check_krb5_error failed");
298                 } else if (test_context->packet_count == 1) {
299                         ok = torture_check_krb5_error(test_context,
300                                                       recv_buf,
301                                                       KRB5KDC_ERR_PREAUTH_FAILED,
302                                                       true);
303                         torture_assert(test_context->tctx,
304                                        ok,
305                                        "torture_check_krb5_error failed");
306                 }
307                 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
308                 free_AS_REQ(&test_context->as_req);
309                 break;
310
311                 /*
312                  * Confirm correct error codes when we deliberatly skew the client clock
313                  */
314         case TORTURE_KRB5_TEST_CLOCK_SKEW:
315                 if (test_context->packet_count == 0) {
316                         ok = torture_check_krb5_error(test_context,
317                                                       recv_buf,
318                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
319                                                       false);
320                         torture_assert(test_context->tctx,
321                                        ok,
322                                        "torture_check_krb5_error failed");
323                 } else if (test_context->packet_count == 1) {
324                         ok = torture_check_krb5_error(test_context,
325                                                       recv_buf,
326                                                       KRB5KRB_AP_ERR_SKEW,
327                                                       false);
328                         torture_assert(test_context->tctx,
329                                        ok,
330                                        "torture_check_krb5_error failed");
331                 }
332                 torture_assert(test_context->tctx, test_context->packet_count < 2, "too many packets");
333                 free_AS_REQ(&test_context->as_req);
334                 break;
335         case TORTURE_KRB5_TEST_AES:
336                 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES\n");
337
338                 if (test_context->packet_count == 0) {
339                         ok = torture_check_krb5_error(test_context,
340                                                       recv_buf,
341                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
342                                                       false);
343                         torture_assert(test_context->tctx,
344                                        ok,
345                                        "torture_check_krb5_error failed");
346                 } else if (krb5_is_krb_error(recv_buf)) {
347                         ok = torture_check_krb5_error(test_context,
348                                                       recv_buf,
349                                                       KRB5KRB_ERR_RESPONSE_TOO_BIG,
350                                                       false);
351                         torture_assert(test_context->tctx,
352                                        ok,
353                                        "torture_check_krb5_error failed");
354                 } else {
355                         ok = torture_check_krb5_as_rep_enctype(test_context,
356                                                                recv_buf,
357                                                                KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
358                         torture_assert(test_context->tctx,
359                                        ok,
360                                        "torture_check_krb5_as_rep_enctype failed");
361                 }
362
363                 torture_assert(test_context->tctx,
364                                test_context->packet_count < 3,
365                                "Too many packets");
366                 break;
367         case TORTURE_KRB5_TEST_RC4:
368                 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_RC4\n");
369
370                 if (test_context->packet_count == 0) {
371                         ok = torture_check_krb5_error(test_context,
372                                                       recv_buf,
373                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
374                                                       false);
375                         torture_assert(test_context->tctx,
376                                        ok,
377                                        "torture_check_krb5_error failed");
378                 } else if (krb5_is_krb_error(recv_buf)) {
379                         ok = torture_check_krb5_error(test_context,
380                                                       recv_buf,
381                                                       KRB5KRB_ERR_RESPONSE_TOO_BIG,
382                                                       false);
383                         torture_assert(test_context->tctx,
384                                        ok,
385                                        "torture_check_krb5_error failed");
386                 } else {
387                         ok = torture_check_krb5_as_rep_enctype(test_context,
388                                                                recv_buf,
389                                                                KRB5_ENCTYPE_ARCFOUR_HMAC_MD5);
390                         torture_assert(test_context->tctx,
391                                        ok,
392                                        "torture_check_krb5_as_rep_enctype failed");
393                 }
394
395                 torture_assert(test_context->tctx,
396                                test_context->packet_count < 3,
397                                "Too many packets");
398                 break;
399         case TORTURE_KRB5_TEST_AES_RC4:
400                 torture_comment(test_context->tctx, "TORTURE_KRB5_TEST_AES_RC4\n");
401
402                 if (test_context->packet_count == 0) {
403                         ok = torture_check_krb5_error(test_context,
404                                                       recv_buf,
405                                                       KRB5KDC_ERR_PREAUTH_REQUIRED,
406                                                       false);
407                         torture_assert(test_context->tctx,
408                                        ok,
409                                        "torture_check_krb5_error failed");
410                 } else if (krb5_is_krb_error(recv_buf)) {
411                         ok = torture_check_krb5_error(test_context,
412                                                       recv_buf,
413                                                       KRB5KRB_ERR_RESPONSE_TOO_BIG,
414                                                       false);
415                         torture_assert(test_context->tctx,
416                                        ok,
417                                        "torture_check_krb5_error failed");
418                 } else {
419                         ok = torture_check_krb5_as_rep_enctype(test_context,
420                                                                recv_buf,
421                                                                KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96);
422                         torture_assert(test_context->tctx,
423                                        ok,
424                                        "torture_check_krb5_as_rep_enctype failed");
425                 }
426
427                 torture_assert(test_context->tctx,
428                                test_context->packet_count < 3,
429                                "Too many packets");
430                 break;
431         }
432         return true;
433 }
434
435
436 /*
437  * This function is set in torture_krb5_init_context as krb5
438  * send_and_recv function.  This allows us to override what server the
439  * test is aimed at, and to inspect the packets just before they are
440  * sent to the network, and before they are processed on the recv
441  * side.
442  *
443  * The torture_krb5_pre_send_test() and torture_krb5_post_recv_test()
444  * functions are implement the actual tests.
445  *
446  * When this asserts, the caller will get a spurious 'cannot contact
447  * any KDC' message.
448  *
449  */
450 static krb5_error_code smb_krb5_send_and_recv_func_override(krb5_context context,
451                                                     void *data, /* struct torture_krb5_context */
452                                                     krb5_krbhst_info *hi,
453                                                     time_t timeout,
454                                                     const krb5_data *send_buf,
455                                                     krb5_data *recv_buf)
456 {
457         krb5_error_code k5ret;
458         bool ok;
459
460         struct torture_krb5_context *test_context
461                 = talloc_get_type_abort(data, struct torture_krb5_context);
462
463         ok = torture_krb5_pre_send_test(test_context, send_buf);
464         if (ok == false) {
465                 return EINVAL;
466         }
467
468         k5ret = smb_krb5_send_and_recv_func_forced(context, test_context->server,
469                                                     hi, timeout, send_buf, recv_buf);
470         if (k5ret != 0) {
471                 return k5ret;
472         }
473         ok = torture_krb5_post_recv_test(test_context, recv_buf);
474         if (ok == false) {
475                 return EINVAL;
476         }
477
478         test_context->packet_count++;
479
480         return k5ret;
481 }
482
483 static int test_context_destructor(struct torture_krb5_context *test_context)
484 {
485         freeaddrinfo(test_context->server);
486         return 0;
487 }
488
489
490 static bool torture_krb5_init_context(struct torture_context *tctx,
491                                       enum torture_krb5_test test,
492                                       struct smb_krb5_context **smb_krb5_context)
493 {
494         const char *host = torture_setting_string(tctx, "host", NULL);
495         krb5_error_code k5ret;
496         bool ok;
497
498         struct torture_krb5_context *test_context = talloc_zero(tctx, struct torture_krb5_context);
499         torture_assert(tctx, test_context != NULL, "Failed to allocate");
500
501         test_context->test = test;
502         test_context->tctx = tctx;
503
504         k5ret = smb_krb5_init_context(tctx, tctx->lp_ctx, smb_krb5_context);
505         torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
506
507         ok = interpret_string_addr_internal(&test_context->server, host, AI_NUMERICHOST);
508         torture_assert(tctx, ok, "Failed to parse target server");
509
510         talloc_set_destructor(test_context, test_context_destructor);
511
512         set_sockaddr_port(test_context->server->ai_addr, 88);
513
514         k5ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
515                                           smb_krb5_send_and_recv_func_override,
516                                           test_context);
517         torture_assert_int_equal(tctx, k5ret, 0, "krb5_set_send_to_kdc_func failed");
518         return true;
519 }
520
521 static bool torture_krb5_as_req_creds(struct torture_context *tctx,
522                                       struct cli_credentials *credentials,
523                                       enum torture_krb5_test test)
524 {
525         krb5_error_code k5ret;
526         bool ok;
527         krb5_creds my_creds;
528         krb5_principal principal;
529         struct smb_krb5_context *smb_krb5_context;
530         enum credentials_obtained obtained;
531         const char *error_string;
532         const char *password = cli_credentials_get_password(credentials);
533         krb5_get_init_creds_opt *krb_options = NULL;
534
535         ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
536         torture_assert(tctx, ok, "torture_krb5_init_context failed");
537
538         k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context,
539                                            &principal, &obtained,  &error_string);
540         torture_assert_int_equal(tctx, k5ret, 0, error_string);
541
542         switch (test)
543         {
544         case TORTURE_KRB5_TEST_PLAIN:
545                 break;
546
547         case TORTURE_KRB5_TEST_PAC_REQUEST:
548                 torture_assert_int_equal(tctx,
549                                          krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options),
550                                          0, "krb5_get_init_creds_opt_alloc failed");
551
552                 torture_assert_int_equal(tctx,
553                                          krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context, krb_options, true),
554                                          0, "krb5_get_init_creds_opt_set_pac_request failed");
555                 break;
556
557         case TORTURE_KRB5_TEST_BREAK_PW:
558                 password = "NOT the password";
559                 break;
560
561         case TORTURE_KRB5_TEST_CLOCK_SKEW:
562                 torture_assert_int_equal(tctx,
563                                          krb5_set_real_time(smb_krb5_context->krb5_context, time(NULL) + 3600, 0),
564                                          0, "krb5_set_real_time failed");
565                 break;
566
567         case TORTURE_KRB5_TEST_AES: {
568                 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96 };
569
570                 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
571                                                       &krb_options);
572                 torture_assert_int_equal(tctx,
573                                          k5ret, 0,
574                                          "krb5_get_init_creds_opt_alloc failed");
575
576                 krb5_get_init_creds_opt_set_etype_list(krb_options,
577                                                        etype_list,
578                                                        1);
579                 break;
580         }
581         case TORTURE_KRB5_TEST_RC4: {
582                 krb5_enctype etype_list[] = { KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
583
584                 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
585                                                       &krb_options);
586                 torture_assert_int_equal(tctx,
587                                          k5ret, 0,
588                                          "krb5_get_init_creds_opt_alloc failed");
589
590                 krb5_get_init_creds_opt_set_etype_list(krb_options,
591                                                        etype_list,
592                                                        1);
593                 break;
594         }
595         case TORTURE_KRB5_TEST_AES_RC4: {
596                 krb5_enctype etype_list[] = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
597                                               KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 };
598
599                 k5ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context,
600                                                       &krb_options);
601                 torture_assert_int_equal(tctx,
602                                          k5ret, 0,
603                                          "krb5_get_init_creds_opt_alloc failed");
604
605                 krb5_get_init_creds_opt_set_etype_list(krb_options,
606                                                        etype_list,
607                                                        2);
608                 break;
609         }
610
611         } /* end switch */
612
613         k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal,
614                                              password, NULL, NULL, 0,
615                                              NULL, krb_options);
616         krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
617
618         switch (test)
619         {
620         case TORTURE_KRB5_TEST_PLAIN:
621         case TORTURE_KRB5_TEST_PAC_REQUEST:
622         case TORTURE_KRB5_TEST_AES:
623         case TORTURE_KRB5_TEST_RC4:
624         case TORTURE_KRB5_TEST_AES_RC4:
625                 torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
626                 break;
627
628         case TORTURE_KRB5_TEST_BREAK_PW:
629                 torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed");
630                 return true;
631
632         case TORTURE_KRB5_TEST_CLOCK_SKEW:
633                 torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_SKEW, "krb5_get_init_creds_password should have failed");
634                 return true;
635
636         }
637
638         k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds);
639         torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed");
640
641         return true;
642 }
643
644 static bool torture_krb5_as_req_cmdline(struct torture_context *tctx)
645 {
646         return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
647                         TORTURE_KRB5_TEST_PLAIN);
648 }
649
650 static bool torture_krb5_as_req_pac_request(struct torture_context *tctx)
651 {
652         if (torture_setting_bool(tctx, "expect_rodc", false)) {
653                 torture_skip(tctx, "This test needs further investigation in the RODC case against a Windows DC, in particular with non-cached users");
654         }
655         return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
656                         TORTURE_KRB5_TEST_PAC_REQUEST);
657 }
658
659 static bool torture_krb5_as_req_break_pw(struct torture_context *tctx)
660 {
661         return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
662                         TORTURE_KRB5_TEST_BREAK_PW);
663 }
664
665 static bool torture_krb5_as_req_clock_skew(struct torture_context *tctx)
666 {
667         return torture_krb5_as_req_creds(tctx, popt_get_cmdline_credentials(),
668                         TORTURE_KRB5_TEST_CLOCK_SKEW);
669 }
670
671 static bool torture_krb5_as_req_aes(struct torture_context *tctx)
672 {
673         return torture_krb5_as_req_creds(tctx,
674                                          popt_get_cmdline_credentials(),
675                                          TORTURE_KRB5_TEST_AES);
676 }
677
678 static bool torture_krb5_as_req_rc4(struct torture_context *tctx)
679 {
680         return torture_krb5_as_req_creds(tctx,
681                                          popt_get_cmdline_credentials(),
682                                          TORTURE_KRB5_TEST_RC4);
683 }
684
685 static bool torture_krb5_as_req_aes_rc4(struct torture_context *tctx)
686 {
687         return torture_krb5_as_req_creds(tctx,
688                                          popt_get_cmdline_credentials(),
689                                          TORTURE_KRB5_TEST_AES_RC4);
690 }
691
692 NTSTATUS torture_krb5_init(TALLOC_CTX *ctx)
693 {
694         struct torture_suite *suite = torture_suite_create(ctx, "krb5");
695         struct torture_suite *kdc_suite = torture_suite_create(suite, "kdc");
696         suite->description = talloc_strdup(suite, "Kerberos tests");
697         kdc_suite->description = talloc_strdup(kdc_suite, "Kerberos KDC tests");
698
699         torture_suite_add_simple_test(kdc_suite, "as-req-cmdline",
700                                       torture_krb5_as_req_cmdline);
701
702         torture_suite_add_simple_test(kdc_suite, "as-req-pac-request",
703                                       torture_krb5_as_req_pac_request);
704
705         torture_suite_add_simple_test(kdc_suite, "as-req-break-pw",
706                                       torture_krb5_as_req_break_pw);
707
708         torture_suite_add_simple_test(kdc_suite, "as-req-clock-skew",
709                                       torture_krb5_as_req_clock_skew);
710
711         torture_suite_add_simple_test(kdc_suite,
712                                       "as-req-aes",
713                                       torture_krb5_as_req_aes);
714
715         torture_suite_add_simple_test(kdc_suite,
716                                       "as-req-rc4",
717                                       torture_krb5_as_req_rc4);
718
719         torture_suite_add_simple_test(kdc_suite,
720                                       "as-req-aes-rc4",
721                                       torture_krb5_as_req_aes_rc4);
722
723         torture_suite_add_suite(kdc_suite, torture_krb5_canon(kdc_suite));
724         torture_suite_add_suite(suite, kdc_suite);
725
726         torture_register_suite(ctx, suite);
727         return NT_STATUS_OK;
728 }