pam_get_authtok.c revision 110556
191094Sdes/*-
292289Sdes * Copyright (c) 2002 Networks Associates Technology, Inc.
391094Sdes * All rights reserved.
491094Sdes *
591094Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and
699158Sdes * Network Associates Laboratories, the Security Research Division of
799158Sdes * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
899158Sdes * ("CBOSS"), as part of the DARPA CHATS research program.
991094Sdes *
1091094Sdes * Redistribution and use in source and binary forms, with or without
1191094Sdes * modification, are permitted provided that the following conditions
1291094Sdes * are met:
1391094Sdes * 1. Redistributions of source code must retain the above copyright
1491094Sdes *    notice, this list of conditions and the following disclaimer.
1591094Sdes * 2. Redistributions in binary form must reproduce the above copyright
1691094Sdes *    notice, this list of conditions and the following disclaimer in the
1791094Sdes *    documentation and/or other materials provided with the distribution.
1891094Sdes * 3. The name of the author may not be used to endorse or promote
1991094Sdes *    products derived from this software without specific prior written
2091094Sdes *    permission.
2191094Sdes *
2291094Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2391094Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2491094Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2591094Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2691094Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2791094Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2891094Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2991094Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3091094Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3191094Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3291094Sdes * SUCH DAMAGE.
3391094Sdes *
34110556Sdes * $P4: //depot/projects/openpam/lib/pam_get_authtok.c#21 $
3591094Sdes */
3691094Sdes
3791094Sdes#include <sys/param.h>
3891094Sdes
3993982Sdes#include <stdlib.h>
4096364Sdes#include <string.h>
4193982Sdes
4291094Sdes#include <security/pam_appl.h>
4391094Sdes#include <security/openpam.h>
4491094Sdes
4591094Sdes#include "openpam_impl.h"
4691094Sdes
4793982Sdesconst char authtok_prompt[] = "Password:";
4893982Sdesconst char oldauthtok_prompt[] = "Old Password:";
4993982Sdesconst char newauthtok_prompt[] = "New Password:";
5093982Sdes
5191094Sdes/*
5291094Sdes * OpenPAM extension
5391094Sdes *
5491094Sdes * Retrieve authentication token
5591094Sdes */
5691094Sdes
5791094Sdesint
5891094Sdespam_get_authtok(pam_handle_t *pamh,
5993982Sdes	int item,
6091094Sdes	const char **authtok,
6191094Sdes	const char *prompt)
6291094Sdes{
6393982Sdes	const void *oldauthtok;
6493982Sdes	const char *default_prompt;
6593982Sdes	char *resp, *resp2;
6693982Sdes	int pitem, r, style, twice;
6791094Sdes
68107937Sdes	ENTER();
6991094Sdes	if (pamh == NULL || authtok == NULL)
70107937Sdes		RETURNC(PAM_SYSTEM_ERR);
7193982Sdes	*authtok = NULL;
7293982Sdes	twice = 0;
7393982Sdes	switch (item) {
7493982Sdes	case PAM_AUTHTOK:
7593982Sdes		pitem = PAM_AUTHTOK_PROMPT;
7693982Sdes		default_prompt = authtok_prompt;
7793982Sdes		r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok);
7893982Sdes		if (r == PAM_SUCCESS && oldauthtok != NULL) {
7993982Sdes			default_prompt = newauthtok_prompt;
8093982Sdes			twice = 1;
8193982Sdes		}
8293982Sdes		break;
8393982Sdes	case PAM_OLDAUTHTOK:
8493982Sdes		pitem = PAM_OLDAUTHTOK_PROMPT;
8593982Sdes		default_prompt = oldauthtok_prompt;
8693982Sdes		twice = 0;
8793982Sdes		break;
8893982Sdes	default:
89107937Sdes		RETURNC(PAM_SYMBOL_ERR);
9093982Sdes	}
9191100Sdes	if (openpam_get_option(pamh, "try_first_pass") ||
9291100Sdes	    openpam_get_option(pamh, "use_first_pass")) {
9393982Sdes		r = pam_get_item(pamh, item, (const void **)authtok);
9491100Sdes		if (r == PAM_SUCCESS && *authtok != NULL)
95107937Sdes			RETURNC(PAM_SUCCESS);
9691100Sdes		else if (openpam_get_option(pamh, "use_first_pass"))
97107937Sdes			RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r);
9891100Sdes	}
9993982Sdes	if (prompt == NULL) {
10093982Sdes		r = pam_get_item(pamh, pitem, (const void **)&prompt);
10193982Sdes		if (r != PAM_SUCCESS || prompt == NULL)
10293982Sdes			prompt = default_prompt;
10393982Sdes	}
10491100Sdes	style = openpam_get_option(pamh, "echo_pass") ?
10591100Sdes	    PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
10693982Sdes	r = pam_prompt(pamh, style, &resp, "%s", prompt);
10791094Sdes	if (r != PAM_SUCCESS)
108107937Sdes		RETURNC(r);
10993982Sdes	if (twice) {
11093982Sdes		r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt);
11193982Sdes		if (r != PAM_SUCCESS) {
11293982Sdes			free(resp);
113107937Sdes			RETURNC(r);
11493982Sdes		}
11593982Sdes		if (strcmp(resp, resp2) != 0) {
11693982Sdes			free(resp);
11793982Sdes			resp = NULL;
11893982Sdes		}
11993982Sdes		free(resp2);
12093982Sdes	}
12193982Sdes	if (resp == NULL)
122107937Sdes		RETURNC(PAM_TRY_AGAIN);
12394706Sdes	r = pam_set_item(pamh, item, resp);
12493982Sdes	free(resp);
12593982Sdes	if (r != PAM_SUCCESS)
126107937Sdes		RETURNC(r);
127110556Sdes	r = pam_get_item(pamh, item, (const void **)authtok);
128110556Sdes	RETURNC(r);
12991094Sdes}
13091100Sdes
13191100Sdes/*
13291100Sdes * Error codes:
13391100Sdes *
13491100Sdes *	=pam_get_item
13591100Sdes *	=pam_prompt
13691100Sdes *	=pam_set_item
13791100Sdes *	!PAM_SYMBOL_ERR
13893982Sdes *	PAM_TRY_AGAIN
13991100Sdes */
14093982Sdes
14193982Sdes/**
14293982Sdes * The =pam_get_authtok function returns the cached authentication token,
14393982Sdes * or prompts the user if no token is currently cached.  Either way, a
14493982Sdes * pointer to the authentication token is stored in the location pointed
14593982Sdes * to by the =authtok argument.
14693982Sdes *
14793982Sdes * The =item argument must have one of the following values:
14893982Sdes *
14995908Sdes *	=PAM_AUTHTOK:
15093982Sdes *		Returns the current authentication token, or the new token
15193982Sdes *		when changing authentication tokens.
15295908Sdes *	=PAM_OLDAUTHTOK:
15393982Sdes *		Returns the previous authentication token when changing
15493982Sdes *		authentication tokens.
15593982Sdes *
15693982Sdes * The =prompt argument specifies a prompt to use if no token is cached.
15793982Sdes * If it is =NULL, the =PAM_AUTHTOK_PROMPT or =PAM_OLDAUTHTOK_PROMPT item,
15893982Sdes * as appropriate, will be used.  If that item is also =NULL, a hardcoded
15993982Sdes * default prompt will be used.
16093982Sdes *
16193982Sdes * If =item is set to =PAM_AUTHTOK and there is a non-null =PAM_OLDAUTHTOK
16293982Sdes * item, =pam_get_authtok will ask the user to confirm the new token by
16393982Sdes * retyping it.  If there is a mismatch, =pam_get_authtok will return
16493982Sdes * =PAM_TRY_AGAIN.
16593982Sdes *
16693982Sdes * >pam_get_item
16793982Sdes * >pam_get_user
16893982Sdes */
169