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