blob: fb237ce2e9b05d91471d23de2b14cbc4bdf47c91 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
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"
Damien Millerc7b38ce1999-11-09 10:28:04 +110017RCSID("$Id: ssh-add.c,v 1.5 1999/11/08 23:28:04 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100018
19#include "rsa.h"
20#include "ssh.h"
21#include "xmalloc.h"
22#include "authfd.h"
23
24void
Damien Miller01ab4a21999-10-28 15:23:30 +100025delete_file(AuthenticationConnection *ac, const char *filename)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100026{
27 RSA *key;
28 char *comment;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100029
30 key = RSA_new();
31 if (!load_public_key(filename, key, &comment))
32 {
33 printf("Bad key file %s: %s\n", filename, strerror(errno));
34 return;
35 }
36
Damien Millerd4a8b7e1999-10-27 13:42:43 +100037 if (ssh_remove_identity(ac, key))
38 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
39 else
40 fprintf(stderr, "Could not remove identity: %s\n", filename);
41 RSA_free(key);
42 xfree(comment);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100043}
44
45void
Damien Miller01ab4a21999-10-28 15:23:30 +100046delete_all(AuthenticationConnection *ac)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100047{
Damien Millerd4a8b7e1999-10-27 13:42:43 +100048 /* Send a request to remove all identities. */
49 if (ssh_remove_all_identities(ac))
50 fprintf(stderr, "All identities removed.\n");
51 else
52 fprintf(stderr, "Failed to remove all identitities.\n");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100053}
54
Damien Miller356a0b01999-11-08 15:30:59 +110055#define BUFSIZE 1024
Damien Millerd4a8b7e1999-10-27 13:42:43 +100056void
Damien Miller01ab4a21999-10-28 15:23:30 +100057add_file(AuthenticationConnection *ac, const char *filename)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100058{
59 RSA *key;
60 RSA *public_key;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100061 char *saved_comment, *comment, *pass;
62 int first;
Damien Miller356a0b01999-11-08 15:30:59 +110063 int pipes[2];
64 char buf[BUFSIZE];
65 int tmp;
66 pid_t child;
67 FILE *pipef;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100068
69 key = RSA_new();
70 public_key = RSA_new();
71 if (!load_public_key(filename, public_key, &saved_comment))
72 {
73 printf("Bad key file %s: %s\n", filename, strerror(errno));
74 return;
75 }
76 RSA_free(public_key);
77
78 pass = xstrdup("");
79 first = 1;
80 while (!load_private_key(filename, pass, key, &comment))
81 {
82 /* Free the old passphrase. */
83 memset(pass, 0, strlen(pass));
84 xfree(pass);
85
86 /* Ask for a passphrase. */
87 if (getenv("DISPLAY") && !isatty(fileno(stdin)))
88 {
Damien Miller356a0b01999-11-08 15:30:59 +110089 if (pipe(pipes) ==-1)
90 {
91 fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
92 exit(1);
93 }
94 if (fflush(NULL)==EOF)
95 {
96 fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
97 exit(1);
98 }
99 switch (child=fork())
100 {
101 case -1:
102 fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
103 exit(1);
104 case 0:
105 close(pipes[0]);
106 if (dup2(pipes[1], 1) ==-1)
107 {
108 fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
109 exit(1);
110 }
111 tmp=snprintf(buf, BUFSIZE, "Need passphrase for %s (%s)",
112 filename, saved_comment);
113 /* skip the prompt if it won't fit */
114 if (tmp < 0 || tmp >= BUFSIZE)
Damien Millerc7b38ce1999-11-09 10:28:04 +1100115 tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
Damien Miller356a0b01999-11-08 15:30:59 +1100116 else
Damien Millerc7b38ce1999-11-09 10:28:04 +1100117 tmp=execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
Damien Miller356a0b01999-11-08 15:30:59 +1100118 if (tmp==-1)
119 {
120 fprintf(stderr, "Executing ssh-askpass failed: %s\n",
121 strerror(errno));
122 exit(1);
123 }
124 break;
125 default:
126 close(pipes[1]);
127 if ( (pipef=fdopen(pipes[0], "r")) ==NULL)
128 {
129 fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
130 exit(1);
131 }
132 if(fgets(buf, sizeof(buf), pipef)==NULL)
133 {
134 xfree(saved_comment);
135 return;
136 }
137 fclose(pipef);
138 if (strchr(buf, '\n'))
139 *strchr(buf, '\n') = 0;
140 pass = xstrdup(buf);
141 memset(buf, 0, sizeof(buf));
142 if (waitpid(child, NULL, 0) ==-1)
143 {
144 fprintf(stderr, "Waiting for child failed: %s\n",
145 strerror(errno));
146 exit(1);
147 }
148 if (strcmp(pass, "") == 0)
149 {
150 xfree(saved_comment);
151 xfree(pass);
152 return;
153 }
154 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000155 }
156 else
157 {
158 if (first)
159 printf("Need passphrase for %s (%s).\n", filename, saved_comment);
160 else
161 printf("Bad passphrase.\n");
162 pass = read_passphrase("Enter passphrase: ", 1);
163 if (strcmp(pass, "") == 0)
164 {
165 xfree(saved_comment);
166 xfree(pass);
167 return;
168 }
169 }
170 first = 0;
171 }
172 memset(pass, 0, strlen(pass));
173 xfree(pass);
174
175 xfree(saved_comment);
176
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000177 if (ssh_add_identity(ac, key, comment))
178 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
179 else
180 fprintf(stderr, "Could not add identity: %s\n", filename);
181 RSA_free(key);
182 xfree(comment);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000183}
184
185void
Damien Miller01ab4a21999-10-28 15:23:30 +1000186list_identities(AuthenticationConnection *ac)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000187{
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000188 BIGNUM *e, *n;
189 int bits, status;
190 char *comment;
191 int had_identities;
192
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000193 e = BN_new();
194 n = BN_new();
195 had_identities = 0;
196 for (status = ssh_get_first_identity(ac, &bits, e, n, &comment);
197 status;
198 status = ssh_get_next_identity(ac, &bits, e, n, &comment))
199 {
200 char *buf;
201 had_identities = 1;
202 printf("%d ", bits);
203 buf = BN_bn2dec(e);
Damien Millerfd7c9111999-11-08 16:15:55 +1100204 if (buf != NULL) {
205 printf("%s ", buf);
206 free (buf);
207 } else {
208 error("list_identities: BN_bn2dec #1 failed.");
209 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000210 buf = BN_bn2dec(n);
Damien Millerfd7c9111999-11-08 16:15:55 +1100211 if (buf != NULL) {
212 printf("%s %s\n", buf, comment);
213 free (buf);
214 } else {
215 error("list_identities: BN_bn2dec #2 failed.");
216 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000217 xfree(comment);
218 }
219 BN_clear_free(e);
220 BN_clear_free(n);
221 if (!had_identities)
222 printf("The agent has no identities.\n");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000223}
224
225int
Damien Miller01ab4a21999-10-28 15:23:30 +1000226main(int argc, char **argv)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000227{
Damien Miller01ab4a21999-10-28 15:23:30 +1000228 AuthenticationConnection *ac = NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000229 struct passwd *pw;
230 char buf[1024];
231 int no_files = 1;
232 int i;
233 int deleting = 0;
234
235 /* check if RSA support exists */
236 if (rsa_alive() == 0) {
237 extern char *__progname;
238
239 fprintf(stderr,
240 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
241 __progname);
242 exit(1);
243 }
244
Damien Miller01ab4a21999-10-28 15:23:30 +1000245 /* At first, get a connection to the authentication agent. */
246 ac = ssh_get_authentication_connection();
247 if (ac == NULL) {
248 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
249 exit(1);
250 }
251
252 for (i = 1; i < argc; i++)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000253 {
Damien Miller01ab4a21999-10-28 15:23:30 +1000254 if (strcmp(argv[i], "-l") == 0)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000255 {
Damien Miller01ab4a21999-10-28 15:23:30 +1000256 list_identities(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000257 no_files = 0; /* Don't default-add/delete if -l. */
258 continue;
259 }
Damien Miller01ab4a21999-10-28 15:23:30 +1000260 if (strcmp(argv[i], "-d") == 0)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000261 {
262 deleting = 1;
263 continue;
264 }
Damien Miller01ab4a21999-10-28 15:23:30 +1000265 if (strcmp(argv[i], "-D") == 0)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000266 {
Damien Miller01ab4a21999-10-28 15:23:30 +1000267 delete_all(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000268 no_files = 0;
269 continue;
270 }
271 no_files = 0;
272 if (deleting)
Damien Miller01ab4a21999-10-28 15:23:30 +1000273 delete_file(ac, argv[i]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000274 else
Damien Miller01ab4a21999-10-28 15:23:30 +1000275 add_file(ac, argv[i]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000276 }
277 if (no_files)
278 {
279 pw = getpwuid(getuid());
280 if (!pw)
281 {
282 fprintf(stderr, "No user found with uid %d\n", (int)getuid());
Damien Miller01ab4a21999-10-28 15:23:30 +1000283 ssh_close_authentication_connection(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000284 exit(1);
285 }
286 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
287 if (deleting)
Damien Miller01ab4a21999-10-28 15:23:30 +1000288 delete_file(ac, buf);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000289 else
Damien Miller01ab4a21999-10-28 15:23:30 +1000290 add_file(ac, buf);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000291 }
Damien Miller01ab4a21999-10-28 15:23:30 +1000292 ssh_close_authentication_connection(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000293 exit(0);
294}