1f7e6344dSDag-Erling Smørgrav /*- 2f7e6344dSDag-Erling Smørgrav * Copyright (c) 2002-2003 Networks Associates Technology, Inc. 3f3b0ac34SDag-Erling Smørgrav * Copyright (c) 2004-2017 Dag-Erling Smørgrav 4f7e6344dSDag-Erling Smørgrav * All rights reserved. 5f7e6344dSDag-Erling Smørgrav * 6f7e6344dSDag-Erling Smørgrav * This software was developed for the FreeBSD Project by ThinkSec AS and 7f7e6344dSDag-Erling Smørgrav * Network Associates Laboratories, the Security Research Division of 8f7e6344dSDag-Erling Smørgrav * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9f7e6344dSDag-Erling Smørgrav * ("CBOSS"), as part of the DARPA CHATS research program. 10f7e6344dSDag-Erling Smørgrav * 11f7e6344dSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 12f7e6344dSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 13f7e6344dSDag-Erling Smørgrav * are met: 14f7e6344dSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 15f7e6344dSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 16f7e6344dSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 17f7e6344dSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 18f7e6344dSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 19f7e6344dSDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote 20f7e6344dSDag-Erling Smørgrav * products derived from this software without specific prior written 21f7e6344dSDag-Erling Smørgrav * permission. 22f7e6344dSDag-Erling Smørgrav * 23f7e6344dSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24f7e6344dSDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25f7e6344dSDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26f7e6344dSDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27f7e6344dSDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28f7e6344dSDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29f7e6344dSDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30f7e6344dSDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31f7e6344dSDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32f7e6344dSDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33f7e6344dSDag-Erling Smørgrav * SUCH DAMAGE. 34f7e6344dSDag-Erling Smørgrav * 35*49e56509SDag-Erling Smørgrav * $OpenPAM: pam_get_authtok.c 938 2017-04-30 21:34:42Z des $ 36f7e6344dSDag-Erling Smørgrav */ 37f7e6344dSDag-Erling Smørgrav 38f7e6344dSDag-Erling Smørgrav #ifdef HAVE_CONFIG_H 39f7e6344dSDag-Erling Smørgrav # include "config.h" 40f7e6344dSDag-Erling Smørgrav #endif 41f7e6344dSDag-Erling Smørgrav 42f7e6344dSDag-Erling Smørgrav #include <sys/param.h> 43f7e6344dSDag-Erling Smørgrav 44f7e6344dSDag-Erling Smørgrav #include <stdlib.h> 45f7e6344dSDag-Erling Smørgrav #include <string.h> 46f7e6344dSDag-Erling Smørgrav 47f7e6344dSDag-Erling Smørgrav #include <security/pam_appl.h> 48f7e6344dSDag-Erling Smørgrav #include <security/openpam.h> 49f7e6344dSDag-Erling Smørgrav 50f7e6344dSDag-Erling Smørgrav #include "openpam_impl.h" 51d64f4044SDag-Erling Smørgrav #include "openpam_strlset.h" 52f7e6344dSDag-Erling Smørgrav 53f7e6344dSDag-Erling Smørgrav static const char authtok_prompt[] = "Password:"; 54f7e6344dSDag-Erling Smørgrav static const char authtok_prompt_remote[] = "Password for %u@%h:"; 55f7e6344dSDag-Erling Smørgrav static const char oldauthtok_prompt[] = "Old Password:"; 56f7e6344dSDag-Erling Smørgrav static const char newauthtok_prompt[] = "New Password:"; 57f7e6344dSDag-Erling Smørgrav 58f7e6344dSDag-Erling Smørgrav /* 59f7e6344dSDag-Erling Smørgrav * OpenPAM extension 60f7e6344dSDag-Erling Smørgrav * 61f7e6344dSDag-Erling Smørgrav * Retrieve authentication token 62f7e6344dSDag-Erling Smørgrav */ 63f7e6344dSDag-Erling Smørgrav 64f7e6344dSDag-Erling Smørgrav int 65f7e6344dSDag-Erling Smørgrav pam_get_authtok(pam_handle_t *pamh, 66f7e6344dSDag-Erling Smørgrav int item, 67f7e6344dSDag-Erling Smørgrav const char **authtok, 68f7e6344dSDag-Erling Smørgrav const char *prompt) 69f7e6344dSDag-Erling Smørgrav { 70f7e6344dSDag-Erling Smørgrav char prompt_buf[1024]; 71f7e6344dSDag-Erling Smørgrav size_t prompt_size; 72f7e6344dSDag-Erling Smørgrav const void *oldauthtok, *prevauthtok, *promptp; 73f7e6344dSDag-Erling Smørgrav const char *prompt_option, *default_prompt; 74f7e6344dSDag-Erling Smørgrav const void *lhost, *rhost; 75f7e6344dSDag-Erling Smørgrav char *resp, *resp2; 76f7e6344dSDag-Erling Smørgrav int pitem, r, style, twice; 77f7e6344dSDag-Erling Smørgrav 78f7e6344dSDag-Erling Smørgrav ENTER(); 79f7e6344dSDag-Erling Smørgrav *authtok = NULL; 80f7e6344dSDag-Erling Smørgrav twice = 0; 81f7e6344dSDag-Erling Smørgrav switch (item) { 82f7e6344dSDag-Erling Smørgrav case PAM_AUTHTOK: 83f7e6344dSDag-Erling Smørgrav pitem = PAM_AUTHTOK_PROMPT; 84f7e6344dSDag-Erling Smørgrav prompt_option = "authtok_prompt"; 85f7e6344dSDag-Erling Smørgrav default_prompt = authtok_prompt; 86f7e6344dSDag-Erling Smørgrav r = pam_get_item(pamh, PAM_RHOST, &rhost); 87f7e6344dSDag-Erling Smørgrav if (r == PAM_SUCCESS && rhost != NULL) { 88f7e6344dSDag-Erling Smørgrav r = pam_get_item(pamh, PAM_HOST, &lhost); 89f7e6344dSDag-Erling Smørgrav if (r == PAM_SUCCESS && lhost != NULL) { 90f7e6344dSDag-Erling Smørgrav if (strcmp(rhost, lhost) != 0) 91f7e6344dSDag-Erling Smørgrav default_prompt = authtok_prompt_remote; 92f7e6344dSDag-Erling Smørgrav } 93f7e6344dSDag-Erling Smørgrav } 94f7e6344dSDag-Erling Smørgrav r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok); 95f7e6344dSDag-Erling Smørgrav if (r == PAM_SUCCESS && oldauthtok != NULL) { 96f7e6344dSDag-Erling Smørgrav default_prompt = newauthtok_prompt; 97f7e6344dSDag-Erling Smørgrav twice = 1; 98f7e6344dSDag-Erling Smørgrav } 99f7e6344dSDag-Erling Smørgrav break; 100f7e6344dSDag-Erling Smørgrav case PAM_OLDAUTHTOK: 101f7e6344dSDag-Erling Smørgrav pitem = PAM_OLDAUTHTOK_PROMPT; 102f7e6344dSDag-Erling Smørgrav prompt_option = "oldauthtok_prompt"; 103f7e6344dSDag-Erling Smørgrav default_prompt = oldauthtok_prompt; 104f7e6344dSDag-Erling Smørgrav twice = 0; 105f7e6344dSDag-Erling Smørgrav break; 106f7e6344dSDag-Erling Smørgrav default: 107*49e56509SDag-Erling Smørgrav RETURNC(PAM_BAD_CONSTANT); 108f7e6344dSDag-Erling Smørgrav } 109f7e6344dSDag-Erling Smørgrav if (openpam_get_option(pamh, "try_first_pass") || 110f7e6344dSDag-Erling Smørgrav openpam_get_option(pamh, "use_first_pass")) { 111f7e6344dSDag-Erling Smørgrav r = pam_get_item(pamh, item, &prevauthtok); 112f7e6344dSDag-Erling Smørgrav if (r == PAM_SUCCESS && prevauthtok != NULL) { 113f7e6344dSDag-Erling Smørgrav *authtok = prevauthtok; 114f7e6344dSDag-Erling Smørgrav RETURNC(PAM_SUCCESS); 115ce77a8d6SDag-Erling Smørgrav } else if (openpam_get_option(pamh, "use_first_pass")) { 116f7e6344dSDag-Erling Smørgrav RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r); 117f7e6344dSDag-Erling Smørgrav } 118ce77a8d6SDag-Erling Smørgrav } 119f7e6344dSDag-Erling Smørgrav /* pam policy overrides the module's choice */ 120f7e6344dSDag-Erling Smørgrav if ((promptp = openpam_get_option(pamh, prompt_option)) != NULL) 121f7e6344dSDag-Erling Smørgrav prompt = promptp; 122f7e6344dSDag-Erling Smørgrav /* no prompt provided, see if there is one tucked away somewhere */ 123f3b0ac34SDag-Erling Smørgrav if (prompt == NULL) { 124f3b0ac34SDag-Erling Smørgrav r = pam_get_item(pamh, pitem, &promptp); 125f3b0ac34SDag-Erling Smørgrav if (r == PAM_SUCCESS && promptp != NULL) 126f7e6344dSDag-Erling Smørgrav prompt = promptp; 127f3b0ac34SDag-Erling Smørgrav } 128f7e6344dSDag-Erling Smørgrav /* fall back to hardcoded default */ 129f7e6344dSDag-Erling Smørgrav if (prompt == NULL) 130f7e6344dSDag-Erling Smørgrav prompt = default_prompt; 131f7e6344dSDag-Erling Smørgrav /* expand */ 132f7e6344dSDag-Erling Smørgrav prompt_size = sizeof prompt_buf; 133f7e6344dSDag-Erling Smørgrav r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt); 134f7e6344dSDag-Erling Smørgrav if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf) 135f7e6344dSDag-Erling Smørgrav prompt = prompt_buf; 136f7e6344dSDag-Erling Smørgrav style = openpam_get_option(pamh, "echo_pass") ? 137f7e6344dSDag-Erling Smørgrav PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; 138f7e6344dSDag-Erling Smørgrav r = pam_prompt(pamh, style, &resp, "%s", prompt); 139f7e6344dSDag-Erling Smørgrav if (r != PAM_SUCCESS) 140f7e6344dSDag-Erling Smørgrav RETURNC(r); 141f7e6344dSDag-Erling Smørgrav if (twice) { 142f7e6344dSDag-Erling Smørgrav r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt); 143f7e6344dSDag-Erling Smørgrav if (r != PAM_SUCCESS) { 144d64f4044SDag-Erling Smørgrav strlset(resp, 0, PAM_MAX_RESP_SIZE); 145f7e6344dSDag-Erling Smørgrav FREE(resp); 146f7e6344dSDag-Erling Smørgrav RETURNC(r); 147f7e6344dSDag-Erling Smørgrav } 148d64f4044SDag-Erling Smørgrav if (strcmp(resp, resp2) != 0) { 149d64f4044SDag-Erling Smørgrav strlset(resp, 0, PAM_MAX_RESP_SIZE); 150f7e6344dSDag-Erling Smørgrav FREE(resp); 151d64f4044SDag-Erling Smørgrav } 152d64f4044SDag-Erling Smørgrav strlset(resp2, 0, PAM_MAX_RESP_SIZE); 153f7e6344dSDag-Erling Smørgrav FREE(resp2); 154f7e6344dSDag-Erling Smørgrav } 155f7e6344dSDag-Erling Smørgrav if (resp == NULL) 156f7e6344dSDag-Erling Smørgrav RETURNC(PAM_TRY_AGAIN); 157f7e6344dSDag-Erling Smørgrav r = pam_set_item(pamh, item, resp); 158d64f4044SDag-Erling Smørgrav strlset(resp, 0, PAM_MAX_RESP_SIZE); 159f7e6344dSDag-Erling Smørgrav FREE(resp); 160f7e6344dSDag-Erling Smørgrav if (r != PAM_SUCCESS) 161f7e6344dSDag-Erling Smørgrav RETURNC(r); 162f7e6344dSDag-Erling Smørgrav r = pam_get_item(pamh, item, (const void **)authtok); 163f7e6344dSDag-Erling Smørgrav RETURNC(r); 164f7e6344dSDag-Erling Smørgrav } 165f7e6344dSDag-Erling Smørgrav 166f7e6344dSDag-Erling Smørgrav /* 167f7e6344dSDag-Erling Smørgrav * Error codes: 168f7e6344dSDag-Erling Smørgrav * 169f7e6344dSDag-Erling Smørgrav * =pam_get_item 170f7e6344dSDag-Erling Smørgrav * =pam_prompt 171f7e6344dSDag-Erling Smørgrav * =pam_set_item 172f7e6344dSDag-Erling Smørgrav * !PAM_SYMBOL_ERR 173*49e56509SDag-Erling Smørgrav * PAM_BAD_CONSTANT 174f7e6344dSDag-Erling Smørgrav * PAM_TRY_AGAIN 175f7e6344dSDag-Erling Smørgrav */ 176f7e6344dSDag-Erling Smørgrav 177f7e6344dSDag-Erling Smørgrav /** 178ce77a8d6SDag-Erling Smørgrav * The =pam_get_authtok function either prompts the user for an 179ce77a8d6SDag-Erling Smørgrav * authentication token or retrieves a cached authentication token, 180ce77a8d6SDag-Erling Smørgrav * depending on circumstances. 181f7e6344dSDag-Erling Smørgrav * Either way, a pointer to the authentication token is stored in the 182ce77a8d6SDag-Erling Smørgrav * location pointed to by the =authtok argument, and the corresponding PAM 183ce77a8d6SDag-Erling Smørgrav * item is updated. 184f7e6344dSDag-Erling Smørgrav * 185f7e6344dSDag-Erling Smørgrav * The =item argument must have one of the following values: 186f7e6344dSDag-Erling Smørgrav * 187f7e6344dSDag-Erling Smørgrav * =PAM_AUTHTOK: 188f7e6344dSDag-Erling Smørgrav * Returns the current authentication token, or the new token 189f7e6344dSDag-Erling Smørgrav * when changing authentication tokens. 190f7e6344dSDag-Erling Smørgrav * =PAM_OLDAUTHTOK: 191f7e6344dSDag-Erling Smørgrav * Returns the previous authentication token when changing 192f7e6344dSDag-Erling Smørgrav * authentication tokens. 193f7e6344dSDag-Erling Smørgrav * 194f7e6344dSDag-Erling Smørgrav * The =prompt argument specifies a prompt to use if no token is cached. 195f7e6344dSDag-Erling Smørgrav * If it is =NULL, the =PAM_AUTHTOK_PROMPT or =PAM_OLDAUTHTOK_PROMPT item, 196f7e6344dSDag-Erling Smørgrav * as appropriate, will be used. 197f7e6344dSDag-Erling Smørgrav * If that item is also =NULL, a hardcoded default prompt will be used. 198ce77a8d6SDag-Erling Smørgrav * Additionally, when =pam_get_authtok is called from a service module, 199ce77a8d6SDag-Erling Smørgrav * the prompt may be affected by module options as described below. 200ce77a8d6SDag-Erling Smørgrav * The prompt is then expanded using =openpam_subst before it is passed to 201ce77a8d6SDag-Erling Smørgrav * the conversation function. 202f7e6344dSDag-Erling Smørgrav * 203f7e6344dSDag-Erling Smørgrav * If =item is set to =PAM_AUTHTOK and there is a non-null =PAM_OLDAUTHTOK 204f7e6344dSDag-Erling Smørgrav * item, =pam_get_authtok will ask the user to confirm the new token by 205f7e6344dSDag-Erling Smørgrav * retyping it. 206f7e6344dSDag-Erling Smørgrav * If there is a mismatch, =pam_get_authtok will return =PAM_TRY_AGAIN. 207f7e6344dSDag-Erling Smørgrav * 208ce77a8d6SDag-Erling Smørgrav * MODULE OPTIONS 209ce77a8d6SDag-Erling Smørgrav * 210ce77a8d6SDag-Erling Smørgrav * When called by a service module, =pam_get_authtok will recognize the 211ce77a8d6SDag-Erling Smørgrav * following module options: 212ce77a8d6SDag-Erling Smørgrav * 213ce77a8d6SDag-Erling Smørgrav * ;authtok_prompt: 214ce77a8d6SDag-Erling Smørgrav * Prompt to use when =item is set to =PAM_AUTHTOK. 215ce77a8d6SDag-Erling Smørgrav * This option overrides both the =prompt argument and the 216ce77a8d6SDag-Erling Smørgrav * =PAM_AUTHTOK_PROMPT item. 217ce77a8d6SDag-Erling Smørgrav * ;echo_pass: 218ce77a8d6SDag-Erling Smørgrav * If the application's conversation function allows it, this 219ce77a8d6SDag-Erling Smørgrav * lets the user see what they are typing. 220ce77a8d6SDag-Erling Smørgrav * This should only be used for non-reusable authentication 221ce77a8d6SDag-Erling Smørgrav * tokens. 222ce77a8d6SDag-Erling Smørgrav * ;oldauthtok_prompt: 223ce77a8d6SDag-Erling Smørgrav * Prompt to use when =item is set to =PAM_OLDAUTHTOK. 224ce77a8d6SDag-Erling Smørgrav * This option overrides both the =prompt argument and the 225ce77a8d6SDag-Erling Smørgrav * =PAM_OLDAUTHTOK_PROMPT item. 226ce77a8d6SDag-Erling Smørgrav * ;try_first_pass: 227ce77a8d6SDag-Erling Smørgrav * If the requested item is non-null, return it without 228ce77a8d6SDag-Erling Smørgrav * prompting the user. 229ce77a8d6SDag-Erling Smørgrav * Typically, the service module will verify the token, and 230ce77a8d6SDag-Erling Smørgrav * if it does not match, clear the item before calling 231ce77a8d6SDag-Erling Smørgrav * =pam_get_authtok a second time. 232ce77a8d6SDag-Erling Smørgrav * ;use_first_pass: 233ce77a8d6SDag-Erling Smørgrav * Do not prompt the user at all; just return the cached 234ce77a8d6SDag-Erling Smørgrav * value, or =PAM_AUTH_ERR if there is none. 235ce77a8d6SDag-Erling Smørgrav * 236ce77a8d6SDag-Erling Smørgrav * >pam_conv 237f7e6344dSDag-Erling Smørgrav * >pam_get_item 238f7e6344dSDag-Erling Smørgrav * >pam_get_user 239ce77a8d6SDag-Erling Smørgrav * >openpam_get_option 240f7e6344dSDag-Erling Smørgrav * >openpam_subst 241f7e6344dSDag-Erling Smørgrav */ 242