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