diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2025-04-17 02:13:41 +0000 |
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2025-05-27 16:20:06 +0000 |
| commit | 24f0b4ca2d565cdbb4fe7839ff28320706bf2386 (patch) | |
| tree | bc9ce87edb73f767f5580887d0fc8c643b9d7a49 /tests/module | |
Diffstat (limited to 'tests/module')
| -rw-r--r-- | tests/module/alt-auth-t.c | 117 | ||||
| -rw-r--r-- | tests/module/bad-authtok-t.c | 53 | ||||
| -rw-r--r-- | tests/module/basic-t.c | 67 | ||||
| -rw-r--r-- | tests/module/cache-cleanup-t.c | 104 | ||||
| -rw-r--r-- | tests/module/cache-t.c | 210 | ||||
| -rw-r--r-- | tests/module/expired-t.c | 175 | ||||
| -rw-r--r-- | tests/module/fast-anon-t.c | 108 | ||||
| -rw-r--r-- | tests/module/fast-t.c | 57 | ||||
| -rw-r--r-- | tests/module/long-t.c | 46 | ||||
| -rw-r--r-- | tests/module/no-cache-t.c | 47 | ||||
| -rw-r--r-- | tests/module/pam-user-t.c | 80 | ||||
| -rw-r--r-- | tests/module/password-t.c | 152 | ||||
| -rw-r--r-- | tests/module/pkinit-t.c | 98 | ||||
| -rw-r--r-- | tests/module/realm-t.c | 87 | ||||
| -rw-r--r-- | tests/module/stacked-t.c | 50 | ||||
| -rw-r--r-- | tests/module/trace-t.c | 48 |
16 files changed, 1499 insertions, 0 deletions
diff --git a/tests/module/alt-auth-t.c b/tests/module/alt-auth-t.c new file mode 100644 index 000000000000..df32ff941001 --- /dev/null +++ b/tests/module/alt-auth-t.c @@ -0,0 +1,117 @@ +/* + * Tests for the alt_auth_map functionality in libpam-krb5. + * + * This test case tests the variations of the alt_auth_map functionality for + * both authentication and account management. It requires a Kerberos + * configuration, but does not attempt to save a session ticket cache (to + * avoid requiring user configuration). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + char *user; + + /* + * Load the Kerberos principal and password from a file, but set the + * principal as extra[0] and use something else bogus as the user. We + * want to test that alt_auth_map works when there's no relationship + * between the mapped principal and the user. + */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = "bogus-nonexistent-account"; + config.authtok = krbconf->password; + config.extra[0] = krbconf->username; + config.extra[1] = krbconf->userprinc; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + config.extra[2] = "bogus.example.com"; + + /* Test without password prompting. */ + plan_lazy(); + run_script("data/scripts/alt-auth/basic", &config); + run_script("data/scripts/alt-auth/basic-debug", &config); + run_script("data/scripts/alt-auth/fail", &config); + run_script("data/scripts/alt-auth/fail-debug", &config); + run_script("data/scripts/alt-auth/force", &config); + run_script("data/scripts/alt-auth/only", &config); + + /* + * If the alternate account exists but the password is incorrect, we + * should not fall back to the regular account. Test with debug so that + * we don't need two principals configured. + */ + config.authtok = "bogus incorrect password"; + run_script("data/scripts/alt-auth/force-fail-debug", &config); + + /* + * Switch to our correct user (but wrong realm) realm to test username + * mapping to a different realm. + */ + config.authtok = krbconf->password; + config.user = krbconf->username; + config.extra[2] = krbconf->realm; + run_script("data/scripts/alt-auth/username-map", &config); + + /* + * Split the username into two parts, one in the PAM configuration and one + * in the real username, so that we can test interpolation of the username + * when %s isn't the first token. + */ + config.user = &krbconf->username[1]; + user = bstrndup(krbconf->username, 1); + config.extra[3] = user; + run_script("data/scripts/alt-auth/username-map-prefix", &config); + free(user); + config.extra[3] = NULL; + + /* + * Ensure that we don't add the realm of the authentication username when + * the alt_auth_map already includes a realm. + */ + basprintf(&user, "%s@foo.example.com", krbconf->username); + config.user = user; + diag("re-running username-map with fully-qualified PAM user"); + run_script("data/scripts/alt-auth/username-map", &config); + free(user); + + /* + * Add the password and make the user match our authentication principal, + * and then test fallback to normal authentication when alternative + * authentication fails. + */ + config.user = krbconf->userprinc; + config.password = krbconf->password; + config.extra[2] = krbconf->realm; + run_script("data/scripts/alt-auth/fallback", &config); + run_script("data/scripts/alt-auth/fallback-debug", &config); + run_script("data/scripts/alt-auth/fallback-realm", &config); + run_script("data/scripts/alt-auth/force-fallback", &config); + run_script("data/scripts/alt-auth/only-fail", &config); + + return 0; +} diff --git a/tests/module/bad-authtok-t.c b/tests/module/bad-authtok-t.c new file mode 100644 index 000000000000..385dd5946849 --- /dev/null +++ b/tests/module/bad-authtok-t.c @@ -0,0 +1,53 @@ +/* + * Authentication tests for the pam-krb5 module with an incorrect AUTHTOK. + * + * This test case includes tests that require Kerberos to be configured and a + * username and password available and that run with an incorrect AUTHTOK + * already set. They test various prompting fallback cases. They don't write + * a ticket cache (which requires additional work to test the cache + * ownership). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011-2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->userprinc; + config.password = krbconf->password; + + /* Set the authtok to something bogus. */ + config.authtok = "BAD PASSWORD THAT WILL NOT WORK"; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + + plan_lazy(); + run_script_dir("data/scripts/bad-authtok", &config); + + return 0; +} diff --git a/tests/module/basic-t.c b/tests/module/basic-t.c new file mode 100644 index 000000000000..cacad5906ffb --- /dev/null +++ b/tests/module/basic-t.c @@ -0,0 +1,67 @@ +/* + * Basic tests for the pam-krb5 module. + * + * This test case includes all tests that can be done without having Kerberos + * configured and a username and password available, and without any special + * configuration. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <pwd.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct passwd pwd; + char *uid; + char *uidplus; + + plan_lazy(); + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that this test will run on any system. + */ + kerberos_generate_conf("bogus.example.com"); + + /* Create a fake passwd struct for our user. */ + memset(&pwd, 0, sizeof(pwd)); + pwd.pw_name = (char *) "root"; + pwd.pw_uid = getuid(); + pwd.pw_gid = getgid(); + pam_set_pwd(&pwd); + + /* + * Attempt login as the root user to test ignore_root. Set our current + * UID and a UID one larger for testing minimum_uid. + */ + basprintf(&uid, "%lu", (unsigned long) pwd.pw_uid); + basprintf(&uidplus, "%lu", (unsigned long) pwd.pw_uid + 1); + memset(&config, 0, sizeof(config)); + config.user = "root"; + config.extra[0] = uid; + config.extra[1] = uidplus; + + run_script_dir("data/scripts/basic", &config); + + free(uid); + free(uidplus); + return 0; +} diff --git a/tests/module/cache-cleanup-t.c b/tests/module/cache-cleanup-t.c new file mode 100644 index 000000000000..8b5012fc3507 --- /dev/null +++ b/tests/module/cache-cleanup-t.c @@ -0,0 +1,104 @@ +/* + * Test for properly cleaning up ticket caches. + * + * Verify that the temporary Kerberos ticket cache generated during + * authentication is cleaned up on pam_end, even if no session was opened. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <dirent.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + DIR *tmpdir; + struct dirent *file; + char *tmppath, *path; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + config.authtok = krbconf->password; + config.extra[0] = krbconf->userprinc; + + /* Generate a testing krb5.conf file. */ + kerberos_generate_conf(krbconf->realm); + + /* Get the temporary directory and store that as the %1 substitution. */ + tmppath = test_tmpdir(); + config.extra[1] = tmppath; + + plan_lazy(); + + /* + * We need to ensure that the only thing in the test temporary directory + * is the krb5.conf file that we generated and any valgrind logs, since + * we're going to check for cleanup by looking for any out-of-place files. + */ + tmpdir = opendir(tmppath); + if (tmpdir == NULL) + sysbail("cannot open directory %s", tmppath); + while ((file = readdir(tmpdir)) != NULL) { + if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) + continue; + if (strcmp(file->d_name, "krb5.conf") == 0) + continue; + if (strcmp(file->d_name, "valgrind") == 0) + continue; + basprintf(&path, "%s/%s", tmppath, file->d_name); + if (unlink(path) < 0) + sysbail("cannot delete temporary file %s", path); + free(path); + } + closedir(tmpdir); + + /* + * Authenticate only, call pam_end, and be sure the ticket cache is + * gone. The auth-only script sets ccache_dir to the temporary directory, + * so the module will create a temporary ticket cache there and then + * should clean it up. + */ + run_script("data/scripts/cache-cleanup/auth-only", &config); + path = NULL; + tmpdir = opendir(tmppath); + if (tmpdir == NULL) + sysbail("cannot open directory %s", tmppath); + while ((file = readdir(tmpdir)) != NULL) { + if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) + continue; + if (strcmp(file->d_name, "krb5.conf") == 0) + continue; + if (strcmp(file->d_name, "valgrind") == 0) + continue; + if (path == NULL) + basprintf(&path, "%s/%s", tmppath, file->d_name); + } + closedir(tmpdir); + if (path != NULL) + diag("found stray temporary file %s", path); + ok(path == NULL, "ticket cache cleaned up"); + if (path != NULL) + free(path); + + test_tmpdir_free(tmppath); + return 0; +} diff --git a/tests/module/cache-t.c b/tests/module/cache-t.c new file mode 100644 index 000000000000..8ec82df7c460 --- /dev/null +++ b/tests/module/cache-t.c @@ -0,0 +1,210 @@ +/* + * Authentication tests for the pam-krb5 module with ticket cache. + * + * This test case includes all tests that require Kerberos to be configured, a + * username and password available, and a ticket cache created, but with the + * PAM module running as the same user for which the ticket cache will be + * created (so without setuid and with chown doing nothing). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2017, 2020-2021 Russ Allbery <eagle@eyrie.org> + * Copyright 2011, 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/krb5.h> +#include <portable/system.h> + +#include <pwd.h> +#include <sys/stat.h> +#include <time.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + +/* Additional data used by the cache check callback. */ +struct extra { + char *realm; + char *cache_path; +}; + + +/* + * PAM test callback to check whether we created a ticket cache and the ticket + * cache is for the correct user. + */ +static void +check_cache(const char *file, const struct script_config *config, + const struct extra *extra) +{ + struct stat st; + krb5_error_code code; + krb5_context ctx = NULL; + krb5_ccache ccache = NULL; + krb5_principal princ = NULL; + krb5_principal tgtprinc = NULL; + krb5_creds in, out; + char *principal = NULL; + + /* Check ownership and permissions. */ + is_int(0, stat(file, &st), "cache exists"); + is_int(getuid(), st.st_uid, "...with correct UID"); + is_int(getgid(), st.st_gid, "...with correct GID"); + is_int(0600, (st.st_mode & 0777), "...with correct permissions"); + + /* Check the existence of the ticket cache and its principal. */ + code = krb5_init_context(&ctx); + if (code != 0) + bail("cannot create Kerberos context"); + code = krb5_cc_resolve(ctx, file, &ccache); + is_int(0, code, "able to resolve Kerberos ticket cache"); + code = krb5_cc_get_principal(ctx, ccache, &princ); + is_int(0, code, "able to get principal"); + code = krb5_unparse_name(ctx, princ, &principal); + is_int(0, code, "...and principal is valid"); + is_string(config->extra[0], principal, "...and matches our principal"); + + /* Retrieve the krbtgt for the realm and check properties. */ + code = krb5_build_principal_ext( + ctx, &tgtprinc, (unsigned int) strlen(extra->realm), extra->realm, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, strlen(extra->realm), extra->realm, + NULL); + if (code != 0) + bail("cannot create krbtgt principal name"); + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.server = tgtprinc; + in.client = princ; + code = krb5_cc_retrieve_cred(ctx, ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &in, + &out); + is_int(0, code, "able to get krbtgt credentials"); + ok(out.times.endtime > time(NULL) + 30 * 60, "...good for 30 minutes"); + krb5_free_cred_contents(ctx, &out); + + /* Close things and release memory. */ + krb5_free_principal(ctx, tgtprinc); + krb5_free_unparsed_name(ctx, principal); + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); +} + + +/* + * Same as check_cache except unlink the ticket cache afterwards. Used to + * check the ticket cache in cases where the PAM module will not clean it up + * afterwards, such as calling pam_end with PAM_DATA_SILENT. + */ +static void +check_cache_callback(pam_handle_t *pamh, const struct script_config *config, + void *data) +{ + struct extra *extra = data; + const char *cache, *file; + char *prefix; + + cache = pam_getenv(pamh, "KRB5CCNAME"); + ok(cache != NULL, "KRB5CCNAME is set in PAM environment"); + if (cache == NULL) + return; + basprintf(&prefix, "FILE:/tmp/krb5cc_%lu_", (unsigned long) getuid()); + diag("KRB5CCNAME = %s", cache); + ok(strncmp(prefix, cache, strlen(prefix)) == 0, + "cache file name prefix is correct"); + free(prefix); + file = cache + strlen("FILE:"); + extra->cache_path = bstrdup(file); + check_cache(file, config, extra); +} + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + char *k5login; + struct extra extra; + struct passwd pwd; + FILE *file; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + extra.realm = krbconf->realm; + extra.cache_path = NULL; + config.authtok = krbconf->password; + config.extra[0] = krbconf->userprinc; + + /* Generate a testing krb5.conf file. */ + kerberos_generate_conf(krbconf->realm); + + /* Create a fake passwd struct for our user. */ + memset(&pwd, 0, sizeof(pwd)); + pwd.pw_name = krbconf->username; + pwd.pw_uid = getuid(); + pwd.pw_gid = getgid(); + basprintf(&pwd.pw_dir, "%s/tmp", getenv("BUILD")); + pam_set_pwd(&pwd); + + plan_lazy(); + + /* Basic test. */ + run_script("data/scripts/cache/basic", &config); + + /* Check the cache status before the session is closed. */ + config.callback = check_cache_callback; + config.data = &extra; + run_script("data/scripts/cache/open-session", &config); + free(extra.cache_path); + extra.cache_path = NULL; + + /* + * Try again but passing PAM_DATA_SILENT to pam_end. This should leave + * the ticket cache intact. + */ + run_script("data/scripts/cache/end-data-silent", &config); + check_cache(extra.cache_path, &config, &extra); + if (unlink(extra.cache_path) < 0) + sysdiag("unable to unlink temporary cache %s", extra.cache_path); + free(extra.cache_path); + extra.cache_path = NULL; + + /* Change the authenticating user and test search_k5login. */ + pwd.pw_name = (char *) "testuser"; + pam_set_pwd(&pwd); + config.user = "testuser"; + basprintf(&k5login, "%s/.k5login", pwd.pw_dir); + file = fopen(k5login, "w"); + if (file == NULL) + sysbail("cannot create %s", k5login); + if (fprintf(file, "%s\n", krbconf->userprinc) < 0) + sysbail("cannot write to %s", k5login); + if (fclose(file) < 0) + sysbail("cannot flush %s", k5login); + run_script("data/scripts/cache/search-k5login", &config); + free(extra.cache_path); + extra.cache_path = NULL; + config.callback = NULL; + run_script("data/scripts/cache/search-k5login-debug", &config); + unlink(k5login); + free(k5login); + + /* Test search_k5login when no .k5login file exists. */ + pwd.pw_name = krbconf->username; + pam_set_pwd(&pwd); + config.user = krbconf->username; + diag("testing search_k5login with no .k5login file"); + run_script("data/scripts/cache/search-k5login", &config); + + free(pwd.pw_dir); + return 0; +} diff --git a/tests/module/expired-t.c b/tests/module/expired-t.c new file mode 100644 index 000000000000..01a1892a0d04 --- /dev/null +++ b/tests/module/expired-t.c @@ -0,0 +1,175 @@ +/* + * Tests for the pam-krb5 module with an expired password. + * + * This test case checks correct handling of an account whose password has + * expired and the multiple different paths the module can take for handling + * that case. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011-2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <pwd.h> +#include <time.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kadmin.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + char *newpass, *date; + struct passwd pwd; + time_t now; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + config.password = krbconf->password; + config.extra[0] = krbconf->userprinc; + + /* + * Ensure we can expire the password. Heimdal has a prompt for the + * expiration time, so save that to use as a substitution in the script. + */ + now = time(NULL) - 1; + if (!kerberos_expire_password(krbconf->userprinc, now)) + skip_all("kadmin not configured or kadmin mismatch"); + date = bstrdup(ctime(&now)); + date[strlen(date) - 1] = '\0'; + config.extra[1] = date; + + /* Generate a testing krb5.conf file. */ + kerberos_generate_conf(krbconf->realm); + + /* Create a fake passwd struct for our user. */ + memset(&pwd, 0, sizeof(pwd)); + pwd.pw_name = krbconf->username; + pwd.pw_uid = getuid(); + pwd.pw_gid = getgid(); + basprintf(&pwd.pw_dir, "%s/tmp", getenv("BUILD")); + pam_set_pwd(&pwd); + + /* + * We'll be changing the password to something new. This needs to be + * sufficiently random that it's unlikely to fall afoul of password + * strength checking. + */ + basprintf(&newpass, "ngh1,a%lu nn9af6", (unsigned long) getpid()); + config.newpass = newpass; + + plan_lazy(); + + /* + * Default behavior. We have to distinguish between two versions of + * Heimdal for testing because the prompts changed substantially. Use the + * existence of krb5_principal_set_comp_string to distinguish because it + * was introduced at the same time. + */ +#ifdef HAVE_KRB5_HEIMDAL +# ifdef HAVE_KRB5_PRINCIPAL_SET_COMP_STRING + run_script("data/scripts/expired/basic-heimdal", &config); + config.newpass = krbconf->password; + config.password = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-heimdal-debug", &config); +# else + run_script("data/scripts/expired/basic-heimdal-old", &config); + config.newpass = krbconf->password; + config.password = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-heimdal-old-debug", &config); +# endif +#else + run_script("data/scripts/expired/basic-mit", &config); + config.newpass = krbconf->password; + config.password = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-mit-debug", &config); +#endif + + /* Test again with PAM_SILENT, specified two ways. */ +#ifdef HAVE_KRB5_HEIMDAL + config.newpass = newpass; + config.password = krbconf->password; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-heimdal-silent", &config); + config.newpass = krbconf->password; + config.password = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-heimdal-flag-silent", &config); +#else + config.newpass = newpass; + config.password = krbconf->password; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-mit-silent", &config); + config.newpass = krbconf->password; + config.password = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/basic-mit-flag-silent", &config); +#endif + + /* + * We can only run the remaining checks if we can suppress the Kerberos + * library behavior of prompting for a new password when the password has + * expired. + */ +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT + + /* Check the forced failure behavior. */ + run_script("data/scripts/expired/fail", &config); + run_script("data/scripts/expired/fail-debug", &config); + + /* + * Defer the error to the account management check. + * + * Skip this check on Heimdal currently (Heimdal 7.4.0) because its + * implementation of krb5_get_init_creds_opt_set_change_password_prompt is + * incomplete. See <https://github.com/heimdal/heimdal/issues/322>. + */ +# ifdef HAVE_KRB5_HEIMDAL + skip_block(2, "deferring password changes broken in Heimdal"); +# else + config.newpass = newpass; + config.password = krbconf->password; + config.authtok = krbconf->password; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/defer-mit", &config); + config.newpass = krbconf->password; + config.password = newpass; + config.authtok = newpass; + kerberos_expire_password(krbconf->userprinc, now); + run_script("data/scripts/expired/defer-mit-debug", &config); +# endif + +#else /* !HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT */ + + /* Mention that we skipped something for the record. */ + skip_block(4, "cannot disable library password prompting"); + +#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT */ + + /* In case we ran into some error, try to unexpire the password. */ + kerberos_expire_password(krbconf->userprinc, 0); + + free(date); + free(newpass); + free(pwd.pw_dir); + return 0; +} diff --git a/tests/module/fast-anon-t.c b/tests/module/fast-anon-t.c new file mode 100644 index 000000000000..6355a5154f69 --- /dev/null +++ b/tests/module/fast-anon-t.c @@ -0,0 +1,108 @@ +/* + * Tests for anonymous FAST support in pam-krb5. + * + * Tests for anonymous Flexible Authentication Secure Tunneling, a mechanism + * for improving the preauthentication part of the Kerberos protocol and + * protecting it against various attacks. + * + * This is broken out from the other FAST tests because it uses PKINIT, and + * PKINIT code cannot be tested under valgrind with MIT Kerberos due to some + * bug in valgrind. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2017, 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/krb5.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> + + +/* + * Test whether anonymous authentication works. If this doesn't, we need to + * skip the tests of anonymous FAST. + */ +static bool +anon_fast_works(void) +{ + krb5_context ctx; + krb5_error_code retval; + krb5_principal princ = NULL; + char *realm; + krb5_creds creds; + krb5_get_init_creds_opt *opts = NULL; + + /* Construct the anonymous principal name. */ + retval = krb5_init_context(&ctx); + if (retval != 0) + bail("cannot initialize Kerberos"); + retval = krb5_get_default_realm(ctx, &realm); + if (retval != 0) + bail("cannot get default realm"); + retval = krb5_build_principal_ext( + ctx, &princ, (unsigned int) strlen(realm), realm, + strlen(KRB5_WELLKNOWN_NAME), KRB5_WELLKNOWN_NAME, + strlen(KRB5_ANON_NAME), KRB5_ANON_NAME, NULL); + if (retval != 0) + bail("cannot construct anonymous principal"); + krb5_free_default_realm(ctx, realm); + + /* Obtain the credentials. */ + memset(&creds, 0, sizeof(creds)); + retval = krb5_get_init_creds_opt_alloc(ctx, &opts); + if (retval != 0) + bail("cannot create credential options"); + krb5_get_init_creds_opt_set_anonymous(opts, 1); + krb5_get_init_creds_opt_set_tkt_life(opts, 60); + retval = krb5_get_init_creds_password(ctx, &creds, princ, NULL, NULL, NULL, + 0, NULL, opts); + + /* Clean up. */ + if (princ != NULL) + krb5_free_principal(ctx, princ); + if (opts != NULL) + krb5_get_init_creds_opt_free(ctx, opts); + krb5_free_cred_contents(ctx, &creds); + + /* Return whether authentication succeeded. */ + return (retval == 0); +} + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Skip the test if FAST is not available. */ +#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME + skip_all("FAST support not available"); +#endif + + /* Initialize Kerberos configuration. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + config.authtok = krbconf->password; + config.extra[0] = krbconf->userprinc; + kerberos_generate_conf(krbconf->realm); + + /* Skip the test if anonymous PKINIT doesn't work. */ + if (!anon_fast_works()) + skip_all("anonymous PKINIT failed"); + + /* Test anonymous FAST. */ + plan_lazy(); + run_script("data/scripts/fast/anonymous", &config); + run_script("data/scripts/fast/anonymous-debug", &config); + + return 0; +} diff --git a/tests/module/fast-t.c b/tests/module/fast-t.c new file mode 100644 index 000000000000..51fee27098c8 --- /dev/null +++ b/tests/module/fast-t.c @@ -0,0 +1,57 @@ +/* + * Tests for authenticated FAST support in pam-krb5. + * + * Tests for Flexible Authentication Secure Tunneling, a mechanism for + * improving the preauthentication part of the Kerberos protocol and + * protecting it against various attacks. This tests authenticated FAST; + * anonymous FAST is tested separately. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2017, 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Skip the test if FAST is not available. */ +#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME + skip_all("FAST support not available"); +#endif + + /* Initialize Kerberos configuration. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_BOTH); + memset(&config, 0, sizeof(config)); + config.user = krbconf->userprinc; + config.authtok = krbconf->password; + config.extra[0] = krbconf->cache; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + + /* Test fast_ccache */ + plan_lazy(); + run_script("data/scripts/fast/ccache", &config); + run_script("data/scripts/fast/ccache-debug", &config); + run_script("data/scripts/fast/no-ccache", &config); + run_script("data/scripts/fast/no-ccache-debug", &config); + + return 0; +} diff --git a/tests/module/long-t.c b/tests/module/long-t.c new file mode 100644 index 000000000000..73614b0f6ec9 --- /dev/null +++ b/tests/module/long-t.c @@ -0,0 +1,46 @@ +/* + * Excessively long password tests for the pam-krb5 module. + * + * This test case includes all tests for excessively long passwords that can + * be done without having Kerberos configured and a username and password + * available. + * + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> + + +int +main(void) +{ + struct script_config config; + char *password; + + plan_lazy(); + + memset(&config, 0, sizeof(config)); + config.user = "test"; + + /* Test a password that is too long. */ + password = bcalloc_type(PAM_MAX_RESP_SIZE + 1, char); + memset(password, 'a', PAM_MAX_RESP_SIZE); + config.password = password; + run_script("data/scripts/long/password", &config); + run_script("data/scripts/long/password-debug", &config); + + /* Test a stored authtok that's too long. */ + config.authtok = password; + config.password = "testing"; + run_script("data/scripts/long/use-first", &config); + run_script("data/scripts/long/use-first-debug", &config); + + free(password); + return 0; +} diff --git a/tests/module/no-cache-t.c b/tests/module/no-cache-t.c new file mode 100644 index 000000000000..8b282d1de397 --- /dev/null +++ b/tests/module/no-cache-t.c @@ -0,0 +1,47 @@ +/* + * Authentication tests for the pam-krb5 module without a ticket cache. + * + * This test case includes tests that require Kerberos to be configured and a + * username and password available, but which don't write a ticket cache + * (which requires additional work to test the cache ownership). This test + * does not set AUTHTOK. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011, 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->userprinc; + config.password = krbconf->password; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + + plan_lazy(); + run_script_dir("data/scripts/no-cache", &config); + + return 0; +} diff --git a/tests/module/pam-user-t.c b/tests/module/pam-user-t.c new file mode 100644 index 000000000000..72cc21eebae3 --- /dev/null +++ b/tests/module/pam-user-t.c @@ -0,0 +1,80 @@ +/* + * Tests for PAM_USER handling. + * + * This test case includes tests that require Kerberos to be configured and a + * username and password available, but which don't write a ticket cache + * (which requires additional work to test the cache ownership). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2014, 2020 Russ Allbery <eagle@eyrie.org> + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/macros.h> + + +/* + * Callback to check that PAM_USER matches the desired value, passed in as the + * data parameter. + */ +static void +check_pam_user(pam_handle_t *pamh, const struct script_config *config UNUSED, + void *data) +{ + int retval; + const char *name = NULL; + const char *expected = data; + + retval = pam_get_item(pamh, PAM_USER, (PAM_CONST void **) &name); + is_int(PAM_SUCCESS, retval, "Found PAM_USER"); + is_string(expected, name, "...matching %s", expected); +} + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.password = krbconf->password; + config.callback = check_pam_user; + config.extra[0] = krbconf->username; + config.extra[1] = krbconf->userprinc; + + /* + * Generate a testing krb5.conf file matching the realm of the Kerberos + * configuration so that canonicalization will work. + */ + kerberos_generate_conf(krbconf->realm); + + /* Declare our plan. */ + plan_lazy(); + + /* Authentication without a realm. No canonicalization. */ + config.user = krbconf->username; + config.data = krbconf->username; + run_script("data/scripts/pam-user/update", &config); + + /* Authentication with the local realm. Should be canonicalized. */ + config.user = krbconf->userprinc; + run_script("data/scripts/pam-user/update", &config); + + /* + * Now, test again with user updates disabled. The PAM_USER value should + * now not be canonicalized. + */ + config.data = krbconf->userprinc; + run_script("data/scripts/pam-user/no-update", &config); + + return 0; +} diff --git a/tests/module/password-t.c b/tests/module/password-t.c new file mode 100644 index 000000000000..bdf9762bc6cb --- /dev/null +++ b/tests/module/password-t.c @@ -0,0 +1,152 @@ +/* + * Authentication tests for the pam-krb5 module with ticket cache. + * + * This test case includes all tests that require Kerberos to be configured, a + * username and password available, and a ticket cache created, but with the + * PAM module running as the same user for which the ticket cache will be + * created (so without setuid and with chown doing nothing). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011-2012, 2014 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/krb5.h> +#include <portable/pam.h> +#include <portable/system.h> + +#include <pwd.h> +#include <sys/stat.h> +#include <time.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/macros.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +static void +check_authtok(pam_handle_t *pamh, const struct script_config *config, + void *data UNUSED) +{ + int retval; + const char *authtok; + + retval = pam_get_item(pamh, PAM_AUTHTOK, (PAM_CONST void **) &authtok); + is_int(PAM_SUCCESS, retval, "Found PAM_AUTHTOK"); + is_string(config->newpass, authtok, "...and it is correct"); +} + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + char *newpass; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + config.password = krbconf->password; + config.extra[0] = krbconf->userprinc; + + /* Generate a testing krb5.conf file. */ + kerberos_generate_conf(krbconf->realm); + + plan_lazy(); + + /* + * First test trying to change the password to something that's + * excessively long. + */ + newpass = bcalloc_type(PAM_MAX_RESP_SIZE + 1, char); + memset(newpass, 'a', PAM_MAX_RESP_SIZE); + config.newpass = newpass; + run_script("data/scripts/password/too-long", &config); + run_script("data/scripts/password/too-long-debug", &config); + + /* Test use_authtok with an excessively long password. */ + config.newpass = NULL; + config.authtok = newpass; + run_script("data/scripts/password/authtok-too-long", &config); + run_script("data/scripts/password/authtok-too-long-debug", &config); + + /* + * Change the password to something new. This needs to be sufficiently + * random that it's unlikely to fall afoul of password strength checking. + */ + free(newpass); + config.authtok = NULL; + basprintf(&newpass, "ngh1,a%lu nn9af6%lu", (unsigned long) getpid(), + (unsigned long) time(NULL)); + config.newpass = newpass; + run_script("data/scripts/password/basic", &config); + config.password = newpass; + config.newpass = krbconf->password; + run_script("data/scripts/password/basic-debug", &config); + + /* Test prompt_principal with password change. */ + config.password = krbconf->password; + config.newpass = newpass; + run_script("data/scripts/password/prompt-principal", &config); + + /* Change the password back and test expose-account. */ + config.password = newpass; + config.newpass = krbconf->password; + run_script("data/scripts/password/expose", &config); + + /* + * Test two banner settings by changing the password and then changing it + * back again. + */ + config.password = krbconf->password; + config.newpass = newpass; + run_script("data/scripts/password/banner", &config); + config.password = newpass; + config.newpass = krbconf->password; + run_script("data/scripts/password/no-banner", &config); + + /* Do the same, but with expose_account set as well. */ + config.password = krbconf->password; + config.newpass = newpass; + run_script("data/scripts/password/banner-expose", &config); + config.password = newpass; + config.newpass = krbconf->password; + run_script("data/scripts/password/no-banner-expose", &config); + + /* Test use_authtok. */ + config.password = krbconf->password; + config.newpass = NULL; + config.authtok = newpass; + run_script("data/scripts/password/authtok", &config); + + /* Test use_authtok with force_first_pass. */ + config.password = NULL; + config.authtok = krbconf->password; + config.oldauthtok = newpass; + run_script("data/scripts/password/authtok-force", &config); + + /* + * Ensure PAM_AUTHTOK and PAM_OLDAUTHTOK are set even if the user is + * ignored. + */ + config.user = "root"; + config.authtok = NULL; + config.oldauthtok = NULL; + config.password = "old-password"; + config.newpass = "new-password"; + config.callback = check_authtok; + run_script("data/scripts/password/ignore", &config); + + free(newpass); + return 0; +} diff --git a/tests/module/pkinit-t.c b/tests/module/pkinit-t.c new file mode 100644 index 000000000000..6bbb6993b2af --- /dev/null +++ b/tests/module/pkinit-t.c @@ -0,0 +1,98 @@ +/* + * PKINIT authentication tests for the pam-krb5 module. + * + * This test case includes tests that require a PKINIT certificate, but which + * don't write a Kerberos ticket cache. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; +#if defined(HAVE_KRB5_MIT) && defined(PATH_OPENSSL) + const char **generate_pkcs12; + char *tmpdir, *pkcs12_path; +#endif + + /* Load the Kerberos principal and certificate path. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PKINIT); + memset(&config, 0, sizeof(config)); + config.user = krbconf->pkinit_principal; + config.extra[0] = krbconf->pkinit_cert; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + + /* Check things that are the same with both Kerberos implementations. */ + plan_lazy(); + run_script("data/scripts/pkinit/basic", &config); + run_script("data/scripts/pkinit/basic-debug", &config); + run_script("data/scripts/pkinit/prompt-use", &config); + run_script("data/scripts/pkinit/prompt-try", &config); + run_script("data/scripts/pkinit/try-pkinit", &config); + + /* Debugging output is a little different between the implementations. */ +#ifdef HAVE_KRB5_HEIMDAL + run_script("data/scripts/pkinit/try-pkinit-debug", &config); +#else + run_script("data/scripts/pkinit/try-pkinit-debug-mit", &config); +#endif + + /* Only MIT Kerberos supports setting preauth options. */ +#ifdef HAVE_KRB5_MIT + run_script("data/scripts/pkinit/preauth-opt-mit", &config); +#endif + + /* + * If OpenSSL is available, test prompting with MIT Kerberos since we have + * to implement the prompting for the use_pkinit case ourselves. To do + * this, convert the input PKINIT certificate to a PKCS12 file with a + * password. + */ +#if defined(HAVE_KRB5_MIT) && defined(PATH_OPENSSL) + tmpdir = test_tmpdir(); + basprintf(&pkcs12_path, "%s/%s", tmpdir, "pkinit-pkcs12"); + generate_pkcs12 = bcalloc_type(10, const char *); + generate_pkcs12[0] = PATH_OPENSSL; + generate_pkcs12[1] = "pkcs12"; + generate_pkcs12[2] = "-export"; + generate_pkcs12[3] = "-in"; + generate_pkcs12[4] = krbconf->pkinit_cert; + generate_pkcs12[5] = "-password"; + generate_pkcs12[6] = "pass:some-password"; + generate_pkcs12[7] = "-out"; + generate_pkcs12[8] = pkcs12_path; + generate_pkcs12[9] = NULL; + run_setup(generate_pkcs12); + free(generate_pkcs12); + config.extra[0] = pkcs12_path; + config.extra[1] = "some-password"; + run_script("data/scripts/pkinit/pin-mit", &config); + unlink(pkcs12_path); + free(pkcs12_path); + test_tmpdir_free(tmpdir); +#endif /* HAVE_KRB5_MIT && PATH_OPENSSL */ + + return 0; +} diff --git a/tests/module/realm-t.c b/tests/module/realm-t.c new file mode 100644 index 000000000000..d5643ca1f3e5 --- /dev/null +++ b/tests/module/realm-t.c @@ -0,0 +1,87 @@ +/* + * Authentication tests for realm support in pam-krb5. + * + * Test the realm and user_realm option in the PAM configuration, which is + * special in several ways since it influences krb5.conf parsing and is read + * out of order in the initial configuration. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011-2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/krb5.h> +#include <portable/system.h> + +#include <pwd.h> + +#include <tests/fakepam/pam.h> +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + struct passwd pwd; + FILE *file; + char *k5login; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->username; + config.authtok = krbconf->password; + + /* Don't keep track of the tests in each script. */ + plan_lazy(); + + /* Start with a nonexistent default realm for authentication failure. */ + kerberos_generate_conf("bogus.example.com"); + config.extra[0] = "bogus.example.com"; + run_script("data/scripts/realm/fail-no-realm", &config); + run_script("data/scripts/realm/fail-no-realm-debug", &config); + + /* Running a script that sets realm properly should pass. */ + config.extra[0] = krbconf->realm; + run_script("data/scripts/realm/pass-realm", &config); + + /* Setting user_realm should continue to fail due to no .k5login file. */ + run_script("data/scripts/realm/fail-user-realm", &config); + + /* If we add a .k5login file for the user, user_realm should work. */ + pwd.pw_name = krbconf->username; + pwd.pw_uid = getuid(); + pwd.pw_gid = getgid(); + pwd.pw_dir = test_tmpdir(); + pam_set_pwd(&pwd); + basprintf(&k5login, "%s/.k5login", pwd.pw_dir); + file = fopen(k5login, "w"); + if (file == NULL) + sysbail("cannot create %s", k5login); + if (fprintf(file, "%s\n", krbconf->userprinc) < 0) + sysbail("cannot write to %s", k5login); + if (fclose(file) < 0) + sysbail("cannot flush %s", k5login); + run_script("data/scripts/realm/pass-user-realm", &config); + pam_set_pwd(NULL); + unlink(k5login); + free(k5login); + test_tmpdir_free(pwd.pw_dir); + + /* Switch to the correct realm, but set the wrong realm in PAM. */ + kerberos_generate_conf(krbconf->realm); + config.extra[0] = "bogus.example.com"; + run_script("data/scripts/realm/fail-realm", &config); + run_script("data/scripts/realm/fail-bad-user-realm", &config); + + return 0; +} diff --git a/tests/module/stacked-t.c b/tests/module/stacked-t.c new file mode 100644 index 000000000000..ef8e70885ecb --- /dev/null +++ b/tests/module/stacked-t.c @@ -0,0 +1,50 @@ +/* + * Authentication tests for the pam-krb5 module with an existing AUTHTOK. + * + * This test case includes tests that require Kerberos to be configured and a + * username and password available and that run with AUTHTOK already set, but + * which don't write a ticket cache (which requires additional work to test + * the cache ownership). + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2011-2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/kerberos.h> +#include <tests/tap/process.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + struct kerberos_config *krbconf; + + /* Load the Kerberos principal and password from a file. */ + krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); + memset(&config, 0, sizeof(config)); + config.user = krbconf->userprinc; + config.password = krbconf->password; + config.authtok = krbconf->password; + + /* + * Generate a testing krb5.conf file with a nonexistent default realm so + * that we can be sure that our principals will stay fully-qualified in + * the logs. + */ + kerberos_generate_conf("bogus.example.com"); + + plan_lazy(); + run_script_dir("data/scripts/stacked", &config); + + return 0; +} diff --git a/tests/module/trace-t.c b/tests/module/trace-t.c new file mode 100644 index 000000000000..db3aa67f9e24 --- /dev/null +++ b/tests/module/trace-t.c @@ -0,0 +1,48 @@ +/* + * Tests for trace logging in the pam-krb5 module. + * + * Checks that trace logging is handled properly. This is currently very + * simple and just checks that the file is created. + * + * Written by Russ Allbery <eagle@eyrie.org> + * Copyright 2020 Russ Allbery <eagle@eyrie.org> + * Copyright 2012 + * The Board of Trustees of the Leland Stanford Junior University + * + * SPDX-License-Identifier: BSD-3-clause or GPL-1+ + */ + +#include <config.h> +#include <portable/system.h> + +#include <tests/fakepam/script.h> +#include <tests/tap/basic.h> +#include <tests/tap/string.h> + + +int +main(void) +{ + struct script_config config; + char *tmpdir, *trace; + + plan_lazy(); + + memset(&config, 0, sizeof(config)); + config.user = "testuser"; + tmpdir = test_tmpdir(); + basprintf(&trace, "%s/trace", tmpdir); + config.extra[0] = trace; +#ifdef HAVE_KRB5_SET_TRACE_FILENAME + run_script("data/scripts/trace/supported", &config); + is_int(0, access(trace, F_OK), "Trace file was created"); + unlink(trace); +#else + run_script("data/scripts/trace/unsupported", &config); + is_int(-1, access(trace, F_OK), "Trace file does not exist"); +#endif + + free(trace); + test_tmpdir_free(tmpdir); + return 0; +} |
