auth-chall.c revision 162856
133965Sjdp/* $OpenBSD: auth-chall.c,v 1.12 2006/08/03 03:34:41 deraadt Exp $ */
233965Sjdp/*
338889Sjdp * Copyright (c) 2001 Markus Friedl.  All rights reserved.
433965Sjdp *
533965Sjdp * Redistribution and use in source and binary forms, with or without
633965Sjdp * modification, are permitted provided that the following conditions
738889Sjdp * are met:
838889Sjdp * 1. Redistributions of source code must retain the above copyright
938889Sjdp *    notice, this list of conditions and the following disclaimer.
1038889Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1138889Sjdp *    notice, this list of conditions and the following disclaimer in the
1238889Sjdp *    documentation and/or other materials provided with the distribution.
1338889Sjdp *
1438889Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1538889Sjdp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1638889Sjdp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1738889Sjdp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1838889Sjdp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1938889Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2038889Sjdp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2138889Sjdp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2238889Sjdp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2333965Sjdp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2433965Sjdp */
2533965Sjdp
2633965Sjdp#include "includes.h"
2733965Sjdp__RCSID("$FreeBSD: head/crypto/openssh/auth-chall.c 162856 2006-09-30 13:38:06Z des $");
2833965Sjdp
2933965Sjdp#include <sys/types.h>
3033965Sjdp
3133965Sjdp#include <stdarg.h>
3233965Sjdp
3333965Sjdp#include "xmalloc.h"
3433965Sjdp#include "key.h"
3533965Sjdp#include "hostfile.h"
3633965Sjdp#include "auth.h"
3733965Sjdp#include "log.h"
3833965Sjdp#include "servconf.h"
3933965Sjdp
4033965Sjdp/* limited protocol v1 interface to kbd-interactive authentication */
4133965Sjdp
4233965Sjdpextern KbdintDevice *devices[];
4333965Sjdpstatic KbdintDevice *device;
4433965Sjdpextern ServerOptions options;
4533965Sjdp
4633965Sjdpchar *
4733965Sjdpget_challenge(Authctxt *authctxt)
4833965Sjdp{
4933965Sjdp	char *challenge, *name, *info, **prompts;
5033965Sjdp	u_int i, numprompts;
5133965Sjdp	u_int *echo_on;
5233965Sjdp
5338889Sjdp#ifdef USE_PAM
5433965Sjdp	if (!options.use_pam)
5533965Sjdp		remove_kbdint_device("pam");
5633965Sjdp#endif
5733965Sjdp
5833965Sjdp	device = devices[0]; /* we always use the 1st device for protocol 1 */
5933965Sjdp	if (device == NULL)
6038889Sjdp		return NULL;
6138889Sjdp	if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL)
6238889Sjdp		return NULL;
6338889Sjdp	if (device->query(authctxt->kbdintctxt, &name, &info,
6433965Sjdp	    &numprompts, &prompts, &echo_on)) {
6533965Sjdp		device->free_ctx(authctxt->kbdintctxt);
6633965Sjdp		authctxt->kbdintctxt = NULL;
6733965Sjdp		return NULL;
6833965Sjdp	}
6933965Sjdp	if (numprompts < 1)
7033965Sjdp		fatal("get_challenge: numprompts < 1");
7133965Sjdp	challenge = xstrdup(prompts[0]);
7233965Sjdp	for (i = 0; i < numprompts; i++)
7333965Sjdp		xfree(prompts[i]);
7433965Sjdp	xfree(prompts);
7538889Sjdp	xfree(name);
7633965Sjdp	xfree(echo_on);
7733965Sjdp	xfree(info);
7833965Sjdp
7933965Sjdp	return (challenge);
8033965Sjdp}
8133965Sjdpint
8233965Sjdpverify_response(Authctxt *authctxt, const char *response)
8333965Sjdp{
8433965Sjdp	char *resp[1], *name, *info, **prompts;
8533965Sjdp	u_int i, numprompts, *echo_on;
8633965Sjdp	int authenticated = 0;
8733965Sjdp
8833965Sjdp	if (device == NULL)
8933965Sjdp		return 0;
9033965Sjdp	if (authctxt->kbdintctxt == NULL)
9133965Sjdp		return 0;
9233965Sjdp	resp[0] = (char *)response;
9333965Sjdp	switch (device->respond(authctxt->kbdintctxt, 1, resp)) {
9433965Sjdp	case 0: /* Success */
9533965Sjdp		authenticated = 1;
9633965Sjdp		break;
9733965Sjdp	case 1: /* Postponed - retry with empty query for PAM */
9838889Sjdp		if ((device->query(authctxt->kbdintctxt, &name, &info,
9933965Sjdp		    &numprompts, &prompts, &echo_on)) != 0)
10033965Sjdp			break;
10133965Sjdp		if (numprompts == 0 &&
10233965Sjdp		    device->respond(authctxt->kbdintctxt, 0, resp) == 0)
10333965Sjdp			authenticated = 1;
10433965Sjdp
10533965Sjdp		for (i = 0; i < numprompts; i++)
10633965Sjdp			xfree(prompts[i]);
10733965Sjdp		xfree(prompts);
10833965Sjdp		xfree(name);
10933965Sjdp		xfree(echo_on);
11033965Sjdp		xfree(info);
11133965Sjdp		break;
11233965Sjdp	}
11338889Sjdp	device->free_ctx(authctxt->kbdintctxt);
11438889Sjdp	authctxt->kbdintctxt = NULL;
11533965Sjdp	return authenticated;
11633965Sjdp}
11738889Sjdpvoid
11838889Sjdpabandon_challenge_response(Authctxt *authctxt)
11938889Sjdp{
12038889Sjdp	if (authctxt->kbdintctxt != NULL) {
12138889Sjdp		device->free_ctx(authctxt->kbdintctxt);
12238889Sjdp		authctxt->kbdintctxt = NULL;
12333965Sjdp	}
12433965Sjdp}
12533965Sjdp