]> andersk Git - openssh.git/blame - ssh-add.c
- Add recommendation to use GNU make to INSTALL document
[openssh.git] / ssh-add.c
CommitLineData
8efc0c15 1/*
2
3ssh-add.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved
9
10Created: Thu Apr 6 00:52:24 1995 ylo
11
12Adds an identity to the authentication server, or removes an identity.
13
14*/
15
16#include "includes.h"
17RCSID("$Id$");
18
19#include "rsa.h"
20#include "ssh.h"
21#include "xmalloc.h"
22#include "authfd.h"
f095fcc7 23#include "fingerprint.h"
8efc0c15 24
dad9a31e 25#ifdef USE_EXTERNAL_ASKPASS
26int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment);
27#endif /* USE_EXTERNAL_ASKPASS */
28
f601d847 29#ifdef HAVE___PROGNAME
30extern char *__progname;
31#else /* HAVE___PROGNAME */
32const char *__progname = "ssh-add";
33#endif /* HAVE___PROGNAME */
34
8efc0c15 35void
5068f573 36delete_file(AuthenticationConnection *ac, const char *filename)
8efc0c15 37{
38 RSA *key;
39 char *comment;
8efc0c15 40
41 key = RSA_new();
42 if (!load_public_key(filename, key, &comment))
43 {
44 printf("Bad key file %s: %s\n", filename, strerror(errno));
45 return;
46 }
47
8efc0c15 48 if (ssh_remove_identity(ac, key))
49 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
50 else
51 fprintf(stderr, "Could not remove identity: %s\n", filename);
52 RSA_free(key);
53 xfree(comment);
8efc0c15 54}
55
56void
5068f573 57delete_all(AuthenticationConnection *ac)
8efc0c15 58{
8efc0c15 59 /* Send a request to remove all identities. */
60 if (ssh_remove_all_identities(ac))
61 fprintf(stderr, "All identities removed.\n");
62 else
63 fprintf(stderr, "Failed to remove all identitities.\n");
8efc0c15 64}
65
66void
5068f573 67add_file(AuthenticationConnection *ac, const char *filename)
8efc0c15 68{
69 RSA *key;
70 RSA *public_key;
dad9a31e 71 char *saved_comment, *comment;
72 int success;
73
8efc0c15 74 key = RSA_new();
75 public_key = RSA_new();
76 if (!load_public_key(filename, public_key, &saved_comment))
77 {
78 printf("Bad key file %s: %s\n", filename, strerror(errno));
79 return;
80 }
81 RSA_free(public_key);
8efc0c15 82
dad9a31e 83 /* At first, try empty passphrase */
84 success = load_private_key(filename, "", key, &comment);
85 if (!success) {
86 printf("Need passphrase for %s (%s).\n", filename, saved_comment);
87 if (!isatty(STDIN_FILENO)) {
88#ifdef USE_EXTERNAL_ASKPASS
89 int prompts = 3;
90
91 while (prompts && !success)
92 {
93 success = askpass(filename, key, saved_comment, &comment);
94 prompts--;
95 }
96 if (!success)
97 {
98 xfree(saved_comment);
99 return;
100 }
101#else /* !USE_EXTERNAL_ASKPASS */
045672f9 102 xfree(saved_comment);
103 return;
dad9a31e 104#endif /* USE_EXTERNAL_ASKPASS */
8efc0c15 105 }
8efc0c15 106
dad9a31e 107 while (!success) {
108 char *pass = read_passphrase("Enter passphrase: ", 1);
109 if (strcmp(pass, "") == 0){
110 xfree(pass);
111 xfree(saved_comment);
112 return;
113 }
114 success = load_private_key(filename, pass, key, &comment);
115 memset(pass, 0, strlen(pass));
116 xfree(pass);
117 if (success)
118 break;
dad9a31e 119 printf("Bad passphrase.\n");
120 }
121 }
8efc0c15 122 xfree(saved_comment);
123
8efc0c15 124 if (ssh_add_identity(ac, key, comment))
125 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
126 else
127 fprintf(stderr, "Could not add identity: %s\n", filename);
128 RSA_free(key);
129 xfree(comment);
8efc0c15 130}
131
132void
f095fcc7 133list_identities(AuthenticationConnection *ac, int fp)
8efc0c15 134{
8efc0c15 135 BIGNUM *e, *n;
4d195447 136 int status;
8efc0c15 137 char *comment;
138 int had_identities;
139
8efc0c15 140 e = BN_new();
141 n = BN_new();
142 had_identities = 0;
4d195447 143 for (status = ssh_get_first_identity(ac, e, n, &comment);
8efc0c15 144 status;
4d195447 145 status = ssh_get_next_identity(ac, e, n, &comment))
8efc0c15 146 {
f095fcc7 147 unsigned int bits = BN_num_bits(n);
8efc0c15 148 had_identities = 1;
f095fcc7 149 if (fp) {
150 printf("%d %s %s\n", bits, fingerprint(e, n), comment);
151 } else {
152 char *ebuf, *nbuf;
153 ebuf = BN_bn2dec(e);
154 if (ebuf == NULL) {
155 error("list_identities: BN_bn2dec(e) failed.");
156 }else{
157 nbuf = BN_bn2dec(n);
158 if (nbuf == NULL) {
159 error("list_identities: BN_bn2dec(n) failed.");
160 }else{
161 printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
162 free(nbuf);
163 }
164 free(ebuf);
165 }
5bae4ab8 166 }
8efc0c15 167 xfree(comment);
168 }
169 BN_clear_free(e);
170 BN_clear_free(n);
171 if (!had_identities)
172 printf("The agent has no identities.\n");
8efc0c15 173}
174
175int
5068f573 176main(int argc, char **argv)
8efc0c15 177{
5068f573 178 AuthenticationConnection *ac = NULL;
8efc0c15 179 struct passwd *pw;
180 char buf[1024];
181 int no_files = 1;
182 int i;
183 int deleting = 0;
184
185 /* check if RSA support exists */
186 if (rsa_alive() == 0) {
8efc0c15 187 fprintf(stderr,
188 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
189 __progname);
190 exit(1);
191 }
192
5068f573 193 /* At first, get a connection to the authentication agent. */
194 ac = ssh_get_authentication_connection();
195 if (ac == NULL) {
196 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
197 exit(1);
198 }
199
200 for (i = 1; i < argc; i++)
8efc0c15 201 {
f095fcc7 202 if ((strcmp(argv[i], "-l") == 0) ||
203 (strcmp(argv[i], "-L") == 0))
8efc0c15 204 {
f095fcc7 205 list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
8efc0c15 206 no_files = 0; /* Don't default-add/delete if -l. */
207 continue;
208 }
5068f573 209 if (strcmp(argv[i], "-d") == 0)
8efc0c15 210 {
211 deleting = 1;
212 continue;
213 }
5068f573 214 if (strcmp(argv[i], "-D") == 0)
8efc0c15 215 {
5068f573 216 delete_all(ac);
8efc0c15 217 no_files = 0;
218 continue;
219 }
220 no_files = 0;
221 if (deleting)
5068f573 222 delete_file(ac, argv[i]);
8efc0c15 223 else
5068f573 224 add_file(ac, argv[i]);
8efc0c15 225 }
226 if (no_files)
227 {
228 pw = getpwuid(getuid());
229 if (!pw)
230 {
231 fprintf(stderr, "No user found with uid %d\n", (int)getuid());
5068f573 232 ssh_close_authentication_connection(ac);
8efc0c15 233 exit(1);
234 }
235 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
236 if (deleting)
5068f573 237 delete_file(ac, buf);
8efc0c15 238 else
5068f573 239 add_file(ac, buf);
8efc0c15 240 }
5068f573 241 ssh_close_authentication_connection(ac);
8efc0c15 242 exit(0);
243}
dad9a31e 244
245#ifdef USE_EXTERNAL_ASKPASS
246int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment)
247{
248 int pipes[2];
249 char buf[1024];
250 int tmp;
251 pid_t child;
252 FILE *pipef;
253
254 /* Check that we are X11-capable */
255 if (getenv("DISPLAY") == NULL)
256 exit(1);
257
258 if (pipe(pipes) == -1) {
259 fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
260 exit(1);
261 }
262
263 if (fflush(NULL) == EOF) {
264 fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
265 exit(1);
266 }
267
268 child = fork();
269 if (child == -1) {
270 fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
271 exit(1);
272 }
273
274 if (child == 0) {
275 /* In child */
276
277 close(pipes[0]);
278 if (dup2(pipes[1], 1) ==-1) {
279 fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
280 exit(1);
281 }
282
d84a9a44 283 tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment);
dad9a31e 284 /* skip the prompt if it won't fit */
285 if ((tmp < 0) || (tmp >= sizeof(buf)))
286 tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
287 else
288 tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
289
290 /* Shouldn't get this far */
291 fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno));
292 exit(1);
293 }
294
295 /* In parent */
296 close(pipes[1]);
297
298 if ((pipef = fdopen(pipes[0], "r")) == NULL) {
299 fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
300 exit(1);
301 }
302
303 /* Read passphrase back from child, abort if none presented */
304 if(fgets(buf, sizeof(buf), pipef) == NULL)
305 exit(1);
306
307 fclose(pipef);
308
309 if (strchr(buf, '\n'))
310 *strchr(buf, '\n') = 0;
311
312 if (waitpid(child, NULL, 0) == -1) {
313 fprintf(stderr, "Waiting for child failed: %s\n",
314 strerror(errno));
315 exit(1);
316 }
317
318 /* Try password as it was presented */
319 tmp = load_private_key(filename, buf, key, comment);
320
321 memset(buf, 0, sizeof(buf));
322
323 return(tmp);
324}
325#endif /* USE_EXTERNAL_ASKPASS */
This page took 0.356243 seconds and 5 git commands to generate.