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