1/*- 2 * Copyright (c) 2002-2003 Networks Associates Technology, Inc. 3 * Copyright (c) 2004-2007 Dag-Erling Smørgrav 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by ThinkSec AS and 7 * Network Associates Laboratories, the Security Research Division of 8 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9 * ("CBOSS"), as part of the DARPA CHATS research program. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote 20 * products derived from this software without specific prior written 21 * permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $Id: pam_get_authtok.c 408 2007-12-21 11:36:24Z des $ 36 */ 37 38#include <sys/param.h> 39 40#include <stdlib.h> 41#include <string.h> 42 43#include <security/pam_appl.h> 44#include <security/openpam.h> 45 46#include "openpam_impl.h" 47 48static const char authtok_prompt[] = "Password:"; 49static const char oldauthtok_prompt[] = "Old Password:"; 50static const char newauthtok_prompt[] = "New Password:"; 51 52/* 53 * OpenPAM extension 54 * 55 * Retrieve authentication token 56 */ 57 58int 59pam_get_authtok(pam_handle_t *pamh, 60 int item, 61 const char **authtok, 62 const char *prompt) 63{ 64 const void *oldauthtok, *prevauthtok, *promptp; 65 const char *default_prompt; 66 char *resp, *resp2; 67 int pitem, r, style, twice; 68 69 ENTER(); 70 if (pamh == NULL || authtok == NULL) 71 RETURNC(PAM_SYSTEM_ERR); 72 *authtok = NULL; 73 twice = 0; 74 switch (item) { 75 case PAM_AUTHTOK: 76 pitem = PAM_AUTHTOK_PROMPT; 77 default_prompt = authtok_prompt; 78 r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok); 79 if (r == PAM_SUCCESS && oldauthtok != NULL) { 80 default_prompt = newauthtok_prompt; 81 twice = 1; 82 } 83 break; 84 case PAM_OLDAUTHTOK: 85 pitem = PAM_OLDAUTHTOK_PROMPT; 86 default_prompt = oldauthtok_prompt; 87 twice = 0; 88 break; 89 default: 90 RETURNC(PAM_SYMBOL_ERR); 91 } 92 if (openpam_get_option(pamh, "try_first_pass") || 93 openpam_get_option(pamh, "use_first_pass")) { 94 r = pam_get_item(pamh, item, &prevauthtok); 95 if (r == PAM_SUCCESS && prevauthtok != NULL) { 96 *authtok = prevauthtok; 97 RETURNC(PAM_SUCCESS); 98 } 99 else if (openpam_get_option(pamh, "use_first_pass")) 100 RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r); 101 } 102 if (prompt == NULL) { 103 r = pam_get_item(pamh, pitem, &promptp); 104 if (r != PAM_SUCCESS || promptp == NULL) 105 prompt = default_prompt; 106 else 107 prompt = promptp; 108 } 109 style = openpam_get_option(pamh, "echo_pass") ? 110 PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; 111 r = pam_prompt(pamh, style, &resp, "%s", prompt); 112 if (r != PAM_SUCCESS) 113 RETURNC(r); 114 if (twice) { 115 r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt); 116 if (r != PAM_SUCCESS) { 117 FREE(resp); 118 RETURNC(r); 119 } 120 if (strcmp(resp, resp2) != 0) 121 FREE(resp); 122 FREE(resp2); 123 } 124 if (resp == NULL) 125 RETURNC(PAM_TRY_AGAIN); 126 r = pam_set_item(pamh, item, resp); 127 FREE(resp); 128 if (r != PAM_SUCCESS) 129 RETURNC(r); 130 r = pam_get_item(pamh, item, (const void **)authtok); 131 RETURNC(r); 132} 133 134/* 135 * Error codes: 136 * 137 * =pam_get_item 138 * =pam_prompt 139 * =pam_set_item 140 * !PAM_SYMBOL_ERR 141 * PAM_TRY_AGAIN 142 */ 143 144/** 145 * The =pam_get_authtok function returns the cached authentication token, 146 * or prompts the user if no token is currently cached. 147 * Either way, a pointer to the authentication token is stored in the 148 * location pointed to by the =authtok argument. 149 * 150 * The =item argument must have one of the following values: 151 * 152 * =PAM_AUTHTOK: 153 * Returns the current authentication token, or the new token 154 * when changing authentication tokens. 155 * =PAM_OLDAUTHTOK: 156 * Returns the previous authentication token when changing 157 * authentication tokens. 158 * 159 * The =prompt argument specifies a prompt to use if no token is cached. 160 * If it is =NULL, the =PAM_AUTHTOK_PROMPT or =PAM_OLDAUTHTOK_PROMPT item, 161 * as appropriate, will be used. 162 * If that item is also =NULL, a hardcoded default prompt will be used. 163 * 164 * If =item is set to =PAM_AUTHTOK and there is a non-null =PAM_OLDAUTHTOK 165 * item, =pam_get_authtok will ask the user to confirm the new token by 166 * retyping it. 167 * If there is a mismatch, =pam_get_authtok will return =PAM_TRY_AGAIN. 168 * 169 * >pam_get_item 170 * >pam_get_user 171 */ 172