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