1 /* 2 * Dropbear SSH 3 * 4 * Copyright (c) 2002,2003 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_PASSWORD_AUTH 33 34 #ifdef ENABLE_CLI_ASKPASS_HELPER 35 /* Returns 1 if we want to use the askpass program, 0 otherwise */ 36 static int want_askpass() 37 { 38 char* askpass_prog = NULL; 39 40 askpass_prog = getenv("SSH_ASKPASS"); 41 return askpass_prog && !isatty(STDIN_FILENO) && getenv("DISPLAY"); 42 } 43 44 /* returns a statically allocated password from a helper app, or NULL 45 * on failure */ 46 static char *gui_getpass(const char *prompt) { 47 48 pid_t pid; 49 int p[2], maxlen, len, status; 50 static char buf[DROPBEAR_MAX_CLI_PASS + 1]; 51 char* helper = NULL; 52 53 TRACE(("enter gui_getpass")) 54 55 helper = getenv("SSH_ASKPASS"); 56 if (!helper) 57 { 58 TRACE(("leave gui_getpass: no askpass program")) 59 return NULL; 60 } 61 62 if (pipe(p) < 0) { 63 TRACE(("error creating child pipe")) 64 return NULL; 65 } 66 67 pid = fork(); 68 69 if (pid < 0) { 70 TRACE(("fork error")) 71 return NULL; 72 } 73 74 if (!pid) { 75 /* child */ 76 close(p[0]); 77 if (dup2(p[1], STDOUT_FILENO) < 0) { 78 TRACE(("error redirecting stdout")) 79 exit(1); 80 } 81 close(p[1]); 82 execlp(helper, helper, prompt, (char *)0); 83 TRACE(("execlp error")) 84 exit(1); 85 } 86 87 close(p[1]); 88 maxlen = sizeof(buf); 89 while (maxlen > 0) { 90 len = read(p[0], buf + sizeof(buf) - maxlen, maxlen); 91 if (len > 0) { 92 maxlen -= len; 93 } else { 94 if (errno != EINTR) 95 break; 96 } 97 } 98 99 close(p[0]); 100 101 while (waitpid(pid, &status, 0) < 0 && errno == EINTR) 102 ; 103 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 104 return(NULL); 105 106 len = sizeof(buf) - maxlen; 107 buf[len] = '\0'; 108 if (len > 0 && buf[len - 1] == '\n') 109 buf[len - 1] = '\0'; 110 111 TRACE(("leave gui_getpass")) 112 return(buf); 113 } 114 #endif /* ENABLE_CLI_ASKPASS_HELPER */ 115 116 void cli_auth_password() { 117 118 char* password = NULL; 119 char prompt[80]; 120 121 TRACE(("enter cli_auth_password")) 122 CHECKCLEARTOWRITE(); 123 124 snprintf(prompt, sizeof(prompt), "%s@%s's password: ", 125 cli_opts.username, cli_opts.remotehost); 126 #ifdef ENABLE_CLI_ASKPASS_HELPER 127 if (want_askpass()) 128 password = gui_getpass(prompt); 129 else 130 #endif 131 password = getpass_or_cancel(prompt); 132 133 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); 134 135 buf_putstring(ses.writepayload, cli_opts.username, 136 strlen(cli_opts.username)); 137 138 buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, 139 SSH_SERVICE_CONNECTION_LEN); 140 141 buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD, 142 AUTH_METHOD_PASSWORD_LEN); 143 144 buf_putbyte(ses.writepayload, 0); /* FALSE - so says the spec */ 145 146 buf_putstring(ses.writepayload, password, strlen(password)); 147 148 encrypt_packet(); 149 m_burn(password, strlen(password)); 150 151 TRACE(("leave cli_auth_password")) 152 } 153 #endif /* ENABLE_CLI_PASSWORD_AUTH */ 154