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.60 2001/04/23 22:14:13 markus 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 31 /* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ 32 int bits = 1024; 33 34 /* 35 * Flag indicating that we just want to change the passphrase. This can be 36 * set on the command line. 37 */ 38 int change_passphrase = 0; 39 40 /* 41 * Flag indicating that we just want to change the comment. This can be set 42 * on the command line. 43 */ 44 int change_comment = 0; 45 46 int quiet = 0; 47 48 /* Flag indicating that we just want to see the key fingerprint */ 49 int print_fingerprint = 0; 50 int print_bubblebabble = 0; 51 52 /* The identity file name, given on the command line or entered by the user. */ 53 char identity_file[1024]; 54 int have_identity = 0; 55 56 /* This is set to the passphrase if given on the command line. */ 57 char *identity_passphrase = NULL; 58 59 /* This is set to the new passphrase if given on the command line. */ 60 char *identity_new_passphrase = NULL; 61 62 /* This is set to the new comment if given on the command line. */ 63 char *identity_comment = NULL; 64 65 /* Dump public key file in format used by real and the original SSH 2 */ 66 int convert_to_ssh2 = 0; 67 int convert_from_ssh2 = 0; 68 int print_public = 0; 69 70 /* default to RSA for SSH-1 */ 71 char *key_type_name = "rsa1"; 72 73 /* argv0 */ 74 extern char *__progname; 75 76 char hostname[MAXHOSTNAMELEN]; 77 78 void 79 ask_filename(struct passwd *pw, const char *prompt) 80 { 81 char buf[1024]; 82 char *name = NULL; 83 84 switch (key_type_from_name(key_type_name)) { 85 case KEY_RSA1: 86 name = _PATH_SSH_CLIENT_IDENTITY; 87 break; 88 case KEY_DSA: 89 name = _PATH_SSH_CLIENT_ID_DSA; 90 break; 91 case KEY_RSA: 92 name = _PATH_SSH_CLIENT_ID_RSA; 93 break; 94 default: 95 fprintf(stderr, "bad key type"); 96 exit(1); 97 break; 98 } 99 snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); 100 fprintf(stderr, "%s (%s): ", prompt, identity_file); 101 fflush(stderr); 102 if (fgets(buf, sizeof(buf), stdin) == NULL) 103 exit(1); 104 if (strchr(buf, '\n')) 105 *strchr(buf, '\n') = 0; 106 if (strcmp(buf, "") != 0) 107 strlcpy(identity_file, buf, sizeof(identity_file)); 108 have_identity = 1; 109 } 110 111 Key * 112 try_load_pem_key(char *filename) 113 { 114 char *pass; 115 Key *prv; 116 117 prv = key_load_private(filename, "", NULL); 118 if (prv == NULL) { 119 pass = read_passphrase("Enter passphrase: ", 1); 120 prv = key_load_private(filename, pass, NULL); 121 memset(pass, 0, strlen(pass)); 122 xfree(pass); 123 } 124 return prv; 125 } 126 127 #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" 128 #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" 129 #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" 130 #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb 131 132 void 133 do_convert_to_ssh2(struct passwd *pw) 134 { 135 Key *k; 136 int len; 137 u_char *blob; 138 struct stat st; 139 140 if (!have_identity) 141 ask_filename(pw, "Enter file in which the key is"); 142 if (stat(identity_file, &st) < 0) { 143 perror(identity_file); 144 exit(1); 145 } 146 if ((k = key_load_public(identity_file, NULL)) == NULL) { 147 if ((k = try_load_pem_key(identity_file)) == NULL) { 148 fprintf(stderr, "load failed\n"); 149 exit(1); 150 } 151 } 152 key_to_blob(k, &blob, &len); 153 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); 154 fprintf(stdout, 155 "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n", 156 key_size(k), key_type(k), 157 pw->pw_name, hostname); 158 dump_base64(stdout, blob, len); 159 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); 160 key_free(k); 161 xfree(blob); 162 exit(0); 163 } 164 165 void 166 buffer_get_bignum_bits(Buffer *b, BIGNUM *value) 167 { 168 int bits = buffer_get_int(b); 169 int bytes = (bits + 7) / 8; 170 171 if (buffer_len(b) < bytes) 172 fatal("buffer_get_bignum_bits: input buffer too small: " 173 "need %d have %d", bytes, buffer_len(b)); 174 BN_bin2bn((u_char *)buffer_ptr(b), bytes, value); 175 buffer_consume(b, bytes); 176 } 177 178 Key * 179 do_convert_private_ssh2_from_blob(char *blob, int blen) 180 { 181 Buffer b; 182 Key *key = NULL; 183 int ignore, magic, rlen, ktype; 184 char *type, *cipher; 185 186 buffer_init(&b); 187 buffer_append(&b, blob, blen); 188 189 magic = buffer_get_int(&b); 190 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { 191 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); 192 buffer_free(&b); 193 return NULL; 194 } 195 ignore = buffer_get_int(&b); 196 type = buffer_get_string(&b, NULL); 197 cipher = buffer_get_string(&b, NULL); 198 ignore = buffer_get_int(&b); 199 ignore = buffer_get_int(&b); 200 ignore = buffer_get_int(&b); 201 202 if (strcmp(cipher, "none") != 0) { 203 error("unsupported cipher %s", cipher); 204 xfree(cipher); 205 buffer_free(&b); 206 xfree(type); 207 return NULL; 208 } 209 xfree(cipher); 210 211 if (strstr(type, "dsa")) { 212 ktype = KEY_DSA; 213 } else if (strstr(type, "rsa")) { 214 ktype = KEY_RSA; 215 } else { 216 xfree(type); 217 return NULL; 218 } 219 key = key_new_private(ktype); 220 xfree(type); 221 222 switch (key->type) { 223 case KEY_DSA: 224 buffer_get_bignum_bits(&b, key->dsa->p); 225 buffer_get_bignum_bits(&b, key->dsa->g); 226 buffer_get_bignum_bits(&b, key->dsa->q); 227 buffer_get_bignum_bits(&b, key->dsa->pub_key); 228 buffer_get_bignum_bits(&b, key->dsa->priv_key); 229 break; 230 case KEY_RSA: 231 if (!BN_set_word(key->rsa->e, (u_long) buffer_get_char(&b))) { 232 buffer_free(&b); 233 key_free(key); 234 return NULL; 235 } 236 buffer_get_bignum_bits(&b, key->rsa->d); 237 buffer_get_bignum_bits(&b, key->rsa->n); 238 buffer_get_bignum_bits(&b, key->rsa->iqmp); 239 buffer_get_bignum_bits(&b, key->rsa->q); 240 buffer_get_bignum_bits(&b, key->rsa->p); 241 generate_additional_parameters(key->rsa); 242 break; 243 } 244 rlen = buffer_len(&b); 245 if(rlen != 0) 246 error("do_convert_private_ssh2_from_blob: " 247 "remaining bytes in key blob %d", rlen); 248 buffer_free(&b); 249 #ifdef DEBUG_PK 250 { 251 u_int slen; 252 u_char *sig, data[10] = "abcde12345"; 253 254 key_sign(key, &sig, &slen, data, sizeof data); 255 key_verify(key, sig, slen, data, sizeof data); 256 xfree(sig); 257 } 258 #endif 259 return key; 260 } 261 262 void 263 do_convert_from_ssh2(struct passwd *pw) 264 { 265 Key *k; 266 int blen; 267 char line[1024], *p; 268 char blob[8096]; 269 char encoded[8096]; 270 struct stat st; 271 int escaped = 0, private = 0, ok; 272 FILE *fp; 273 274 if (!have_identity) 275 ask_filename(pw, "Enter file in which the key is"); 276 if (stat(identity_file, &st) < 0) { 277 perror(identity_file); 278 exit(1); 279 } 280 fp = fopen(identity_file, "r"); 281 if (fp == NULL) { 282 perror(identity_file); 283 exit(1); 284 } 285 encoded[0] = '\0'; 286 while (fgets(line, sizeof(line), fp)) { 287 if (!(p = strchr(line, '\n'))) { 288 fprintf(stderr, "input line too long.\n"); 289 exit(1); 290 } 291 if (p > line && p[-1] == '\\') 292 escaped++; 293 if (strncmp(line, "----", 4) == 0 || 294 strstr(line, ": ") != NULL) { 295 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) 296 private = 1; 297 /* fprintf(stderr, "ignore: %s", line); */ 298 continue; 299 } 300 if (escaped) { 301 escaped--; 302 /* fprintf(stderr, "escaped: %s", line); */ 303 continue; 304 } 305 *p = '\0'; 306 strlcat(encoded, line, sizeof(encoded)); 307 } 308 blen = uudecode(encoded, (u_char *)blob, sizeof(blob)); 309 if (blen < 0) { 310 fprintf(stderr, "uudecode failed.\n"); 311 exit(1); 312 } 313 k = private ? 314 do_convert_private_ssh2_from_blob(blob, blen) : 315 key_from_blob(blob, blen); 316 if (k == NULL) { 317 fprintf(stderr, "decode blob failed.\n"); 318 exit(1); 319 } 320 ok = private ? 321 (k->type == KEY_DSA ? 322 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : 323 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : 324 key_write(k, stdout); 325 if (!ok) { 326 fprintf(stderr, "key write failed"); 327 exit(1); 328 } 329 key_free(k); 330 fprintf(stdout, "\n"); 331 fclose(fp); 332 exit(0); 333 } 334 335 void 336 do_print_public(struct passwd *pw) 337 { 338 Key *prv; 339 struct stat st; 340 341 if (!have_identity) 342 ask_filename(pw, "Enter file in which the key is"); 343 if (stat(identity_file, &st) < 0) { 344 perror(identity_file); 345 exit(1); 346 } 347 prv = try_load_pem_key(identity_file); 348 if (prv == NULL) { 349 fprintf(stderr, "load failed\n"); 350 exit(1); 351 } 352 if (!key_write(prv, stdout)) 353 fprintf(stderr, "key_write failed"); 354 key_free(prv); 355 fprintf(stdout, "\n"); 356 exit(0); 357 } 358 359 void 360 do_fingerprint(struct passwd *pw) 361 { 362 FILE *f; 363 Key *public; 364 char *comment = NULL, *cp, *ep, line[16*1024], *fp; 365 int i, skip = 0, num = 1, invalid = 1, rep, fptype; 366 struct stat st; 367 368 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 369 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 370 371 if (!have_identity) 372 ask_filename(pw, "Enter file in which the key is"); 373 if (stat(identity_file, &st) < 0) { 374 perror(identity_file); 375 exit(1); 376 } 377 public = key_load_public(identity_file, &comment); 378 if (public != NULL) { 379 fp = key_fingerprint(public, fptype, rep); 380 printf("%d %s %s\n", key_size(public), fp, comment); 381 key_free(public); 382 xfree(comment); 383 xfree(fp); 384 exit(0); 385 } 386 if (comment) 387 xfree(comment); 388 389 f = fopen(identity_file, "r"); 390 if (f != NULL) { 391 while (fgets(line, sizeof(line), f)) { 392 i = strlen(line) - 1; 393 if (line[i] != '\n') { 394 error("line %d too long: %.40s...", num, line); 395 skip = 1; 396 continue; 397 } 398 num++; 399 if (skip) { 400 skip = 0; 401 continue; 402 } 403 line[i] = '\0'; 404 405 /* Skip leading whitespace, empty and comment lines. */ 406 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 407 ; 408 if (!*cp || *cp == '\n' || *cp == '#') 409 continue ; 410 i = strtol(cp, &ep, 10); 411 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { 412 int quoted = 0; 413 comment = cp; 414 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 415 if (*cp == '\\' && cp[1] == '"') 416 cp++; /* Skip both */ 417 else if (*cp == '"') 418 quoted = !quoted; 419 } 420 if (!*cp) 421 continue; 422 *cp++ = '\0'; 423 } 424 ep = cp; 425 public = key_new(KEY_RSA1); 426 if (key_read(public, &cp) != 1) { 427 cp = ep; 428 key_free(public); 429 public = key_new(KEY_UNSPEC); 430 if (key_read(public, &cp) != 1) { 431 key_free(public); 432 continue; 433 } 434 } 435 comment = *cp ? cp : comment; 436 fp = key_fingerprint(public, fptype, rep); 437 printf("%d %s %s\n", key_size(public), fp, 438 comment ? comment : "no comment"); 439 xfree(fp); 440 key_free(public); 441 invalid = 0; 442 } 443 fclose(f); 444 } 445 if (invalid) { 446 printf("%s is not a valid key file.\n", identity_file); 447 exit(1); 448 } 449 exit(0); 450 } 451 452 /* 453 * Perform changing a passphrase. The argument is the passwd structure 454 * for the current user. 455 */ 456 void 457 do_change_passphrase(struct passwd *pw) 458 { 459 char *comment; 460 char *old_passphrase, *passphrase1, *passphrase2; 461 struct stat st; 462 Key *private; 463 464 if (!have_identity) 465 ask_filename(pw, "Enter file in which the key is"); 466 if (stat(identity_file, &st) < 0) { 467 perror(identity_file); 468 exit(1); 469 } 470 /* Try to load the file with empty passphrase. */ 471 private = key_load_private(identity_file, "", &comment); 472 if (private == NULL) { 473 if (identity_passphrase) 474 old_passphrase = xstrdup(identity_passphrase); 475 else 476 old_passphrase = read_passphrase("Enter old passphrase: ", 1); 477 private = key_load_private(identity_file, old_passphrase , &comment); 478 memset(old_passphrase, 0, strlen(old_passphrase)); 479 xfree(old_passphrase); 480 if (private == NULL) { 481 printf("Bad passphrase.\n"); 482 exit(1); 483 } 484 } 485 printf("Key has comment '%s'\n", comment); 486 487 /* Ask the new passphrase (twice). */ 488 if (identity_new_passphrase) { 489 passphrase1 = xstrdup(identity_new_passphrase); 490 passphrase2 = NULL; 491 } else { 492 passphrase1 = 493 read_passphrase("Enter new passphrase (empty for no passphrase): ", 1); 494 passphrase2 = read_passphrase("Enter same passphrase again: ", 1); 495 496 /* Verify that they are the same. */ 497 if (strcmp(passphrase1, passphrase2) != 0) { 498 memset(passphrase1, 0, strlen(passphrase1)); 499 memset(passphrase2, 0, strlen(passphrase2)); 500 xfree(passphrase1); 501 xfree(passphrase2); 502 printf("Pass phrases do not match. Try again.\n"); 503 exit(1); 504 } 505 /* Destroy the other copy. */ 506 memset(passphrase2, 0, strlen(passphrase2)); 507 xfree(passphrase2); 508 } 509 510 /* Save the file using the new passphrase. */ 511 if (!key_save_private(private, identity_file, passphrase1, comment)) { 512 printf("Saving the key failed: %s.\n", identity_file); 513 memset(passphrase1, 0, strlen(passphrase1)); 514 xfree(passphrase1); 515 key_free(private); 516 xfree(comment); 517 exit(1); 518 } 519 /* Destroy the passphrase and the copy of the key in memory. */ 520 memset(passphrase1, 0, strlen(passphrase1)); 521 xfree(passphrase1); 522 key_free(private); /* Destroys contents */ 523 xfree(comment); 524 525 printf("Your identification has been saved with the new passphrase.\n"); 526 exit(0); 527 } 528 529 /* 530 * Change the comment of a private key file. 531 */ 532 void 533 do_change_comment(struct passwd *pw) 534 { 535 char new_comment[1024], *comment, *passphrase; 536 Key *private; 537 Key *public; 538 struct stat st; 539 FILE *f; 540 int fd; 541 542 if (!have_identity) 543 ask_filename(pw, "Enter file in which the key is"); 544 if (stat(identity_file, &st) < 0) { 545 perror(identity_file); 546 exit(1); 547 } 548 private = key_load_private(identity_file, "", &comment); 549 if (private == NULL) { 550 if (identity_passphrase) 551 passphrase = xstrdup(identity_passphrase); 552 else if (identity_new_passphrase) 553 passphrase = xstrdup(identity_new_passphrase); 554 else 555 passphrase = read_passphrase("Enter passphrase: ", 1); 556 /* Try to load using the passphrase. */ 557 private = key_load_private(identity_file, passphrase, &comment); 558 if (private == NULL) { 559 memset(passphrase, 0, strlen(passphrase)); 560 xfree(passphrase); 561 printf("Bad passphrase.\n"); 562 exit(1); 563 } 564 } else { 565 passphrase = xstrdup(""); 566 } 567 if (private->type != KEY_RSA1) { 568 fprintf(stderr, "Comments are only supported for RSA1 keys.\n"); 569 key_free(private); 570 exit(1); 571 } 572 printf("Key now has comment '%s'\n", comment); 573 574 if (identity_comment) { 575 strlcpy(new_comment, identity_comment, sizeof(new_comment)); 576 } else { 577 printf("Enter new comment: "); 578 fflush(stdout); 579 if (!fgets(new_comment, sizeof(new_comment), stdin)) { 580 memset(passphrase, 0, strlen(passphrase)); 581 key_free(private); 582 exit(1); 583 } 584 if (strchr(new_comment, '\n')) 585 *strchr(new_comment, '\n') = 0; 586 } 587 588 /* Save the file using the new passphrase. */ 589 if (!key_save_private(private, identity_file, passphrase, new_comment)) { 590 printf("Saving the key failed: %s.\n", identity_file); 591 memset(passphrase, 0, strlen(passphrase)); 592 xfree(passphrase); 593 key_free(private); 594 xfree(comment); 595 exit(1); 596 } 597 memset(passphrase, 0, strlen(passphrase)); 598 xfree(passphrase); 599 public = key_from_private(private); 600 key_free(private); 601 602 strlcat(identity_file, ".pub", sizeof(identity_file)); 603 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 604 if (fd == -1) { 605 printf("Could not save your public key in %s\n", identity_file); 606 exit(1); 607 } 608 f = fdopen(fd, "w"); 609 if (f == NULL) { 610 printf("fdopen %s failed", identity_file); 611 exit(1); 612 } 613 if (!key_write(public, f)) 614 fprintf(stderr, "write key failed"); 615 key_free(public); 616 fprintf(f, " %s\n", new_comment); 617 fclose(f); 618 619 xfree(comment); 620 621 printf("The comment in your key file has been changed.\n"); 622 exit(0); 623 } 624 625 void 626 usage(void) 627 { 628 printf("Usage: %s [-ceilpqyB] [-t type] [-b bits] [-f file] [-C comment] " 629 "[-N new-pass] [-P pass]\n", __progname); 630 exit(1); 631 } 632 633 /* 634 * Main program for key management. 635 */ 636 int 637 main(int ac, char **av) 638 { 639 char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2; 640 Key *private, *public; 641 struct passwd *pw; 642 int opt, type, fd; 643 struct stat st; 644 FILE *f; 645 646 extern int optind; 647 extern char *optarg; 648 649 SSLeay_add_all_algorithms(); 650 651 /* we need this for the home * directory. */ 652 pw = getpwuid(getuid()); 653 if (!pw) { 654 printf("You don't exist, go away!\n"); 655 exit(1); 656 } 657 if (gethostname(hostname, sizeof(hostname)) < 0) { 658 perror("gethostname"); 659 exit(1); 660 } 661 662 while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:P:N:C:")) != -1) { 663 switch (opt) { 664 case 'b': 665 bits = atoi(optarg); 666 if (bits < 512 || bits > 32768) { 667 printf("Bits has bad value.\n"); 668 exit(1); 669 } 670 break; 671 672 case 'l': 673 print_fingerprint = 1; 674 break; 675 676 case 'B': 677 print_bubblebabble = 1; 678 break; 679 680 case 'p': 681 change_passphrase = 1; 682 break; 683 684 case 'c': 685 change_comment = 1; 686 break; 687 688 case 'f': 689 strlcpy(identity_file, optarg, sizeof(identity_file)); 690 have_identity = 1; 691 break; 692 693 case 'P': 694 identity_passphrase = optarg; 695 break; 696 697 case 'N': 698 identity_new_passphrase = optarg; 699 break; 700 701 case 'C': 702 identity_comment = optarg; 703 break; 704 705 case 'q': 706 quiet = 1; 707 break; 708 709 case 'R': 710 /* unused */ 711 exit(0); 712 break; 713 714 case 'e': 715 case 'x': 716 /* export key */ 717 convert_to_ssh2 = 1; 718 break; 719 720 case 'i': 721 case 'X': 722 /* import key */ 723 convert_from_ssh2 = 1; 724 break; 725 726 case 'y': 727 print_public = 1; 728 break; 729 730 case 'd': 731 key_type_name = "dsa"; 732 break; 733 734 case 't': 735 key_type_name = optarg; 736 break; 737 738 case '?': 739 default: 740 usage(); 741 } 742 } 743 if (optind < ac) { 744 printf("Too many arguments.\n"); 745 usage(); 746 } 747 if (change_passphrase && change_comment) { 748 printf("Can only have one of -p and -c.\n"); 749 usage(); 750 } 751 if (print_fingerprint || print_bubblebabble) 752 do_fingerprint(pw); 753 if (change_passphrase) 754 do_change_passphrase(pw); 755 if (change_comment) 756 do_change_comment(pw); 757 if (convert_to_ssh2) 758 do_convert_to_ssh2(pw); 759 if (convert_from_ssh2) 760 do_convert_from_ssh2(pw); 761 if (print_public) 762 do_print_public(pw); 763 764 arc4random_stir(); 765 766 type = key_type_from_name(key_type_name); 767 if (type == KEY_UNSPEC) { 768 fprintf(stderr, "unknown key type %s\n", key_type_name); 769 exit(1); 770 } 771 if (!quiet) 772 printf("Generating public/private %s key pair.\n", key_type_name); 773 private = key_generate(type, bits); 774 if (private == NULL) { 775 fprintf(stderr, "key_generate failed"); 776 exit(1); 777 } 778 public = key_from_private(private); 779 780 if (!have_identity) 781 ask_filename(pw, "Enter file in which to save the key"); 782 783 /* Create ~/.ssh directory if it doesn\'t already exist. */ 784 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); 785 if (strstr(identity_file, dotsshdir) != NULL && 786 stat(dotsshdir, &st) < 0) { 787 if (mkdir(dotsshdir, 0700) < 0) 788 error("Could not create directory '%s'.", dotsshdir); 789 else if (!quiet) 790 printf("Created directory '%s'.\n", dotsshdir); 791 } 792 /* If the file already exists, ask the user to confirm. */ 793 if (stat(identity_file, &st) >= 0) { 794 char yesno[3]; 795 printf("%s already exists.\n", identity_file); 796 printf("Overwrite (y/n)? "); 797 fflush(stdout); 798 if (fgets(yesno, sizeof(yesno), stdin) == NULL) 799 exit(1); 800 if (yesno[0] != 'y' && yesno[0] != 'Y') 801 exit(1); 802 } 803 /* Ask for a passphrase (twice). */ 804 if (identity_passphrase) 805 passphrase1 = xstrdup(identity_passphrase); 806 else if (identity_new_passphrase) 807 passphrase1 = xstrdup(identity_new_passphrase); 808 else { 809 passphrase_again: 810 passphrase1 = 811 read_passphrase("Enter passphrase (empty for no passphrase): ", 1); 812 passphrase2 = read_passphrase("Enter same passphrase again: ", 1); 813 if (strcmp(passphrase1, passphrase2) != 0) { 814 /* The passphrases do not match. Clear them and retry. */ 815 memset(passphrase1, 0, strlen(passphrase1)); 816 memset(passphrase2, 0, strlen(passphrase2)); 817 xfree(passphrase1); 818 xfree(passphrase2); 819 printf("Passphrases do not match. Try again.\n"); 820 goto passphrase_again; 821 } 822 /* Clear the other copy of the passphrase. */ 823 memset(passphrase2, 0, strlen(passphrase2)); 824 xfree(passphrase2); 825 } 826 827 if (identity_comment) { 828 strlcpy(comment, identity_comment, sizeof(comment)); 829 } else { 830 /* Create default commend field for the passphrase. */ 831 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); 832 } 833 834 /* Save the key with the given passphrase and comment. */ 835 if (!key_save_private(private, identity_file, passphrase1, comment)) { 836 printf("Saving the key failed: %s.\n", identity_file); 837 memset(passphrase1, 0, strlen(passphrase1)); 838 xfree(passphrase1); 839 exit(1); 840 } 841 /* Clear the passphrase. */ 842 memset(passphrase1, 0, strlen(passphrase1)); 843 xfree(passphrase1); 844 845 /* Clear the private key and the random number generator. */ 846 key_free(private); 847 arc4random_stir(); 848 849 if (!quiet) 850 printf("Your identification has been saved in %s.\n", identity_file); 851 852 strlcat(identity_file, ".pub", sizeof(identity_file)); 853 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 854 if (fd == -1) { 855 printf("Could not save your public key in %s\n", identity_file); 856 exit(1); 857 } 858 f = fdopen(fd, "w"); 859 if (f == NULL) { 860 printf("fdopen %s failed", identity_file); 861 exit(1); 862 } 863 if (!key_write(public, f)) 864 fprintf(stderr, "write key failed"); 865 fprintf(f, " %s\n", comment); 866 fclose(f); 867 868 if (!quiet) { 869 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); 870 printf("Your public key has been saved in %s.\n", 871 identity_file); 872 printf("The key fingerprint is:\n"); 873 printf("%s %s\n", fp, comment); 874 xfree(fp); 875 } 876 877 key_free(public); 878 exit(0); 879 } 880