]> andersk Git - openssh.git/blob - ssh-add.c
- (djm) OpenBSD CVS updates:
[openssh.git] / ssh-add.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Created: Thu Apr  6 00:52:24 1995 ylo
6  * Adds an identity to the authentication server, or removes an identity.
7  */
8
9 #include "includes.h"
10 RCSID("$OpenBSD: ssh-add.c,v 1.18 2000/07/16 08:27:21 markus Exp $");
11
12 #include <openssl/rsa.h>
13 #include <openssl/dsa.h>
14
15 #include "rsa.h"
16 #include "ssh.h"
17 #include "xmalloc.h"
18 #include "fingerprint.h"
19 #include "key.h"
20 #include "authfd.h"
21 #include "authfile.h"
22
23 #ifdef HAVE___PROGNAME
24 extern char *__progname;
25 #else /* HAVE___PROGNAME */
26 static const char *__progname = "ssh-add";
27 #endif /* HAVE___PROGNAME */
28
29 void
30 delete_file(AuthenticationConnection *ac, const char *filename)
31 {
32         Key *public;
33         char *comment;
34
35         public = key_new(KEY_RSA);
36         if (!load_public_key(filename, public, &comment)) {
37                 printf("Bad key file %s: %s\n", filename, strerror(errno));
38                 return;
39         }
40         if (ssh_remove_identity(ac, public->rsa))
41                 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
42         else
43                 fprintf(stderr, "Could not remove identity: %s\n", filename);
44         key_free(public);
45         xfree(comment);
46 }
47
48 void
49 delete_all(AuthenticationConnection *ac)
50 {
51         /* Send a request to remove all identities. */
52         if (ssh_remove_all_identities(ac))
53                 fprintf(stderr, "All identities removed.\n");
54         else
55                 fprintf(stderr, "Failed to remove all identitities.\n");
56 }
57
58 char *
59 ssh_askpass(char *askpass, char *msg)
60 {
61         pid_t pid;
62         size_t len;
63         char *nl, *pass;
64         int p[2], status;
65         char buf[1024];
66
67         if (askpass == NULL)
68                 fatal("internal error: askpass undefined");
69         if (pipe(p) < 0)
70                 fatal("ssh_askpass: pipe: %s", strerror(errno));
71         if ((pid = fork()) < 0)
72                 fatal("ssh_askpass: fork: %s", strerror(errno));
73         if (pid == 0) {
74                 close(p[0]);
75                 if (dup2(p[1], STDOUT_FILENO) < 0)
76                         fatal("ssh_askpass: dup2: %s", strerror(errno));
77                 execlp(askpass, askpass, msg, (char *) 0);
78                 fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
79         }
80         close(p[1]);
81         len = read(p[0], buf, sizeof buf);
82         close(p[0]);
83         while (waitpid(pid, &status, 0) < 0)
84                 if (errno != EINTR)
85                         break;
86         if (len <= 1)
87                 return xstrdup("");
88         nl = strchr(buf, '\n');
89         if (nl)
90                 *nl = '\0';
91         pass = xstrdup(buf);
92         memset(buf, 0, sizeof(buf));
93         return pass;
94 }
95
96 void
97 add_file(AuthenticationConnection *ac, const char *filename)
98 {
99         Key *public;
100         Key *private;
101         char *saved_comment, *comment, *askpass = NULL;
102         char buf[1024], msg[1024];
103         int success;
104         int interactive = isatty(STDIN_FILENO);
105         int type = KEY_RSA;
106
107         /*
108          * try to load the public key. right now this only works for RSA,
109          * since DSA keys are fully encrypted
110          */
111         public = key_new(KEY_RSA);
112         if (!load_public_key(filename, public, &saved_comment)) {
113                 /* ok, so we will asume this is a DSA key */
114                 type = KEY_DSA;
115                 saved_comment = xstrdup(filename);
116         }
117         key_free(public);
118
119         if (!interactive && getenv("DISPLAY")) {
120                 if (getenv(SSH_ASKPASS_ENV))
121                         askpass = getenv(SSH_ASKPASS_ENV);
122                 else
123                         askpass = SSH_ASKPASS_DEFAULT;
124         }
125
126         /* At first, try empty passphrase */
127         private = key_new(type);
128         success = load_private_key(filename, "", private, &comment);
129         if (!success) {
130                 printf("Need passphrase for %.200s\n", filename);
131                 if (!interactive && askpass == NULL) {
132                         xfree(saved_comment);
133                         return;
134                 }
135                 snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
136                 for (;;) {
137                         char *pass;
138                         if (interactive) {
139                                 snprintf(buf, sizeof buf, "%s: ", msg);
140                                 pass = read_passphrase(buf, 1);
141                         } else {
142                                 pass = ssh_askpass(askpass, msg);
143                         }
144                         if (strcmp(pass, "") == 0) {
145                                 xfree(pass);
146                                 xfree(saved_comment);
147                                 return;
148                         }
149                         success = load_private_key(filename, pass, private, &comment);
150                         memset(pass, 0, strlen(pass));
151                         xfree(pass);
152                         if (success)
153                                 break;
154                         strlcpy(msg, "Bad passphrase, try again", sizeof msg);
155                 }
156         }
157         xfree(saved_comment);
158
159         if (ssh_add_identity(ac, private, comment))
160                 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
161         else
162                 fprintf(stderr, "Could not add identity: %s\n", filename);
163         key_free(private);
164         xfree(comment);
165 }
166
167 void
168 list_identities(AuthenticationConnection *ac, int fp)
169 {
170         BIGNUM *e, *n;
171         int status;
172         char *comment;
173         int had_identities;
174
175         e = BN_new();
176         n = BN_new();
177         had_identities = 0;
178         for (status = ssh_get_first_identity(ac, e, n, &comment);
179              status;
180              status = ssh_get_next_identity(ac, e, n, &comment)) {
181                 unsigned int bits = BN_num_bits(n);
182                 had_identities = 1;
183                 if (fp) {
184                         printf("%d %s %s\n", bits, fingerprint(e, n), comment);
185                 } else {
186                         char *ebuf, *nbuf;
187                         ebuf = BN_bn2dec(e);
188                         if (ebuf == NULL) {
189                                 error("list_identities: BN_bn2dec(e) failed.");
190                         } else {
191                                 nbuf = BN_bn2dec(n);
192                                 if (nbuf == NULL) {
193                                         error("list_identities: BN_bn2dec(n) failed.");
194                                 } else {
195                                         printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
196                                         free(nbuf);
197                                 }
198                                 free(ebuf);
199                         }
200                 }
201                 xfree(comment);
202         }
203         BN_clear_free(e);
204         BN_clear_free(n);
205         if (!had_identities)
206                 printf("The agent has no identities.\n");
207 }
208
209 int
210 main(int argc, char **argv)
211 {
212         AuthenticationConnection *ac = NULL;
213         struct passwd *pw;
214         char buf[1024];
215         int no_files = 1;
216         int i;
217         int deleting = 0;
218
219         init_rng();
220
221         /* check if RSA support exists */
222         if (rsa_alive() == 0) {
223                 fprintf(stderr,
224                         "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
225                         __progname);
226                 exit(1);
227         }
228         /* At first, get a connection to the authentication agent. */
229         ac = ssh_get_authentication_connection();
230         if (ac == NULL) {
231                 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
232                 exit(1);
233         }
234         for (i = 1; i < argc; i++) {
235                 if ((strcmp(argv[i], "-l") == 0) ||
236                     (strcmp(argv[i], "-L") == 0)) {
237                         list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
238                         /* Don't default-add/delete if -l. */
239                         no_files = 0;
240                         continue;
241                 }
242                 if (strcmp(argv[i], "-d") == 0) {
243                         deleting = 1;
244                         continue;
245                 }
246                 if (strcmp(argv[i], "-D") == 0) {
247                         delete_all(ac);
248                         no_files = 0;
249                         continue;
250                 }
251                 no_files = 0;
252                 if (deleting)
253                         delete_file(ac, argv[i]);
254                 else
255                         add_file(ac, argv[i]);
256         }
257         if (no_files) {
258                 pw = getpwuid(getuid());
259                 if (!pw) {
260                         fprintf(stderr, "No user found with uid %d\n", (int) getuid());
261                         ssh_close_authentication_connection(ac);
262                         exit(1);
263                 }
264                 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
265                 if (deleting)
266                         delete_file(ac, buf);
267                 else
268                         add_file(ac, buf);
269         }
270         ssh_close_authentication_connection(ac);
271         exit(0);
272 }
This page took 0.116005 seconds and 5 git commands to generate.