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