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