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