diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 11:54:57 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 11:54:57 +1100 |
commit | 5428f646ad32da88ddd04a8c287d595524674fbf (patch) | |
tree | cc1f1e5d7852e1f44d41077f776abf7dab7ac06d /ssh-add.c | |
parent | 9072e1889648988da38b7b81bce95291c1dc3a23 (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.c | 167 |
1 files changed, 59 insertions, 108 deletions
@@ -7,7 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "includes.h" | 9 | #include "includes.h" |
10 | RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $"); | 10 | RCSID("$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 | ||
19 | int 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 |
23 | extern char *__progname; | 19 | extern 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 | ||
53 | char * | ||
54 | ssh_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 | |||
57 | void | 91 | void |
58 | add_file(AuthenticationConnection *ac, const char *filename) | 92 | add_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 | ||
227 | int 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 */ | ||