summaryrefslogtreecommitdiff
path: root/ssh-add.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-11-25 11:54:57 +1100
committerDamien Miller <djm@mindrot.org>1999-11-25 11:54:57 +1100
commit5428f646ad32da88ddd04a8c287d595524674fbf (patch)
treecc1f1e5d7852e1f44d41077f776abf7dab7ac06d /ssh-add.c
parent9072e1889648988da38b7b81bce95291c1dc3a23 (diff)
- More reformatting merged from OpenBSD CVS
- Merged OpenBSD CVS changes: - [channels.c] report from mrwizard@psu.edu via djm@ibs.com.au - [channels.c] set SO_REUSEADDR and SO_LINGER for forwarded ports. chip@valinux.com via damien@ibs.com.au - [nchan.c] it's not an error() if shutdown_write failes in nchan. - [readconf.c] remove dead #ifdef-0-code - [readconf.c servconf.c] strcasecmp instead of tolower - [scp.c] progress meter overflow fix from damien@ibs.com.au - [ssh-add.1 ssh-add.c] SSH_ASKPASS support - [ssh.1 ssh.c] postpone fork_after_authentication until command execution, request/patch from jahakala@cc.jyu.fi via damien@ibs.com.au plus: use daemon() for backgrounding
Diffstat (limited to 'ssh-add.c')
-rw-r--r--ssh-add.c167
1 files changed, 59 insertions, 108 deletions
diff --git a/ssh-add.c b/ssh-add.c
index f94dcdabb..711ae126e 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -7,7 +7,7 @@
7 */ 7 */
8 8
9#include "includes.h" 9#include "includes.h"
10RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $"); 10RCSID("$Id: ssh-add.c,v 1.14 1999/11/25 00:54:59 damien Exp $");
11 11
12#include "rsa.h" 12#include "rsa.h"
13#include "ssh.h" 13#include "ssh.h"
@@ -15,10 +15,6 @@ RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $");
15#include "authfd.h" 15#include "authfd.h"
16#include "fingerprint.h" 16#include "fingerprint.h"
17 17
18#ifdef USE_EXTERNAL_ASKPASS
19int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment);
20#endif /* USE_EXTERNAL_ASKPASS */
21
22#ifdef HAVE___PROGNAME 18#ifdef HAVE___PROGNAME
23extern char *__progname; 19extern char *__progname;
24#else /* HAVE___PROGNAME */ 20#else /* HAVE___PROGNAME */
@@ -54,13 +50,53 @@ delete_all(AuthenticationConnection *ac)
54 fprintf(stderr, "Failed to remove all identitities.\n"); 50 fprintf(stderr, "Failed to remove all identitities.\n");
55} 51}
56 52
53char *
54ssh_askpass(char *askpass, char *msg)
55{
56 pid_t pid;
57 size_t len;
58 char *nl, *pass;
59 int p[2], status;
60 char buf[1024];
61
62 if (askpass == NULL)
63 fatal("internal error: askpass undefined");
64 if (pipe(p) < 0)
65 fatal("ssh_askpass: pipe: %s", strerror(errno));
66 if ((pid = fork()) < 0)
67 fatal("ssh_askpass: fork: %s", strerror(errno));
68 if (pid == 0) {
69 close(p[0]);
70 if (dup2(p[1], STDOUT_FILENO) < 0)
71 fatal("ssh_askpass: dup2: %s", strerror(errno));
72 execlp(askpass, askpass, msg, (char *) 0);
73 fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
74 }
75 close(p[1]);
76 len = read(p[0], buf, sizeof buf);
77 close(p[0]);
78 while (waitpid(pid, &status, 0) < 0)
79 if (errno != EINTR)
80 break;
81 if (len <= 1)
82 return xstrdup("");
83 nl = strchr(buf, '\n');
84 if (nl)
85 *nl = '\0';
86 pass = xstrdup(buf);
87 memset(buf, 0, sizeof(buf));
88 return pass;
89}
90
57void 91void
58add_file(AuthenticationConnection *ac, const char *filename) 92add_file(AuthenticationConnection *ac, const char *filename)
59{ 93{
60 RSA *key; 94 RSA *key;
61 RSA *public_key; 95 RSA *public_key;
62 char *saved_comment, *comment; 96 char *saved_comment, *comment, *askpass = NULL;
97 char buf[1024], msg[1024];
63 int success; 98 int success;
99 int interactive = isatty(STDIN_FILENO);
64 100
65 key = RSA_new(); 101 key = RSA_new();
66 public_key = RSA_new(); 102 public_key = RSA_new();
@@ -70,29 +106,26 @@ add_file(AuthenticationConnection *ac, const char *filename)
70 } 106 }
71 RSA_free(public_key); 107 RSA_free(public_key);
72 108
109 if (!interactive && getenv("DISPLAY"))
110 askpass = getenv("SSH_ASKPASS");
111
73 /* At first, try empty passphrase */ 112 /* At first, try empty passphrase */
74 success = load_private_key(filename, "", key, &comment); 113 success = load_private_key(filename, "", key, &comment);
75 if (!success) { 114 if (!success) {
76 printf("Need passphrase for %s (%s).\n", filename, saved_comment); 115 printf("Need passphrase for %.200s\n", filename);
77 if (!isatty(STDIN_FILENO)) { 116 if (!interactive && askpass == NULL) {
78#ifdef USE_EXTERNAL_ASKPASS 117 xfree(saved_comment);
79 int prompts = 3; 118 return;
80 while (prompts && !success) {
81 success = askpass(filename, key, saved_comment, &comment);
82 prompts--;
83 }
84 if (!success) {
85 xfree(saved_comment);
86 return;
87 }
88#else /* !USE_EXTERNAL_ASKPASS */
89 xfree(saved_comment);
90 return;
91#endif /* USE_EXTERNAL_ASKPASS */
92 } 119 }
93 120 snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
94 while (!success) { 121 for (;;) {
95 char *pass = read_passphrase("Enter passphrase: ", 1); 122 char *pass;
123 if (interactive) {
124 snprintf(buf, sizeof buf, "%s: ", msg);
125 pass = read_passphrase(buf, 1);
126 } else {
127 pass = ssh_askpass(askpass, msg);
128 }
96 if (strcmp(pass, "") == 0) { 129 if (strcmp(pass, "") == 0) {
97 xfree(pass); 130 xfree(pass);
98 xfree(saved_comment); 131 xfree(saved_comment);
@@ -103,7 +136,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
103 xfree(pass); 136 xfree(pass);
104 if (success) 137 if (success)
105 break; 138 break;
106 printf("Bad passphrase.\n"); 139 strlcpy(msg, "Bad passphrase, try again", sizeof msg);
107 } 140 }
108 } 141 }
109 xfree(saved_comment); 142 xfree(saved_comment);
@@ -222,85 +255,3 @@ main(int argc, char **argv)
222 ssh_close_authentication_connection(ac); 255 ssh_close_authentication_connection(ac);
223 exit(0); 256 exit(0);
224} 257}
225
226#ifdef USE_EXTERNAL_ASKPASS
227int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment)
228{
229 int pipes[2];
230 char buf[1024];
231 int tmp;
232 pid_t child;
233 FILE *pipef;
234
235 /* Check that we are X11-capable */
236 if (getenv("DISPLAY") == NULL)
237 exit(1);
238
239 if (pipe(pipes) == -1) {
240 fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
241 exit(1);
242 }
243
244 if (fflush(NULL) == EOF) {
245 fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
246 exit(1);
247 }
248
249 child = fork();
250 if (child == -1) {
251 fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
252 exit(1);
253 }
254
255 if (child == 0) {
256 /* In child */
257
258 close(pipes[0]);
259 if (dup2(pipes[1], 1) ==-1) {
260 fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
261 exit(1);
262 }
263
264 tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment);
265 /* skip the prompt if it won't fit */
266 if ((tmp < 0) || (tmp >= sizeof(buf)))
267 tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
268 else
269 tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
270
271 /* Shouldn't get this far */
272 fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno));
273 exit(1);
274 }
275
276 /* In parent */
277 close(pipes[1]);
278
279 if ((pipef = fdopen(pipes[0], "r")) == NULL) {
280 fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
281 exit(1);
282 }
283
284 /* Read passphrase back from child, abort if none presented */
285 if(fgets(buf, sizeof(buf), pipef) == NULL)
286 exit(1);
287
288 fclose(pipef);
289
290 if (strchr(buf, '\n'))
291 *strchr(buf, '\n') = 0;
292
293 if (waitpid(child, NULL, 0) == -1) {
294 fprintf(stderr, "Waiting for child failed: %s\n",
295 strerror(errno));
296 exit(1);
297 }
298
299 /* Try password as it was presented */
300 tmp = load_private_key(filename, buf, key, comment);
301
302 memset(buf, 0, sizeof(buf));
303
304 return(tmp);
305}
306#endif /* USE_EXTERNAL_ASKPASS */