pam_get_authtok.c revision 107937
11573Srgrimes/*-
21573Srgrimes * Copyright (c) 2002 Networks Associates Technology, Inc.
31573Srgrimes * All rights reserved.
41573Srgrimes *
51573Srgrimes * This software was developed for the FreeBSD Project by ThinkSec AS and
61573Srgrimes * Network Associates Laboratories, the Security Research Division of
71573Srgrimes * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
81573Srgrimes * ("CBOSS"), as part of the DARPA CHATS research program.
91573Srgrimes *
101573Srgrimes * Redistribution and use in source and binary forms, with or without
111573Srgrimes * modification, are permitted provided that the following conditions
121573Srgrimes * are met:
131573Srgrimes * 1. Redistributions of source code must retain the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer.
151573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161573Srgrimes *    notice, this list of conditions and the following disclaimer in the
171573Srgrimes *    documentation and/or other materials provided with the distribution.
181573Srgrimes * 3. The name of the author may not be used to endorse or promote
191573Srgrimes *    products derived from this software without specific prior written
201573Srgrimes *    permission.
211573Srgrimes *
221573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
231573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
261573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321573Srgrimes * SUCH DAMAGE.
3392986Sobrien *
3492986Sobrien * $P4: //depot/projects/openpam/lib/pam_get_authtok.c#20 $
351573Srgrimes */
361573Srgrimes
371573Srgrimes#include <sys/param.h>
381573Srgrimes
391573Srgrimes#include <stdlib.h>
40218285Sjilles#include <string.h>
41218285Sjilles
42218285Sjilles#include <security/pam_appl.h>
43218285Sjilles#include <security/openpam.h>
44218285Sjilles
45218285Sjilles#include "openpam_impl.h"
46218285Sjilles
47218285Sjillesconst char authtok_prompt[] = "Password:";
48218285Sjillesconst char oldauthtok_prompt[] = "Old Password:";
49218285Sjillesconst char newauthtok_prompt[] = "New Password:";
50218285Sjilles
51218285Sjilles/*
52218285Sjilles * OpenPAM extension
53218285Sjilles *
54218285Sjilles * Retrieve authentication token
55218285Sjilles */
56218285Sjilles
57218285Sjillesint
58218285Sjillespam_get_authtok(pam_handle_t *pamh,
59218285Sjilles	int item,
60218285Sjilles	const char **authtok,
61218285Sjilles	const char *prompt)
62218285Sjilles{
63218285Sjilles	const void *oldauthtok;
64218285Sjilles	const char *default_prompt;
65218285Sjilles	char *resp, *resp2;
66218285Sjilles	int pitem, r, style, twice;
67218285Sjilles
68218285Sjilles	ENTER();
69218285Sjilles	if (pamh == NULL || authtok == NULL)
70218285Sjilles		RETURNC(PAM_SYSTEM_ERR);
711573Srgrimes	*authtok = NULL;
721573Srgrimes	twice = 0;
731573Srgrimes	switch (item) {
741573Srgrimes	case PAM_AUTHTOK:
751573Srgrimes		pitem = PAM_AUTHTOK_PROMPT;
761573Srgrimes		default_prompt = authtok_prompt;
771573Srgrimes		r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok);
781573Srgrimes		if (r == PAM_SUCCESS && oldauthtok != NULL) {
791573Srgrimes			default_prompt = newauthtok_prompt;
801573Srgrimes			twice = 1;
811573Srgrimes		}
821573Srgrimes		break;
831573Srgrimes	case PAM_OLDAUTHTOK:
841573Srgrimes		pitem = PAM_OLDAUTHTOK_PROMPT;
851573Srgrimes		default_prompt = oldauthtok_prompt;
861573Srgrimes		twice = 0;
871573Srgrimes		break;
881573Srgrimes	default:
891573Srgrimes		RETURNC(PAM_SYMBOL_ERR);
901573Srgrimes	}
911573Srgrimes	if (openpam_get_option(pamh, "try_first_pass") ||
921573Srgrimes	    openpam_get_option(pamh, "use_first_pass")) {
931573Srgrimes		r = pam_get_item(pamh, item, (const void **)authtok);
941573Srgrimes		if (r == PAM_SUCCESS && *authtok != NULL)
951573Srgrimes			RETURNC(PAM_SUCCESS);
961573Srgrimes		else if (openpam_get_option(pamh, "use_first_pass"))
971573Srgrimes			RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r);
981573Srgrimes	}
991573Srgrimes	if (prompt == NULL) {
1001573Srgrimes		r = pam_get_item(pamh, pitem, (const void **)&prompt);
1011573Srgrimes		if (r != PAM_SUCCESS || prompt == NULL)
1021573Srgrimes			prompt = default_prompt;
1031573Srgrimes	}
1041573Srgrimes	style = openpam_get_option(pamh, "echo_pass") ?
1051573Srgrimes	    PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
1061573Srgrimes	r = pam_prompt(pamh, style, &resp, "%s", prompt);
10747289Speter	if (r != PAM_SUCCESS)
108		RETURNC(r);
109	if (twice) {
110		r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt);
111		if (r != PAM_SUCCESS) {
112			free(resp);
113			RETURNC(r);
114		}
115		if (strcmp(resp, resp2) != 0) {
116			free(resp);
117			resp = NULL;
118		}
119		free(resp2);
120	}
121	if (resp == NULL)
122		RETURNC(PAM_TRY_AGAIN);
123	r = pam_set_item(pamh, item, resp);
124	free(resp);
125	if (r != PAM_SUCCESS)
126		RETURNC(r);
127	RETURNC(pam_get_item(pamh, item, (const void **)authtok));
128}
129
130/*
131 * Error codes:
132 *
133 *	=pam_get_item
134 *	=pam_prompt
135 *	=pam_set_item
136 *	!PAM_SYMBOL_ERR
137 *	PAM_TRY_AGAIN
138 */
139
140/**
141 * The =pam_get_authtok function returns the cached authentication token,
142 * or prompts the user if no token is currently cached.  Either way, a
143 * pointer to the authentication token is stored in the location pointed
144 * to by the =authtok argument.
145 *
146 * The =item argument must have one of the following values:
147 *
148 *	=PAM_AUTHTOK:
149 *		Returns the current authentication token, or the new token
150 *		when changing authentication tokens.
151 *	=PAM_OLDAUTHTOK:
152 *		Returns the previous authentication token when changing
153 *		authentication tokens.
154 *
155 * The =prompt argument specifies a prompt to use if no token is cached.
156 * If it is =NULL, the =PAM_AUTHTOK_PROMPT or =PAM_OLDAUTHTOK_PROMPT item,
157 * as appropriate, will be used.  If that item is also =NULL, a hardcoded
158 * default prompt will be used.
159 *
160 * If =item is set to =PAM_AUTHTOK and there is a non-null =PAM_OLDAUTHTOK
161 * item, =pam_get_authtok will ask the user to confirm the new token by
162 * retyping it.  If there is a mismatch, =pam_get_authtok will return
163 * =PAM_TRY_AGAIN.
164 *
165 * >pam_get_item
166 * >pam_get_user
167 */
168