diff options
author | Matt Johnston <matt@ucc.asn.au> | 2005-02-28 13:01:00 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2005-02-28 13:01:00 +0000 |
commit | 4127be0a95248508895a06585476eebaaa94619e (patch) | |
tree | 73c33dc1b96bca5d3826f691cdd8efcf901e39e4 /cli-authpasswd.c | |
parent | 03d78bbb31828d7ba7e578e5d7c76e7229c67b62 (diff) |
* 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)
--HG--
extra : convert_revision : 02fb18acdb680a868b2bfbd6452b2ccdb4cdde99
Diffstat (limited to 'cli-authpasswd.c')
-rw-r--r-- | cli-authpasswd.c | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/cli-authpasswd.c b/cli-authpasswd.c index 02bce18..a9f34bd 100644 --- a/cli-authpasswd.c +++ b/cli-authpasswd.c @@ -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")) + TRACE(("enter cli_auth_password")) 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 @@ int cli_auth_password() { return 1; /* Password auth can always be tried */ } -#endif +#endif /* ENABLE_CLI_PASSWORD_AUTH */ |