]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/ssh-add.c
Vendor import of OpenSSH.
[FreeBSD/FreeBSD.git] / crypto / openssh / 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("$Id: ssh-add.c,v 1.15 1999/12/02 20:05:40 markus Exp $");
11
12 #include "rsa.h"
13 #include "ssh.h"
14 #include "xmalloc.h"
15 #include "authfd.h"
16 #include "fingerprint.h"
17
18 void
19 delete_file(AuthenticationConnection *ac, const char *filename)
20 {
21         RSA *key;
22         char *comment;
23
24         key = RSA_new();
25         if (!load_public_key(filename, key, &comment)) {
26                 printf("Bad key file %s: %s\n", filename, strerror(errno));
27                 return;
28         }
29         if (ssh_remove_identity(ac, key))
30                 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
31         else
32                 fprintf(stderr, "Could not remove identity: %s\n", filename);
33         RSA_free(key);
34         xfree(comment);
35 }
36
37 void
38 delete_all(AuthenticationConnection *ac)
39 {
40         /* Send a request to remove all identities. */
41         if (ssh_remove_all_identities(ac))
42                 fprintf(stderr, "All identities removed.\n");
43         else
44                 fprintf(stderr, "Failed to remove all identitities.\n");
45 }
46
47 char *
48 ssh_askpass(char *askpass, char *msg)
49 {
50         pid_t pid;
51         size_t len;
52         char *nl, *pass;
53         int p[2], status;
54         char buf[1024];
55
56         if (askpass == NULL)
57                 fatal("internal error: askpass undefined");
58         if (pipe(p) < 0)
59                 fatal("ssh_askpass: pipe: %s", strerror(errno));
60         if ((pid = fork()) < 0)
61                 fatal("ssh_askpass: fork: %s", strerror(errno));
62         if (pid == 0) {
63                 close(p[0]);
64                 if (dup2(p[1], STDOUT_FILENO) < 0)
65                         fatal("ssh_askpass: dup2: %s", strerror(errno));
66                 execlp(askpass, askpass, msg, (char *) 0);
67                 fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
68         }
69         close(p[1]);
70         len = read(p[0], buf, sizeof buf);
71         close(p[0]);
72         while (waitpid(pid, &status, 0) < 0)
73                 if (errno != EINTR)
74                         break;
75         if (len <= 1)
76                 return xstrdup("");
77         nl = strchr(buf, '\n');
78         if (nl)
79                 *nl = '\0';
80         pass = xstrdup(buf);
81         memset(buf, 0, sizeof(buf));
82         return pass;
83 }
84
85 void
86 add_file(AuthenticationConnection *ac, const char *filename)
87 {
88         RSA *key;
89         RSA *public_key;
90         char *saved_comment, *comment, *askpass = NULL;
91         char buf[1024], msg[1024];
92         int success;
93         int interactive = isatty(STDIN_FILENO);
94
95         key = RSA_new();
96         public_key = RSA_new();
97         if (!load_public_key(filename, public_key, &saved_comment)) {
98                 printf("Bad key file %s: %s\n", filename, strerror(errno));
99                 return;
100         }
101         RSA_free(public_key);
102
103         if (!interactive && getenv("DISPLAY")) {
104                 if (getenv(SSH_ASKPASS_ENV))
105                         askpass = getenv(SSH_ASKPASS_ENV);
106                 else
107                         askpass = SSH_ASKPASS_DEFAULT;
108         }
109
110         /* At first, try empty passphrase */
111         success = load_private_key(filename, "", key, &comment);
112         if (!success) {
113                 printf("Need passphrase for %.200s\n", filename);
114                 if (!interactive && askpass == NULL) {
115                         xfree(saved_comment);
116                         return;
117                 }
118                 snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
119                 for (;;) {
120                         char *pass;
121                         if (interactive) {
122                                 snprintf(buf, sizeof buf, "%s: ", msg);
123                                 pass = read_passphrase(buf, 1);
124                         } else {
125                                 pass = ssh_askpass(askpass, msg);
126                         }
127                         if (strcmp(pass, "") == 0) {
128                                 xfree(pass);
129                                 xfree(saved_comment);
130                                 return;
131                         }
132                         success = load_private_key(filename, pass, key, &comment);
133                         memset(pass, 0, strlen(pass));
134                         xfree(pass);
135                         if (success)
136                                 break;
137                         strlcpy(msg, "Bad passphrase, try again", sizeof msg);
138                 }
139         }
140         xfree(saved_comment);
141
142         if (ssh_add_identity(ac, key, comment))
143                 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
144         else
145                 fprintf(stderr, "Could not add identity: %s\n", filename);
146         RSA_free(key);
147         xfree(comment);
148 }
149
150 void
151 list_identities(AuthenticationConnection *ac, int fp)
152 {
153         BIGNUM *e, *n;
154         int status;
155         char *comment;
156         int had_identities;
157
158         e = BN_new();
159         n = BN_new();
160         had_identities = 0;
161         for (status = ssh_get_first_identity(ac, e, n, &comment);
162              status;
163              status = ssh_get_next_identity(ac, e, n, &comment)) {
164                 unsigned int bits = BN_num_bits(n);
165                 had_identities = 1;
166                 if (fp) {
167                         printf("%d %s %s\n", bits, fingerprint(e, n), comment);
168                 } else {
169                         char *ebuf, *nbuf;
170                         ebuf = BN_bn2dec(e);
171                         if (ebuf == NULL) {
172                                 error("list_identities: BN_bn2dec(e) failed.");
173                         } else {
174                                 nbuf = BN_bn2dec(n);
175                                 if (nbuf == NULL) {
176                                         error("list_identities: BN_bn2dec(n) failed.");
177                                 } else {
178                                         printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
179                                         free(nbuf);
180                                 }
181                                 free(ebuf);
182                         }
183                 }
184                 xfree(comment);
185         }
186         BN_clear_free(e);
187         BN_clear_free(n);
188         if (!had_identities)
189                 printf("The agent has no identities.\n");
190 }
191
192 int
193 main(int argc, char **argv)
194 {
195         AuthenticationConnection *ac = NULL;
196         struct passwd *pw;
197         char buf[1024];
198         int no_files = 1;
199         int i;
200         int deleting = 0;
201
202         /* check if RSA support exists */
203         if (rsa_alive() == 0) {
204                 extern char *__progname;
205
206                 fprintf(stderr,
207                         "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
208                         __progname);
209                 exit(1);
210         }
211         /* At first, get a connection to the authentication agent. */
212         ac = ssh_get_authentication_connection();
213         if (ac == NULL) {
214                 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
215                 exit(1);
216         }
217         for (i = 1; i < argc; i++) {
218                 if ((strcmp(argv[i], "-l") == 0) ||
219                     (strcmp(argv[i], "-L") == 0)) {
220                         list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
221                         /* Don't default-add/delete if -l. */
222                         no_files = 0;
223                         continue;
224                 }
225                 if (strcmp(argv[i], "-d") == 0) {
226                         deleting = 1;
227                         continue;
228                 }
229                 if (strcmp(argv[i], "-D") == 0) {
230                         delete_all(ac);
231                         no_files = 0;
232                         continue;
233                 }
234                 no_files = 0;
235                 if (deleting)
236                         delete_file(ac, argv[i]);
237                 else
238                         add_file(ac, argv[i]);
239         }
240         if (no_files) {
241                 pw = getpwuid(getuid());
242                 if (!pw) {
243                         fprintf(stderr, "No user found with uid %d\n", (int) getuid());
244                         ssh_close_authentication_connection(ac);
245                         exit(1);
246                 }
247                 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
248                 if (deleting)
249                         delete_file(ac, buf);
250                 else
251                         add_file(ac, buf);
252         }
253         ssh_close_authentication_connection(ac);
254         exit(0);
255 }