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.89 2001/12/29 21:56:01 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, (u_char *)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 fprintf(stdout, "\n"); 354 fclose(fp); 355 exit(0); 356 } 357 358 static void 359 do_print_public(struct passwd *pw) 360 { 361 Key *prv; 362 struct stat st; 363 364 if (!have_identity) 365 ask_filename(pw, "Enter file in which the key is"); 366 if (stat(identity_file, &st) < 0) { 367 perror(identity_file); 368 exit(1); 369 } 370 prv = load_identity(identity_file); 371 if (prv == NULL) { 372 fprintf(stderr, "load failed\n"); 373 exit(1); 374 } 375 if (!key_write(prv, stdout)) 376 fprintf(stderr, "key_write failed"); 377 key_free(prv); 378 fprintf(stdout, "\n"); 379 exit(0); 380 } 381 382 #ifdef SMARTCARD 383 #define NUM_RSA_KEY_ELEMENTS 5+1 384 #define COPY_RSA_KEY(x, i) \ 385 do { \ 386 len = BN_num_bytes(prv->rsa->x); \ 387 elements[i] = xmalloc(len); \ 388 debug("#bytes %d", len); \ 389 if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \ 390 goto done; \ 391 } while (0) 392 393 static int 394 get_AUT0(char *aut0) 395 { 396 EVP_MD *evp_md = EVP_sha1(); 397 EVP_MD_CTX md; 398 char *pass; 399 400 pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN); 401 if (pass == NULL) 402 return -1; 403 EVP_DigestInit(&md, evp_md); 404 EVP_DigestUpdate(&md, pass, strlen(pass)); 405 EVP_DigestFinal(&md, aut0, NULL); 406 memset(pass, 0, strlen(pass)); 407 xfree(pass); 408 return 0; 409 } 410 411 static void 412 do_upload(struct passwd *pw, const char *sc_reader_id) 413 { 414 Key *prv = NULL; 415 struct stat st; 416 u_char *elements[NUM_RSA_KEY_ELEMENTS]; 417 u_char key_fid[2]; 418 u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63}; 419 u_char AUT0[EVP_MAX_MD_SIZE]; 420 int len, status = 1, i, fd = -1, ret; 421 int sw = 0, cla = 0x00; 422 423 for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) 424 elements[i] = NULL; 425 if (!have_identity) 426 ask_filename(pw, "Enter file in which the key is"); 427 if (stat(identity_file, &st) < 0) { 428 perror(identity_file); 429 goto done; 430 } 431 prv = load_identity(identity_file); 432 if (prv == NULL) { 433 error("load failed"); 434 goto done; 435 } 436 COPY_RSA_KEY(q, 0); 437 COPY_RSA_KEY(p, 1); 438 COPY_RSA_KEY(iqmp, 2); 439 COPY_RSA_KEY(dmq1, 3); 440 COPY_RSA_KEY(dmp1, 4); 441 COPY_RSA_KEY(n, 5); 442 len = BN_num_bytes(prv->rsa->n); 443 fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw); 444 if (fd < 0) { 445 error("sectok_open failed: %s", sectok_get_sw(sw)); 446 goto done; 447 } 448 if (! sectok_cardpresent(fd)) { 449 error("smartcard in reader %s not present", 450 sc_reader_id); 451 goto done; 452 } 453 ret = sectok_reset(fd, 0, NULL, &sw); 454 if (ret <= 0) { 455 error("sectok_reset failed: %s", sectok_get_sw(sw)); 456 goto done; 457 } 458 if ((cla = cyberflex_inq_class(fd)) < 0) { 459 error("cyberflex_inq_class failed"); 460 goto done; 461 } 462 memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0)); 463 if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { 464 if (get_AUT0(AUT0) < 0 || 465 cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { 466 error("cyberflex_verify_AUT0 failed"); 467 goto done; 468 } 469 } 470 key_fid[0] = 0x00; 471 key_fid[1] = 0x12; 472 if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements, 473 &sw) < 0) { 474 error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw)); 475 goto done; 476 } 477 if (!sectok_swOK(sw)) 478 goto done; 479 log("cyberflex_load_rsa_priv done"); 480 key_fid[0] = 0x73; 481 key_fid[1] = 0x68; 482 if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5], 483 &sw) < 0) { 484 error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw)); 485 goto done; 486 } 487 if (!sectok_swOK(sw)) 488 goto done; 489 log("cyberflex_load_rsa_pub done"); 490 status = 0; 491 log("loading key done"); 492 done: 493 494 memset(elements[0], '\0', BN_num_bytes(prv->rsa->q)); 495 memset(elements[1], '\0', BN_num_bytes(prv->rsa->p)); 496 memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp)); 497 memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1)); 498 memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1)); 499 memset(elements[5], '\0', BN_num_bytes(prv->rsa->n)); 500 501 if (prv) 502 key_free(prv); 503 for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) 504 if (elements[i]) 505 xfree(elements[i]); 506 if (fd != -1) 507 sectok_close(fd); 508 exit(status); 509 } 510 511 static void 512 do_download(struct passwd *pw, const char *sc_reader_id) 513 { 514 Key *pub = NULL; 515 516 pub = sc_get_key(sc_reader_id); 517 if (pub == NULL) 518 fatal("cannot read public key from smartcard"); 519 key_write(pub, stdout); 520 key_free(pub); 521 fprintf(stdout, "\n"); 522 exit(0); 523 } 524 #endif /* SMARTCARD */ 525 526 static void 527 do_fingerprint(struct passwd *pw) 528 { 529 FILE *f; 530 Key *public; 531 char *comment = NULL, *cp, *ep, line[16*1024], *fp; 532 int i, skip = 0, num = 1, invalid = 1; 533 enum fp_rep rep; 534 enum fp_type fptype; 535 struct stat st; 536 537 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; 538 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; 539 540 if (!have_identity) 541 ask_filename(pw, "Enter file in which the key is"); 542 if (stat(identity_file, &st) < 0) { 543 perror(identity_file); 544 exit(1); 545 } 546 public = key_load_public(identity_file, &comment); 547 if (public != NULL) { 548 fp = key_fingerprint(public, fptype, rep); 549 printf("%d %s %s\n", key_size(public), fp, comment); 550 key_free(public); 551 xfree(comment); 552 xfree(fp); 553 exit(0); 554 } 555 if (comment) 556 xfree(comment); 557 558 f = fopen(identity_file, "r"); 559 if (f != NULL) { 560 while (fgets(line, sizeof(line), f)) { 561 i = strlen(line) - 1; 562 if (line[i] != '\n') { 563 error("line %d too long: %.40s...", num, line); 564 skip = 1; 565 continue; 566 } 567 num++; 568 if (skip) { 569 skip = 0; 570 continue; 571 } 572 line[i] = '\0'; 573 574 /* Skip leading whitespace, empty and comment lines. */ 575 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 576 ; 577 if (!*cp || *cp == '\n' || *cp == '#') 578 continue ; 579 i = strtol(cp, &ep, 10); 580 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { 581 int quoted = 0; 582 comment = cp; 583 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 584 if (*cp == '\\' && cp[1] == '"') 585 cp++; /* Skip both */ 586 else if (*cp == '"') 587 quoted = !quoted; 588 } 589 if (!*cp) 590 continue; 591 *cp++ = '\0'; 592 } 593 ep = cp; 594 public = key_new(KEY_RSA1); 595 if (key_read(public, &cp) != 1) { 596 cp = ep; 597 key_free(public); 598 public = key_new(KEY_UNSPEC); 599 if (key_read(public, &cp) != 1) { 600 key_free(public); 601 continue; 602 } 603 } 604 comment = *cp ? cp : comment; 605 fp = key_fingerprint(public, fptype, rep); 606 printf("%d %s %s\n", key_size(public), fp, 607 comment ? comment : "no comment"); 608 xfree(fp); 609 key_free(public); 610 invalid = 0; 611 } 612 fclose(f); 613 } 614 if (invalid) { 615 printf("%s is not a public key file.\n", identity_file); 616 exit(1); 617 } 618 exit(0); 619 } 620 621 /* 622 * Perform changing a passphrase. The argument is the passwd structure 623 * for the current user. 624 */ 625 static void 626 do_change_passphrase(struct passwd *pw) 627 { 628 char *comment; 629 char *old_passphrase, *passphrase1, *passphrase2; 630 struct stat st; 631 Key *private; 632 633 if (!have_identity) 634 ask_filename(pw, "Enter file in which the key is"); 635 if (stat(identity_file, &st) < 0) { 636 perror(identity_file); 637 exit(1); 638 } 639 /* Try to load the file with empty passphrase. */ 640 private = key_load_private(identity_file, "", &comment); 641 if (private == NULL) { 642 if (identity_passphrase) 643 old_passphrase = xstrdup(identity_passphrase); 644 else 645 old_passphrase = 646 read_passphrase("Enter old passphrase: ", 647 RP_ALLOW_STDIN); 648 private = key_load_private(identity_file, old_passphrase, 649 &comment); 650 memset(old_passphrase, 0, strlen(old_passphrase)); 651 xfree(old_passphrase); 652 if (private == NULL) { 653 printf("Bad passphrase.\n"); 654 exit(1); 655 } 656 } 657 printf("Key has comment '%s'\n", comment); 658 659 /* Ask the new passphrase (twice). */ 660 if (identity_new_passphrase) { 661 passphrase1 = xstrdup(identity_new_passphrase); 662 passphrase2 = NULL; 663 } else { 664 passphrase1 = 665 read_passphrase("Enter new passphrase (empty for no " 666 "passphrase): ", RP_ALLOW_STDIN); 667 passphrase2 = read_passphrase("Enter same passphrase again: ", 668 RP_ALLOW_STDIN); 669 670 /* Verify that they are the same. */ 671 if (strcmp(passphrase1, passphrase2) != 0) { 672 memset(passphrase1, 0, strlen(passphrase1)); 673 memset(passphrase2, 0, strlen(passphrase2)); 674 xfree(passphrase1); 675 xfree(passphrase2); 676 printf("Pass phrases do not match. Try again.\n"); 677 exit(1); 678 } 679 /* Destroy the other copy. */ 680 memset(passphrase2, 0, strlen(passphrase2)); 681 xfree(passphrase2); 682 } 683 684 /* Save the file using the new passphrase. */ 685 if (!key_save_private(private, identity_file, passphrase1, comment)) { 686 printf("Saving the key failed: %s.\n", identity_file); 687 memset(passphrase1, 0, strlen(passphrase1)); 688 xfree(passphrase1); 689 key_free(private); 690 xfree(comment); 691 exit(1); 692 } 693 /* Destroy the passphrase and the copy of the key in memory. */ 694 memset(passphrase1, 0, strlen(passphrase1)); 695 xfree(passphrase1); 696 key_free(private); /* Destroys contents */ 697 xfree(comment); 698 699 printf("Your identification has been saved with the new passphrase.\n"); 700 exit(0); 701 } 702 703 /* 704 * Change the comment of a private key file. 705 */ 706 static void 707 do_change_comment(struct passwd *pw) 708 { 709 char new_comment[1024], *comment, *passphrase; 710 Key *private; 711 Key *public; 712 struct stat st; 713 FILE *f; 714 int fd; 715 716 if (!have_identity) 717 ask_filename(pw, "Enter file in which the key is"); 718 if (stat(identity_file, &st) < 0) { 719 perror(identity_file); 720 exit(1); 721 } 722 private = key_load_private(identity_file, "", &comment); 723 if (private == NULL) { 724 if (identity_passphrase) 725 passphrase = xstrdup(identity_passphrase); 726 else if (identity_new_passphrase) 727 passphrase = xstrdup(identity_new_passphrase); 728 else 729 passphrase = read_passphrase("Enter passphrase: ", 730 RP_ALLOW_STDIN); 731 /* Try to load using the passphrase. */ 732 private = key_load_private(identity_file, passphrase, &comment); 733 if (private == NULL) { 734 memset(passphrase, 0, strlen(passphrase)); 735 xfree(passphrase); 736 printf("Bad passphrase.\n"); 737 exit(1); 738 } 739 } else { 740 passphrase = xstrdup(""); 741 } 742 if (private->type != KEY_RSA1) { 743 fprintf(stderr, "Comments are only supported for RSA1 keys.\n"); 744 key_free(private); 745 exit(1); 746 } 747 printf("Key now has comment '%s'\n", comment); 748 749 if (identity_comment) { 750 strlcpy(new_comment, identity_comment, sizeof(new_comment)); 751 } else { 752 printf("Enter new comment: "); 753 fflush(stdout); 754 if (!fgets(new_comment, sizeof(new_comment), stdin)) { 755 memset(passphrase, 0, strlen(passphrase)); 756 key_free(private); 757 exit(1); 758 } 759 if (strchr(new_comment, '\n')) 760 *strchr(new_comment, '\n') = 0; 761 } 762 763 /* Save the file using the new passphrase. */ 764 if (!key_save_private(private, identity_file, passphrase, new_comment)) { 765 printf("Saving the key failed: %s.\n", identity_file); 766 memset(passphrase, 0, strlen(passphrase)); 767 xfree(passphrase); 768 key_free(private); 769 xfree(comment); 770 exit(1); 771 } 772 memset(passphrase, 0, strlen(passphrase)); 773 xfree(passphrase); 774 public = key_from_private(private); 775 key_free(private); 776 777 strlcat(identity_file, ".pub", sizeof(identity_file)); 778 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 779 if (fd == -1) { 780 printf("Could not save your public key in %s\n", identity_file); 781 exit(1); 782 } 783 f = fdopen(fd, "w"); 784 if (f == NULL) { 785 printf("fdopen %s failed", identity_file); 786 exit(1); 787 } 788 if (!key_write(public, f)) 789 fprintf(stderr, "write key failed"); 790 key_free(public); 791 fprintf(f, " %s\n", new_comment); 792 fclose(f); 793 794 xfree(comment); 795 796 printf("The comment in your key file has been changed.\n"); 797 exit(0); 798 } 799 800 static void 801 usage(void) 802 { 803 fprintf(stderr, "Usage: %s [options]\n", __progname); 804 fprintf(stderr, "Options:\n"); 805 fprintf(stderr, " -b bits Number of bits in the key to create.\n"); 806 fprintf(stderr, " -c Change comment in private and public key files.\n"); 807 fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); 808 fprintf(stderr, " -f filename Filename of the key file.\n"); 809 fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); 810 fprintf(stderr, " -l Show fingerprint of key file.\n"); 811 fprintf(stderr, " -p Change passphrase of private key file.\n"); 812 fprintf(stderr, " -q Quiet.\n"); 813 fprintf(stderr, " -y Read private key file and print public key.\n"); 814 fprintf(stderr, " -t type Specify type of key to create.\n"); 815 fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); 816 fprintf(stderr, " -C comment Provide new comment.\n"); 817 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 818 fprintf(stderr, " -P phrase Provide old passphrase.\n"); 819 #ifdef SMARTCARD 820 fprintf(stderr, " -D reader Download public key from smartcard.\n"); 821 fprintf(stderr, " -U reader Upload private key to smartcard.\n"); 822 #endif /* SMARTCARD */ 823 824 exit(1); 825 } 826 827 /* 828 * Main program for key management. 829 */ 830 int 831 main(int ac, char **av) 832 { 833 char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; 834 char *reader_id = NULL; 835 Key *private, *public; 836 struct passwd *pw; 837 struct stat st; 838 int opt, type, fd, download = 0; 839 FILE *f; 840 841 extern int optind; 842 extern char *optarg; 843 844 SSLeay_add_all_algorithms(); 845 846 /* we need this for the home * directory. */ 847 pw = getpwuid(getuid()); 848 if (!pw) { 849 printf("You don't exist, go away!\n"); 850 exit(1); 851 } 852 if (gethostname(hostname, sizeof(hostname)) < 0) { 853 perror("gethostname"); 854 exit(1); 855 } 856 857 while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) { 858 switch (opt) { 859 case 'b': 860 bits = atoi(optarg); 861 if (bits < 512 || bits > 32768) { 862 printf("Bits has bad value.\n"); 863 exit(1); 864 } 865 break; 866 case 'l': 867 print_fingerprint = 1; 868 break; 869 case 'B': 870 print_bubblebabble = 1; 871 break; 872 case 'p': 873 change_passphrase = 1; 874 break; 875 case 'c': 876 change_comment = 1; 877 break; 878 case 'f': 879 strlcpy(identity_file, optarg, sizeof(identity_file)); 880 have_identity = 1; 881 break; 882 case 'P': 883 identity_passphrase = optarg; 884 break; 885 case 'N': 886 identity_new_passphrase = optarg; 887 break; 888 case 'C': 889 identity_comment = optarg; 890 break; 891 case 'q': 892 quiet = 1; 893 break; 894 case 'R': 895 /* unused */ 896 exit(0); 897 break; 898 case 'e': 899 case 'x': 900 /* export key */ 901 convert_to_ssh2 = 1; 902 break; 903 case 'i': 904 case 'X': 905 /* import key */ 906 convert_from_ssh2 = 1; 907 break; 908 case 'y': 909 print_public = 1; 910 break; 911 case 'd': 912 key_type_name = "dsa"; 913 break; 914 case 't': 915 key_type_name = optarg; 916 break; 917 case 'D': 918 download = 1; 919 case 'U': 920 reader_id = optarg; 921 break; 922 case '?': 923 default: 924 usage(); 925 } 926 } 927 if (optind < ac) { 928 printf("Too many arguments.\n"); 929 usage(); 930 } 931 if (change_passphrase && change_comment) { 932 printf("Can only have one of -p and -c.\n"); 933 usage(); 934 } 935 if (print_fingerprint || print_bubblebabble) 936 do_fingerprint(pw); 937 if (change_passphrase) 938 do_change_passphrase(pw); 939 if (change_comment) 940 do_change_comment(pw); 941 if (convert_to_ssh2) 942 do_convert_to_ssh2(pw); 943 if (convert_from_ssh2) 944 do_convert_from_ssh2(pw); 945 if (print_public) 946 do_print_public(pw); 947 if (reader_id != NULL) { 948 #ifdef SMARTCARD 949 if (download) 950 do_download(pw, reader_id); 951 else 952 do_upload(pw, reader_id); 953 #else /* SMARTCARD */ 954 fatal("no support for smartcards."); 955 #endif /* SMARTCARD */ 956 } 957 958 arc4random_stir(); 959 960 if (key_type_name == NULL) { 961 printf("You must specify a key type (-t).\n"); 962 usage(); 963 } 964 type = key_type_from_name(key_type_name); 965 if (type == KEY_UNSPEC) { 966 fprintf(stderr, "unknown key type %s\n", key_type_name); 967 exit(1); 968 } 969 if (!quiet) 970 printf("Generating public/private %s key pair.\n", key_type_name); 971 private = key_generate(type, bits); 972 if (private == NULL) { 973 fprintf(stderr, "key_generate failed"); 974 exit(1); 975 } 976 public = key_from_private(private); 977 978 if (!have_identity) 979 ask_filename(pw, "Enter file in which to save the key"); 980 981 /* Create ~/.ssh directory if it doesn\'t already exist. */ 982 snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); 983 if (strstr(identity_file, dotsshdir) != NULL && 984 stat(dotsshdir, &st) < 0) { 985 if (mkdir(dotsshdir, 0700) < 0) 986 error("Could not create directory '%s'.", dotsshdir); 987 else if (!quiet) 988 printf("Created directory '%s'.\n", dotsshdir); 989 } 990 /* If the file already exists, ask the user to confirm. */ 991 if (stat(identity_file, &st) >= 0) { 992 char yesno[3]; 993 printf("%s already exists.\n", identity_file); 994 printf("Overwrite (y/n)? "); 995 fflush(stdout); 996 if (fgets(yesno, sizeof(yesno), stdin) == NULL) 997 exit(1); 998 if (yesno[0] != 'y' && yesno[0] != 'Y') 999 exit(1); 1000 } 1001 /* Ask for a passphrase (twice). */ 1002 if (identity_passphrase) 1003 passphrase1 = xstrdup(identity_passphrase); 1004 else if (identity_new_passphrase) 1005 passphrase1 = xstrdup(identity_new_passphrase); 1006 else { 1007 passphrase_again: 1008 passphrase1 = 1009 read_passphrase("Enter passphrase (empty for no " 1010 "passphrase): ", RP_ALLOW_STDIN); 1011 passphrase2 = read_passphrase("Enter same passphrase again: ", 1012 RP_ALLOW_STDIN); 1013 if (strcmp(passphrase1, passphrase2) != 0) { 1014 /* 1015 * The passphrases do not match. Clear them and 1016 * retry. 1017 */ 1018 memset(passphrase1, 0, strlen(passphrase1)); 1019 memset(passphrase2, 0, strlen(passphrase2)); 1020 xfree(passphrase1); 1021 xfree(passphrase2); 1022 printf("Passphrases do not match. Try again.\n"); 1023 goto passphrase_again; 1024 } 1025 /* Clear the other copy of the passphrase. */ 1026 memset(passphrase2, 0, strlen(passphrase2)); 1027 xfree(passphrase2); 1028 } 1029 1030 if (identity_comment) { 1031 strlcpy(comment, identity_comment, sizeof(comment)); 1032 } else { 1033 /* Create default commend field for the passphrase. */ 1034 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); 1035 } 1036 1037 /* Save the key with the given passphrase and comment. */ 1038 if (!key_save_private(private, identity_file, passphrase1, comment)) { 1039 printf("Saving the key failed: %s.\n", identity_file); 1040 memset(passphrase1, 0, strlen(passphrase1)); 1041 xfree(passphrase1); 1042 exit(1); 1043 } 1044 /* Clear the passphrase. */ 1045 memset(passphrase1, 0, strlen(passphrase1)); 1046 xfree(passphrase1); 1047 1048 /* Clear the private key and the random number generator. */ 1049 key_free(private); 1050 arc4random_stir(); 1051 1052 if (!quiet) 1053 printf("Your identification has been saved in %s.\n", identity_file); 1054 1055 strlcat(identity_file, ".pub", sizeof(identity_file)); 1056 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1057 if (fd == -1) { 1058 printf("Could not save your public key in %s\n", identity_file); 1059 exit(1); 1060 } 1061 f = fdopen(fd, "w"); 1062 if (f == NULL) { 1063 printf("fdopen %s failed", identity_file); 1064 exit(1); 1065 } 1066 if (!key_write(public, f)) 1067 fprintf(stderr, "write key failed"); 1068 fprintf(f, " %s\n", comment); 1069 fclose(f); 1070 1071 if (!quiet) { 1072 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); 1073 printf("Your public key has been saved in %s.\n", 1074 identity_file); 1075 printf("The key fingerprint is:\n"); 1076 printf("%s %s\n", fp, comment); 1077 xfree(fp); 1078 } 1079 1080 key_free(public); 1081 exit(0); 1082 } 1083