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