1 /* 2 * Dropbear SSH 3 * 4 * Copyright (c) 2005 Matt Johnston 5 * All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. */ 24 25 #include "includes.h" 26 #include "buffer.h" 27 #include "dbutil.h" 28 #include "session.h" 29 #include "ssh.h" 30 #include "runopts.h" 31 32 #ifdef ENABLE_CLI_INTERACT_AUTH 33 34 static unsigned char* get_response(unsigned char* prompt) 35 { 36 FILE* tty = NULL; 37 unsigned char* response = NULL; 38 /* not a password, but a reasonable limit */ 39 char buf[DROPBEAR_MAX_CLI_PASS]; 40 char* ret = NULL; 41 42 fprintf(stderr, "%s", prompt); 43 44 tty = fopen(_PATH_TTY, "r"); 45 if (tty) { 46 ret = fgets(buf, sizeof(buf), tty); 47 fclose(tty); 48 } else { 49 ret = fgets(buf, sizeof(buf), stdin); 50 } 51 52 if (ret == NULL) { 53 response = (unsigned char*)m_strdup(""); 54 } else { 55 unsigned int buflen = strlen(buf); 56 /* fgets includes newlines */ 57 if (buflen > 0 && buf[buflen-1] == '\n') 58 buf[buflen-1] = '\0'; 59 response = (unsigned char*)m_strdup(buf); 60 } 61 62 m_burn(buf, sizeof(buf)); 63 64 return response; 65 } 66 67 void recv_msg_userauth_info_request() { 68 69 unsigned char *name = NULL; 70 unsigned char *instruction = NULL; 71 unsigned int num_prompts = 0; 72 unsigned int i; 73 74 unsigned char *prompt = NULL; 75 unsigned int echo = 0; 76 unsigned char *response = NULL; 77 78 TRACE(("enter recv_msg_recv_userauth_info_request")) 79 80 cli_ses.interact_request_received = 1; 81 82 name = buf_getstring(ses.payload, NULL); 83 instruction = buf_getstring(ses.payload, NULL); 84 85 /* language tag */ 86 buf_eatstring(ses.payload); 87 88 num_prompts = buf_getint(ses.payload); 89 90 if (num_prompts >= DROPBEAR_MAX_CLI_INTERACT_PROMPTS) { 91 dropbear_exit("Too many prompts received for keyboard-interactive"); 92 } 93 94 /* we'll build the response as we go */ 95 CHECKCLEARTOWRITE(); 96 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_INFO_RESPONSE); 97 buf_putint(ses.writepayload, num_prompts); 98 99 if (strlen(name) > 0) { 100 cleantext(name); 101 fprintf(stderr, "%s", name); 102 } 103 m_free(name); 104 105 if (strlen(instruction) > 0) { 106 cleantext(instruction); 107 fprintf(stderr, "%s", instruction); 108 } 109 m_free(instruction); 110 111 for (i = 0; i < num_prompts; i++) { 112 unsigned int response_len = 0; 113 prompt = buf_getstring(ses.payload, NULL); 114 cleantext(prompt); 115 116 echo = buf_getbool(ses.payload); 117 118 if (!echo) { 119 unsigned char* p = getpass_or_cancel(prompt); 120 response = m_strdup(p); 121 m_burn(p, strlen(p)); 122 } else { 123 response = get_response(prompt); 124 } 125 126 response_len = strlen(response); 127 buf_putstring(ses.writepayload, response, response_len); 128 m_burn(response, response_len); 129 m_free(response); 130 } 131 132 encrypt_packet(); 133 134 135 TRACE(("leave recv_msg_recv_userauth_info_request")) 136 } 137 138 void cli_auth_interactive() { 139 140 TRACE(("enter cli_auth_interactive")) 141 CHECKCLEARTOWRITE(); 142 143 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); 144 145 /* username */ 146 buf_putstring(ses.writepayload, cli_opts.username, 147 strlen(cli_opts.username)); 148 149 /* service name */ 150 buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, 151 SSH_SERVICE_CONNECTION_LEN); 152 153 /* method */ 154 buf_putstring(ses.writepayload, AUTH_METHOD_INTERACT, 155 AUTH_METHOD_INTERACT_LEN); 156 157 /* empty language tag */ 158 buf_putstring(ses.writepayload, "", 0); 159 160 /* empty submethods */ 161 buf_putstring(ses.writepayload, "", 0); 162 163 encrypt_packet(); 164 cli_ses.interact_request_received = 0; 165 166 TRACE(("leave cli_auth_interactive")) 167 168 } 169 #endif /* ENABLE_CLI_INTERACT_AUTH */ 170