From d05a247953572b5aa9c28f48410cb3608dfc118f Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 15 Nov 1999 14:25:30 +1100 Subject: - Merged OpenBSD CVS changes: - [ssh-add.c] change passphrase loop logic and remove ref to $DISPLAY, ok niels - Changed to ssh-add.c broke askpass support. Revised it to be a little more modular. - Revised autoconf support for enabling/disabling askpass support. --- ChangeLog | 8 ++ Makefile.in | 2 +- acconfig.h | 2 +- configure.in | 23 +++++- ssh-add.c | 236 +++++++++++++++++++++++++++++++---------------------------- 5 files changed, 155 insertions(+), 116 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15f2e16e6..528994344 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +19991115 + - Merged OpenBSD CVS changes: + - [ssh-add.c] change passphrase loop logic and remove ref to + $DISPLAY, ok niels + - Changed to ssh-add.c broke askpass support. Revised it to be a little more + modular. + - Revised autoconf support for enabling/disabling askpass support. + 19991114 - Solaris compilation fixes (still imcomplete) diff --git a/Makefile.in b/Makefile.in index 365df018f..93c4a0c01 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,7 +80,7 @@ install: all ln -sf ssh $(bindir)/slogin ln -sf ssh.1 $(mandir)/man1/slogin.1 - if [ ! -z "@INSTALL_ASKPASS@" ] ; then \ + if [ "x@INSTALL_ASKPASS@" = "xyes" ] ; then \ install -d $(libdir) ; \ install -d $(libdir)/ssh ; \ if [ -z "@GNOME_ASKPASS@" ] ; then \ diff --git a/acconfig.h b/acconfig.h index e5eca5b30..8678b7cdb 100644 --- a/acconfig.h +++ b/acconfig.h @@ -22,7 +22,7 @@ #undef HAVE_LIBUTIL_LOGIN /* Define if you *don't* want to use an external ssh-askpass */ -#undef DISABLE_EXTERNAL_ASKPASS +#undef USE_EXTERNAL_ASKPASS @BOTTOM@ diff --git a/configure.in b/configure.in index cd0c9a3de..ace3aaaa3 100644 --- a/configure.in +++ b/configure.in @@ -109,11 +109,26 @@ if test -z "$RANDOM_POOL" -a -z "$EGD_POOL"; then fi dnl Check whether use wants to disable the external ssh-askpass +INSTALL_ASKPASS="yes" +AC_MSG_CHECKING([whether to enable external ssh-askpass support]) AC_ARG_WITH(askpass, - [ --without-askpass Disable external ssh-askpass support], - [AC_DEFINE(DISABLE_EXTERNAL_ASKPASS)], - [INSTALL_ASKPASS="yes"] + [ --with-askpass=yes/no Enable external ssh-askpass support (default=yes)], + [ + if test x$withval = xno ; then + INSTALL_ASKPASS="no" + else + INSTALL_ASKPASS="yes" + fi + + ] ) -AC_SUBST(INSTALL_ASKPASS) + +if test "x$INSTALL_ASKPASS" = "xyes" ; then + AC_DEFINE(USE_EXTERNAL_ASKPASS) + AC_SUBST(INSTALL_ASKPASS) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi AC_OUTPUT(Makefile) diff --git a/ssh-add.c b/ssh-add.c index 9ec34180f..bf3d7faea 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -14,13 +14,17 @@ Adds an identity to the authentication server, or removes an identity. */ #include "includes.h" -RCSID("$Id: ssh-add.c,v 1.6 1999/11/12 04:46:08 damien Exp $"); +RCSID("$Id: ssh-add.c,v 1.7 1999/11/15 03:25:30 damien Exp $"); #include "rsa.h" #include "ssh.h" #include "xmalloc.h" #include "authfd.h" +#ifdef USE_EXTERNAL_ASKPASS +int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment); +#endif /* USE_EXTERNAL_ASKPASS */ + void delete_file(AuthenticationConnection *ac, const char *filename) { @@ -52,22 +56,14 @@ delete_all(AuthenticationConnection *ac) fprintf(stderr, "Failed to remove all identitities.\n"); } -#define BUFSIZE 1024 void add_file(AuthenticationConnection *ac, const char *filename) { RSA *key; RSA *public_key; - char *saved_comment, *comment, *pass; - int first; -#ifndef DISABLE_EXTERNAL_ASKPASS - int pipes[2]; - char buf[BUFSIZE]; - int tmp; - pid_t child; - FILE *pipef; -#endif /* !DISABLE_EXTERNAL_ASKPASS */ - + char *saved_comment, *comment; + int success; + key = RSA_new(); public_key = RSA_new(); if (!load_public_key(filename, public_key, &saved_comment)) @@ -76,109 +72,47 @@ add_file(AuthenticationConnection *ac, const char *filename) return; } RSA_free(public_key); - - pass = xstrdup(""); - first = 1; - while (!load_private_key(filename, pass, key, &comment)) - { - /* Free the old passphrase. */ - memset(pass, 0, strlen(pass)); - xfree(pass); - /* Ask for a passphrase. */ - if (getenv("DISPLAY") && !isatty(fileno(stdin))) - { -#ifndef DISABLE_EXTERNAL_ASKPASS - if (pipe(pipes) ==-1) - { - fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); - exit(1); - } - if (fflush(NULL)==EOF) - { - fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); - exit(1); - } - switch (child=fork()) - { - case -1: - fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); - exit(1); - case 0: - close(pipes[0]); - if (dup2(pipes[1], 1) ==-1) - { - fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); - exit(1); - } - tmp=snprintf(buf, BUFSIZE, "Need passphrase for %s (%s)", - filename, saved_comment); - /* skip the prompt if it won't fit */ - if (tmp < 0 || tmp >= BUFSIZE) - tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); - else - tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); - if (tmp==-1) - { - fprintf(stderr, "Executing ssh-askpass failed: %s\n", - strerror(errno)); - exit(1); - } - break; - default: - close(pipes[1]); - if ( (pipef=fdopen(pipes[0], "r")) ==NULL) - { - fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); - exit(1); - } - if(fgets(buf, sizeof(buf), pipef)==NULL) - { - xfree(saved_comment); - return; - } - fclose(pipef); - if (strchr(buf, '\n')) - *strchr(buf, '\n') = 0; - pass = xstrdup(buf); - memset(buf, 0, sizeof(buf)); - if (waitpid(child, NULL, 0) ==-1) - { - fprintf(stderr, "Waiting for child failed: %s\n", - strerror(errno)); - exit(1); - } - if (strcmp(pass, "") == 0) - { - xfree(saved_comment); - xfree(pass); - return; - } - } -#else /* !DISABLE_EXTERNAL_ASKPASS */ + /* At first, try empty passphrase */ + success = load_private_key(filename, "", key, &comment); + if (!success) { + printf("Need passphrase for %s (%s).\n", filename, saved_comment); + if (!isatty(STDIN_FILENO)) { +#ifdef USE_EXTERNAL_ASKPASS + int prompts = 3; + + while (prompts && !success) + { + success = askpass(filename, key, saved_comment, &comment); + prompts--; + } + if (!success) + { + xfree(saved_comment); + return; + } +#else /* !USE_EXTERNAL_ASKPASS */ xfree(saved_comment); return; -#endif /* !DISABLE_EXTERNAL_ASKPASS */ - } - else - { - if (first) - printf("Need passphrase for %s (%s).\n", filename, saved_comment); - else - printf("Bad passphrase.\n"); - pass = read_passphrase("Enter passphrase: ", 1); - if (strcmp(pass, "") == 0) - { - xfree(saved_comment); - xfree(pass); - return; - } - } - first = 0; +#endif /* USE_EXTERNAL_ASKPASS */ } - memset(pass, 0, strlen(pass)); - xfree(pass); + while (!success) { + char *pass = read_passphrase("Enter passphrase: ", 1); + if (strcmp(pass, "") == 0){ + xfree(pass); + xfree(saved_comment); + return; + } + success = load_private_key(filename, pass, key, &comment); + memset(pass, 0, strlen(pass)); + xfree(pass); + if (success) + break; + + printf("Bad passphrase.\n"); + } + } xfree(saved_comment); if (ssh_add_identity(ac, key, comment)) @@ -299,3 +233,85 @@ main(int argc, char **argv) ssh_close_authentication_connection(ac); exit(0); } + +#ifdef USE_EXTERNAL_ASKPASS +int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment) +{ + int pipes[2]; + char buf[1024]; + int tmp; + pid_t child; + FILE *pipef; + + /* Check that we are X11-capable */ + if (getenv("DISPLAY") == NULL) + exit(1); + + if (pipe(pipes) == -1) { + fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); + exit(1); + } + + if (fflush(NULL) == EOF) { + fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); + exit(1); + } + + child = fork(); + if (child == -1) { + fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); + exit(1); + } + + if (child == 0) { + /* In child */ + + close(pipes[0]); + if (dup2(pipes[1], 1) ==-1) { + fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); + exit(1); + } + + tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s (%s)", filename, saved_comment); + /* skip the prompt if it won't fit */ + if ((tmp < 0) || (tmp >= sizeof(buf))) + tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); + else + tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); + + /* Shouldn't get this far */ + fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno)); + exit(1); + } + + /* In parent */ + close(pipes[1]); + + if ((pipef = fdopen(pipes[0], "r")) == NULL) { + fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); + exit(1); + } + + /* Read passphrase back from child, abort if none presented */ + if(fgets(buf, sizeof(buf), pipef) == NULL) + exit(1); + + fclose(pipef); + + if (strchr(buf, '\n')) + *strchr(buf, '\n') = 0; + + if (waitpid(child, NULL, 0) == -1) { + fprintf(stderr, "Waiting for child failed: %s\n", + strerror(errno)); + exit(1); + } + + /* Try password as it was presented */ + tmp = load_private_key(filename, buf, key, comment); + + memset(buf, 0, sizeof(buf)); + + return(tmp); +} +#endif /* USE_EXTERNAL_ASKPASS */ -- cgit v1.2.3