]> andersk Git - openssh.git/blame_incremental - ssh-add.c
- (djm) Define USE_PIPES to avoid socketpair problems on HPUX 10 and SunOS 4
[openssh.git] / ssh-add.c
... / ...
CommitLineData
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"
10RCSID("$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
24extern char *__progname;
25#else /* HAVE___PROGNAME */
26static const char *__progname = "ssh-add";
27#endif /* HAVE___PROGNAME */
28
29void
30delete_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
48void
49delete_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
58char *
59ssh_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
96void
97add_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
167void
168list_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
209int
210main(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.034341 seconds and 5 git commands to generate.