1 /* 2 * Authentication tests for the pam-krb5 module with ticket cache. 3 * 4 * This test case includes all tests that require Kerberos to be configured, a 5 * username and password available, and a ticket cache created, but with the 6 * PAM module running as the same user for which the ticket cache will be 7 * created (so without setuid and with chown doing nothing). 8 * 9 * Written by Russ Allbery <eagle@eyrie.org> 10 * Copyright 2020 Russ Allbery <eagle@eyrie.org> 11 * Copyright 2011-2012, 2014 12 * The Board of Trustees of the Leland Stanford Junior University 13 * 14 * SPDX-License-Identifier: BSD-3-clause or GPL-1+ 15 */ 16 17 #include <config.h> 18 #include <portable/krb5.h> 19 #include <portable/pam.h> 20 #include <portable/system.h> 21 22 #include <pwd.h> 23 #include <sys/stat.h> 24 #include <time.h> 25 26 #include <tests/fakepam/pam.h> 27 #include <tests/fakepam/script.h> 28 #include <tests/tap/basic.h> 29 #include <tests/tap/kerberos.h> 30 #include <tests/tap/macros.h> 31 #include <tests/tap/process.h> 32 #include <tests/tap/string.h> 33 34 35 static void 36 check_authtok(pam_handle_t *pamh, const struct script_config *config, 37 void *data UNUSED) 38 { 39 int retval; 40 const char *authtok; 41 42 retval = pam_get_item(pamh, PAM_AUTHTOK, (PAM_CONST void **) &authtok); 43 is_int(PAM_SUCCESS, retval, "Found PAM_AUTHTOK"); 44 is_string(config->newpass, authtok, "...and it is correct"); 45 } 46 47 48 int 49 main(void) 50 { 51 struct script_config config; 52 struct kerberos_config *krbconf; 53 char *newpass; 54 55 /* Load the Kerberos principal and password from a file. */ 56 krbconf = kerberos_setup(TAP_KRB_NEEDS_PASSWORD); 57 memset(&config, 0, sizeof(config)); 58 config.user = krbconf->username; 59 config.password = krbconf->password; 60 config.extra[0] = krbconf->userprinc; 61 62 /* Generate a testing krb5.conf file. */ 63 kerberos_generate_conf(krbconf->realm); 64 65 plan_lazy(); 66 67 /* 68 * First test trying to change the password to something that's 69 * excessively long. 70 */ 71 newpass = bcalloc_type(PAM_MAX_RESP_SIZE + 1, char); 72 memset(newpass, 'a', PAM_MAX_RESP_SIZE); 73 config.newpass = newpass; 74 run_script("data/scripts/password/too-long", &config); 75 run_script("data/scripts/password/too-long-debug", &config); 76 77 /* Test use_authtok with an excessively long password. */ 78 config.newpass = NULL; 79 config.authtok = newpass; 80 run_script("data/scripts/password/authtok-too-long", &config); 81 run_script("data/scripts/password/authtok-too-long-debug", &config); 82 83 /* 84 * Change the password to something new. This needs to be sufficiently 85 * random that it's unlikely to fall afoul of password strength checking. 86 */ 87 free(newpass); 88 config.authtok = NULL; 89 basprintf(&newpass, "ngh1,a%lu nn9af6%lu", (unsigned long) getpid(), 90 (unsigned long) time(NULL)); 91 config.newpass = newpass; 92 run_script("data/scripts/password/basic", &config); 93 config.password = newpass; 94 config.newpass = krbconf->password; 95 run_script("data/scripts/password/basic-debug", &config); 96 97 /* Test prompt_principal with password change. */ 98 config.password = krbconf->password; 99 config.newpass = newpass; 100 run_script("data/scripts/password/prompt-principal", &config); 101 102 /* Change the password back and test expose-account. */ 103 config.password = newpass; 104 config.newpass = krbconf->password; 105 run_script("data/scripts/password/expose", &config); 106 107 /* 108 * Test two banner settings by changing the password and then changing it 109 * back again. 110 */ 111 config.password = krbconf->password; 112 config.newpass = newpass; 113 run_script("data/scripts/password/banner", &config); 114 config.password = newpass; 115 config.newpass = krbconf->password; 116 run_script("data/scripts/password/no-banner", &config); 117 118 /* Do the same, but with expose_account set as well. */ 119 config.password = krbconf->password; 120 config.newpass = newpass; 121 run_script("data/scripts/password/banner-expose", &config); 122 config.password = newpass; 123 config.newpass = krbconf->password; 124 run_script("data/scripts/password/no-banner-expose", &config); 125 126 /* Test use_authtok. */ 127 config.password = krbconf->password; 128 config.newpass = NULL; 129 config.authtok = newpass; 130 run_script("data/scripts/password/authtok", &config); 131 132 /* Test use_authtok with force_first_pass. */ 133 config.password = NULL; 134 config.authtok = krbconf->password; 135 config.oldauthtok = newpass; 136 run_script("data/scripts/password/authtok-force", &config); 137 138 /* 139 * Ensure PAM_AUTHTOK and PAM_OLDAUTHTOK are set even if the user is 140 * ignored. 141 */ 142 config.user = "root"; 143 config.authtok = NULL; 144 config.oldauthtok = NULL; 145 config.password = "old-password"; 146 config.newpass = "new-password"; 147 config.callback = check_authtok; 148 run_script("data/scripts/password/ignore", &config); 149 150 free(newpass); 151 return 0; 152 } 153