1 /*
2 * Tests for anonymous FAST support in pam-krb5.
3 *
4 * Tests for anonymous Flexible Authentication Secure Tunneling, a mechanism
5 * for improving the preauthentication part of the Kerberos protocol and
6 * protecting it against various attacks.
7 *
8 * This is broken out from the other FAST tests because it uses PKINIT, and
9 * PKINIT code cannot be tested under valgrind with MIT Kerberos due to some
10 * bug in valgrind.
11 *
12 * Written by Russ Allbery <eagle@eyrie.org>
13 * Copyright 2017, 2020 Russ Allbery <eagle@eyrie.org>
14 * Copyright 2012
15 * The Board of Trustees of the Leland Stanford Junior University
16 *
17 * SPDX-License-Identifier: BSD-3-clause or GPL-1+
18 */
19
20 #include <config.h>
21 #include <portable/krb5.h>
22 #include <portable/system.h>
23
24 #include <tests/fakepam/script.h>
25 #include <tests/tap/kerberos.h>
26
27
28 /*
29 * Test whether anonymous authentication works. If this doesn't, we need to
30 * skip the tests of anonymous FAST.
31 */
32 static bool
anon_fast_works(void)33 anon_fast_works(void)
34 {
35 krb5_context ctx;
36 krb5_error_code retval;
37 krb5_principal princ = NULL;
38 char *realm;
39 krb5_creds creds;
40 krb5_get_init_creds_opt *opts = NULL;
41
42 /* Construct the anonymous principal name. */
43 retval = krb5_init_context(&ctx);
44 if (retval != 0)
45 bail("cannot initialize Kerberos");
46 retval = krb5_get_default_realm(ctx, &realm);
47 if (retval != 0)
48 bail("cannot get default realm");
49 retval = krb5_build_principal_ext(
50 ctx, &princ, (unsigned int) strlen(realm), realm,
51 strlen(KRB5_WELLKNOWN_NAME), KRB5_WELLKNOWN_NAME,
52 strlen(KRB5_ANON_NAME), KRB5_ANON_NAME, NULL);
53 if (retval != 0)
54 bail("cannot construct anonymous principal");
55 krb5_free_default_realm(ctx, realm);
56
57 /* Obtain the credentials. */
58 memset(&creds, 0, sizeof(creds));
59 retval = krb5_get_init_creds_opt_alloc(ctx, &opts);
60 if (retval != 0)
61 bail("cannot create credential options");
62 krb5_get_init_creds_opt_set_anonymous(opts, 1);
63 krb5_get_init_creds_opt_set_tkt_life(opts, 60);
64 retval = krb5_get_init_creds_password(ctx, &creds, princ, NULL, NULL, NULL,
65 0, NULL, opts);
66
67 /* Clean up. */
68 if (princ != NULL)
69 krb5_free_principal(ctx, princ);
70 if (opts != NULL)
71 krb5_get_init_creds_opt_free(ctx, opts);
72 krb5_free_cred_contents(ctx, &creds);
73
74 /* Return whether authentication succeeded. */
75 return (retval == 0);
76 }
77
78
79 int
main(void)80 main(void)
81 {
82 struct script_config config;
83 struct kerberos_config *krbconf;
84
85 /* Skip the test if FAST is not available. */
86 #ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME
87 skip_all("FAST support not available");
88 #endif
89
90 /* Initialize Kerberos configuration. */
91 krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD);
92 memset(&config, 0, sizeof(config));
93 config.user = krbconf->username;
94 config.authtok = krbconf->password;
95 config.extra[0] = krbconf->userprinc;
96 kerberos_generate_conf(krbconf->realm);
97
98 /* Skip the test if anonymous PKINIT doesn't work. */
99 if (!anon_fast_works())
100 skip_all("anonymous PKINIT failed");
101
102 /* Test anonymous FAST. */
103 plan_lazy();
104 run_script("data/scripts/fast/anonymous", &config);
105 run_script("data/scripts/fast/anonymous-debug", &config);
106
107 return 0;
108 }
109