diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | ssh-keygen.1 | 13 | ||||
-rw-r--r-- | ssh-keygen.c | 166 |
3 files changed, 157 insertions, 30 deletions
@@ -18,6 +18,14 @@ | |||
18 | [ssh-keyscan.c] | 18 | [ssh-keyscan.c] |
19 | use timerclear macro | 19 | use timerclear macro |
20 | ok djm@ | 20 | ok djm@ |
21 | - stevesk@cvs.openbsd.org 2011/03/23 15:16:22 | ||
22 | [ssh-keygen.1 ssh-keygen.c] | ||
23 | Add -A option. For each of the key types (rsa1, rsa, dsa and ecdsa) | ||
24 | for which host keys do not exist, generate the host keys with the | ||
25 | default key file path, an empty passphrase, default bits for the key | ||
26 | type, and default comment. This will be used by /etc/rc to generate | ||
27 | new host keys. Idea from deraadt. | ||
28 | ok deraadt | ||
21 | 29 | ||
22 | 20110221 | 30 | 20110221 |
23 | - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the | 31 | - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 205f741b8..2573087b3 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.101 2010/10/28 18:33:28 jmc Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.102 2011/03/23 15:16:22 stevesk Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: October 28 2010 $ | 38 | .Dd $Mdocdate: March 23 2011 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -117,6 +117,8 @@ | |||
117 | .Nm ssh-keygen | 117 | .Nm ssh-keygen |
118 | .Fl L | 118 | .Fl L |
119 | .Op Fl f Ar input_keyfile | 119 | .Op Fl f Ar input_keyfile |
120 | .Nm ssh-keygen | ||
121 | .Fl A | ||
120 | .Ek | 122 | .Ek |
121 | .Sh DESCRIPTION | 123 | .Sh DESCRIPTION |
122 | .Nm | 124 | .Nm |
@@ -192,6 +194,13 @@ should be placed to be activated. | |||
192 | .Pp | 194 | .Pp |
193 | The options are as follows: | 195 | The options are as follows: |
194 | .Bl -tag -width Ds | 196 | .Bl -tag -width Ds |
197 | .It Fl A | ||
198 | For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys | ||
199 | do not exist, generate the host keys with the default key file path, | ||
200 | an empty passphrase, default bits for the key type, and default comment. | ||
201 | This is used by | ||
202 | .Pa /etc/rc | ||
203 | to generate new host keys. | ||
195 | .It Fl a Ar trials | 204 | .It Fl a Ar trials |
196 | Specifies the number of primality tests to perform when screening DH-GEX | 205 | Specifies the number of primality tests to perform when screening DH-GEX |
197 | candidates using the | 206 | candidates using the |
diff --git a/ssh-keygen.c b/ssh-keygen.c index d379b1a2c..aae33e308 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.206 2011/03/23 15:16:22 stevesk 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 |
@@ -160,6 +160,38 @@ int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); | |||
160 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); | 160 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); |
161 | 161 | ||
162 | static void | 162 | static void |
163 | type_bits_valid(int type, u_int32_t *bits) | ||
164 | { | ||
165 | u_int maxbits; | ||
166 | |||
167 | if (type == KEY_UNSPEC) { | ||
168 | fprintf(stderr, "unknown key type %s\n", key_type_name); | ||
169 | exit(1); | ||
170 | } | ||
171 | if (*bits == 0) { | ||
172 | if (type == KEY_DSA) | ||
173 | *bits = DEFAULT_BITS_DSA; | ||
174 | else if (type == KEY_ECDSA) | ||
175 | *bits = DEFAULT_BITS_ECDSA; | ||
176 | else | ||
177 | *bits = DEFAULT_BITS; | ||
178 | } | ||
179 | maxbits = (type == KEY_DSA) ? | ||
180 | OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; | ||
181 | if (*bits > maxbits) { | ||
182 | fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); | ||
183 | exit(1); | ||
184 | } | ||
185 | if (type == KEY_DSA && *bits != 1024) | ||
186 | fatal("DSA keys must be 1024 bits"); | ||
187 | else if (type != KEY_ECDSA && *bits < 768) | ||
188 | fatal("Key must at least be 768 bits"); | ||
189 | else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bits) == -1) | ||
190 | fatal("Invalid ECDSA key length - valid lengths are " | ||
191 | "256, 384 or 521 bits"); | ||
192 | } | ||
193 | |||
194 | static void | ||
163 | ask_filename(struct passwd *pw, const char *prompt) | 195 | ask_filename(struct passwd *pw, const char *prompt) |
164 | { | 196 | { |
165 | char buf[1024]; | 197 | char buf[1024]; |
@@ -818,6 +850,98 @@ do_fingerprint(struct passwd *pw) | |||
818 | } | 850 | } |
819 | 851 | ||
820 | static void | 852 | static void |
853 | do_gen_all_hostkeys(struct passwd *pw) | ||
854 | { | ||
855 | struct { | ||
856 | char *key_type; | ||
857 | char *key_type_display; | ||
858 | char *path; | ||
859 | } key_types[] = { | ||
860 | { "rsa1", "RSA1", _PATH_HOST_KEY_FILE }, | ||
861 | { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, | ||
862 | { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, | ||
863 | { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, | ||
864 | { NULL, NULL, NULL } | ||
865 | }; | ||
866 | |||
867 | int first = 0; | ||
868 | struct stat st; | ||
869 | Key *private, *public; | ||
870 | char comment[1024]; | ||
871 | int i, type, fd; | ||
872 | FILE *f; | ||
873 | |||
874 | for (i = 0; key_types[i].key_type; i++) { | ||
875 | if (stat(key_types[i].path, &st) == 0) | ||
876 | continue; | ||
877 | if (errno != ENOENT) { | ||
878 | printf("Could not stat %s: %s", key_types[i].path, | ||
879 | strerror(errno)); | ||
880 | first = 0; | ||
881 | continue; | ||
882 | } | ||
883 | |||
884 | if (first == 0) { | ||
885 | first = 1; | ||
886 | printf("%s: generating new host keys: ", __progname); | ||
887 | } | ||
888 | printf("%s ", key_types[i].key_type_display); | ||
889 | fflush(stdout); | ||
890 | arc4random_stir(); | ||
891 | type = key_type_from_name(key_types[i].key_type); | ||
892 | strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); | ||
893 | bits = 0; | ||
894 | type_bits_valid(type, &bits); | ||
895 | private = key_generate(type, bits); | ||
896 | if (private == NULL) { | ||
897 | fprintf(stderr, "key_generate failed\n"); | ||
898 | first = 0; | ||
899 | continue; | ||
900 | } | ||
901 | public = key_from_private(private); | ||
902 | snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, | ||
903 | hostname); | ||
904 | if (!key_save_private(private, identity_file, "", comment)) { | ||
905 | printf("Saving the key failed: %s.\n", identity_file); | ||
906 | key_free(private); | ||
907 | key_free(public); | ||
908 | first = 0; | ||
909 | continue; | ||
910 | } | ||
911 | key_free(private); | ||
912 | arc4random_stir(); | ||
913 | strlcat(identity_file, ".pub", sizeof(identity_file)); | ||
914 | fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||
915 | if (fd == -1) { | ||
916 | printf("Could not save your public key in %s\n", | ||
917 | identity_file); | ||
918 | key_free(public); | ||
919 | first = 0; | ||
920 | continue; | ||
921 | } | ||
922 | f = fdopen(fd, "w"); | ||
923 | if (f == NULL) { | ||
924 | printf("fdopen %s failed\n", identity_file); | ||
925 | key_free(public); | ||
926 | first = 0; | ||
927 | continue; | ||
928 | } | ||
929 | if (!key_write(public, f)) { | ||
930 | fprintf(stderr, "write key failed\n"); | ||
931 | key_free(public); | ||
932 | first = 0; | ||
933 | continue; | ||
934 | } | ||
935 | fprintf(f, " %s\n", comment); | ||
936 | fclose(f); | ||
937 | key_free(public); | ||
938 | |||
939 | } | ||
940 | if (first != 0) | ||
941 | printf("\n"); | ||
942 | } | ||
943 | |||
944 | static void | ||
821 | printhost(FILE *f, const char *name, Key *public, int ca, int hash) | 945 | printhost(FILE *f, const char *name, Key *public, int ca, int hash) |
822 | { | 946 | { |
823 | if (print_fingerprint) { | 947 | if (print_fingerprint) { |
@@ -1745,6 +1869,7 @@ usage(void) | |||
1745 | { | 1869 | { |
1746 | fprintf(stderr, "usage: %s [options]\n", __progname); | 1870 | fprintf(stderr, "usage: %s [options]\n", __progname); |
1747 | fprintf(stderr, "Options:\n"); | 1871 | fprintf(stderr, "Options:\n"); |
1872 | fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); | ||
1748 | fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); | 1873 | fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); |
1749 | fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); | 1874 | fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); |
1750 | fprintf(stderr, " -b bits Number of bits in the key to create.\n"); | 1875 | fprintf(stderr, " -b bits Number of bits in the key to create.\n"); |
@@ -1799,9 +1924,9 @@ main(int argc, char **argv) | |||
1799 | struct passwd *pw; | 1924 | struct passwd *pw; |
1800 | struct stat st; | 1925 | struct stat st; |
1801 | int opt, type, fd; | 1926 | int opt, type, fd; |
1802 | u_int maxbits; | ||
1803 | u_int32_t memory = 0, generator_wanted = 0, trials = 100; | 1927 | u_int32_t memory = 0, generator_wanted = 0, trials = 100; |
1804 | int do_gen_candidates = 0, do_screen_candidates = 0; | 1928 | int do_gen_candidates = 0, do_screen_candidates = 0; |
1929 | int gen_all_hostkeys = 0; | ||
1805 | BIGNUM *start = NULL; | 1930 | BIGNUM *start = NULL; |
1806 | FILE *f; | 1931 | FILE *f; |
1807 | const char *errstr; | 1932 | const char *errstr; |
@@ -1830,9 +1955,12 @@ main(int argc, char **argv) | |||
1830 | exit(1); | 1955 | exit(1); |
1831 | } | 1956 | } |
1832 | 1957 | ||
1833 | while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" | 1958 | while ((opt = getopt(argc, argv, "AdegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" |
1834 | "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { | 1959 | "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { |
1835 | switch (opt) { | 1960 | switch (opt) { |
1961 | case 'A': | ||
1962 | gen_all_hostkeys = 1; | ||
1963 | break; | ||
1836 | case 'b': | 1964 | case 'b': |
1837 | bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr); | 1965 | bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr); |
1838 | if (errstr) | 1966 | if (errstr) |
@@ -2108,37 +2236,19 @@ main(int argc, char **argv) | |||
2108 | return (0); | 2236 | return (0); |
2109 | } | 2237 | } |
2110 | 2238 | ||
2239 | if (gen_all_hostkeys) { | ||
2240 | do_gen_all_hostkeys(pw); | ||
2241 | return (0); | ||
2242 | } | ||
2243 | |||
2111 | arc4random_stir(); | 2244 | arc4random_stir(); |
2112 | 2245 | ||
2113 | if (key_type_name == NULL) | 2246 | if (key_type_name == NULL) |
2114 | key_type_name = "rsa"; | 2247 | key_type_name = "rsa"; |
2115 | 2248 | ||
2116 | type = key_type_from_name(key_type_name); | 2249 | type = key_type_from_name(key_type_name); |
2117 | if (type == KEY_UNSPEC) { | 2250 | type_bits_valid(type, &bits); |
2118 | fprintf(stderr, "unknown key type %s\n", key_type_name); | 2251 | |
2119 | exit(1); | ||
2120 | } | ||
2121 | if (bits == 0) { | ||
2122 | if (type == KEY_DSA) | ||
2123 | bits = DEFAULT_BITS_DSA; | ||
2124 | else if (type == KEY_ECDSA) | ||
2125 | bits = DEFAULT_BITS_ECDSA; | ||
2126 | else | ||
2127 | bits = DEFAULT_BITS; | ||
2128 | } | ||
2129 | maxbits = (type == KEY_DSA) ? | ||
2130 | OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; | ||
2131 | if (bits > maxbits) { | ||
2132 | fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); | ||
2133 | exit(1); | ||
2134 | } | ||
2135 | if (type == KEY_DSA && bits != 1024) | ||
2136 | fatal("DSA keys must be 1024 bits"); | ||
2137 | else if (type != KEY_ECDSA && bits < 768) | ||
2138 | fatal("Key must at least be 768 bits"); | ||
2139 | else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(bits) == -1) | ||
2140 | fatal("Invalid ECDSA key length - valid lengths are " | ||
2141 | "256, 384 or 521 bits"); | ||
2142 | if (!quiet) | 2252 | if (!quiet) |
2143 | printf("Generating public/private %s key pair.\n", key_type_name); | 2253 | printf("Generating public/private %s key pair.\n", key_type_name); |
2144 | private = key_generate(type, bits); | 2254 | private = key_generate(type, bits); |