summaryrefslogtreecommitdiff
path: root/ssh-add.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-add.c')
-rw-r--r--ssh-add.c236
1 files changed, 126 insertions, 110 deletions
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.
14*/ 14*/
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: ssh-add.c,v 1.6 1999/11/12 04:46:08 damien Exp $"); 17RCSID("$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
25int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment);
26#endif /* USE_EXTERNAL_ASKPASS */
27
24void 28void
25delete_file(AuthenticationConnection *ac, const char *filename) 29delete_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
56void 59void
57add_file(AuthenticationConnection *ac, const char *filename) 60add_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
238int 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 */