]> andersk Git - openssh.git/blame - ssh-add.c
- (djm) Define USE_PIPES to avoid socketpair problems on HPUX 10 and SunOS 4
[openssh.git] / ssh-add.c
CommitLineData
8efc0c15 1/*
5260325f 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 */
8efc0c15 8
9#include "includes.h"
4c8722d9 10RCSID("$OpenBSD: ssh-add.c,v 1.18 2000/07/16 08:27:21 markus Exp $");
8efc0c15 11
a306f2dd 12#include <openssl/rsa.h>
13#include <openssl/dsa.h>
14
8efc0c15 15#include "rsa.h"
16#include "ssh.h"
17#include "xmalloc.h"
f095fcc7 18#include "fingerprint.h"
a306f2dd 19#include "key.h"
4c8722d9 20#include "authfd.h"
a306f2dd 21#include "authfile.h"
8efc0c15 22
f601d847 23#ifdef HAVE___PROGNAME
24extern char *__progname;
25#else /* HAVE___PROGNAME */
3fd95d9a 26static const char *__progname = "ssh-add";
f601d847 27#endif /* HAVE___PROGNAME */
28
8efc0c15 29void
5068f573 30delete_file(AuthenticationConnection *ac, const char *filename)
8efc0c15 31{
a306f2dd 32 Key *public;
5260325f 33 char *comment;
34
a306f2dd 35 public = key_new(KEY_RSA);
36 if (!load_public_key(filename, public, &comment)) {
5260325f 37 printf("Bad key file %s: %s\n", filename, strerror(errno));
38 return;
39 }
a306f2dd 40 if (ssh_remove_identity(ac, public->rsa))
5260325f 41 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
42 else
43 fprintf(stderr, "Could not remove identity: %s\n", filename);
a306f2dd 44 key_free(public);
5260325f 45 xfree(comment);
8efc0c15 46}
47
48void
5068f573 49delete_all(AuthenticationConnection *ac)
8efc0c15 50{
5260325f 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");
8efc0c15 56}
57
aa3378df 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
8efc0c15 96void
5068f573 97add_file(AuthenticationConnection *ac, const char *filename)
8efc0c15 98{
a306f2dd 99 Key *public;
100 Key *private;
aa3378df 101 char *saved_comment, *comment, *askpass = NULL;
102 char buf[1024], msg[1024];
5260325f 103 int success;
aa3378df 104 int interactive = isatty(STDIN_FILENO);
4c8722d9 105 int type = KEY_RSA;
5260325f 106
4c8722d9 107 /*
108 * try to load the public key. right now this only works for RSA,
109 * since DSA keys are fully encrypted
110 */
a306f2dd 111 public = key_new(KEY_RSA);
112 if (!load_public_key(filename, public, &saved_comment)) {
4c8722d9 113 /* ok, so we will asume this is a DSA key */
114 type = KEY_DSA;
115 saved_comment = xstrdup(filename);
5260325f 116 }
a306f2dd 117 key_free(public);
dad9a31e 118
57112b5a 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 }
aa3378df 125
5260325f 126 /* At first, try empty passphrase */
4c8722d9 127 private = key_new(type);
a306f2dd 128 success = load_private_key(filename, "", private, &comment);
5260325f 129 if (!success) {
aa3378df 130 printf("Need passphrase for %.200s\n", filename);
131 if (!interactive && askpass == NULL) {
132 xfree(saved_comment);
133 return;
5260325f 134 }
aa3378df 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 }
5260325f 144 if (strcmp(pass, "") == 0) {
145 xfree(pass);
146 xfree(saved_comment);
147 return;
148 }
a306f2dd 149 success = load_private_key(filename, pass, private, &comment);
5260325f 150 memset(pass, 0, strlen(pass));
151 xfree(pass);
152 if (success)
153 break;
aa3378df 154 strlcpy(msg, "Bad passphrase, try again", sizeof msg);
5260325f 155 }
156 }
157 xfree(saved_comment);
158
4c8722d9 159 if (ssh_add_identity(ac, private, comment))
5260325f 160 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
161 else
162 fprintf(stderr, "Could not add identity: %s\n", filename);
a306f2dd 163 key_free(private);
5260325f 164 xfree(comment);
8efc0c15 165}
166
167void
f095fcc7 168list_identities(AuthenticationConnection *ac, int fp)
8efc0c15 169{
5260325f 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);
f095fcc7 202 }
5260325f 203 BN_clear_free(e);
204 BN_clear_free(n);
205 if (!had_identities)
206 printf("The agent has no identities.\n");
8efc0c15 207}
208
209int
5068f573 210main(int argc, char **argv)
8efc0c15 211{
5260325f 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
264dce47 219 init_rng();
220
5260325f 221 /* check if RSA support exists */
222 if (rsa_alive() == 0) {
5260325f 223 fprintf(stderr,
224 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
225 __progname);
226 exit(1);
8efc0c15 227 }
5260325f 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);
8efc0c15 233 }
5260325f 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]);
8efc0c15 256 }
5260325f 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);
8efc0c15 269 }
5260325f 270 ssh_close_authentication_connection(ac);
271 exit(0);
8efc0c15 272}
This page took 0.107917 seconds and 5 git commands to generate.