# HG changeset patch # User Matt Johnston # Date 1109595660 0 # Node ID 257f09a63dab80959ee03bb5849e1a2429aa5c06 # Parent 3e49d8d180054ca3d653143453cac085150a497f * add SSH_ASKPASS support (based on patch from Paul Whittaker * don't exit if setnonblocking() fails with "not supported by device" (allows redirection from /dev/null) diff -r 3e49d8d18005 -r 257f09a63dab cli-authpasswd.c --- a/cli-authpasswd.c Mon Feb 28 10:15:16 2005 +0000 +++ b/cli-authpasswd.c Mon Feb 28 13:01:00 2005 +0000 @@ -30,13 +30,105 @@ #include "runopts.h" #ifdef ENABLE_CLI_PASSWORD_AUTH + +#ifdef ENABLE_CLI_ASKPASS_HELPER +/* Returns 1 if we want to use the askpass program, 0 otherwise */ +static int want_askpass() +{ + char* askpass_prog = NULL; + + askpass_prog = getenv("SSH_ASKPASS"); + return askpass_prog && !isatty(STDIN_FILENO) && getenv("DISPLAY"); +} + +/* returns a statically allocated password from a helper app, or NULL + * on failure */ +static char *gui_getpass(const char *prompt) { + + pid_t pid; + int p[2], maxlen, len, status; + static char buf[DROPBEAR_MAX_CLI_PASS + 1]; + char* helper = NULL; + + TRACE(("enter gui_getpass")) + + helper = getenv("SSH_ASKPASS"); + if (!helper) + { + TRACE(("leave gui_getpass: no askpass program")) + return NULL; + } + + if (pipe(p) < 0) { + TRACE(("error creating child pipe")) + return NULL; + } + + pid = fork(); + + if (pid < 0) { + TRACE(("fork error")) + return NULL; + } + + if (!pid) { + /* child */ + close(p[0]); + if (dup2(p[1], STDOUT_FILENO) < 0) { + TRACE(("error redirecting stdout")) + exit(1); + } + close(p[1]); + execlp(helper, helper, prompt, (char *)0); + TRACE(("execlp error")) + exit(1); + } + + close(p[1]); + maxlen = sizeof(buf); + while (maxlen > 0) { + len = read(p[0], buf + sizeof(buf) - maxlen, maxlen); + if (len > 0) { + maxlen -= len; + } else { + if (errno != EINTR) + break; + } + } + + close(p[0]); + + while (waitpid(pid, &status, 0) < 0 && errno == EINTR) + ; + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + return(NULL); + + len = sizeof(buf) - maxlen; + buf[len] = '\0'; + if (len > 0 && buf[len - 1] == '\n') + buf[len - 1] = '\0'; + + TRACE(("leave gui_getpass")) + return(buf); +} +#endif /* ENABLE_CLI_ASKPASS_HELPER */ + int cli_auth_password() { char* password = NULL; + TRACE(("enter cli_auth_password")) + CHECKCLEARTOWRITE(); - CHECKCLEARTOWRITE(); - password = getpass("Password: "); +#ifdef ENABLE_CLI_ASKPASS_HELPER + if (want_askpass()) + password = gui_getpass("Password: "); + else +#endif + password = getpass("Password: "); + + if (password == NULL) + return 0; buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); @@ -60,4 +152,4 @@ return 1; /* Password auth can always be tried */ } -#endif +#endif /* ENABLE_CLI_PASSWORD_AUTH */ diff -r 3e49d8d18005 -r 257f09a63dab dbutil.c --- a/dbutil.c Mon Feb 28 10:15:16 2005 +0000 +++ b/dbutil.c Mon Feb 28 13:01:00 2005 +0000 @@ -627,7 +627,13 @@ TRACE(("setnonblocking: %d", fd)) if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - dropbear_exit("Couldn't set nonblocking"); + if (errno == ENODEV) { + /* Some devices (like /dev/null redirected in) + * can't be set to non-blocking */ + TRACE(("ignoring ENODEV for setnonblocking")) + } else { + dropbear_exit("Couldn't set nonblocking"); + } } TRACE(("leave setnonblocking")) } diff -r 3e49d8d18005 -r 257f09a63dab options.h --- a/options.h Mon Feb 28 10:15:16 2005 +0000 +++ b/options.h Mon Feb 28 13:01:00 2005 +0000 @@ -126,6 +126,13 @@ #define ENABLE_CLI_PASSWORD_AUTH #define ENABLE_CLI_PUBKEY_AUTH +/* Define this (as well as ENABLE_CLI_PASSWORD_AUTH) to allow the use of + * a helper program for the ssh client. The helper program should be + * specified in the SSH_ASKPASS environment variable, and dbclient + * should be run with DISPLAY set and no tty. The program should + * return the password on standard output */ +/*#define ENABLE_CLI_ASKPASS_HELPER*/ + /* Random device to use - define either DROPBEAR_RANDOM_DEV or * DROPBEAR_PRNGD_SOCKET. * DROPBEAR_RANDOM_DEV is recommended on hosts with a good /dev/(u)random, @@ -297,6 +304,8 @@ #define DROPBEAR_MAX_SOCKS 2 /* IPv4, IPv6 are all we'll get for now. Revisit in a few years time.... */ +#define DROPBEAR_MAX_CLI_PASS 1024 + #ifndef ENABLE_X11FWD #define DISABLE_X11FWD #endif