diff options
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 236 |
1 files changed, 126 insertions, 110 deletions
@@ -14,13 +14,17 @@ Adds an identity to the authentication server, or removes an identity. | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$Id: ssh-add.c,v 1.6 1999/11/12 04:46:08 damien Exp $"); | 17 | RCSID("$Id: ssh-add.c,v 1.7 1999/11/15 03:25:30 damien Exp $"); |
18 | 18 | ||
19 | #include "rsa.h" | 19 | #include "rsa.h" |
20 | #include "ssh.h" | 20 | #include "ssh.h" |
21 | #include "xmalloc.h" | 21 | #include "xmalloc.h" |
22 | #include "authfd.h" | 22 | #include "authfd.h" |
23 | 23 | ||
24 | #ifdef USE_EXTERNAL_ASKPASS | ||
25 | int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment); | ||
26 | #endif /* USE_EXTERNAL_ASKPASS */ | ||
27 | |||
24 | void | 28 | void |
25 | delete_file(AuthenticationConnection *ac, const char *filename) | 29 | delete_file(AuthenticationConnection *ac, const char *filename) |
26 | { | 30 | { |
@@ -52,22 +56,14 @@ delete_all(AuthenticationConnection *ac) | |||
52 | fprintf(stderr, "Failed to remove all identitities.\n"); | 56 | fprintf(stderr, "Failed to remove all identitities.\n"); |
53 | } | 57 | } |
54 | 58 | ||
55 | #define BUFSIZE 1024 | ||
56 | void | 59 | void |
57 | add_file(AuthenticationConnection *ac, const char *filename) | 60 | add_file(AuthenticationConnection *ac, const char *filename) |
58 | { | 61 | { |
59 | RSA *key; | 62 | RSA *key; |
60 | RSA *public_key; | 63 | RSA *public_key; |
61 | char *saved_comment, *comment, *pass; | 64 | char *saved_comment, *comment; |
62 | int first; | 65 | int success; |
63 | #ifndef DISABLE_EXTERNAL_ASKPASS | 66 | |
64 | int pipes[2]; | ||
65 | char buf[BUFSIZE]; | ||
66 | int tmp; | ||
67 | pid_t child; | ||
68 | FILE *pipef; | ||
69 | #endif /* !DISABLE_EXTERNAL_ASKPASS */ | ||
70 | |||
71 | key = RSA_new(); | 67 | key = RSA_new(); |
72 | public_key = RSA_new(); | 68 | public_key = RSA_new(); |
73 | if (!load_public_key(filename, public_key, &saved_comment)) | 69 | if (!load_public_key(filename, public_key, &saved_comment)) |
@@ -76,109 +72,47 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
76 | return; | 72 | return; |
77 | } | 73 | } |
78 | RSA_free(public_key); | 74 | RSA_free(public_key); |
79 | |||
80 | pass = xstrdup(""); | ||
81 | first = 1; | ||
82 | while (!load_private_key(filename, pass, key, &comment)) | ||
83 | { | ||
84 | /* Free the old passphrase. */ | ||
85 | memset(pass, 0, strlen(pass)); | ||
86 | xfree(pass); | ||
87 | 75 | ||
88 | /* Ask for a passphrase. */ | 76 | /* At first, try empty passphrase */ |
89 | if (getenv("DISPLAY") && !isatty(fileno(stdin))) | 77 | success = load_private_key(filename, "", key, &comment); |
90 | { | 78 | if (!success) { |
91 | #ifndef DISABLE_EXTERNAL_ASKPASS | 79 | printf("Need passphrase for %s (%s).\n", filename, saved_comment); |
92 | if (pipe(pipes) ==-1) | 80 | if (!isatty(STDIN_FILENO)) { |
93 | { | 81 | #ifdef USE_EXTERNAL_ASKPASS |
94 | fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); | 82 | int prompts = 3; |
95 | exit(1); | 83 | |
96 | } | 84 | while (prompts && !success) |
97 | if (fflush(NULL)==EOF) | 85 | { |
98 | { | 86 | success = askpass(filename, key, saved_comment, &comment); |
99 | fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); | 87 | prompts--; |
100 | exit(1); | 88 | } |
101 | } | 89 | if (!success) |
102 | switch (child=fork()) | 90 | { |
103 | { | 91 | xfree(saved_comment); |
104 | case -1: | 92 | return; |
105 | fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); | 93 | } |
106 | exit(1); | 94 | #else /* !USE_EXTERNAL_ASKPASS */ |
107 | case 0: | ||
108 | close(pipes[0]); | ||
109 | if (dup2(pipes[1], 1) ==-1) | ||
110 | { | ||
111 | fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); | ||
112 | exit(1); | ||
113 | } | ||
114 | tmp=snprintf(buf, BUFSIZE, "Need passphrase for %s (%s)", | ||
115 | filename, saved_comment); | ||
116 | /* skip the prompt if it won't fit */ | ||
117 | if (tmp < 0 || tmp >= BUFSIZE) | ||
118 | tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); | ||
119 | else | ||
120 | tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); | ||
121 | if (tmp==-1) | ||
122 | { | ||
123 | fprintf(stderr, "Executing ssh-askpass failed: %s\n", | ||
124 | strerror(errno)); | ||
125 | exit(1); | ||
126 | } | ||
127 | break; | ||
128 | default: | ||
129 | close(pipes[1]); | ||
130 | if ( (pipef=fdopen(pipes[0], "r")) ==NULL) | ||
131 | { | ||
132 | fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); | ||
133 | exit(1); | ||
134 | } | ||
135 | if(fgets(buf, sizeof(buf), pipef)==NULL) | ||
136 | { | ||
137 | xfree(saved_comment); | ||
138 | return; | ||
139 | } | ||
140 | fclose(pipef); | ||
141 | if (strchr(buf, '\n')) | ||
142 | *strchr(buf, '\n') = 0; | ||
143 | pass = xstrdup(buf); | ||
144 | memset(buf, 0, sizeof(buf)); | ||
145 | if (waitpid(child, NULL, 0) ==-1) | ||
146 | { | ||
147 | fprintf(stderr, "Waiting for child failed: %s\n", | ||
148 | strerror(errno)); | ||
149 | exit(1); | ||
150 | } | ||
151 | if (strcmp(pass, "") == 0) | ||
152 | { | ||
153 | xfree(saved_comment); | ||
154 | xfree(pass); | ||
155 | return; | ||
156 | } | ||
157 | } | ||
158 | #else /* !DISABLE_EXTERNAL_ASKPASS */ | ||
159 | xfree(saved_comment); | 95 | xfree(saved_comment); |
160 | return; | 96 | return; |
161 | #endif /* !DISABLE_EXTERNAL_ASKPASS */ | 97 | #endif /* USE_EXTERNAL_ASKPASS */ |
162 | } | ||
163 | else | ||
164 | { | ||
165 | if (first) | ||
166 | printf("Need passphrase for %s (%s).\n", filename, saved_comment); | ||
167 | else | ||
168 | printf("Bad passphrase.\n"); | ||
169 | pass = read_passphrase("Enter passphrase: ", 1); | ||
170 | if (strcmp(pass, "") == 0) | ||
171 | { | ||
172 | xfree(saved_comment); | ||
173 | xfree(pass); | ||
174 | return; | ||
175 | } | ||
176 | } | ||
177 | first = 0; | ||
178 | } | 98 | } |
179 | memset(pass, 0, strlen(pass)); | ||
180 | xfree(pass); | ||
181 | 99 | ||
100 | while (!success) { | ||
101 | char *pass = read_passphrase("Enter passphrase: ", 1); | ||
102 | if (strcmp(pass, "") == 0){ | ||
103 | xfree(pass); | ||
104 | xfree(saved_comment); | ||
105 | return; | ||
106 | } | ||
107 | success = load_private_key(filename, pass, key, &comment); | ||
108 | memset(pass, 0, strlen(pass)); | ||
109 | xfree(pass); | ||
110 | if (success) | ||
111 | break; | ||
112 | |||
113 | printf("Bad passphrase.\n"); | ||
114 | } | ||
115 | } | ||
182 | xfree(saved_comment); | 116 | xfree(saved_comment); |
183 | 117 | ||
184 | if (ssh_add_identity(ac, key, comment)) | 118 | if (ssh_add_identity(ac, key, comment)) |
@@ -299,3 +233,85 @@ main(int argc, char **argv) | |||
299 | ssh_close_authentication_connection(ac); | 233 | ssh_close_authentication_connection(ac); |
300 | exit(0); | 234 | exit(0); |
301 | } | 235 | } |
236 | |||
237 | #ifdef USE_EXTERNAL_ASKPASS | ||
238 | int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment) | ||
239 | { | ||
240 | int pipes[2]; | ||
241 | char buf[1024]; | ||
242 | int tmp; | ||
243 | pid_t child; | ||
244 | FILE *pipef; | ||
245 | |||
246 | /* Check that we are X11-capable */ | ||
247 | if (getenv("DISPLAY") == NULL) | ||
248 | exit(1); | ||
249 | |||
250 | if (pipe(pipes) == -1) { | ||
251 | fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); | ||
252 | exit(1); | ||
253 | } | ||
254 | |||
255 | if (fflush(NULL) == EOF) { | ||
256 | fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); | ||
257 | exit(1); | ||
258 | } | ||
259 | |||
260 | child = fork(); | ||
261 | if (child == -1) { | ||
262 | fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); | ||
263 | exit(1); | ||
264 | } | ||
265 | |||
266 | if (child == 0) { | ||
267 | /* In child */ | ||
268 | |||
269 | close(pipes[0]); | ||
270 | if (dup2(pipes[1], 1) ==-1) { | ||
271 | fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); | ||
272 | exit(1); | ||
273 | } | ||
274 | |||
275 | tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s (%s)", filename, saved_comment); | ||
276 | /* skip the prompt if it won't fit */ | ||
277 | if ((tmp < 0) || (tmp >= sizeof(buf))) | ||
278 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); | ||
279 | else | ||
280 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); | ||
281 | |||
282 | /* Shouldn't get this far */ | ||
283 | fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno)); | ||
284 | exit(1); | ||
285 | } | ||
286 | |||
287 | /* In parent */ | ||
288 | close(pipes[1]); | ||
289 | |||
290 | if ((pipef = fdopen(pipes[0], "r")) == NULL) { | ||
291 | fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); | ||
292 | exit(1); | ||
293 | } | ||
294 | |||
295 | /* Read passphrase back from child, abort if none presented */ | ||
296 | if(fgets(buf, sizeof(buf), pipef) == NULL) | ||
297 | exit(1); | ||
298 | |||
299 | fclose(pipef); | ||
300 | |||
301 | if (strchr(buf, '\n')) | ||
302 | *strchr(buf, '\n') = 0; | ||
303 | |||
304 | if (waitpid(child, NULL, 0) == -1) { | ||
305 | fprintf(stderr, "Waiting for child failed: %s\n", | ||
306 | strerror(errno)); | ||
307 | exit(1); | ||
308 | } | ||
309 | |||
310 | /* Try password as it was presented */ | ||
311 | tmp = load_private_key(filename, buf, key, comment); | ||
312 | |||
313 | memset(buf, 0, sizeof(buf)); | ||
314 | |||
315 | return(tmp); | ||
316 | } | ||
317 | #endif /* USE_EXTERNAL_ASKPASS */ | ||