Annotation of src/usr.bin/ssh/ssh-keygen.c, Revision 1.146
1.146 ! stevesk 1: /* $OpenBSD: ssh-keygen.c,v 1.145 2006/07/06 16:03:53 stevesk Exp $ */
1.1 deraadt 2: /*
1.13 deraadt 3: * Author: Tatu Ylonen <ylo@cs.hut.fi>
4: * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5: * All rights reserved
6: * Identity and host key generation and maintenance.
1.31 deraadt 7: *
8: * As far as I am concerned, the code I have written for this software
9: * can be used freely for any purpose. Any derived versions of this
10: * software must be clearly marked as such, and if the derived work is
11: * incompatible with the protocol description in the RFC file, it must be
12: * called by a name other than "ssh" or "Secure Shell".
1.13 deraadt 13: */
1.1 deraadt 14:
15: #include "includes.h"
1.136 stevesk 16:
17: #include <sys/types.h>
18: #include <sys/stat.h>
1.19 markus 19:
20: #include <openssl/evp.h>
21: #include <openssl/pem.h>
1.145 stevesk 22:
23: #include <pwd.h>
1.1 deraadt 24:
25: #include "xmalloc.h"
1.19 markus 26: #include "key.h"
1.53 markus 27: #include "rsa.h"
1.19 markus 28: #include "authfile.h"
29: #include "uuencode.h"
1.32 markus 30: #include "buffer.h"
31: #include "bufaux.h"
1.40 markus 32: #include "pathnames.h"
1.41 markus 33: #include "log.h"
1.114 djm 34: #include "misc.h"
1.119 djm 35: #include "match.h"
36: #include "hostfile.h"
1.146 ! stevesk 37: #include "dns.h"
1.32 markus 38:
1.75 markus 39: #ifdef SMARTCARD
40: #include "scard.h"
1.106 djm 41: #endif
1.66 markus 42:
1.130 markus 43: /* Number of bits in the RSA/DSA key. This value can be set on the command line. */
44: #define DEFAULT_BITS 2048
45: #define DEFAULT_BITS_DSA 1024
46: u_int32_t bits = 0;
1.1 deraadt 47:
1.14 markus 48: /*
49: * Flag indicating that we just want to change the passphrase. This can be
50: * set on the command line.
51: */
1.1 deraadt 52: int change_passphrase = 0;
53:
1.14 markus 54: /*
55: * Flag indicating that we just want to change the comment. This can be set
56: * on the command line.
57: */
1.1 deraadt 58: int change_comment = 0;
59:
1.2 provos 60: int quiet = 0;
61:
1.119 djm 62: /* Flag indicating that we want to hash a known_hosts file */
63: int hash_hosts = 0;
64: /* Flag indicating that we want lookup a host in known_hosts file */
65: int find_host = 0;
66: /* Flag indicating that we want to delete a host from a known_hosts file */
67: int delete_host = 0;
68:
1.8 markus 69: /* Flag indicating that we just want to see the key fingerprint */
70: int print_fingerprint = 0;
1.49 markus 71: int print_bubblebabble = 0;
1.8 markus 72:
1.10 markus 73: /* The identity file name, given on the command line or entered by the user. */
74: char identity_file[1024];
75: int have_identity = 0;
1.1 deraadt 76:
77: /* This is set to the passphrase if given on the command line. */
78: char *identity_passphrase = NULL;
79:
80: /* This is set to the new passphrase if given on the command line. */
81: char *identity_new_passphrase = NULL;
82:
83: /* This is set to the new comment if given on the command line. */
84: char *identity_comment = NULL;
85:
1.19 markus 86: /* Dump public key file in format used by real and the original SSH 2 */
87: int convert_to_ssh2 = 0;
88: int convert_from_ssh2 = 0;
89: int print_public = 0;
1.105 jakob 90: int print_generic = 0;
1.33 markus 91:
1.87 djm 92: char *key_type_name = NULL;
1.19 markus 93:
1.10 markus 94: /* argv0 */
95: extern char *__progname;
1.1 deraadt 96:
1.19 markus 97: char hostname[MAXHOSTNAMELEN];
98:
1.115 djm 99: /* moduli.c */
1.124 avsm 100: int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
1.115 djm 101: int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
102:
1.63 itojun 103: static void
1.10 markus 104: ask_filename(struct passwd *pw, const char *prompt)
1.1 deraadt 105: {
1.12 markus 106: char buf[1024];
1.35 markus 107: char *name = NULL;
108:
1.92 stevesk 109: if (key_type_name == NULL)
1.40 markus 110: name = _PATH_SSH_CLIENT_ID_RSA;
1.140 deraadt 111: else {
1.92 stevesk 112: switch (key_type_from_name(key_type_name)) {
113: case KEY_RSA1:
114: name = _PATH_SSH_CLIENT_IDENTITY;
115: break;
116: case KEY_DSA:
117: name = _PATH_SSH_CLIENT_ID_DSA;
118: break;
119: case KEY_RSA:
120: name = _PATH_SSH_CLIENT_ID_RSA;
121: break;
122: default:
123: fprintf(stderr, "bad key type");
124: exit(1);
125: break;
126: }
1.140 deraadt 127: }
1.35 markus 128: snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
1.37 markus 129: fprintf(stderr, "%s (%s): ", prompt, identity_file);
1.12 markus 130: if (fgets(buf, sizeof(buf), stdin) == NULL)
131: exit(1);
132: if (strchr(buf, '\n'))
133: *strchr(buf, '\n') = 0;
134: if (strcmp(buf, "") != 0)
135: strlcpy(identity_file, buf, sizeof(identity_file));
136: have_identity = 1;
1.7 markus 137: }
138:
1.63 itojun 139: static Key *
1.61 markus 140: load_identity(char *filename)
1.19 markus 141: {
1.52 markus 142: char *pass;
143: Key *prv;
144:
1.55 markus 145: prv = key_load_private(filename, "", NULL);
1.52 markus 146: if (prv == NULL) {
1.61 markus 147: if (identity_passphrase)
148: pass = xstrdup(identity_passphrase);
149: else
1.65 markus 150: pass = read_passphrase("Enter passphrase: ",
151: RP_ALLOW_STDIN);
1.52 markus 152: prv = key_load_private(filename, pass, NULL);
1.19 markus 153: memset(pass, 0, strlen(pass));
154: xfree(pass);
155: }
1.52 markus 156: return prv;
1.19 markus 157: }
158:
1.32 markus 159: #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
1.100 deraadt 160: #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
1.32 markus 161: #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
1.42 stevesk 162: #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
1.19 markus 163:
1.63 itojun 164: static void
1.19 markus 165: do_convert_to_ssh2(struct passwd *pw)
166: {
1.59 markus 167: Key *k;
1.94 markus 168: u_int len;
1.36 markus 169: u_char *blob;
1.19 markus 170: struct stat st;
171:
172: if (!have_identity)
173: ask_filename(pw, "Enter file in which the key is");
174: if (stat(identity_file, &st) < 0) {
175: perror(identity_file);
176: exit(1);
177: }
1.59 markus 178: if ((k = key_load_public(identity_file, NULL)) == NULL) {
1.61 markus 179: if ((k = load_identity(identity_file)) == NULL) {
1.59 markus 180: fprintf(stderr, "load failed\n");
181: exit(1);
182: }
1.104 markus 183: }
184: if (k->type == KEY_RSA1) {
185: fprintf(stderr, "version 1 keys are not supported\n");
186: exit(1);
1.19 markus 187: }
1.81 markus 188: if (key_to_blob(k, &blob, &len) <= 0) {
189: fprintf(stderr, "key_to_blob failed\n");
190: exit(1);
191: }
1.32 markus 192: fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
1.19 markus 193: fprintf(stdout,
1.101 deraadt 194: "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
1.59 markus 195: key_size(k), key_type(k),
1.19 markus 196: pw->pw_name, hostname);
197: dump_base64(stdout, blob, len);
1.32 markus 198: fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
1.59 markus 199: key_free(k);
1.21 markus 200: xfree(blob);
1.19 markus 201: exit(0);
202: }
203:
1.63 itojun 204: static void
1.32 markus 205: buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
206: {
1.116 avsm 207: u_int bignum_bits = buffer_get_int(b);
208: u_int bytes = (bignum_bits + 7) / 8;
1.53 markus 209:
1.32 markus 210: if (buffer_len(b) < bytes)
1.53 markus 211: fatal("buffer_get_bignum_bits: input buffer too small: "
212: "need %d have %d", bytes, buffer_len(b));
1.89 stevesk 213: BN_bin2bn(buffer_ptr(b), bytes, value);
1.32 markus 214: buffer_consume(b, bytes);
215: }
216:
1.63 itojun 217: static Key *
1.93 markus 218: do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
1.32 markus 219: {
220: Buffer b;
221: Key *key = NULL;
1.64 markus 222: char *type, *cipher;
1.69 stevesk 223: u_char *sig, data[] = "abcde12345";
1.62 markus 224: int magic, rlen, ktype, i1, i2, i3, i4;
1.64 markus 225: u_int slen;
1.62 markus 226: u_long e;
1.32 markus 227:
228: buffer_init(&b);
229: buffer_append(&b, blob, blen);
230:
231: magic = buffer_get_int(&b);
232: if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
233: error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
234: buffer_free(&b);
235: return NULL;
236: }
1.62 markus 237: i1 = buffer_get_int(&b);
1.32 markus 238: type = buffer_get_string(&b, NULL);
239: cipher = buffer_get_string(&b, NULL);
1.62 markus 240: i2 = buffer_get_int(&b);
241: i3 = buffer_get_int(&b);
242: i4 = buffer_get_int(&b);
243: debug("ignore (%d %d %d %d)", i1,i2,i3,i4);
1.32 markus 244: if (strcmp(cipher, "none") != 0) {
245: error("unsupported cipher %s", cipher);
246: xfree(cipher);
247: buffer_free(&b);
1.53 markus 248: xfree(type);
1.32 markus 249: return NULL;
250: }
251: xfree(cipher);
252:
1.53 markus 253: if (strstr(type, "dsa")) {
254: ktype = KEY_DSA;
255: } else if (strstr(type, "rsa")) {
256: ktype = KEY_RSA;
257: } else {
1.118 markus 258: buffer_free(&b);
1.53 markus 259: xfree(type);
1.32 markus 260: return NULL;
261: }
1.53 markus 262: key = key_new_private(ktype);
263: xfree(type);
264:
265: switch (key->type) {
266: case KEY_DSA:
267: buffer_get_bignum_bits(&b, key->dsa->p);
268: buffer_get_bignum_bits(&b, key->dsa->g);
269: buffer_get_bignum_bits(&b, key->dsa->q);
270: buffer_get_bignum_bits(&b, key->dsa->pub_key);
271: buffer_get_bignum_bits(&b, key->dsa->priv_key);
272: break;
273: case KEY_RSA:
1.62 markus 274: e = buffer_get_char(&b);
275: debug("e %lx", e);
276: if (e < 30) {
277: e <<= 8;
278: e += buffer_get_char(&b);
279: debug("e %lx", e);
280: e <<= 8;
281: e += buffer_get_char(&b);
282: debug("e %lx", e);
283: }
284: if (!BN_set_word(key->rsa->e, e)) {
1.53 markus 285: buffer_free(&b);
286: key_free(key);
287: return NULL;
288: }
289: buffer_get_bignum_bits(&b, key->rsa->d);
290: buffer_get_bignum_bits(&b, key->rsa->n);
291: buffer_get_bignum_bits(&b, key->rsa->iqmp);
292: buffer_get_bignum_bits(&b, key->rsa->q);
293: buffer_get_bignum_bits(&b, key->rsa->p);
1.68 markus 294: rsa_generate_additional_parameters(key->rsa);
1.53 markus 295: break;
296: }
1.32 markus 297: rlen = buffer_len(&b);
1.85 deraadt 298: if (rlen != 0)
1.53 markus 299: error("do_convert_private_ssh2_from_blob: "
300: "remaining bytes in key blob %d", rlen);
1.32 markus 301: buffer_free(&b);
1.64 markus 302:
303: /* try the key */
304: key_sign(key, &sig, &slen, data, sizeof(data));
305: key_verify(key, sig, slen, data, sizeof(data));
306: xfree(sig);
1.32 markus 307: return key;
308: }
309:
1.137 dtucker 310: static int
311: get_line(FILE *fp, char *line, size_t len)
312: {
313: int c;
314: size_t pos = 0;
315:
316: line[0] = '\0';
317: while ((c = fgetc(fp)) != EOF) {
318: if (pos >= len - 1) {
319: fprintf(stderr, "input line too long.\n");
320: exit(1);
321: }
1.140 deraadt 322: switch (c) {
1.137 dtucker 323: case '\r':
324: c = fgetc(fp);
325: if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
326: fprintf(stderr, "unget: %s\n", strerror(errno));
327: exit(1);
328: }
329: return pos;
330: case '\n':
331: return pos;
332: }
333: line[pos++] = c;
334: line[pos] = '\0';
335: }
1.143 dtucker 336: if (c == EOF)
337: return -1;
1.137 dtucker 338: return pos;
339: }
340:
1.63 itojun 341: static void
1.19 markus 342: do_convert_from_ssh2(struct passwd *pw)
343: {
344: Key *k;
345: int blen;
1.98 markus 346: u_int len;
1.137 dtucker 347: char line[1024];
1.80 stevesk 348: u_char blob[8096];
1.19 markus 349: char encoded[8096];
350: struct stat st;
1.32 markus 351: int escaped = 0, private = 0, ok;
1.19 markus 352: FILE *fp;
353:
354: if (!have_identity)
355: ask_filename(pw, "Enter file in which the key is");
356: if (stat(identity_file, &st) < 0) {
357: perror(identity_file);
358: exit(1);
359: }
360: fp = fopen(identity_file, "r");
361: if (fp == NULL) {
362: perror(identity_file);
363: exit(1);
364: }
365: encoded[0] = '\0';
1.137 dtucker 366: while ((blen = get_line(fp, line, sizeof(line))) != -1) {
367: if (line[blen - 1] == '\\')
1.25 markus 368: escaped++;
1.19 markus 369: if (strncmp(line, "----", 4) == 0 ||
370: strstr(line, ": ") != NULL) {
1.32 markus 371: if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
372: private = 1;
1.64 markus 373: if (strstr(line, " END ") != NULL) {
374: break;
375: }
1.60 markus 376: /* fprintf(stderr, "ignore: %s", line); */
1.19 markus 377: continue;
378: }
1.25 markus 379: if (escaped) {
380: escaped--;
1.60 markus 381: /* fprintf(stderr, "escaped: %s", line); */
1.25 markus 382: continue;
1.19 markus 383: }
384: strlcat(encoded, line, sizeof(encoded));
385: }
1.98 markus 386: len = strlen(encoded);
387: if (((len % 4) == 3) &&
388: (encoded[len-1] == '=') &&
389: (encoded[len-2] == '=') &&
390: (encoded[len-3] == '='))
391: encoded[len-3] = '\0';
1.91 stevesk 392: blen = uudecode(encoded, blob, sizeof(blob));
1.19 markus 393: if (blen < 0) {
394: fprintf(stderr, "uudecode failed.\n");
395: exit(1);
396: }
1.32 markus 397: k = private ?
398: do_convert_private_ssh2_from_blob(blob, blen) :
1.33 markus 399: key_from_blob(blob, blen);
1.32 markus 400: if (k == NULL) {
401: fprintf(stderr, "decode blob failed.\n");
402: exit(1);
403: }
404: ok = private ?
1.53 markus 405: (k->type == KEY_DSA ?
406: PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
407: PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
1.32 markus 408: key_write(k, stdout);
409: if (!ok) {
410: fprintf(stderr, "key write failed");
411: exit(1);
412: }
1.19 markus 413: key_free(k);
1.90 markus 414: if (!private)
415: fprintf(stdout, "\n");
1.19 markus 416: fclose(fp);
417: exit(0);
418: }
419:
1.63 itojun 420: static void
1.19 markus 421: do_print_public(struct passwd *pw)
422: {
1.52 markus 423: Key *prv;
1.19 markus 424: struct stat st;
425:
426: if (!have_identity)
427: ask_filename(pw, "Enter file in which the key is");
428: if (stat(identity_file, &st) < 0) {
429: perror(identity_file);
430: exit(1);
431: }
1.61 markus 432: prv = load_identity(identity_file);
1.52 markus 433: if (prv == NULL) {
1.19 markus 434: fprintf(stderr, "load failed\n");
435: exit(1);
436: }
1.52 markus 437: if (!key_write(prv, stdout))
1.19 markus 438: fprintf(stderr, "key_write failed");
1.52 markus 439: key_free(prv);
1.19 markus 440: fprintf(stdout, "\n");
441: exit(0);
442: }
443:
1.74 markus 444: #ifdef SMARTCARD
1.66 markus 445: static void
1.75 markus 446: do_upload(struct passwd *pw, const char *sc_reader_id)
1.66 markus 447: {
448: Key *prv = NULL;
449: struct stat st;
1.95 markus 450: int ret;
1.66 markus 451:
452: if (!have_identity)
453: ask_filename(pw, "Enter file in which the key is");
454: if (stat(identity_file, &st) < 0) {
455: perror(identity_file);
1.95 markus 456: exit(1);
1.66 markus 457: }
458: prv = load_identity(identity_file);
459: if (prv == NULL) {
460: error("load failed");
1.95 markus 461: exit(1);
1.66 markus 462: }
1.95 markus 463: ret = sc_put_key(prv, sc_reader_id);
464: key_free(prv);
465: if (ret < 0)
466: exit(1);
1.103 itojun 467: logit("loading key done");
1.95 markus 468: exit(0);
1.74 markus 469: }
1.75 markus 470:
471: static void
472: do_download(struct passwd *pw, const char *sc_reader_id)
473: {
1.97 markus 474: Key **keys = NULL;
475: int i;
1.75 markus 476:
1.97 markus 477: keys = sc_get_keys(sc_reader_id, NULL);
478: if (keys == NULL)
1.75 markus 479: fatal("cannot read public key from smartcard");
1.97 markus 480: for (i = 0; keys[i]; i++) {
481: key_write(keys[i], stdout);
482: key_free(keys[i]);
483: fprintf(stdout, "\n");
484: }
485: xfree(keys);
1.75 markus 486: exit(0);
487: }
1.78 jakob 488: #endif /* SMARTCARD */
1.66 markus 489:
1.63 itojun 490: static void
1.8 markus 491: do_fingerprint(struct passwd *pw)
492: {
1.15 markus 493: FILE *f;
1.19 markus 494: Key *public;
1.49 markus 495: char *comment = NULL, *cp, *ep, line[16*1024], *fp;
1.84 stevesk 496: int i, skip = 0, num = 1, invalid = 1;
497: enum fp_rep rep;
498: enum fp_type fptype;
1.12 markus 499: struct stat st;
500:
1.52 markus 501: fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
502: rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
1.49 markus 503:
1.12 markus 504: if (!have_identity)
505: ask_filename(pw, "Enter file in which the key is");
506: if (stat(identity_file, &st) < 0) {
507: perror(identity_file);
508: exit(1);
509: }
1.52 markus 510: public = key_load_public(identity_file, &comment);
511: if (public != NULL) {
512: fp = key_fingerprint(public, fptype, rep);
1.101 deraadt 513: printf("%u %s %s\n", key_size(public), fp, comment);
1.33 markus 514: key_free(public);
515: xfree(comment);
1.49 markus 516: xfree(fp);
1.15 markus 517: exit(0);
518: }
1.144 markus 519: if (comment) {
1.52 markus 520: xfree(comment);
1.144 markus 521: comment = NULL;
522: }
1.15 markus 523:
524: f = fopen(identity_file, "r");
525: if (f != NULL) {
526: while (fgets(line, sizeof(line), f)) {
527: i = strlen(line) - 1;
528: if (line[i] != '\n') {
529: error("line %d too long: %.40s...", num, line);
530: skip = 1;
531: continue;
532: }
533: num++;
534: if (skip) {
535: skip = 0;
536: continue;
537: }
538: line[i] = '\0';
539:
540: /* Skip leading whitespace, empty and comment lines. */
541: for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
542: ;
543: if (!*cp || *cp == '\n' || *cp == '#')
544: continue ;
545: i = strtol(cp, &ep, 10);
546: if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
547: int quoted = 0;
548: comment = cp;
1.101 deraadt 549: for (; *cp && (quoted || (*cp != ' ' &&
550: *cp != '\t')); cp++) {
1.15 markus 551: if (*cp == '\\' && cp[1] == '"')
552: cp++; /* Skip both */
553: else if (*cp == '"')
554: quoted = !quoted;
555: }
556: if (!*cp)
557: continue;
558: *cp++ = '\0';
559: }
560: ep = cp;
1.38 markus 561: public = key_new(KEY_RSA1);
562: if (key_read(public, &cp) != 1) {
563: cp = ep;
564: key_free(public);
565: public = key_new(KEY_UNSPEC);
566: if (key_read(public, &cp) != 1) {
567: key_free(public);
568: continue;
569: }
1.12 markus 570: }
1.38 markus 571: comment = *cp ? cp : comment;
1.52 markus 572: fp = key_fingerprint(public, fptype, rep);
1.101 deraadt 573: printf("%u %s %s\n", key_size(public), fp,
1.38 markus 574: comment ? comment : "no comment");
1.49 markus 575: xfree(fp);
1.52 markus 576: key_free(public);
1.38 markus 577: invalid = 0;
1.12 markus 578: }
1.15 markus 579: fclose(f);
580: }
581: if (invalid) {
1.83 markus 582: printf("%s is not a public key file.\n", identity_file);
1.15 markus 583: exit(1);
1.12 markus 584: }
585: exit(0);
1.8 markus 586: }
587:
1.119 djm 588: static void
589: print_host(FILE *f, char *name, Key *public, int hash)
590: {
591: if (hash && (name = host_hash(name, NULL, 0)) == NULL)
592: fatal("hash_host failed");
593: fprintf(f, "%s ", name);
594: if (!key_write(public, f))
595: fatal("key_write failed");
596: fprintf(f, "\n");
597: }
598:
599: static void
600: do_known_hosts(struct passwd *pw, const char *name)
601: {
602: FILE *in, *out = stdout;
603: Key *public;
604: char *cp, *cp2, *kp, *kp2;
605: char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
606: int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
607:
608: if (!have_identity) {
609: cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
610: if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
611: sizeof(identity_file))
612: fatal("Specified known hosts path too long");
613: xfree(cp);
614: have_identity = 1;
615: }
616: if ((in = fopen(identity_file, "r")) == NULL)
617: fatal("fopen: %s", strerror(errno));
618:
619: /*
620: * Find hosts goes to stdout, hash and deletions happen in-place
621: * A corner case is ssh-keygen -HF foo, which should go to stdout
622: */
623: if (!find_host && (hash_hosts || delete_host)) {
624: if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
625: strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
626: strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
627: strlcat(old, ".old", sizeof(old)) >= sizeof(old))
628: fatal("known_hosts path too long");
629: umask(077);
630: if ((c = mkstemp(tmp)) == -1)
631: fatal("mkstemp: %s", strerror(errno));
632: if ((out = fdopen(c, "w")) == NULL) {
633: c = errno;
634: unlink(tmp);
635: fatal("fdopen: %s", strerror(c));
636: }
637: inplace = 1;
638: }
639:
640: while (fgets(line, sizeof(line), in)) {
641: num++;
642: i = strlen(line) - 1;
643: if (line[i] != '\n') {
644: error("line %d too long: %.40s...", num, line);
645: skip = 1;
646: invalid = 1;
647: continue;
648: }
649: if (skip) {
650: skip = 0;
651: continue;
652: }
653: line[i] = '\0';
654:
655: /* Skip leading whitespace, empty and comment lines. */
656: for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
657: ;
658: if (!*cp || *cp == '\n' || *cp == '#') {
659: if (inplace)
660: fprintf(out, "%s\n", cp);
661: continue;
662: }
663: /* Find the end of the host name portion. */
664: for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
665: ;
666: if (*kp == '\0' || *(kp + 1) == '\0') {
667: error("line %d missing key: %.40s...",
668: num, line);
669: invalid = 1;
670: continue;
671: }
672: *kp++ = '\0';
673: kp2 = kp;
674:
675: public = key_new(KEY_RSA1);
676: if (key_read(public, &kp) != 1) {
677: kp = kp2;
678: key_free(public);
679: public = key_new(KEY_UNSPEC);
680: if (key_read(public, &kp) != 1) {
681: error("line %d invalid key: %.40s...",
682: num, line);
683: key_free(public);
684: invalid = 1;
685: continue;
686: }
687: }
688:
689: if (*cp == HASH_DELIM) {
690: if (find_host || delete_host) {
691: cp2 = host_hash(name, cp, strlen(cp));
692: if (cp2 == NULL) {
693: error("line %d: invalid hashed "
694: "name: %.64s...", num, line);
695: invalid = 1;
696: continue;
697: }
698: c = (strcmp(cp2, cp) == 0);
699: if (find_host && c) {
700: printf("# Host %s found: "
701: "line %d type %s\n", name,
702: num, key_type(public));
703: print_host(out, cp, public, 0);
704: }
705: if (delete_host && !c)
706: print_host(out, cp, public, 0);
707: } else if (hash_hosts)
708: print_host(out, cp, public, 0);
709: } else {
710: if (find_host || delete_host) {
711: c = (match_hostname(name, cp,
712: strlen(cp)) == 1);
713: if (find_host && c) {
714: printf("# Host %s found: "
715: "line %d type %s\n", name,
716: num, key_type(public));
717: print_host(out, cp, public, hash_hosts);
718: }
719: if (delete_host && !c)
720: print_host(out, cp, public, 0);
721: } else if (hash_hosts) {
1.121 deraadt 722: for (cp2 = strsep(&cp, ",");
1.119 djm 723: cp2 != NULL && *cp2 != '\0';
1.120 djm 724: cp2 = strsep(&cp, ",")) {
725: if (strcspn(cp2, "*?!") != strlen(cp2))
726: fprintf(stderr, "Warning: "
727: "ignoring host name with "
728: "metacharacters: %.64s\n",
729: cp2);
730: else
731: print_host(out, cp2, public, 1);
732: }
1.119 djm 733: has_unhashed = 1;
734: }
735: }
736: key_free(public);
737: }
738: fclose(in);
739:
740: if (invalid) {
741: fprintf(stderr, "%s is not a valid known_host file.\n",
742: identity_file);
743: if (inplace) {
744: fprintf(stderr, "Not replacing existing known_hosts "
1.122 markus 745: "file because of errors\n");
1.119 djm 746: fclose(out);
747: unlink(tmp);
748: }
749: exit(1);
750: }
751:
752: if (inplace) {
753: fclose(out);
754:
755: /* Backup existing file */
756: if (unlink(old) == -1 && errno != ENOENT)
757: fatal("unlink %.100s: %s", old, strerror(errno));
758: if (link(identity_file, old) == -1)
759: fatal("link %.100s to %.100s: %s", identity_file, old,
760: strerror(errno));
761: /* Move new one into place */
762: if (rename(tmp, identity_file) == -1) {
763: error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
764: strerror(errno));
765: unlink(tmp);
766: unlink(old);
767: exit(1);
768: }
769:
770: fprintf(stderr, "%s updated.\n", identity_file);
771: fprintf(stderr, "Original contents retained as %s\n", old);
772: if (has_unhashed) {
773: fprintf(stderr, "WARNING: %s contains unhashed "
774: "entries\n", old);
775: fprintf(stderr, "Delete this file to ensure privacy "
1.128 djm 776: "of hostnames\n");
1.119 djm 777: }
778: }
779:
780: exit(0);
781: }
782:
1.13 deraadt 783: /*
784: * Perform changing a passphrase. The argument is the passwd structure
785: * for the current user.
786: */
1.63 itojun 787: static void
1.7 markus 788: do_change_passphrase(struct passwd *pw)
789: {
1.12 markus 790: char *comment;
791: char *old_passphrase, *passphrase1, *passphrase2;
792: struct stat st;
1.19 markus 793: Key *private;
1.12 markus 794:
795: if (!have_identity)
796: ask_filename(pw, "Enter file in which the key is");
797: if (stat(identity_file, &st) < 0) {
798: perror(identity_file);
799: exit(1);
800: }
801: /* Try to load the file with empty passphrase. */
1.52 markus 802: private = key_load_private(identity_file, "", &comment);
803: if (private == NULL) {
1.12 markus 804: if (identity_passphrase)
805: old_passphrase = xstrdup(identity_passphrase);
806: else
1.65 markus 807: old_passphrase =
808: read_passphrase("Enter old passphrase: ",
809: RP_ALLOW_STDIN);
810: private = key_load_private(identity_file, old_passphrase,
811: &comment);
1.52 markus 812: memset(old_passphrase, 0, strlen(old_passphrase));
813: xfree(old_passphrase);
814: if (private == NULL) {
1.12 markus 815: printf("Bad passphrase.\n");
816: exit(1);
817: }
818: }
819: printf("Key has comment '%s'\n", comment);
820:
821: /* Ask the new passphrase (twice). */
822: if (identity_new_passphrase) {
823: passphrase1 = xstrdup(identity_new_passphrase);
824: passphrase2 = NULL;
825: } else {
826: passphrase1 =
1.65 markus 827: read_passphrase("Enter new passphrase (empty for no "
828: "passphrase): ", RP_ALLOW_STDIN);
829: passphrase2 = read_passphrase("Enter same passphrase again: ",
1.86 deraadt 830: RP_ALLOW_STDIN);
1.12 markus 831:
832: /* Verify that they are the same. */
833: if (strcmp(passphrase1, passphrase2) != 0) {
834: memset(passphrase1, 0, strlen(passphrase1));
835: memset(passphrase2, 0, strlen(passphrase2));
836: xfree(passphrase1);
837: xfree(passphrase2);
838: printf("Pass phrases do not match. Try again.\n");
839: exit(1);
840: }
841: /* Destroy the other copy. */
842: memset(passphrase2, 0, strlen(passphrase2));
843: xfree(passphrase2);
844: }
845:
846: /* Save the file using the new passphrase. */
1.52 markus 847: if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56 markus 848: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 849: memset(passphrase1, 0, strlen(passphrase1));
850: xfree(passphrase1);
1.19 markus 851: key_free(private);
1.12 markus 852: xfree(comment);
853: exit(1);
854: }
855: /* Destroy the passphrase and the copy of the key in memory. */
856: memset(passphrase1, 0, strlen(passphrase1));
857: xfree(passphrase1);
1.19 markus 858: key_free(private); /* Destroys contents */
1.12 markus 859: xfree(comment);
1.1 deraadt 860:
1.12 markus 861: printf("Your identification has been saved with the new passphrase.\n");
862: exit(0);
1.1 deraadt 863: }
864:
1.105 jakob 865: /*
866: * Print the SSHFP RR.
867: */
1.138 jakob 868: static int
869: do_print_resource_record(struct passwd *pw, char *fname, char *hname)
1.105 jakob 870: {
871: Key *public;
872: char *comment = NULL;
873: struct stat st;
874:
1.138 jakob 875: if (fname == NULL)
1.105 jakob 876: ask_filename(pw, "Enter file in which the key is");
1.138 jakob 877: if (stat(fname, &st) < 0) {
878: if (errno == ENOENT)
879: return 0;
880: perror(fname);
1.105 jakob 881: exit(1);
882: }
1.138 jakob 883: public = key_load_public(fname, &comment);
1.105 jakob 884: if (public != NULL) {
1.116 avsm 885: export_dns_rr(hname, public, stdout, print_generic);
1.105 jakob 886: key_free(public);
887: xfree(comment);
1.138 jakob 888: return 1;
1.105 jakob 889: }
890: if (comment)
891: xfree(comment);
892:
1.138 jakob 893: printf("failed to read v2 public key from %s.\n", fname);
1.105 jakob 894: exit(1);
895: }
896:
1.13 deraadt 897: /*
898: * Change the comment of a private key file.
899: */
1.63 itojun 900: static void
1.2 provos 901: do_change_comment(struct passwd *pw)
1.1 deraadt 902: {
1.46 deraadt 903: char new_comment[1024], *comment, *passphrase;
1.52 markus 904: Key *private;
905: Key *public;
1.12 markus 906: struct stat st;
907: FILE *f;
1.46 deraadt 908: int fd;
1.12 markus 909:
910: if (!have_identity)
911: ask_filename(pw, "Enter file in which the key is");
912: if (stat(identity_file, &st) < 0) {
913: perror(identity_file);
914: exit(1);
915: }
1.52 markus 916: private = key_load_private(identity_file, "", &comment);
917: if (private == NULL) {
1.12 markus 918: if (identity_passphrase)
919: passphrase = xstrdup(identity_passphrase);
920: else if (identity_new_passphrase)
921: passphrase = xstrdup(identity_new_passphrase);
922: else
1.65 markus 923: passphrase = read_passphrase("Enter passphrase: ",
924: RP_ALLOW_STDIN);
1.12 markus 925: /* Try to load using the passphrase. */
1.52 markus 926: private = key_load_private(identity_file, passphrase, &comment);
927: if (private == NULL) {
1.12 markus 928: memset(passphrase, 0, strlen(passphrase));
929: xfree(passphrase);
930: printf("Bad passphrase.\n");
931: exit(1);
932: }
1.52 markus 933: } else {
934: passphrase = xstrdup("");
1.12 markus 935: }
1.52 markus 936: if (private->type != KEY_RSA1) {
937: fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
938: key_free(private);
939: exit(1);
1.86 deraadt 940: }
1.12 markus 941: printf("Key now has comment '%s'\n", comment);
942:
943: if (identity_comment) {
944: strlcpy(new_comment, identity_comment, sizeof(new_comment));
945: } else {
946: printf("Enter new comment: ");
947: fflush(stdout);
948: if (!fgets(new_comment, sizeof(new_comment), stdin)) {
949: memset(passphrase, 0, strlen(passphrase));
1.19 markus 950: key_free(private);
1.12 markus 951: exit(1);
952: }
953: if (strchr(new_comment, '\n'))
954: *strchr(new_comment, '\n') = 0;
955: }
956:
957: /* Save the file using the new passphrase. */
1.52 markus 958: if (!key_save_private(private, identity_file, passphrase, new_comment)) {
1.56 markus 959: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 960: memset(passphrase, 0, strlen(passphrase));
961: xfree(passphrase);
1.19 markus 962: key_free(private);
1.12 markus 963: xfree(comment);
964: exit(1);
965: }
966: memset(passphrase, 0, strlen(passphrase));
967: xfree(passphrase);
1.52 markus 968: public = key_from_private(private);
1.19 markus 969: key_free(private);
1.12 markus 970:
971: strlcat(identity_file, ".pub", sizeof(identity_file));
1.46 deraadt 972: fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
973: if (fd == -1) {
1.12 markus 974: printf("Could not save your public key in %s\n", identity_file);
975: exit(1);
976: }
1.46 deraadt 977: f = fdopen(fd, "w");
978: if (f == NULL) {
979: printf("fdopen %s failed", identity_file);
980: exit(1);
981: }
1.19 markus 982: if (!key_write(public, f))
983: fprintf(stderr, "write key failed");
984: key_free(public);
985: fprintf(f, " %s\n", new_comment);
1.12 markus 986: fclose(f);
1.1 deraadt 987:
1.12 markus 988: xfree(comment);
1.1 deraadt 989:
1.12 markus 990: printf("The comment in your key file has been changed.\n");
991: exit(0);
1.1 deraadt 992: }
993:
1.63 itojun 994: static void
1.10 markus 995: usage(void)
996: {
1.77 jakob 997: fprintf(stderr, "Usage: %s [options]\n", __progname);
998: fprintf(stderr, "Options:\n");
1.123 otto 999: fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n");
1000: fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
1.77 jakob 1001: fprintf(stderr, " -b bits Number of bits in the key to create.\n");
1.123 otto 1002: fprintf(stderr, " -C comment Provide new comment.\n");
1.77 jakob 1003: fprintf(stderr, " -c Change comment in private and public key files.\n");
1.123 otto 1004: #ifdef SMARTCARD
1005: fprintf(stderr, " -D reader Download public key from smartcard.\n");
1006: #endif /* SMARTCARD */
1.77 jakob 1007: fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n");
1.123 otto 1008: fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
1.77 jakob 1009: fprintf(stderr, " -f filename Filename of the key file.\n");
1.123 otto 1010: fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
1.105 jakob 1011: fprintf(stderr, " -g Use generic DNS resource record format.\n");
1.123 otto 1012: fprintf(stderr, " -H Hash names in known_hosts file.\n");
1.77 jakob 1013: fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n");
1014: fprintf(stderr, " -l Show fingerprint of key file.\n");
1.123 otto 1015: fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1016: fprintf(stderr, " -N phrase Provide new passphrase.\n");
1017: fprintf(stderr, " -P phrase Provide old passphrase.\n");
1.77 jakob 1018: fprintf(stderr, " -p Change passphrase of private key file.\n");
1019: fprintf(stderr, " -q Quiet.\n");
1.123 otto 1020: fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
1021: fprintf(stderr, " -r hostname Print DNS resource record.\n");
1022: fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
1023: fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
1.77 jakob 1024: fprintf(stderr, " -t type Specify type of key to create.\n");
1025: #ifdef SMARTCARD
1026: fprintf(stderr, " -U reader Upload private key to smartcard.\n");
1027: #endif /* SMARTCARD */
1.123 otto 1028: fprintf(stderr, " -v Verbose.\n");
1029: fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
1030: fprintf(stderr, " -y Read private key file and print public key.\n");
1.107 djm 1031:
1.12 markus 1032: exit(1);
1.10 markus 1033: }
1034:
1.13 deraadt 1035: /*
1036: * Main program for key management.
1037: */
1.2 provos 1038: int
1039: main(int ac, char **av)
1.1 deraadt 1040: {
1.87 djm 1041: char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1.112 djm 1042: char out_file[MAXPATHLEN], *reader_id = NULL;
1.119 djm 1043: char *rr_hostname = NULL;
1.46 deraadt 1044: Key *private, *public;
1.12 markus 1045: struct passwd *pw;
1046: struct stat st;
1.124 avsm 1047: int opt, type, fd, download = 0;
1.126 dtucker 1048: u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1.107 djm 1049: int do_gen_candidates = 0, do_screen_candidates = 0;
1.113 djm 1050: int log_level = SYSLOG_LEVEL_INFO;
1.107 djm 1051: BIGNUM *start = NULL;
1.12 markus 1052: FILE *f;
1.125 avsm 1053: const char *errstr;
1.33 markus 1054:
1.12 markus 1055: extern int optind;
1056: extern char *optarg;
1.129 djm 1057:
1058: /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1059: sanitise_stdfd();
1.12 markus 1060:
1.26 markus 1061: SSLeay_add_all_algorithms();
1.107 djm 1062: log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1.19 markus 1063:
1.14 markus 1064: /* we need this for the home * directory. */
1.12 markus 1065: pw = getpwuid(getuid());
1066: if (!pw) {
1067: printf("You don't exist, go away!\n");
1068: exit(1);
1069: }
1.19 markus 1070: if (gethostname(hostname, sizeof(hostname)) < 0) {
1071: perror("gethostname");
1072: exit(1);
1073: }
1.14 markus 1074:
1.107 djm 1075: while ((opt = getopt(ac, av,
1.119 djm 1076: "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1.12 markus 1077: switch (opt) {
1078: case 'b':
1.142 deraadt 1079: bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1.125 avsm 1080: if (errstr)
1081: fatal("Bits has bad value %s (%s)",
1082: optarg, errstr);
1.12 markus 1083: break;
1.119 djm 1084: case 'F':
1085: find_host = 1;
1086: rr_hostname = optarg;
1087: break;
1088: case 'H':
1089: hash_hosts = 1;
1090: break;
1091: case 'R':
1092: delete_host = 1;
1093: rr_hostname = optarg;
1094: break;
1.12 markus 1095: case 'l':
1096: print_fingerprint = 1;
1097: break;
1.49 markus 1098: case 'B':
1099: print_bubblebabble = 1;
1100: break;
1.12 markus 1101: case 'p':
1102: change_passphrase = 1;
1103: break;
1104: case 'c':
1105: change_comment = 1;
1106: break;
1107: case 'f':
1.124 avsm 1108: if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
1109: sizeof(identity_file))
1110: fatal("Identity filename too long");
1.12 markus 1111: have_identity = 1;
1112: break;
1.105 jakob 1113: case 'g':
1114: print_generic = 1;
1115: break;
1.12 markus 1116: case 'P':
1117: identity_passphrase = optarg;
1118: break;
1119: case 'N':
1120: identity_new_passphrase = optarg;
1121: break;
1122: case 'C':
1123: identity_comment = optarg;
1124: break;
1125: case 'q':
1126: quiet = 1;
1.20 deraadt 1127: break;
1.57 markus 1128: case 'e':
1.19 markus 1129: case 'x':
1.57 markus 1130: /* export key */
1.19 markus 1131: convert_to_ssh2 = 1;
1132: break;
1.57 markus 1133: case 'i':
1.19 markus 1134: case 'X':
1.57 markus 1135: /* import key */
1.19 markus 1136: convert_from_ssh2 = 1;
1137: break;
1138: case 'y':
1139: print_public = 1;
1.47 jakob 1140: break;
1.19 markus 1141: case 'd':
1.33 markus 1142: key_type_name = "dsa";
1.19 markus 1143: break;
1.33 markus 1144: case 't':
1145: key_type_name = optarg;
1146: break;
1.75 markus 1147: case 'D':
1148: download = 1;
1.140 deraadt 1149: /*FALLTHROUGH*/
1.76 jakob 1150: case 'U':
1.75 markus 1151: reader_id = optarg;
1.66 markus 1152: break;
1.113 djm 1153: case 'v':
1154: if (log_level == SYSLOG_LEVEL_INFO)
1155: log_level = SYSLOG_LEVEL_DEBUG1;
1156: else {
1.117 deraadt 1157: if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
1.113 djm 1158: log_level < SYSLOG_LEVEL_DEBUG3)
1159: log_level++;
1160: }
1161: break;
1.105 jakob 1162: case 'r':
1.119 djm 1163: rr_hostname = optarg;
1.105 jakob 1164: break;
1.107 djm 1165: case 'W':
1.142 deraadt 1166: generator_wanted = (u_int32_t)strtonum(optarg, 1,
1167: UINT_MAX, &errstr);
1.124 avsm 1168: if (errstr)
1169: fatal("Desired generator has bad value: %s (%s)",
1170: optarg, errstr);
1.107 djm 1171: break;
1172: case 'a':
1.142 deraadt 1173: trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1.124 avsm 1174: if (errstr)
1175: fatal("Invalid number of trials: %s (%s)",
1176: optarg, errstr);
1.107 djm 1177: break;
1178: case 'M':
1.142 deraadt 1179: memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1.124 avsm 1180: if (errstr) {
1181: fatal("Memory limit is %s: %s", errstr, optarg);
1182: }
1.107 djm 1183: break;
1184: case 'G':
1185: do_gen_candidates = 1;
1.124 avsm 1186: if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1187: sizeof(out_file))
1188: fatal("Output filename too long");
1.107 djm 1189: break;
1190: case 'T':
1191: do_screen_candidates = 1;
1.124 avsm 1192: if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1193: sizeof(out_file))
1194: fatal("Output filename too long");
1.107 djm 1195: break;
1196: case 'S':
1197: /* XXX - also compare length against bits */
1198: if (BN_hex2bn(&start, optarg) == 0)
1199: fatal("Invalid start point.");
1200: break;
1.12 markus 1201: case '?':
1202: default:
1203: usage();
1204: }
1205: }
1.113 djm 1206:
1207: /* reinit */
1208: log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1);
1209:
1.12 markus 1210: if (optind < ac) {
1211: printf("Too many arguments.\n");
1.87 djm 1212: usage();
1213: }
1.12 markus 1214: if (change_passphrase && change_comment) {
1215: printf("Can only have one of -p and -c.\n");
1216: usage();
1217: }
1.119 djm 1218: if (delete_host || hash_hosts || find_host)
1219: do_known_hosts(pw, rr_hostname);
1.49 markus 1220: if (print_fingerprint || print_bubblebabble)
1.12 markus 1221: do_fingerprint(pw);
1222: if (change_passphrase)
1223: do_change_passphrase(pw);
1224: if (change_comment)
1225: do_change_comment(pw);
1.19 markus 1226: if (convert_to_ssh2)
1227: do_convert_to_ssh2(pw);
1228: if (convert_from_ssh2)
1229: do_convert_from_ssh2(pw);
1230: if (print_public)
1231: do_print_public(pw);
1.119 djm 1232: if (rr_hostname != NULL) {
1.138 jakob 1233: unsigned int n = 0;
1234:
1235: if (have_identity) {
1236: n = do_print_resource_record(pw,
1237: identity_file, rr_hostname);
1238: if (n == 0) {
1239: perror(identity_file);
1240: exit(1);
1241: }
1242: exit(0);
1243: } else {
1244:
1245: n += do_print_resource_record(pw,
1246: _PATH_HOST_RSA_KEY_FILE, rr_hostname);
1247: n += do_print_resource_record(pw,
1248: _PATH_HOST_DSA_KEY_FILE, rr_hostname);
1249:
1250: if (n == 0)
1251: fatal("no keys found.");
1252: exit(0);
1253: }
1.105 jakob 1254: }
1.75 markus 1255: if (reader_id != NULL) {
1.74 markus 1256: #ifdef SMARTCARD
1.75 markus 1257: if (download)
1258: do_download(pw, reader_id);
1259: else
1260: do_upload(pw, reader_id);
1.78 jakob 1261: #else /* SMARTCARD */
1.74 markus 1262: fatal("no support for smartcards.");
1.78 jakob 1263: #endif /* SMARTCARD */
1.107 djm 1264: }
1265:
1266: if (do_gen_candidates) {
1267: FILE *out = fopen(out_file, "w");
1.111 djm 1268:
1.107 djm 1269: if (out == NULL) {
1270: error("Couldn't open modulus candidate file \"%s\": %s",
1271: out_file, strerror(errno));
1272: return (1);
1273: }
1.130 markus 1274: if (bits == 0)
1275: bits = DEFAULT_BITS;
1.107 djm 1276: if (gen_candidates(out, memory, bits, start) != 0)
1.131 stevesk 1277: fatal("modulus candidate generation failed");
1.107 djm 1278:
1279: return (0);
1280: }
1281:
1282: if (do_screen_candidates) {
1283: FILE *in;
1284: FILE *out = fopen(out_file, "w");
1285:
1286: if (have_identity && strcmp(identity_file, "-") != 0) {
1287: if ((in = fopen(identity_file, "r")) == NULL) {
1288: fatal("Couldn't open modulus candidate "
1.111 djm 1289: "file \"%s\": %s", identity_file,
1.107 djm 1290: strerror(errno));
1291: }
1292: } else
1293: in = stdin;
1294:
1295: if (out == NULL) {
1296: fatal("Couldn't open moduli file \"%s\": %s",
1297: out_file, strerror(errno));
1298: }
1299: if (prime_test(in, out, trials, generator_wanted) != 0)
1.131 stevesk 1300: fatal("modulus screening failed");
1.108 markus 1301: return (0);
1.75 markus 1302: }
1.12 markus 1303:
1304: arc4random_stir();
1305:
1.133 djm 1306: if (key_type_name == NULL)
1307: key_type_name = "rsa";
1308:
1.35 markus 1309: type = key_type_from_name(key_type_name);
1310: if (type == KEY_UNSPEC) {
1311: fprintf(stderr, "unknown key type %s\n", key_type_name);
1312: exit(1);
1.19 markus 1313: }
1.135 dtucker 1314: if (bits == 0)
1315: bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
1.134 dtucker 1316: if (type == KEY_DSA && bits != 1024)
1317: fatal("DSA keys must be 1024 bits");
1.33 markus 1318: if (!quiet)
1.35 markus 1319: printf("Generating public/private %s key pair.\n", key_type_name);
1.33 markus 1320: private = key_generate(type, bits);
1321: if (private == NULL) {
1322: fprintf(stderr, "key_generate failed");
1323: exit(1);
1324: }
1325: public = key_from_private(private);
1.12 markus 1326:
1327: if (!have_identity)
1328: ask_filename(pw, "Enter file in which to save the key");
1329:
1.132 djm 1330: /* Create ~/.ssh directory if it doesn't already exist. */
1.40 markus 1331: snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1.12 markus 1332: if (strstr(identity_file, dotsshdir) != NULL &&
1333: stat(dotsshdir, &st) < 0) {
1.29 djm 1334: if (mkdir(dotsshdir, 0700) < 0)
1.12 markus 1335: error("Could not create directory '%s'.", dotsshdir);
1336: else if (!quiet)
1337: printf("Created directory '%s'.\n", dotsshdir);
1338: }
1339: /* If the file already exists, ask the user to confirm. */
1340: if (stat(identity_file, &st) >= 0) {
1341: char yesno[3];
1342: printf("%s already exists.\n", identity_file);
1343: printf("Overwrite (y/n)? ");
1344: fflush(stdout);
1345: if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1346: exit(1);
1347: if (yesno[0] != 'y' && yesno[0] != 'Y')
1348: exit(1);
1349: }
1350: /* Ask for a passphrase (twice). */
1351: if (identity_passphrase)
1352: passphrase1 = xstrdup(identity_passphrase);
1353: else if (identity_new_passphrase)
1354: passphrase1 = xstrdup(identity_new_passphrase);
1355: else {
1356: passphrase_again:
1357: passphrase1 =
1.65 markus 1358: read_passphrase("Enter passphrase (empty for no "
1359: "passphrase): ", RP_ALLOW_STDIN);
1360: passphrase2 = read_passphrase("Enter same passphrase again: ",
1361: RP_ALLOW_STDIN);
1.12 markus 1362: if (strcmp(passphrase1, passphrase2) != 0) {
1.65 markus 1363: /*
1364: * The passphrases do not match. Clear them and
1365: * retry.
1366: */
1.12 markus 1367: memset(passphrase1, 0, strlen(passphrase1));
1368: memset(passphrase2, 0, strlen(passphrase2));
1369: xfree(passphrase1);
1370: xfree(passphrase2);
1371: printf("Passphrases do not match. Try again.\n");
1372: goto passphrase_again;
1373: }
1374: /* Clear the other copy of the passphrase. */
1375: memset(passphrase2, 0, strlen(passphrase2));
1376: xfree(passphrase2);
1377: }
1378:
1379: if (identity_comment) {
1380: strlcpy(comment, identity_comment, sizeof(comment));
1381: } else {
1.18 markus 1382: /* Create default commend field for the passphrase. */
1.12 markus 1383: snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1384: }
1385:
1386: /* Save the key with the given passphrase and comment. */
1.52 markus 1387: if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56 markus 1388: printf("Saving the key failed: %s.\n", identity_file);
1.12 markus 1389: memset(passphrase1, 0, strlen(passphrase1));
1390: xfree(passphrase1);
1391: exit(1);
1392: }
1393: /* Clear the passphrase. */
1394: memset(passphrase1, 0, strlen(passphrase1));
1395: xfree(passphrase1);
1396:
1397: /* Clear the private key and the random number generator. */
1.33 markus 1398: key_free(private);
1.12 markus 1399: arc4random_stir();
1400:
1401: if (!quiet)
1402: printf("Your identification has been saved in %s.\n", identity_file);
1403:
1404: strlcat(identity_file, ".pub", sizeof(identity_file));
1.46 deraadt 1405: fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1406: if (fd == -1) {
1.12 markus 1407: printf("Could not save your public key in %s\n", identity_file);
1.46 deraadt 1408: exit(1);
1409: }
1410: f = fdopen(fd, "w");
1411: if (f == NULL) {
1412: printf("fdopen %s failed", identity_file);
1.12 markus 1413: exit(1);
1414: }
1.19 markus 1415: if (!key_write(public, f))
1416: fprintf(stderr, "write key failed");
1417: fprintf(f, " %s\n", comment);
1.12 markus 1418: fclose(f);
1419:
1420: if (!quiet) {
1.50 markus 1421: char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1.19 markus 1422: printf("Your public key has been saved in %s.\n",
1423: identity_file);
1.12 markus 1424: printf("The key fingerprint is:\n");
1.50 markus 1425: printf("%s %s\n", fp, comment);
1426: xfree(fp);
1.12 markus 1427: }
1.19 markus 1428:
1429: key_free(public);
1.12 markus 1430: exit(0);
1.1 deraadt 1431: }