auth-chall.c revision 181104
155714Skris/* $OpenBSD: auth-chall.c,v 1.12 2006/08/03 03:34:41 deraadt Exp $ */ 255714Skris/* 355714Skris * Copyright (c) 2001 Markus Friedl. All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 8280304Sjkim * 1. Redistributions of source code must retain the above copyright 955714Skris * notice, this list of conditions and the following disclaimer. 1055714Skris * 2. Redistributions in binary form must reproduce the above copyright 1155714Skris * notice, this list of conditions and the following disclaimer in the 1255714Skris * documentation and/or other materials provided with the distribution. 1355714Skris * 1455714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15280304Sjkim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1655714Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1755714Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1855714Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1955714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2055714Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2155714Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22280304Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2355714Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2455714Skris */ 2555714Skris 2655714Skris#include "includes.h" 2755714Skris 2855714Skris#include <sys/types.h> 2955714Skris 3055714Skris#include <stdarg.h> 3155714Skris 3255714Skris#include "xmalloc.h" 3355714Skris#include "key.h" 3455714Skris#include "hostfile.h" 3555714Skris#include "auth.h" 3655714Skris#include "log.h" 37280304Sjkim#include "servconf.h" 3855714Skris 3955714Skris/* limited protocol v1 interface to kbd-interactive authentication */ 40280304Sjkim 4155714Skrisextern KbdintDevice *devices[]; 4255714Skrisstatic KbdintDevice *device; 4355714Skrisextern ServerOptions options; 4455714Skris 4555714Skrischar * 4655714Skrisget_challenge(Authctxt *authctxt) 4755714Skris{ 4855714Skris char *challenge, *name, *info, **prompts; 4955714Skris u_int i, numprompts; 5055714Skris u_int *echo_on; 5155714Skris 52280304Sjkim#ifdef USE_PAM 5355714Skris if (!options.use_pam) 5455714Skris remove_kbdint_device("pam"); 5555714Skris#endif 5655714Skris 5755714Skris device = devices[0]; /* we always use the 1st device for protocol 1 */ 5855714Skris if (device == NULL) 59280304Sjkim return NULL; 60280304Sjkim if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL) 61280304Sjkim return NULL; 62280304Sjkim if (device->query(authctxt->kbdintctxt, &name, &info, 63280304Sjkim &numprompts, &prompts, &echo_on)) { 64280304Sjkim device->free_ctx(authctxt->kbdintctxt); 65280304Sjkim authctxt->kbdintctxt = NULL; 66280304Sjkim return NULL; 67280304Sjkim } 68280304Sjkim if (numprompts < 1) 69280304Sjkim fatal("get_challenge: numprompts < 1"); 70280304Sjkim challenge = xstrdup(prompts[0]); 71280304Sjkim for (i = 0; i < numprompts; i++) 72280304Sjkim xfree(prompts[i]); 73280304Sjkim xfree(prompts); 74280304Sjkim xfree(name); 75280304Sjkim xfree(echo_on); 76280304Sjkim xfree(info); 77280304Sjkim 78280304Sjkim return (challenge); 79280304Sjkim} 80280304Sjkimint 81280304Sjkimverify_response(Authctxt *authctxt, const char *response) 82280304Sjkim{ 83280304Sjkim char *resp[1], *name, *info, **prompts; 84280304Sjkim u_int i, numprompts, *echo_on; 85280304Sjkim int authenticated = 0; 86280304Sjkim 87280304Sjkim if (device == NULL) 88280304Sjkim return 0; 89280304Sjkim if (authctxt->kbdintctxt == NULL) 90280304Sjkim return 0; 91280304Sjkim resp[0] = (char *)response; 92280304Sjkim switch (device->respond(authctxt->kbdintctxt, 1, resp)) { 93280304Sjkim case 0: /* Success */ 94280304Sjkim authenticated = 1; 95280304Sjkim break; 96280304Sjkim case 1: /* Postponed - retry with empty query for PAM */ 97280304Sjkim if ((device->query(authctxt->kbdintctxt, &name, &info, 98280304Sjkim &numprompts, &prompts, &echo_on)) != 0) 99280304Sjkim break; 100280304Sjkim if (numprompts == 0 && 101280304Sjkim device->respond(authctxt->kbdintctxt, 0, resp) == 0) 102280304Sjkim authenticated = 1; 103280304Sjkim 104280304Sjkim for (i = 0; i < numprompts; i++) 105280304Sjkim xfree(prompts[i]); 106280304Sjkim xfree(prompts); 107280304Sjkim xfree(name); 108280304Sjkim xfree(echo_on); 109280304Sjkim xfree(info); 110280304Sjkim break; 111280304Sjkim } 112280304Sjkim device->free_ctx(authctxt->kbdintctxt); 113280304Sjkim authctxt->kbdintctxt = NULL; 114280304Sjkim return authenticated; 115280304Sjkim} 116280304Sjkimvoid 117280304Sjkimabandon_challenge_response(Authctxt *authctxt) 118280304Sjkim{ 119280304Sjkim if (authctxt->kbdintctxt != NULL) { 120280304Sjkim device->free_ctx(authctxt->kbdintctxt); 121280304Sjkim authctxt->kbdintctxt = NULL; 122280304Sjkim } 123280304Sjkim} 124280304Sjkim