From 876b7081d8f073edd4717ccdb7091fe3a6975ef6 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 20 Sep 2005 17:35:21 +0000 Subject: added keyboard-interactive client support --HG-- extra : convert_revision : 3df738e42f4fc8b7f0f3ff9ca767386f54edb1ea --- cli-authinteract.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 cli-authinteract.c (limited to 'cli-authinteract.c') diff --git a/cli-authinteract.c b/cli-authinteract.c new file mode 100644 index 0000000..90105e9 --- /dev/null +++ b/cli-authinteract.c @@ -0,0 +1,168 @@ +/* + * Dropbear SSH + * + * Copyright (c) 2005 Matt Johnston + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ + +#include "includes.h" +#include "buffer.h" +#include "dbutil.h" +#include "session.h" +#include "ssh.h" +#include "runopts.h" + +#ifdef ENABLE_CLI_INTERACT_AUTH + +static unsigned char* get_response(unsigned char* prompt) +{ + FILE* tty = NULL; + unsigned char* response = NULL; + /* not a password, but a reasonable limit */ + char buf[DROPBEAR_MAX_CLI_PASS]; + char* ret = NULL; + + fprintf(stderr, "%s", prompt); + + tty = fopen(_PATH_TTY, "r"); + if (tty) { + ret = fgets(buf, sizeof(buf), tty); + fclose(tty); + } else { + ret = fgets(buf, sizeof(buf), stdin); + } + + if (ret == NULL) { + response = (unsigned char*)m_strdup(""); + } else { + unsigned int buflen = strlen(buf); + /* fgets includes newlines */ + if (buflen > 0 && buf[buflen-1] == '\n') + buf[buflen-1] = '\0'; + response = (unsigned char*)m_strdup(buf); + } + + m_burn(buf, sizeof(buf)); + + return response; +} + +void recv_msg_userauth_info_request() { + + unsigned char *name = NULL; + unsigned char *instruction = NULL; + unsigned int num_prompts = 0; + unsigned int i; + + unsigned char *prompt = NULL; + unsigned int echo = 0; + unsigned char *response = NULL; + + TRACE(("enter recv_msg_recv_userauth_info_request")) + + cli_ses.interact_request_received = 1; + + name = buf_getstring(ses.payload, NULL); + instruction = buf_getstring(ses.payload, NULL); + + /* language tag */ + buf_eatstring(ses.payload); + + num_prompts = buf_getint(ses.payload); + + if (num_prompts >= DROPBEAR_MAX_CLI_INTERACT_PROMPTS) { + dropbear_exit("Too many prompts received for keyboard-interactive"); + } + + /* we'll build the response as we go */ + CHECKCLEARTOWRITE(); + buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_INFO_RESPONSE); + buf_putint(ses.writepayload, num_prompts); + + if (strlen(name) > 0) { + cleantext(name); + fprintf(stderr, "%s", name); + m_free(name); + } + if (strlen(instruction) > 0) { + cleantext(instruction); + fprintf(stderr, "%s", instruction); + m_free(instruction); + } + + for (i = 0; i < num_prompts; i++) { + unsigned int response_len = 0; + prompt = buf_getstring(ses.payload, NULL); + cleantext(prompt); + + echo = buf_getbool(ses.payload); + + if (echo) { + unsigned char* p = getpass(prompt); + response = m_strdup(p); + m_burn(p, strlen(p)); + } else { + response = get_response(prompt); + } + + response_len = strlen(response); + buf_putstring(ses.writepayload, response, response_len); + m_burn(response, response_len); + m_free(response); + } + + encrypt_packet(); + + + TRACE(("leave recv_msg_recv_userauth_info_request")) +} + +void cli_auth_interactive() { + + TRACE(("enter cli_auth_interactive")) + CHECKCLEARTOWRITE(); + + buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); + + /* username */ + buf_putstring(ses.writepayload, cli_opts.username, + strlen(cli_opts.username)); + + /* service name */ + buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, + SSH_SERVICE_CONNECTION_LEN); + + /* method */ + buf_putstring(ses.writepayload, AUTH_METHOD_INTERACT, + AUTH_METHOD_INTERACT_LEN); + + /* empty language tag */ + buf_putstring(ses.writepayload, "", 0); + + /* empty submethods */ + buf_putstring(ses.writepayload, "", 0); + + encrypt_packet(); + cli_ses.interact_request_received = 0; + + TRACE(("leave cli_auth_interactive")) + +} +#endif /* ENABLE_CLI_INTERACT_AUTH */ -- cgit v1.2.3 From a43af44e9ce514c257209d89f78b794490d8a681 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 20 Sep 2005 17:36:32 +0000 Subject: Forgot to revert echo flag --HG-- extra : convert_revision : edab4eafef0717badd628115fac4f4e2793ba22d --- cli-authinteract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cli-authinteract.c') diff --git a/cli-authinteract.c b/cli-authinteract.c index 90105e9..ef65517 100644 --- a/cli-authinteract.c +++ b/cli-authinteract.c @@ -114,7 +114,7 @@ void recv_msg_userauth_info_request() { echo = buf_getbool(ses.payload); - if (echo) { + if (!echo) { unsigned char* p = getpass(prompt); response = m_strdup(p); m_burn(p, strlen(p)); -- cgit v1.2.3 From fd0f873a367b133fd41af34dc168bd594ee2928c Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sun, 15 Jan 2006 06:43:24 +0000 Subject: Cancel a dbclient password prompt if the user presses ctrl-c. Enter still has to be pressed since glibc blocks ctrl-c in getpass() --HG-- extra : convert_revision : 1c8128fba89431f2460dd5914f0614850d529b76 --- auth.h | 1 + cli-auth.c | 15 +++++++++++++++ cli-authinteract.c | 2 +- cli-authpasswd.c | 5 +---- 4 files changed, 18 insertions(+), 5 deletions(-) (limited to 'cli-authinteract.c') diff --git a/auth.h b/auth.h index 7e83247..c407ad5 100644 --- a/auth.h +++ b/auth.h @@ -52,6 +52,7 @@ void cli_pubkeyfail(); void cli_auth_password(); int cli_auth_pubkey(); void cli_auth_interactive(); +char* getpass_or_cancel(); #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */ diff --git a/cli-auth.c b/cli-auth.c index 6a6d53a..d08de9a 100644 --- a/cli-auth.c +++ b/cli-auth.c @@ -278,3 +278,18 @@ void cli_auth_try() { TRACE(("leave cli_auth_try")) } + +/* A helper for getpass() that exits if the user cancels. The returned + * password is statically allocated by getpass() */ +char* getpass_or_cancel() +{ + char* password = NULL; + + password = getpass("Password: "); + + /* 0x03 is a ctrl-c character in the buffer. */ + if (password == NULL || strchr(password, '\3') != NULL) { + dropbear_close("Interrupted."); + } + return password; +} diff --git a/cli-authinteract.c b/cli-authinteract.c index ef65517..5a169cb 100644 --- a/cli-authinteract.c +++ b/cli-authinteract.c @@ -115,7 +115,7 @@ void recv_msg_userauth_info_request() { echo = buf_getbool(ses.payload); if (!echo) { - unsigned char* p = getpass(prompt); + unsigned char* p = getpass_or_cancel(prompt); response = m_strdup(p); m_burn(p, strlen(p)); } else { diff --git a/cli-authpasswd.c b/cli-authpasswd.c index ec290e0..5dffac4 100644 --- a/cli-authpasswd.c +++ b/cli-authpasswd.c @@ -125,10 +125,7 @@ void cli_auth_password() { password = gui_getpass("Password: "); else #endif - password = getpass("Password: "); - - if (password == NULL) - return 0; + password = getpass_or_cancel("Password: "); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); -- cgit v1.2.3