1 /* 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. 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". 12 */ 13 14 #include "includes.h" 15 RCSID("$OpenBSD: ssh-keygen.c,v 1.107 2003/07/28 09:49:56 djm Exp $"); 16 17 #include <openssl/evp.h> 18 #include <openssl/pem.h> 19 20 #include "xmalloc.h" 21 #include "key.h" 22 #include "rsa.h" 23 #include "authfile.h" 24 #include "uuencode.h" 25 #include "buffer.h" 26 #include "bufaux.h" 27 #include "pathnames.h" 28 #include "log.h" 29 #include "readpass.h" 30 #include "moduli.h" 31 32 #ifdef SMARTCARD 33 #include "scard.h" 34 #endif 35 #ifdef DNS 36 #include "dns.h" 37 #endif 38 39 /* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ 40 int bits = 1024; 41 42 /* 43 * Flag indicating that we just want to change the passphrase. This can be 44 * set on the command line. 45 */ 46 int change_passphrase = 0; 47 48 /* 49 * Flag indicating that we just want to change the comment. This can be set 50 * on the command line. 51 */ 52 int change_comment = 0; 53 54 int quiet = 0; 55 56 /* Flag indicating that we just want to see the key fingerprint */ 57 int print_fingerprint = 0; 58 int print_bubblebabble = 0; 59 60 /* The identity file name, given on the command line or entered by the user. */ 61 char identity_file[1024]; 62 int have_identity = 0; 63 64 /* This is set to the passphrase if given on the command line. */ 65 char *identity_passphrase = NULL; 66 67 /* This is set to the new passphrase if given on the command line. */ 68 char *identity_new_passphrase = NULL; 69 70 /* This is set to the new comment if given on the command line. */ 71 char *identity_comment = NULL; 72 73 /* Dump public key file in format used by real and the original SSH 2 */ 74 int convert_to_ssh2 = 0; 75 int convert_from_ssh2 = 0; 76 int print_public = 0; 77 int print_generic = 0; 78 79 char *key_type_name = NULL; 80 81 /* argv0 */ 82 extern char *__progname; 83 84 char hostname[MAXHOSTNAMELEN]; 85 86 static void 87 ask_filename(struct passwd *pw, const char *prompt) 88 { 89 char buf[1024]; 90 char *name = NULL; 91 92 if (key_type_name == NULL) 93 name = _PATH_SSH_CLIENT_ID_RSA; 94 else 95 switch (key_type_from_name(key_type_name)) { 96 case KEY_RSA1: 97 name = _PATH_SSH_CLIENT_IDENTITY; 98 break; 99 case KEY_DSA: 100 name = _PATH_SSH_CLIENT_ID_DSA; 101 break; 102 case KEY_RSA: 103 name = _PATH_SSH_CLIENT_ID_RSA; 104 break; 105 default: 106 fprintf(stderr, "bad key type"); 107 exit(1); 108 break; 109 } 110 111 snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); 112 fprintf(stderr, "%s (%s): ", prompt, identity_file); 113 if (fgets(buf, sizeof(buf), stdin) == NULL) 114 exit(1); 115 if (strchr(buf, '\n')) 116 *strchr(buf, '\n') = 0; 117 if (strcmp(buf, "") != 0) 118 strlcpy(identity_file, buf, sizeof(identity_file)); 119 have_identity = 1; 120 } 121 122 static Key * 123 load_identity(char *filename) 124 { 125 char *pass; 126 Key *prv; 127 128 prv = key_load_private(filename, "", NULL); 129 if (prv == NULL) { 130 if (identity_passphrase) 131 pass = xstrdup(identity_passphrase); 132 else 133 pass = read_passphrase("Enter passphrase: ", 134 RP_ALLOW_STDIN); 135 prv = key_load_private(filename, pass, NULL); 136 memset(pass, 0, strlen(pass)); 137 xfree(pass); 138 } 139 return prv; 140 } 141 142 #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" 143 #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" 144 #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" 145 #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb 146 147 static void 148 do_convert_to_ssh2(struct passwd *pw) 149 { 150 Key *k; 151 u_int len; 152 u_char *blob; 153 struct stat st; 154 155 if (!have_identity) 156 ask_filename(pw, "Enter file in which the key is"); 157 if (stat(identity_file, &st) < 0) { 158 perror(identity_file); 159 exit(1); 160 } 161 if ((k = key_load_public(identity_file, NULL)) == NULL) { 162 if ((k = load_identity(identity_file)) == NULL) { 163 fprintf(stderr, "load failed\n"); 164 exit(1); 165 } 166 } 167 if (k->type == KEY_RSA1) { 168 fprintf(stderr, "version 1 keys are not supported\n"); 169 exit(1); 170 } 171 if (key_to_blob(k, &blob, &len) <= 0) { 172 fprintf(stderr, "key_to_blob failed\n"); 173 exit(1); 174 } 175 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); 176 fprintf(stdout, 177 "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n", 178 key_size(k), key_type(k), 179 pw->pw_name, hostname); 180 dump_base64(stdout, blob, len); 181 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); 182 key_free(k); 183 xfree(blob); 184 exit(0); 185 } 186 187 static void 188 buffer_get_bignum_bits(Buffer *b, BIGNUM *value) 189 { 190 int bits = buffer_get_int(b); 191 int bytes = (bits + 7) / 8; 192 193 if (buffer_len(b) < bytes) 194 fatal("buffer_get_bignum_bits: input buffer too small: " 195 "need %d have %d", bytes, buffer_len(b)); 196 BN_bin2bn(buffer_ptr(b), bytes, value); 197 buffer_consume(b, bytes); 198 } 199 200 static Key * 201 do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) 202 { 203 Buffer b; 204 Key *key = NULL; 205 char *type, *cipher; 206 u_char *sig, data[] = "abcde12345"; 207 int magic, rlen, ktype, i1, i2, i3, i4; 208 u_int slen; 209 u_long e; 210 211 buffer_init(&b); 212 buffer_append(&b, blob, blen); 213 214 magic = buffer_get_int(&b); 215 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { 216 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); 217 buffer_free(&b); 218 return NULL; 219 } 220 i1 = buffer_get_int(&b); 221 type = buffer_get_string(&b, NULL); 222 cipher = buffer_get_string(&b, NULL); 223 i2 = buffer_get_int(&b); 224 i3 = buffer_get_int(&b); 225 i4 = buffer_get_int(&b); 226 debug("ignore (%d %d %d %d)", i1,i2,i3,i4); 227 if (strcmp(cipher, "none") != 0) { 228 error("unsupported cipher %s", cipher); 229 xfree(cipher); 230 buffer_free(&b); 231 xfree(type); 232 return NULL; 233 } 234 xfree(cipher); 235 236 if (strstr(type, "dsa")) { 237 ktype = KEY_DSA; 238 } else if (strstr(type, "rsa")) { 239 ktype = KEY_RSA; 240 } else { 241 xfree(type); 242 return NULL; 243 } 244 key = key_new_private(ktype); 245 xfree(type); 246 247 switch (key->type) { 248 case KEY_DSA: 249 buffer_get_bignum_bits(&b, key->dsa->p); 250 buffer_get_bignum_bits(&b, key->dsa->g); 251 buffer_get_bignum_bits(&b, key->dsa->q); 252 buffer_get_bignum_bits(&b, key->dsa->pub_key); 253 buffer_get_bignum_bits(&b, key->dsa->priv_key); 254 break; 255 case KEY_RSA: 256 e = buffer_get_char(&b); 257 debug("e %lx", e); 258 if (e < 30) { 259 e <<= 8; 260 e += buffer_get_char(&b); 261 debug("e %lx", e); 262 e <<= 8; 263 e += buffer_get_char(&b); 264 debug("e %lx", e); 265 } 266 if (!BN_set_word(key->rsa->e, e)) { 267 buffer_free(&b); 268 key_free(key); 269 return NULL; 270 } 271 buffer_get_bignum_bits(&b, key->rsa->d); 272 buffer_get_bignum_bits(&b, key->rsa->n); 273 buffer_get_bignum_bits(&b, key->rsa->iqmp); 274 buffer_get_bignum_bits(&b, key->rsa->q); 275 buffer_get_bignum_bits(&b, key->rsa->p); 276 rsa_generate_additional_parameters(key->rsa); 277 break; 278 } 279 rlen = buffer_len(&b); 280 if (rlen != 0) 281 error("do_convert_private_ssh2_from_blob: " 282 "remaining bytes in key blob %d", rlen); 283 buffer_free(&b); 284 285 /* try the key */ 286 key_sign(key, &sig, &slen, data, sizeof(data)); 287 key_verify(key, sig, slen, data, sizeof(data)); 288 xfree(sig); 289 return key; 290 } 291 292 static void 293 do_convert_from_ssh2(struct passwd *pw) 294 { 295 Key *k; 296 int blen; 297 u_int len; 298 char line[1024], *p; 299 u_char blob[8096]; 300 char encoded[8096]; 301 struct stat st; 302 int escaped = 0, private = 0, ok; 303 FILE *fp; 304 305 if (!have_identity) 306 ask_filename(pw, "Enter file in which the key is"); 307 if (stat(identity_file, &st) < 0) { 308 perror(identity_file); 309 exit(1); 310 } 311 fp = fopen(identity_file, "r"); 312 if (fp == NULL) { 313 perror(identity_file); 314 exit(1); 315 } 316 encoded[0] = '\0'; 317 while (fgets(line, sizeof(line), fp)) { 318 if (!(p = strchr(line, '\n'))) { 319 fprintf(stderr, "input line too long.\n"); 320 exit(1); 321 } 322 if (p > line && p[-1] == '\\') 323 escaped++; 324 if (strncmp(line, "----", 4) == 0 || 325 strstr(line, ": ") != NULL) { 326 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) 327 private = 1; 328 if (strstr(line, " END ") != NULL) { 329 break; 330 } 331 /* fprintf(stderr, "ignore: %s", line); */ 332 continue; 333 } 334 if (escaped) { 335 escaped--; 336 /* fprintf(stderr, "escaped: %s", line); */ 337 continue; 338 } 339 *p = '\0'; 340 strlcat(encoded, line, sizeof(encoded)); 341 } 342 len = strlen(encoded); 343 if (((len % 4) == 3) && 344 (encoded[len-1] == '=') && 345 (encoded[len-2] == '=') && 346 (encoded[len-3] == '=')) 347 encoded[len-3] = '\0'; 348 blen = uudecode(encoded, blob, sizeof(blob)); 349 if (blen < 0) { 350 fprintf(stderr, "uudecode failed.\n"); 351 exit(1); 352 } 353 k = private ? 354 do_convert_private_ssh2_from_blob(blob, blen) : 355 key_from_blob(blob, blen); 356 if (k == NULL) { 357 fprintf(stderr, "decode blob failed.\n"); 358 exit(1); 359 } 360 ok = private ? 361 (k->type == KEY_DSA ? 362 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : 363 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : 364 key_write(k, stdout); 365 if (!ok) { 366 fprintf(stderr, "key write failed"); 367 exit(1); 368 } 369 key_free(k); 370 if (!private) 371 fprintf(stdout, "\n"); 372 fclose(fp); 373 exit(0); 374 } 375 376 static void 377 do_print_public(struct passwd *pw) 378 { 379 Key *prv; 380 struct stat st; 381 382 if (!have_identity) 383 ask_filename(pw, "Enter file in which the key is"); 384 if (stat(identity_file, &st) < 0) { 385 perror(identity_file); 386 exit(1); 387 } 388 prv = load_identity(identity_file); 389 if (prv == NULL) { 390 fprintf(stderr, "load failed\n"); 391 exit(1); 392 } 393 if (!key_write(prv, stdout)) 394 fprintf(stderr, "key_write failed"); 395 key_free(prv); 396 fprintf(stdout, "\n"); 397 exit(0); 398 } 399 400 #ifdef SMARTCARD 401 static void 402 do_upload(struct passwd *pw, const char *sc_reader_id) 403 { 404 Key *prv = NULL; 405 struct stat st; 406 int ret; 407 408 if (!have_identity) 409 ask_filename(pw, "Enter file in which the key is"); 410 if (stat(identity_file, &st) < 0) { 411 perror(identity_file); 412 exit(1); 413 } 414 prv = load_identity(identity_file); 415 if (prv == NULL) { 416 error("load failed"); 417 exit(1); 418 } 419 ret = sc_put_key(prv, sc_reader_id); 420 key_free(prv); 421 if (ret < 0) 422 exit(1); 423 logit("loading key done"); 424 exit(0); 425 } 426 427 static void 428 do_download(struct passwd *pw, const char *sc_reader_id) 429 { 430 Key **keys = NULL; 431 int i; 432 433 keys = sc_get_keys(sc_reader_id, NULL); 434 if (keys == NULL) 435 fatal("cannot read public key from smartcard"); 436 for (i = 0; keys[i]; i++) { 437 key_write(keys[i], stdout); 438 key_free(keys[i]); 439 fprintf(stdout, "\n"); 440 } 441 xfree(keys); 442 exit(0); 443 } 444 #endif /* SMARTCARD */ 445 446 static void 447 do_fingerprint(struct passwd *pw) 448 { 449 FILE *f; 450 Key *public; 451 char *comment = NULL, *cp, *ep, line[16*1024], *fp; 452 int i, skip = 0, num = 1, invalid = 1; 453 enum fp_rep rep; 454 enum fp_type fptype; 455 struct stat st; 456 457 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 458 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 459 460 if (!have_identity) 461 ask_filename(pw, "Enter file in which the key is"); 462 if (stat(identity_file, &st) < 0) { 463 perror(identity_file); 464 exit(1); 465 } 466 public = key_load_public(identity_file, &comment); 467 if (public != NULL) { 468 fp = key_fingerprint(public, fptype, rep); 469 printf("%u %s %s\n", key_size(public), fp, comment); 470 key_free(public); 471 xfree(comment); 472 xfree(fp); 473 exit(0); 474 } 475 if (comment) 476 xfree(comment); 477 478 f = fopen(identity_file, "r"); 479 if (f != NULL) { 480 while (fgets(line, sizeof(line), f)) { 481 i = strlen(line) - 1; 482 if (line[i] != '\n') { 483 error("line %d too long: %.40s...", num, line); 484 skip = 1; 485 continue; 486 } 487 num++; 488 if (skip) { 489 skip = 0; 490 continue; 491 } 492 line[i] = '\0'; 493 494 /* Skip leading whitespace, empty and comment lines. */ 495 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 496 ; 497 if (!*cp || *cp == '\n' || *cp == '#') 498 continue ; 499 i = strtol(cp, &ep, 10); 500 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { 501 int quoted = 0; 502 comment = cp; 503 for (; *cp && (quoted || (*cp != ' ' && 504 *cp != '\t')); cp++) { 505 if (*cp == '\\' && cp[1] == '"') 506 cp++; /* Skip both */ 507 else if (*cp == '"') 508 quoted = !quoted; 509 } 510 if (!*cp) 511 continue; 512 *cp++ = '\0'; 513 } 514 ep = cp; 515 public = key_new(KEY_RSA1); 516 if (key_read(public, &cp) != 1) { 517 cp = ep; 518 key_free(public); 519 public = key_new(KEY_UNSPEC); 520 if (key_read(public, &cp) != 1) { 521 key_free(public); 522 continue; 523 } 524 } 525 comment = *cp ? cp : comment; 526 fp = key_fingerprint(public, fptype, rep); 527 printf("%u %s %s\n", key_size(public), fp, 528 comment ? comment : "no comment"); 529 xfree(fp); 530 key_free(public); 531 invalid = 0; 532 } 533 fclose(f); 534 } 535 if (invalid) { 536 printf("%s is not a public key file.\n", identity_file); 537 exit(1); 538 } 539 exit(0); 540 } 541 542 /* 543 * Perform changing a passphrase. The argument is the passwd structure 544 * for the current user. 545 */ 546 static void 547 do_change_passphrase(struct passwd *pw) 548 { 549 char *comment; 550 char *old_passphrase, *passphrase1, *passphrase2; 551 struct stat st; 552 Key *private; 553 554 if (!have_identity) 555 ask_filename(pw, "Enter file in which the key is"); 556 if (stat(identity_file, &st) < 0) { 557 perror(identity_file); 558 exit(1); 559 } 560 /* Try to load the file with empty passphrase. */ 561 private = key_load_private(identity_file, "", &comment); 562 if (private == NULL) { 563 if (identity_passphrase) 564 old_passphrase = xstrdup(identity_passphrase); 565 else 566 old_passphrase = 567 read_passphrase("Enter old passphrase: ", 568 RP_ALLOW_STDIN); 569 private = key_load_private(identity_file, old_passphrase, 570 &comment); 571 memset(old_passphrase, 0, strlen(old_passphrase)); 572 xfree(old_passphrase); 573 if (private == NULL) { 574 printf("Bad passphrase.\n"); 575 exit(1); 576 } 577 } 578 printf("Key has comment '%s'\n", comment); 579 580 /* Ask the new passphrase (twice). */ 581 if (identity_new_passphrase) { 582 passphrase1 = xstrdup(identity_new_passphrase); 583 passphrase2 = NULL; 584 } else { 585 passphrase1 = 586 read_passphrase("Enter new passphrase (empty for no " 587 "passphrase): ", RP_ALLOW_STDIN); 588 passphrase2 = read_passphrase("Enter same passphrase again: ", 589 RP_ALLOW_STDIN); 590 591 /* Verify that they are the same. */ 592 if (strcmp(passphrase1, passphrase2) != 0) { 593 memset(passphrase1, 0, strlen(passphrase1)); 594 memset(passphrase2, 0, strlen(passphrase2)); 595 xfree(passphrase1); 596 xfree(passphrase2); 597 printf("Pass phrases do not match. Try again.\n"); 598 exit(1); 599 } 600 /* Destroy the other copy. */ 601 memset(passphrase2, 0, strlen(passphrase2)); 602 xfree(passphrase2); 603 } 604 605 /* Save the file using the new passphrase. */ 606 if (!key_save_private(private, identity_file, passphrase1, comment)) { 607 printf("Saving the key failed: %s.\n", identity_file); 608 memset(passphrase1, 0, strlen(passphrase1)); 609 xfree(passphrase1); 610 key_free(private); 611 xfree(comment); 612 exit(1); 613 } 614 /* Destroy the passphrase and the copy of the key in memory. */ 615 memset(passphrase1, 0, strlen(passphrase1)); 616 xfree(passphrase1); 617 key_free(private); /* Destroys contents */ 618 xfree(comment); 619 620 printf("Your identification has been saved with the new passphrase.\n"); 621 exit(0); 622 } 623 624 #ifdef DNS 625 /* 626 * Print the SSHFP RR. 627 */ 628 static void 629 do_print_resource_record(struct passwd *pw, char *hostname) 630 { 631 Key *public; 632 char *comment = NULL; 633 struct stat st; 634 635 if (!have_identity) 636 ask_filename(pw, "Enter file in which the key is"); 637 if (stat(identity_file, &st) < 0) { 638 perror(identity_file); 639 exit(1); 640 } 641 public = key_load_public(identity_file, &comment); 642 if (public != NULL) { 643 export_dns_rr(hostname, public, stdout, print_generic); 644 key_free(public); 645 xfree(comment); 646 exit(0); 647 } 648 if (comment) 649 xfree(comment); 650 651 printf("failed to read v2 public key from %s.\n", identity_file); 652 exit(1); 653 } 654 #endif /* DNS */ 655 656 /* 657 * Change the comment of a private key file. 658 */ 659 static void 660 do_change_comment(struct passwd *pw) 661 { 662 char new_comment[1024], *comment, *passphrase; 663 Key *private; 664 Key *public; 665 struct stat st; 666 FILE *f; 667 int fd; 668 669 if (!have_identity) 670 ask_filename(pw, "Enter file in which the key is"); 671 if (stat(identity_file, &st) < 0) { 672 perror(identity_file); 673 exit(1); 674 } 675 private = key_load_private(identity_file, "", &comment); 676 if (private == NULL) { 677 if (identity_passphrase) 678 passphrase = xstrdup(identity_passphrase); 679 else if (identity_new_passphrase) 680 passphrase = xstrdup(identity_new_passphrase); 681 else 682 passphrase = read_passphrase("Enter passphrase: ", 683 RP_ALLOW_STDIN); 684 /* Try to load using the passphrase. */ 685 private = key_load_private(identity_file, passphrase, &comment); 686 if (private == NULL) { 687 memset(passphrase, 0, strlen(passphrase)); 688 xfree(passphrase); 689 printf("Bad passphrase.\n"); 690 exit(1); 691 } 692 } else { 693 passphrase = xstrdup(""); 694 } 695 if (private->type != KEY_RSA1) { 696 fprintf(stderr, "Comments are only supported for RSA1 keys.\n"); 697 key_free(private); 698 exit(1); 699 } 700 printf("Key now has comment '%s'\n", comment); 701 702 if (identity_comment) { 703 strlcpy(new_comment, identity_comment, sizeof(new_comment)); 704 } else { 705 printf("Enter new comment: "); 706 fflush(stdout); 707 if (!fgets(new_comment, sizeof(new_comment), stdin)) { 708 memset(passphrase, 0, strlen(passphrase)); 709 key_free(private); 710 exit(1); 711 } 712 if (strchr(new_comment, '\n')) 713 *strchr(new_comment, '\n') = 0; 714 } 715 716 /* Save the file using the new passphrase. */ 717 if (!key_save_private(private, identity_file, passphrase, new_comment)) { 718 printf("Saving the key failed: %s.\n", identity_file); 719 memset(passphrase, 0, strlen(passphrase)); 720 xfree(passphrase); 721 key_free(private); 722 xfree(comment); 723 exit(1); 724 } 725 memset(passphrase, 0, strlen(passphrase)); 726 xfree(passphrase); 727 public = key_from_private(private); 728 key_free(private); 729 730 strlcat(identity_file, ".pub", sizeof(identity_file)); 731 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 732 if (fd == -1) { 733 printf("Could not save your public key in %s\n", identity_file); 734 exit(1); 735 } 736 f = fdopen(fd, "w"); 737 if (f == NULL) { 738 printf("fdopen %s failed", identity_file); 739 exit(1); 740 } 741 if (!key_write(public, f)) 742 fprintf(stderr, "write key failed"); 743 key_free(public); 744 fprintf(f, " %s\n", new_comment); 745 fclose(f); 746 747 xfree(comment); 748 749 printf("The comment in your key file has been changed.\n"); 750 exit(0); 751 } 752 753 static void 754 usage(void) 755 { 756 fprintf(stderr, "Usage: %s [options]\n", __progname); 757 fprintf(stderr, "Options:\n"); 758 fprintf(stderr, " -b bits Number of bits in the key to create.\n"); 759 fprintf(stderr, " -c Change comment in private and public key files.\n"); 760 fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); 761 fprintf(stderr, " -f filename Filename of the key file.\n"); 762 fprintf(stderr, " -g Use generic DNS resource record format.\n"); 763 fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); 764 fprintf(stderr, " -l Show fingerprint of key file.\n"); 765 fprintf(stderr, " -p Change passphrase of private key file.\n"); 766 fprintf(stderr, " -q Quiet.\n"); 767 fprintf(stderr, " -y Read private key file and print public key.\n"); 768 fprintf(stderr, " -t type Specify type of key to create.\n"); 769 fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); 770 fprintf(stderr, " -C comment Provide new comment.\n"); 771 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 772 fprintf(stderr, " -P phrase Provide old passphrase.\n"); 773 #ifdef DNS 774 fprintf(stderr, " -r hostname Print DNS resource record.\n"); 775 #endif /* DNS */ 776 #ifdef SMARTCARD 777 fprintf(stderr, " -D reader Download public key from smartcard.\n"); 778 fprintf(stderr, " -U reader Upload private key to smartcard.\n"); 779 #endif /* SMARTCARD */ 780 781 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli\n"); 782 fprintf(stderr, " -T file Screen candidates for DH-GEX moduli\n"); 783 784 exit(1); 785 } 786 787 /* 788 * Main program for key management. 789 */ 790 int 791 main(int ac, char **av) 792 { 793 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; 794 char out_file[PATH_MAX], *reader_id = NULL; 795 char *resource_record_hostname = NULL; 796 Key *private, *public; 797 struct passwd *pw; 798 struct stat st; 799 int opt, type, fd, download = 0, memory = 0; 800 int generator_wanted = 0, trials = 100; 801 int do_gen_candidates = 0, do_screen_candidates = 0; 802 BIGNUM *start = NULL; 803 FILE *f; 804 805 extern int optind; 806 extern char *optarg; 807 808 SSLeay_add_all_algorithms(); 809 log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); 810 811 /* we need this for the home * directory. */ 812 pw = getpwuid(getuid()); 813 if (!pw) { 814 printf("You don't exist, go away!\n"); 815 exit(1); 816 } 817 if (gethostname(hostname, sizeof(hostname)) < 0) { 818 perror("gethostname"); 819 exit(1); 820 } 821 822 while ((opt = getopt(ac, av, 823 "degiqpclBRxXyb:f:t:U:D:P:N:C:r:g:T:G:M:S:a:W:")) != -1) { 824 switch (opt) { 825 case 'b': 826 bits = atoi(optarg); 827 if (bits < 512 || bits > 32768) { 828 printf("Bits has bad value.\n"); 829 exit(1); 830 } 831 break; 832 case 'l': 833 print_fingerprint = 1; 834 break; 835 case 'B': 836 print_bubblebabble = 1; 837 break; 838 case 'p': 839 change_passphrase = 1; 840 break; 841 case 'c': 842 change_comment = 1; 843 break; 844 case 'f': 845 strlcpy(identity_file, optarg, sizeof(identity_file)); 846 have_identity = 1; 847 break; 848 case 'g': 849 print_generic = 1; 850 break; 851 case 'P': 852 identity_passphrase = optarg; 853 break; 854 case 'N': 855 identity_new_passphrase = optarg; 856 break; 857 case 'C': 858 identity_comment = optarg; 859 break; 860 case 'q': 861 quiet = 1; 862 break; 863 case 'R': 864 /* unused */ 865 exit(0); 866 break; 867 case 'e': 868 case 'x': 869 /* export key */ 870 convert_to_ssh2 = 1; 871 break; 872 case 'i': 873 case 'X': 874 /* import key */ 875 convert_from_ssh2 = 1; 876 break; 877 case 'y': 878 print_public = 1; 879 break; 880 case 'd': 881 key_type_name = "dsa"; 882 break; 883 case 't': 884 key_type_name = optarg; 885 break; 886 case 'D': 887 download = 1; 888 case 'U': 889 reader_id = optarg; 890 break; 891 case 'r': 892 resource_record_hostname = optarg; 893 break; 894 case 'W': 895 generator_wanted = atoi(optarg); 896 if (generator_wanted < 1) 897 fatal("Desired generator has bad value."); 898 break; 899 case 'a': 900 trials = atoi(optarg); 901 if (trials < TRIAL_MINIMUM) { 902 fatal("Minimum primality trials is %d", 903 TRIAL_MINIMUM); 904 } 905 break; 906 case 'M': 907 memory = atoi(optarg); 908 if (memory != 0 && 909 (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { 910 fatal("Invalid memory amount (min %ld, max %ld)", 911 LARGE_MINIMUM, LARGE_MAXIMUM); 912 } 913 break; 914 case 'G': 915 do_gen_candidates = 1; 916 strlcpy(out_file, optarg, sizeof(out_file)); 917 break; 918 case 'T': 919 do_screen_candidates = 1; 920 strlcpy(out_file, optarg, sizeof(out_file)); 921 break; 922 case 'S': 923 /* XXX - also compare length against bits */ 924 if (BN_hex2bn(&start, optarg) == 0) 925 fatal("Invalid start point."); 926 break; 927 case '?': 928 default: 929 usage(); 930 } 931 } 932 if (optind < ac) { 933 printf("Too many arguments.\n"); 934 usage(); 935 } 936 if (change_passphrase && change_comment) { 937 printf("Can only have one of -p and -c.\n"); 938 usage(); 939 } 940 if (print_fingerprint || print_bubblebabble) 941 do_fingerprint(pw); 942 if (change_passphrase) 943 do_change_passphrase(pw); 944 if (change_comment) 945 do_change_comment(pw); 946 if (convert_to_ssh2) 947 do_convert_to_ssh2(pw); 948 if (convert_from_ssh2) 949 do_convert_from_ssh2(pw); 950 if (print_public) 951 do_print_public(pw); 952 if (resource_record_hostname != NULL) { 953 #ifdef DNS 954 do_print_resource_record(pw, resource_record_hostname); 955 #else /* DNS */ 956 fatal("no DNS support."); 957 #endif /* DNS */ 958 } 959 if (reader_id != NULL) { 960 #ifdef SMARTCARD 961 if (download) 962 do_download(pw, reader_id); 963 else 964 do_upload(pw, reader_id); 965 #else /* SMARTCARD */ 966 fatal("no support for smartcards."); 967 #endif /* SMARTCARD */ 968 } 969 970 if (do_gen_candidates) { 971 FILE *out = fopen(out_file, "w"); 972 973 if (out == NULL) { 974 error("Couldn't open modulus candidate file \"%s\": %s", 975 out_file, strerror(errno)); 976 return (1); 977 } 978 if (gen_candidates(out, memory, bits, start) != 0) 979 fatal("modulus candidate generation failed\n"); 980 981 return (0); 982 } 983 984 if (do_screen_candidates) { 985 FILE *in; 986 FILE *out = fopen(out_file, "w"); 987 988 if (have_identity && strcmp(identity_file, "-") != 0) { 989 if ((in = fopen(identity_file, "r")) == NULL) { 990 fatal("Couldn't open modulus candidate " 991 "file \"%s\": %s", identity_file, 992 strerror(errno)); 993 } 994 } else 995 in = stdin; 996 997 if (out == NULL) { 998 fatal("Couldn't open moduli file \"%s\": %s", 999 out_file, strerror(errno)); 1000 } 1001 if (prime_test(in, out, trials, generator_wanted) != 0) 1002 fatal("modulus screening failed\n"); 1003 } 1004 1005 arc4random_stir(); 1006 1007 if (key_type_name == NULL) { 1008 printf("You must specify a key type (-t).\n"); 1009 usage(); 1010 } 1011 type = key_type_from_name(key_type_name); 1012 if (type == KEY_UNSPEC) { 1013 fprintf(stderr, "unknown key type %s\n", key_type_name); 1014 exit(1); 1015 } 1016 if (!quiet) 1017 printf("Generating public/private %s key pair.\n", key_type_name); 1018 private = key_generate(type, bits); 1019 if (private == NULL) { 1020 fprintf(stderr, "key_generate failed"); 1021 exit(1); 1022 } 1023 public = key_from_private(private); 1024 1025 if (!have_identity) 1026 ask_filename(pw, "Enter file in which to save the key"); 1027 1028 /* Create ~/.ssh directory if it doesn\'t already exist. */ 1029 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); 1030 if (strstr(identity_file, dotsshdir) != NULL && 1031 stat(dotsshdir, &st) < 0) { 1032 if (mkdir(dotsshdir, 0700) < 0) 1033 error("Could not create directory '%s'.", dotsshdir); 1034 else if (!quiet) 1035 printf("Created directory '%s'.\n", dotsshdir); 1036 } 1037 /* If the file already exists, ask the user to confirm. */ 1038 if (stat(identity_file, &st) >= 0) { 1039 char yesno[3]; 1040 printf("%s already exists.\n", identity_file); 1041 printf("Overwrite (y/n)? "); 1042 fflush(stdout); 1043 if (fgets(yesno, sizeof(yesno), stdin) == NULL) 1044 exit(1); 1045 if (yesno[0] != 'y' && yesno[0] != 'Y') 1046 exit(1); 1047 } 1048 /* Ask for a passphrase (twice). */ 1049 if (identity_passphrase) 1050 passphrase1 = xstrdup(identity_passphrase); 1051 else if (identity_new_passphrase) 1052 passphrase1 = xstrdup(identity_new_passphrase); 1053 else { 1054 passphrase_again: 1055 passphrase1 = 1056 read_passphrase("Enter passphrase (empty for no " 1057 "passphrase): ", RP_ALLOW_STDIN); 1058 passphrase2 = read_passphrase("Enter same passphrase again: ", 1059 RP_ALLOW_STDIN); 1060 if (strcmp(passphrase1, passphrase2) != 0) { 1061 /* 1062 * The passphrases do not match. Clear them and 1063 * retry. 1064 */ 1065 memset(passphrase1, 0, strlen(passphrase1)); 1066 memset(passphrase2, 0, strlen(passphrase2)); 1067 xfree(passphrase1); 1068 xfree(passphrase2); 1069 printf("Passphrases do not match. Try again.\n"); 1070 goto passphrase_again; 1071 } 1072 /* Clear the other copy of the passphrase. */ 1073 memset(passphrase2, 0, strlen(passphrase2)); 1074 xfree(passphrase2); 1075 } 1076 1077 if (identity_comment) { 1078 strlcpy(comment, identity_comment, sizeof(comment)); 1079 } else { 1080 /* Create default commend field for the passphrase. */ 1081 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); 1082 } 1083 1084 /* Save the key with the given passphrase and comment. */ 1085 if (!key_save_private(private, identity_file, passphrase1, comment)) { 1086 printf("Saving the key failed: %s.\n", identity_file); 1087 memset(passphrase1, 0, strlen(passphrase1)); 1088 xfree(passphrase1); 1089 exit(1); 1090 } 1091 /* Clear the passphrase. */ 1092 memset(passphrase1, 0, strlen(passphrase1)); 1093 xfree(passphrase1); 1094 1095 /* Clear the private key and the random number generator. */ 1096 key_free(private); 1097 arc4random_stir(); 1098 1099 if (!quiet) 1100 printf("Your identification has been saved in %s.\n", identity_file); 1101 1102 strlcat(identity_file, ".pub", sizeof(identity_file)); 1103 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1104 if (fd == -1) { 1105 printf("Could not save your public key in %s\n", identity_file); 1106 exit(1); 1107 } 1108 f = fdopen(fd, "w"); 1109 if (f == NULL) { 1110 printf("fdopen %s failed", identity_file); 1111 exit(1); 1112 } 1113 if (!key_write(public, f)) 1114 fprintf(stderr, "write key failed"); 1115 fprintf(f, " %s\n", comment); 1116 fclose(f); 1117 1118 if (!quiet) { 1119 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); 1120 printf("Your public key has been saved in %s.\n", 1121 identity_file); 1122 printf("The key fingerprint is:\n"); 1123 printf("%s %s\n", fp, comment); 1124 xfree(fp); 1125 } 1126 1127 key_free(public); 1128 exit(0); 1129 } 1130