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