diff options
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 97 |
1 files changed, 66 insertions, 31 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index 04a9b939a..f7e284062 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.160 2007/01/21 01:41:54 stevesk Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.171 2008/07/13 21:22:52 sthen Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <openssl/evp.h> | 22 | #include <openssl/evp.h> |
23 | #include <openssl/pem.h> | 23 | #include <openssl/pem.h> |
24 | #include "openbsd-compat/openssl-compat.h" | ||
24 | 25 | ||
25 | #include <errno.h> | 26 | #include <errno.h> |
26 | #include <fcntl.h> | 27 | #include <fcntl.h> |
@@ -71,6 +72,8 @@ int change_comment = 0; | |||
71 | 72 | ||
72 | int quiet = 0; | 73 | int quiet = 0; |
73 | 74 | ||
75 | int log_level = SYSLOG_LEVEL_INFO; | ||
76 | |||
74 | /* Flag indicating that we want to hash a known_hosts file */ | 77 | /* Flag indicating that we want to hash a known_hosts file */ |
75 | int hash_hosts = 0; | 78 | int hash_hosts = 0; |
76 | /* Flag indicating that we want lookup a host in known_hosts file */ | 79 | /* Flag indicating that we want lookup a host in known_hosts file */ |
@@ -141,8 +144,7 @@ ask_filename(struct passwd *pw, const char *prompt) | |||
141 | fprintf(stderr, "%s (%s): ", prompt, identity_file); | 144 | fprintf(stderr, "%s (%s): ", prompt, identity_file); |
142 | if (fgets(buf, sizeof(buf), stdin) == NULL) | 145 | if (fgets(buf, sizeof(buf), stdin) == NULL) |
143 | exit(1); | 146 | exit(1); |
144 | if (strchr(buf, '\n')) | 147 | buf[strcspn(buf, "\n")] = '\0'; |
145 | *strchr(buf, '\n') = 0; | ||
146 | if (strcmp(buf, "") != 0) | 148 | if (strcmp(buf, "") != 0) |
147 | strlcpy(identity_file, buf, sizeof(identity_file)); | 149 | strlcpy(identity_file, buf, sizeof(identity_file)); |
148 | have_identity = 1; | 150 | have_identity = 1; |
@@ -504,8 +506,8 @@ do_fingerprint(struct passwd *pw) | |||
504 | { | 506 | { |
505 | FILE *f; | 507 | FILE *f; |
506 | Key *public; | 508 | Key *public; |
507 | char *comment = NULL, *cp, *ep, line[16*1024], *fp; | 509 | char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; |
508 | int i, skip = 0, num = 1, invalid = 1; | 510 | int i, skip = 0, num = 0, invalid = 1; |
509 | enum fp_rep rep; | 511 | enum fp_rep rep; |
510 | enum fp_type fptype; | 512 | enum fp_type fptype; |
511 | struct stat st; | 513 | struct stat st; |
@@ -522,9 +524,14 @@ do_fingerprint(struct passwd *pw) | |||
522 | public = key_load_public(identity_file, &comment); | 524 | public = key_load_public(identity_file, &comment); |
523 | if (public != NULL) { | 525 | if (public != NULL) { |
524 | fp = key_fingerprint(public, fptype, rep); | 526 | fp = key_fingerprint(public, fptype, rep); |
525 | printf("%u %s %s\n", key_size(public), fp, comment); | 527 | ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART); |
528 | printf("%u %s %s (%s)\n", key_size(public), fp, comment, | ||
529 | key_type(public)); | ||
530 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
531 | printf("%s\n", ra); | ||
526 | key_free(public); | 532 | key_free(public); |
527 | xfree(comment); | 533 | xfree(comment); |
534 | xfree(ra); | ||
528 | xfree(fp); | 535 | xfree(fp); |
529 | exit(0); | 536 | exit(0); |
530 | } | 537 | } |
@@ -536,9 +543,9 @@ do_fingerprint(struct passwd *pw) | |||
536 | f = fopen(identity_file, "r"); | 543 | f = fopen(identity_file, "r"); |
537 | if (f != NULL) { | 544 | if (f != NULL) { |
538 | while (fgets(line, sizeof(line), f)) { | 545 | while (fgets(line, sizeof(line), f)) { |
539 | i = strlen(line) - 1; | 546 | if ((cp = strchr(line, '\n')) == NULL) { |
540 | if (line[i] != '\n') { | 547 | error("line %d too long: %.40s...", |
541 | error("line %d too long: %.40s...", num, line); | 548 | num + 1, line); |
542 | skip = 1; | 549 | skip = 1; |
543 | continue; | 550 | continue; |
544 | } | 551 | } |
@@ -547,7 +554,7 @@ do_fingerprint(struct passwd *pw) | |||
547 | skip = 0; | 554 | skip = 0; |
548 | continue; | 555 | continue; |
549 | } | 556 | } |
550 | line[i] = '\0'; | 557 | *cp = '\0'; |
551 | 558 | ||
552 | /* Skip leading whitespace, empty and comment lines. */ | 559 | /* Skip leading whitespace, empty and comment lines. */ |
553 | for (cp = line; *cp == ' ' || *cp == '\t'; cp++) | 560 | for (cp = line; *cp == ' ' || *cp == '\t'; cp++) |
@@ -582,8 +589,12 @@ do_fingerprint(struct passwd *pw) | |||
582 | } | 589 | } |
583 | comment = *cp ? cp : comment; | 590 | comment = *cp ? cp : comment; |
584 | fp = key_fingerprint(public, fptype, rep); | 591 | fp = key_fingerprint(public, fptype, rep); |
585 | printf("%u %s %s\n", key_size(public), fp, | 592 | ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART); |
586 | comment ? comment : "no comment"); | 593 | printf("%u %s %s (%s)\n", key_size(public), fp, |
594 | comment ? comment : "no comment", key_type(public)); | ||
595 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
596 | printf("%s\n", ra); | ||
597 | xfree(ra); | ||
587 | xfree(fp); | 598 | xfree(fp); |
588 | key_free(public); | 599 | key_free(public); |
589 | invalid = 0; | 600 | invalid = 0; |
@@ -598,14 +609,31 @@ do_fingerprint(struct passwd *pw) | |||
598 | } | 609 | } |
599 | 610 | ||
600 | static void | 611 | static void |
601 | print_host(FILE *f, char *name, Key *public, int hash) | 612 | print_host(FILE *f, const char *name, Key *public, int hash) |
602 | { | 613 | { |
603 | if (hash && (name = host_hash(name, NULL, 0)) == NULL) | 614 | if (print_fingerprint) { |
604 | fatal("hash_host failed"); | 615 | enum fp_rep rep; |
605 | fprintf(f, "%s ", name); | 616 | enum fp_type fptype; |
606 | if (!key_write(public, f)) | 617 | char *fp, *ra; |
607 | fatal("key_write failed"); | 618 | |
608 | fprintf(f, "\n"); | 619 | fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; |
620 | rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; | ||
621 | fp = key_fingerprint(public, fptype, rep); | ||
622 | ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART); | ||
623 | printf("%u %s %s (%s)\n", key_size(public), fp, name, | ||
624 | key_type(public)); | ||
625 | if (log_level >= SYSLOG_LEVEL_VERBOSE) | ||
626 | printf("%s\n", ra); | ||
627 | xfree(ra); | ||
628 | xfree(fp); | ||
629 | } else { | ||
630 | if (hash && (name = host_hash(name, NULL, 0)) == NULL) | ||
631 | fatal("hash_host failed"); | ||
632 | fprintf(f, "%s ", name); | ||
633 | if (!key_write(public, f)) | ||
634 | fatal("key_write failed"); | ||
635 | fprintf(f, "\n"); | ||
636 | } | ||
609 | } | 637 | } |
610 | 638 | ||
611 | static void | 639 | static void |
@@ -615,7 +643,7 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
615 | Key *public; | 643 | Key *public; |
616 | char *cp, *cp2, *kp, *kp2; | 644 | char *cp, *cp2, *kp, *kp2; |
617 | char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; | 645 | char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; |
618 | int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; | 646 | int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; |
619 | 647 | ||
620 | if (!have_identity) { | 648 | if (!have_identity) { |
621 | cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); | 649 | cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); |
@@ -650,19 +678,18 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
650 | } | 678 | } |
651 | 679 | ||
652 | while (fgets(line, sizeof(line), in)) { | 680 | while (fgets(line, sizeof(line), in)) { |
653 | num++; | 681 | if ((cp = strchr(line, '\n')) == NULL) { |
654 | i = strlen(line) - 1; | 682 | error("line %d too long: %.40s...", num + 1, line); |
655 | if (line[i] != '\n') { | ||
656 | error("line %d too long: %.40s...", num, line); | ||
657 | skip = 1; | 683 | skip = 1; |
658 | invalid = 1; | 684 | invalid = 1; |
659 | continue; | 685 | continue; |
660 | } | 686 | } |
687 | num++; | ||
661 | if (skip) { | 688 | if (skip) { |
662 | skip = 0; | 689 | skip = 0; |
663 | continue; | 690 | continue; |
664 | } | 691 | } |
665 | line[i] = '\0'; | 692 | *cp = '\0'; |
666 | 693 | ||
667 | /* Skip leading whitespace, empty and comment lines. */ | 694 | /* Skip leading whitespace, empty and comment lines. */ |
668 | for (cp = line; *cp == ' ' || *cp == '\t'; cp++) | 695 | for (cp = line; *cp == ' ' || *cp == '\t'; cp++) |
@@ -726,7 +753,8 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
726 | printf("# Host %s found: " | 753 | printf("# Host %s found: " |
727 | "line %d type %s\n", name, | 754 | "line %d type %s\n", name, |
728 | num, key_type(public)); | 755 | num, key_type(public)); |
729 | print_host(out, cp, public, hash_hosts); | 756 | print_host(out, name, public, |
757 | hash_hosts); | ||
730 | } | 758 | } |
731 | if (delete_host && !c) | 759 | if (delete_host && !c) |
732 | print_host(out, cp, public, 0); | 760 | print_host(out, cp, public, 0); |
@@ -750,7 +778,7 @@ do_known_hosts(struct passwd *pw, const char *name) | |||
750 | fclose(in); | 778 | fclose(in); |
751 | 779 | ||
752 | if (invalid) { | 780 | if (invalid) { |
753 | fprintf(stderr, "%s is not a valid known_host file.\n", | 781 | fprintf(stderr, "%s is not a valid known_hosts file.\n", |
754 | identity_file); | 782 | identity_file); |
755 | if (inplace) { | 783 | if (inplace) { |
756 | fprintf(stderr, "Not replacing existing known_hosts " | 784 | fprintf(stderr, "Not replacing existing known_hosts " |
@@ -962,8 +990,7 @@ do_change_comment(struct passwd *pw) | |||
962 | key_free(private); | 990 | key_free(private); |
963 | exit(1); | 991 | exit(1); |
964 | } | 992 | } |
965 | if (strchr(new_comment, '\n')) | 993 | new_comment[strcspn(new_comment, "\n")] = '\0'; |
966 | *strchr(new_comment, '\n') = 0; | ||
967 | } | 994 | } |
968 | 995 | ||
969 | /* Save the file using the new passphrase. */ | 996 | /* Save the file using the new passphrase. */ |
@@ -1006,7 +1033,7 @@ do_change_comment(struct passwd *pw) | |||
1006 | static void | 1033 | static void |
1007 | usage(void) | 1034 | usage(void) |
1008 | { | 1035 | { |
1009 | fprintf(stderr, "Usage: %s [options]\n", __progname); | 1036 | fprintf(stderr, "usage: %s [options]\n", __progname); |
1010 | fprintf(stderr, "Options:\n"); | 1037 | fprintf(stderr, "Options:\n"); |
1011 | fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); | 1038 | fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); |
1012 | fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); | 1039 | fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); |
@@ -1059,7 +1086,6 @@ main(int argc, char **argv) | |||
1059 | int opt, type, fd, download = 0; | 1086 | int opt, type, fd, download = 0; |
1060 | u_int32_t memory = 0, generator_wanted = 0, trials = 100; | 1087 | u_int32_t memory = 0, generator_wanted = 0, trials = 100; |
1061 | int do_gen_candidates = 0, do_screen_candidates = 0; | 1088 | int do_gen_candidates = 0, do_screen_candidates = 0; |
1062 | int log_level = SYSLOG_LEVEL_INFO; | ||
1063 | BIGNUM *start = NULL; | 1089 | BIGNUM *start = NULL; |
1064 | FILE *f; | 1090 | FILE *f; |
1065 | const char *errstr; | 1091 | const char *errstr; |
@@ -1232,6 +1258,10 @@ main(int argc, char **argv) | |||
1232 | printf("Can only have one of -p and -c.\n"); | 1258 | printf("Can only have one of -p and -c.\n"); |
1233 | usage(); | 1259 | usage(); |
1234 | } | 1260 | } |
1261 | if (print_fingerprint && (delete_host || hash_hosts)) { | ||
1262 | printf("Cannot use -l with -D or -R.\n"); | ||
1263 | usage(); | ||
1264 | } | ||
1235 | if (delete_host || hash_hosts || find_host) | 1265 | if (delete_host || hash_hosts || find_host) |
1236 | do_known_hosts(pw, rr_hostname); | 1266 | do_known_hosts(pw, rr_hostname); |
1237 | if (print_fingerprint || print_bubblebabble) | 1267 | if (print_fingerprint || print_bubblebabble) |
@@ -1436,10 +1466,15 @@ passphrase_again: | |||
1436 | 1466 | ||
1437 | if (!quiet) { | 1467 | if (!quiet) { |
1438 | char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); | 1468 | char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); |
1469 | char *ra = key_fingerprint(public, SSH_FP_MD5, | ||
1470 | SSH_FP_RANDOMART); | ||
1439 | printf("Your public key has been saved in %s.\n", | 1471 | printf("Your public key has been saved in %s.\n", |
1440 | identity_file); | 1472 | identity_file); |
1441 | printf("The key fingerprint is:\n"); | 1473 | printf("The key fingerprint is:\n"); |
1442 | printf("%s %s\n", fp, comment); | 1474 | printf("%s %s\n", fp, comment); |
1475 | printf("The key's randomart image is:\n"); | ||
1476 | printf("%s\n", ra); | ||
1477 | xfree(ra); | ||
1443 | xfree(fp); | 1478 | xfree(fp); |
1444 | } | 1479 | } |
1445 | 1480 | ||