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