]> andersk Git - openssh.git/blame - ssh-add.c
- Merge big update to OpenSSH-2.0 from OpenBSD CVS
[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"
10RCSID("$Id$");
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"
18#include "authfd.h"
f095fcc7 19#include "fingerprint.h"
a306f2dd 20#include "key.h"
21#include "authfile.h"
8efc0c15 22
f601d847 23#ifdef HAVE___PROGNAME
24extern char *__progname;
25#else /* HAVE___PROGNAME */
26const char *__progname = "ssh-add";
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);
5260325f 105
a306f2dd 106 public = key_new(KEY_RSA);
107 if (!load_public_key(filename, public, &saved_comment)) {
5260325f 108 printf("Bad key file %s: %s\n", filename, strerror(errno));
109 return;
110 }
a306f2dd 111 key_free(public);
dad9a31e 112
57112b5a 113 if (!interactive && getenv("DISPLAY")) {
114 if (getenv(SSH_ASKPASS_ENV))
115 askpass = getenv(SSH_ASKPASS_ENV);
116 else
117 askpass = SSH_ASKPASS_DEFAULT;
118 }
aa3378df 119
5260325f 120 /* At first, try empty passphrase */
a306f2dd 121 private = key_new(KEY_RSA);
122 success = load_private_key(filename, "", private, &comment);
5260325f 123 if (!success) {
aa3378df 124 printf("Need passphrase for %.200s\n", filename);
125 if (!interactive && askpass == NULL) {
126 xfree(saved_comment);
127 return;
5260325f 128 }
aa3378df 129 snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
130 for (;;) {
131 char *pass;
132 if (interactive) {
133 snprintf(buf, sizeof buf, "%s: ", msg);
134 pass = read_passphrase(buf, 1);
135 } else {
136 pass = ssh_askpass(askpass, msg);
137 }
5260325f 138 if (strcmp(pass, "") == 0) {
139 xfree(pass);
140 xfree(saved_comment);
141 return;
142 }
a306f2dd 143 success = load_private_key(filename, pass, private, &comment);
5260325f 144 memset(pass, 0, strlen(pass));
145 xfree(pass);
146 if (success)
147 break;
aa3378df 148 strlcpy(msg, "Bad passphrase, try again", sizeof msg);
5260325f 149 }
150 }
151 xfree(saved_comment);
152
a306f2dd 153 if (ssh_add_identity(ac, private->rsa, comment))
5260325f 154 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
155 else
156 fprintf(stderr, "Could not add identity: %s\n", filename);
a306f2dd 157 key_free(private);
5260325f 158 xfree(comment);
8efc0c15 159}
160
161void
f095fcc7 162list_identities(AuthenticationConnection *ac, int fp)
8efc0c15 163{
5260325f 164 BIGNUM *e, *n;
165 int status;
166 char *comment;
167 int had_identities;
168
169 e = BN_new();
170 n = BN_new();
171 had_identities = 0;
172 for (status = ssh_get_first_identity(ac, e, n, &comment);
173 status;
174 status = ssh_get_next_identity(ac, e, n, &comment)) {
175 unsigned int bits = BN_num_bits(n);
176 had_identities = 1;
177 if (fp) {
178 printf("%d %s %s\n", bits, fingerprint(e, n), comment);
179 } else {
180 char *ebuf, *nbuf;
181 ebuf = BN_bn2dec(e);
182 if (ebuf == NULL) {
183 error("list_identities: BN_bn2dec(e) failed.");
184 } else {
185 nbuf = BN_bn2dec(n);
186 if (nbuf == NULL) {
187 error("list_identities: BN_bn2dec(n) failed.");
188 } else {
189 printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
190 free(nbuf);
191 }
192 free(ebuf);
193 }
194 }
195 xfree(comment);
f095fcc7 196 }
5260325f 197 BN_clear_free(e);
198 BN_clear_free(n);
199 if (!had_identities)
200 printf("The agent has no identities.\n");
8efc0c15 201}
202
203int
5068f573 204main(int argc, char **argv)
8efc0c15 205{
5260325f 206 AuthenticationConnection *ac = NULL;
207 struct passwd *pw;
208 char buf[1024];
209 int no_files = 1;
210 int i;
211 int deleting = 0;
212
213 /* check if RSA support exists */
214 if (rsa_alive() == 0) {
5260325f 215 fprintf(stderr,
216 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
217 __progname);
218 exit(1);
8efc0c15 219 }
5260325f 220 /* At first, get a connection to the authentication agent. */
221 ac = ssh_get_authentication_connection();
222 if (ac == NULL) {
223 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
224 exit(1);
8efc0c15 225 }
5260325f 226 for (i = 1; i < argc; i++) {
227 if ((strcmp(argv[i], "-l") == 0) ||
228 (strcmp(argv[i], "-L") == 0)) {
229 list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
230 /* Don't default-add/delete if -l. */
231 no_files = 0;
232 continue;
233 }
234 if (strcmp(argv[i], "-d") == 0) {
235 deleting = 1;
236 continue;
237 }
238 if (strcmp(argv[i], "-D") == 0) {
239 delete_all(ac);
240 no_files = 0;
241 continue;
242 }
243 no_files = 0;
244 if (deleting)
245 delete_file(ac, argv[i]);
246 else
247 add_file(ac, argv[i]);
8efc0c15 248 }
5260325f 249 if (no_files) {
250 pw = getpwuid(getuid());
251 if (!pw) {
252 fprintf(stderr, "No user found with uid %d\n", (int) getuid());
253 ssh_close_authentication_connection(ac);
254 exit(1);
255 }
256 snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
257 if (deleting)
258 delete_file(ac, buf);
259 else
260 add_file(ac, buf);
8efc0c15 261 }
5260325f 262 ssh_close_authentication_connection(ac);
263 exit(0);
8efc0c15 264}
This page took 0.10558 seconds and 5 git commands to generate.