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