diff options
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 149 |
1 files changed, 143 insertions, 6 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index 6a872bcfd..e74d3cd37 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: ssh-keygen.c,v 1.102 2002/11/26 00:45:03 wcobb Exp $"); | 15 | RCSID("$OpenBSD: ssh-keygen.c,v 1.108 2003/08/14 16:08:58 markus Exp $"); |
16 | 16 | ||
17 | #include <openssl/evp.h> | 17 | #include <openssl/evp.h> |
18 | #include <openssl/pem.h> | 18 | #include <openssl/pem.h> |
@@ -27,10 +27,14 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.102 2002/11/26 00:45:03 wcobb Exp $"); | |||
27 | #include "pathnames.h" | 27 | #include "pathnames.h" |
28 | #include "log.h" | 28 | #include "log.h" |
29 | #include "readpass.h" | 29 | #include "readpass.h" |
30 | #include "moduli.h" | ||
30 | 31 | ||
31 | #ifdef SMARTCARD | 32 | #ifdef SMARTCARD |
32 | #include "scard.h" | 33 | #include "scard.h" |
33 | #endif | 34 | #endif |
35 | #ifdef DNS | ||
36 | #include "dns.h" | ||
37 | #endif | ||
34 | 38 | ||
35 | /* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ | 39 | /* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ |
36 | int bits = 1024; | 40 | int bits = 1024; |
@@ -70,6 +74,7 @@ char *identity_comment = NULL; | |||
70 | int convert_to_ssh2 = 0; | 74 | int convert_to_ssh2 = 0; |
71 | int convert_from_ssh2 = 0; | 75 | int convert_from_ssh2 = 0; |
72 | int print_public = 0; | 76 | int print_public = 0; |
77 | int print_generic = 0; | ||
73 | 78 | ||
74 | char *key_type_name = NULL; | 79 | char *key_type_name = NULL; |
75 | 80 | ||
@@ -163,6 +168,10 @@ do_convert_to_ssh2(struct passwd *pw) | |||
163 | exit(1); | 168 | exit(1); |
164 | } | 169 | } |
165 | } | 170 | } |
171 | if (k->type == KEY_RSA1) { | ||
172 | fprintf(stderr, "version 1 keys are not supported\n"); | ||
173 | exit(1); | ||
174 | } | ||
166 | if (key_to_blob(k, &blob, &len) <= 0) { | 175 | if (key_to_blob(k, &blob, &len) <= 0) { |
167 | fprintf(stderr, "key_to_blob failed\n"); | 176 | fprintf(stderr, "key_to_blob failed\n"); |
168 | exit(1); | 177 | exit(1); |
@@ -415,7 +424,7 @@ do_upload(struct passwd *pw, const char *sc_reader_id) | |||
415 | key_free(prv); | 424 | key_free(prv); |
416 | if (ret < 0) | 425 | if (ret < 0) |
417 | exit(1); | 426 | exit(1); |
418 | log("loading key done"); | 427 | logit("loading key done"); |
419 | exit(0); | 428 | exit(0); |
420 | } | 429 | } |
421 | 430 | ||
@@ -616,6 +625,38 @@ do_change_passphrase(struct passwd *pw) | |||
616 | exit(0); | 625 | exit(0); |
617 | } | 626 | } |
618 | 627 | ||
628 | #ifdef DNS | ||
629 | /* | ||
630 | * Print the SSHFP RR. | ||
631 | */ | ||
632 | static void | ||
633 | do_print_resource_record(struct passwd *pw, char *hostname) | ||
634 | { | ||
635 | Key *public; | ||
636 | char *comment = NULL; | ||
637 | struct stat st; | ||
638 | |||
639 | if (!have_identity) | ||
640 | ask_filename(pw, "Enter file in which the key is"); | ||
641 | if (stat(identity_file, &st) < 0) { | ||
642 | perror(identity_file); | ||
643 | exit(1); | ||
644 | } | ||
645 | public = key_load_public(identity_file, &comment); | ||
646 | if (public != NULL) { | ||
647 | export_dns_rr(hostname, public, stdout, print_generic); | ||
648 | key_free(public); | ||
649 | xfree(comment); | ||
650 | exit(0); | ||
651 | } | ||
652 | if (comment) | ||
653 | xfree(comment); | ||
654 | |||
655 | printf("failed to read v2 public key from %s.\n", identity_file); | ||
656 | exit(1); | ||
657 | } | ||
658 | #endif /* DNS */ | ||
659 | |||
619 | /* | 660 | /* |
620 | * Change the comment of a private key file. | 661 | * Change the comment of a private key file. |
621 | */ | 662 | */ |
@@ -722,6 +763,7 @@ usage(void) | |||
722 | fprintf(stderr, " -c Change comment in private and public key files.\n"); | 763 | fprintf(stderr, " -c Change comment in private and public key files.\n"); |
723 | fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); | 764 | fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); |
724 | fprintf(stderr, " -f filename Filename of the key file.\n"); | 765 | fprintf(stderr, " -f filename Filename of the key file.\n"); |
766 | fprintf(stderr, " -g Use generic DNS resource record format.\n"); | ||
725 | fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); | 767 | fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); |
726 | fprintf(stderr, " -l Show fingerprint of key file.\n"); | 768 | fprintf(stderr, " -l Show fingerprint of key file.\n"); |
727 | fprintf(stderr, " -p Change passphrase of private key file.\n"); | 769 | fprintf(stderr, " -p Change passphrase of private key file.\n"); |
@@ -732,11 +774,17 @@ usage(void) | |||
732 | fprintf(stderr, " -C comment Provide new comment.\n"); | 774 | fprintf(stderr, " -C comment Provide new comment.\n"); |
733 | fprintf(stderr, " -N phrase Provide new passphrase.\n"); | 775 | fprintf(stderr, " -N phrase Provide new passphrase.\n"); |
734 | fprintf(stderr, " -P phrase Provide old passphrase.\n"); | 776 | fprintf(stderr, " -P phrase Provide old passphrase.\n"); |
777 | #ifdef DNS | ||
778 | fprintf(stderr, " -r hostname Print DNS resource record.\n"); | ||
779 | #endif /* DNS */ | ||
735 | #ifdef SMARTCARD | 780 | #ifdef SMARTCARD |
736 | fprintf(stderr, " -D reader Download public key from smartcard.\n"); | 781 | fprintf(stderr, " -D reader Download public key from smartcard.\n"); |
737 | fprintf(stderr, " -U reader Upload private key to smartcard.\n"); | 782 | fprintf(stderr, " -U reader Upload private key to smartcard.\n"); |
738 | #endif /* SMARTCARD */ | 783 | #endif /* SMARTCARD */ |
739 | 784 | ||
785 | fprintf(stderr, " -G file Generate candidates for DH-GEX moduli\n"); | ||
786 | fprintf(stderr, " -T file Screen candidates for DH-GEX moduli\n"); | ||
787 | |||
740 | exit(1); | 788 | exit(1); |
741 | } | 789 | } |
742 | 790 | ||
@@ -747,19 +795,25 @@ int | |||
747 | main(int ac, char **av) | 795 | main(int ac, char **av) |
748 | { | 796 | { |
749 | char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; | 797 | char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; |
750 | char *reader_id = NULL; | 798 | char out_file[MAXPATHLEN], *reader_id = NULL; |
799 | char *resource_record_hostname = NULL; | ||
751 | Key *private, *public; | 800 | Key *private, *public; |
752 | struct passwd *pw; | 801 | struct passwd *pw; |
753 | struct stat st; | 802 | struct stat st; |
754 | int opt, type, fd, download = 0; | 803 | int opt, type, fd, download = 0, memory = 0; |
804 | int generator_wanted = 0, trials = 100; | ||
805 | int do_gen_candidates = 0, do_screen_candidates = 0; | ||
806 | BIGNUM *start = NULL; | ||
755 | FILE *f; | 807 | FILE *f; |
756 | 808 | ||
757 | extern int optind; | 809 | extern int optind; |
758 | extern char *optarg; | 810 | extern char *optarg; |
759 | 811 | ||
760 | __progname = get_progname(av[0]); | 812 | __progname = ssh_get_progname(av[0]); |
761 | 813 | ||
762 | SSLeay_add_all_algorithms(); | 814 | SSLeay_add_all_algorithms(); |
815 | log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); | ||
816 | |||
763 | init_rng(); | 817 | init_rng(); |
764 | seed_rng(); | 818 | seed_rng(); |
765 | 819 | ||
@@ -774,7 +828,8 @@ main(int ac, char **av) | |||
774 | exit(1); | 828 | exit(1); |
775 | } | 829 | } |
776 | 830 | ||
777 | while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) { | 831 | while ((opt = getopt(ac, av, |
832 | "degiqpclBRxXyb:f:t:U:D:P:N:C:r:g:T:G:M:S:a:W:")) != -1) { | ||
778 | switch (opt) { | 833 | switch (opt) { |
779 | case 'b': | 834 | case 'b': |
780 | bits = atoi(optarg); | 835 | bits = atoi(optarg); |
@@ -799,6 +854,9 @@ main(int ac, char **av) | |||
799 | strlcpy(identity_file, optarg, sizeof(identity_file)); | 854 | strlcpy(identity_file, optarg, sizeof(identity_file)); |
800 | have_identity = 1; | 855 | have_identity = 1; |
801 | break; | 856 | break; |
857 | case 'g': | ||
858 | print_generic = 1; | ||
859 | break; | ||
802 | case 'P': | 860 | case 'P': |
803 | identity_passphrase = optarg; | 861 | identity_passphrase = optarg; |
804 | break; | 862 | break; |
@@ -839,6 +897,42 @@ main(int ac, char **av) | |||
839 | case 'U': | 897 | case 'U': |
840 | reader_id = optarg; | 898 | reader_id = optarg; |
841 | break; | 899 | break; |
900 | case 'r': | ||
901 | resource_record_hostname = optarg; | ||
902 | break; | ||
903 | case 'W': | ||
904 | generator_wanted = atoi(optarg); | ||
905 | if (generator_wanted < 1) | ||
906 | fatal("Desired generator has bad value."); | ||
907 | break; | ||
908 | case 'a': | ||
909 | trials = atoi(optarg); | ||
910 | if (trials < TRIAL_MINIMUM) { | ||
911 | fatal("Minimum primality trials is %d", | ||
912 | TRIAL_MINIMUM); | ||
913 | } | ||
914 | break; | ||
915 | case 'M': | ||
916 | memory = atoi(optarg); | ||
917 | if (memory != 0 && | ||
918 | (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { | ||
919 | fatal("Invalid memory amount (min %ld, max %ld)", | ||
920 | LARGE_MINIMUM, LARGE_MAXIMUM); | ||
921 | } | ||
922 | break; | ||
923 | case 'G': | ||
924 | do_gen_candidates = 1; | ||
925 | strlcpy(out_file, optarg, sizeof(out_file)); | ||
926 | break; | ||
927 | case 'T': | ||
928 | do_screen_candidates = 1; | ||
929 | strlcpy(out_file, optarg, sizeof(out_file)); | ||
930 | break; | ||
931 | case 'S': | ||
932 | /* XXX - also compare length against bits */ | ||
933 | if (BN_hex2bn(&start, optarg) == 0) | ||
934 | fatal("Invalid start point."); | ||
935 | break; | ||
842 | case '?': | 936 | case '?': |
843 | default: | 937 | default: |
844 | usage(); | 938 | usage(); |
@@ -864,6 +958,13 @@ main(int ac, char **av) | |||
864 | do_convert_from_ssh2(pw); | 958 | do_convert_from_ssh2(pw); |
865 | if (print_public) | 959 | if (print_public) |
866 | do_print_public(pw); | 960 | do_print_public(pw); |
961 | if (resource_record_hostname != NULL) { | ||
962 | #ifdef DNS | ||
963 | do_print_resource_record(pw, resource_record_hostname); | ||
964 | #else /* DNS */ | ||
965 | fatal("no DNS support."); | ||
966 | #endif /* DNS */ | ||
967 | } | ||
867 | if (reader_id != NULL) { | 968 | if (reader_id != NULL) { |
868 | #ifdef SMARTCARD | 969 | #ifdef SMARTCARD |
869 | if (download) | 970 | if (download) |
@@ -875,6 +976,42 @@ main(int ac, char **av) | |||
875 | #endif /* SMARTCARD */ | 976 | #endif /* SMARTCARD */ |
876 | } | 977 | } |
877 | 978 | ||
979 | if (do_gen_candidates) { | ||
980 | FILE *out = fopen(out_file, "w"); | ||
981 | |||
982 | if (out == NULL) { | ||
983 | error("Couldn't open modulus candidate file \"%s\": %s", | ||
984 | out_file, strerror(errno)); | ||
985 | return (1); | ||
986 | } | ||
987 | if (gen_candidates(out, memory, bits, start) != 0) | ||
988 | fatal("modulus candidate generation failed\n"); | ||
989 | |||
990 | return (0); | ||
991 | } | ||
992 | |||
993 | if (do_screen_candidates) { | ||
994 | FILE *in; | ||
995 | FILE *out = fopen(out_file, "w"); | ||
996 | |||
997 | if (have_identity && strcmp(identity_file, "-") != 0) { | ||
998 | if ((in = fopen(identity_file, "r")) == NULL) { | ||
999 | fatal("Couldn't open modulus candidate " | ||
1000 | "file \"%s\": %s", identity_file, | ||
1001 | strerror(errno)); | ||
1002 | } | ||
1003 | } else | ||
1004 | in = stdin; | ||
1005 | |||
1006 | if (out == NULL) { | ||
1007 | fatal("Couldn't open moduli file \"%s\": %s", | ||
1008 | out_file, strerror(errno)); | ||
1009 | } | ||
1010 | if (prime_test(in, out, trials, generator_wanted) != 0) | ||
1011 | fatal("modulus screening failed\n"); | ||
1012 | return (0); | ||
1013 | } | ||
1014 | |||
878 | arc4random_stir(); | 1015 | arc4random_stir(); |
879 | 1016 | ||
880 | if (key_type_name == NULL) { | 1017 | if (key_type_name == NULL) { |