auth-chall.c revision 147005
1285SN/A/*
2461SN/A * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3285SN/A *
4285SN/A * Redistribution and use in source and binary forms, with or without
5285SN/A * modification, are permitted provided that the following conditions
6285SN/A * are met:
7285SN/A * 1. Redistributions of source code must retain the above copyright
8285SN/A *    notice, this list of conditions and the following disclaimer.
9285SN/A * 2. Redistributions in binary form must reproduce the above copyright
10285SN/A *    notice, this list of conditions and the following disclaimer in the
11285SN/A *    documentation and/or other materials provided with the distribution.
12285SN/A *
13285SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14285SN/A * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15285SN/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16285SN/A * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17285SN/A * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18285SN/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19285SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20285SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21285SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22285SN/A * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23285SN/A */
24285SN/A
25285SN/A#include "includes.h"
26285SN/ARCSID("$OpenBSD: auth-chall.c,v 1.9 2003/11/03 09:03:37 djm Exp $");
27285SN/ARCSID("$FreeBSD: head/crypto/openssh/auth-chall.c 147005 2005-06-05 15:46:09Z des $");
28285SN/A
29285SN/A#include "auth.h"
30285SN/A#include "log.h"
31285SN/A#include "xmalloc.h"
32285SN/A#include "servconf.h"
33285SN/A
34285SN/A/* limited protocol v1 interface to kbd-interactive authentication */
35285SN/A
36285SN/Aextern KbdintDevice *devices[];
37285SN/Astatic KbdintDevice *device;
38285SN/Aextern ServerOptions options;
39285SN/A
40285SN/Achar *
41285SN/Aget_challenge(Authctxt *authctxt)
42285SN/A{
43285SN/A	char *challenge, *name, *info, **prompts;
44285SN/A	u_int i, numprompts;
45285SN/A	u_int *echo_on;
46285SN/A
47285SN/A#ifdef USE_PAM
48285SN/A	if (!options.use_pam)
49285SN/A		remove_kbdint_device("pam");
50285SN/A#endif
51285SN/A
52285SN/A	device = devices[0]; /* we always use the 1st device for protocol 1 */
53285SN/A	if (device == NULL)
54285SN/A		return NULL;
55285SN/A	if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL)
56285SN/A		return NULL;
57285SN/A	if (device->query(authctxt->kbdintctxt, &name, &info,
58285SN/A	    &numprompts, &prompts, &echo_on)) {
59285SN/A		device->free_ctx(authctxt->kbdintctxt);
60285SN/A		authctxt->kbdintctxt = NULL;
61285SN/A		return NULL;
62285SN/A	}
63285SN/A	if (numprompts < 1)
64285SN/A		fatal("get_challenge: numprompts < 1");
65285SN/A	challenge = xstrdup(prompts[0]);
66285SN/A	for (i = 0; i < numprompts; i++)
67285SN/A		xfree(prompts[i]);
68285SN/A	xfree(prompts);
69285SN/A	xfree(name);
70285SN/A	xfree(echo_on);
71285SN/A	xfree(info);
72285SN/A
73285SN/A	return (challenge);
74285SN/A}
75285SN/Aint
76285SN/Averify_response(Authctxt *authctxt, const char *response)
77285SN/A{
78285SN/A	char *resp[1], *name, *info, **prompts;
79285SN/A	u_int i, numprompts, *echo_on;
80285SN/A	int authenticated = 0;
81285SN/A
82285SN/A	if (device == NULL)
83		return 0;
84	if (authctxt->kbdintctxt == NULL)
85		return 0;
86	resp[0] = (char *)response;
87	switch (device->respond(authctxt->kbdintctxt, 1, resp)) {
88	case 0: /* Success */
89		authenticated = 1;
90		break;
91	case 1: /* Postponed - retry with empty query for PAM */
92		if ((device->query(authctxt->kbdintctxt, &name, &info,
93		    &numprompts, &prompts, &echo_on)) != 0)
94			break;
95		if (numprompts == 0 &&
96		    device->respond(authctxt->kbdintctxt, 0, resp) == 0)
97			authenticated = 1;
98
99		for (i = 0; i < numprompts; i++)
100			xfree(prompts[i]);
101		xfree(prompts);
102		xfree(name);
103		xfree(echo_on);
104		xfree(info);
105		break;
106	}
107	device->free_ctx(authctxt->kbdintctxt);
108	authctxt->kbdintctxt = NULL;
109	return authenticated;
110}
111void
112abandon_challenge_response(Authctxt *authctxt)
113{
114	if (authctxt->kbdintctxt != NULL) {
115		device->free_ctx(authctxt->kbdintctxt);
116		authctxt->kbdintctxt = NULL;
117	}
118}
119