1 /* 2 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 #include "includes.h" 25 RCSID("$OpenBSD: auth2-chall.c,v 1.4 2001/03/28 22:43:31 markus Exp $"); 26 27 #include "ssh2.h" 28 #include "auth.h" 29 #include "packet.h" 30 #include "xmalloc.h" 31 #include "dispatch.h" 32 #include "log.h" 33 34 void send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo); 35 void input_userauth_info_response(int type, int plen, void *ctxt); 36 37 /* 38 * try challenge-reponse, return -1 (= postponed) if we have to 39 * wait for the response. 40 */ 41 int 42 auth2_challenge(Authctxt *authctxt, char *devs) 43 { 44 char *challenge; 45 46 if (!authctxt->valid || authctxt->user == NULL) 47 return 0; 48 if ((challenge = get_challenge(authctxt, devs)) == NULL) 49 return 0; 50 send_userauth_into_request(authctxt, challenge, 0); 51 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, 52 &input_userauth_info_response); 53 authctxt->postponed = 1; 54 return 0; 55 } 56 57 void 58 send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo) 59 { 60 int nprompts = 1; 61 62 packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); 63 /* name, instruction and language are unused */ 64 packet_put_cstring(""); 65 packet_put_cstring(""); 66 packet_put_cstring(""); 67 packet_put_int(nprompts); 68 packet_put_cstring(challenge); 69 packet_put_char(echo); 70 packet_send(); 71 packet_write_wait(); 72 } 73 74 void 75 input_userauth_info_response(int type, int plen, void *ctxt) 76 { 77 Authctxt *authctxt = ctxt; 78 int authenticated = 0; 79 u_int nresp, rlen; 80 char *response, *method = "challenge-reponse"; 81 82 if (authctxt == NULL) 83 fatal("input_userauth_info_response: no authctxt"); 84 85 authctxt->postponed = 0; /* reset */ 86 nresp = packet_get_int(); 87 if (nresp == 1) { 88 response = packet_get_string(&rlen); 89 packet_done(); 90 if (strlen(response) == 0) { 91 /* 92 * if we received an empty response, resend challenge 93 * with echo enabled 94 */ 95 char *challenge = get_challenge(authctxt, NULL); 96 if (challenge != NULL) { 97 send_userauth_into_request(authctxt, 98 challenge, 1); 99 authctxt->postponed = 1; 100 } 101 } else if (authctxt->valid) { 102 authenticated = verify_response(authctxt, response); 103 memset(response, 'r', rlen); 104 } 105 xfree(response); 106 } 107 /* unregister callback */ 108 if (!authctxt->postponed) 109 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); 110 111 userauth_finish(authctxt, authenticated, method); 112 } 113