diff options
Diffstat (limited to 'hostfile.c')
-rw-r--r-- | hostfile.c | 202 |
1 files changed, 58 insertions, 144 deletions
diff --git a/hostfile.c b/hostfile.c index ea92fa048..a6684fa2c 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -14,63 +14,32 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: hostfile.c,v 1.13 2000/02/18 10:20:20 markus Exp $"); | 17 | RCSID("$OpenBSD: hostfile.c,v 1.14 2000/03/23 22:15:33 markus Exp $"); |
18 | |||
19 | #ifdef HAVE_OPENSSL | ||
20 | #include <openssl/bn.h> | ||
21 | #include <openssl/rsa.h> | ||
22 | #include <openssl/dsa.h> | ||
23 | #endif | ||
24 | #ifdef HAVE_SSL | ||
25 | #include <ssl/bn.h> | ||
26 | #include <ssl/rsa.h> | ||
27 | #include <ssl/dsa.h> | ||
28 | #endif | ||
18 | 29 | ||
19 | #include "packet.h" | 30 | #include "packet.h" |
31 | #include "match.h" | ||
20 | #include "ssh.h" | 32 | #include "ssh.h" |
33 | #include "key.h" | ||
34 | #include "hostfile.h" | ||
21 | 35 | ||
22 | /* | 36 | /* |
23 | * Reads a multiple-precision integer in decimal from the buffer, and advances | 37 | * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the |
24 | * the pointer. The integer must already be initialized. This function is | 38 | * pointer over the key. Skips any whitespace at the beginning and at end. |
25 | * permitted to modify the buffer. This leaves *cpp to point just beyond the | ||
26 | * last processed (and maybe modified) character. Note that this may modify | ||
27 | * the buffer containing the number. | ||
28 | */ | 39 | */ |
29 | 40 | ||
30 | int | 41 | int |
31 | auth_rsa_read_bignum(char **cpp, BIGNUM * value) | 42 | hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret) |
32 | { | ||
33 | char *cp = *cpp; | ||
34 | int old; | ||
35 | |||
36 | /* Skip any leading whitespace. */ | ||
37 | for (; *cp == ' ' || *cp == '\t'; cp++) | ||
38 | ; | ||
39 | |||
40 | /* Check that it begins with a decimal digit. */ | ||
41 | if (*cp < '0' || *cp > '9') | ||
42 | return 0; | ||
43 | |||
44 | /* Save starting position. */ | ||
45 | *cpp = cp; | ||
46 | |||
47 | /* Move forward until all decimal digits skipped. */ | ||
48 | for (; *cp >= '0' && *cp <= '9'; cp++) | ||
49 | ; | ||
50 | |||
51 | /* Save the old terminating character, and replace it by \0. */ | ||
52 | old = *cp; | ||
53 | *cp = 0; | ||
54 | |||
55 | /* Parse the number. */ | ||
56 | if (BN_dec2bn(&value, *cpp) == 0) | ||
57 | return 0; | ||
58 | |||
59 | /* Restore old terminating character. */ | ||
60 | *cp = old; | ||
61 | |||
62 | /* Move beyond the number and return success. */ | ||
63 | *cpp = cp; | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * Parses an RSA key (number of bits, e, n) from a string. Moves the pointer | ||
69 | * over the key. Skips any whitespace at the beginning and at end. | ||
70 | */ | ||
71 | |||
72 | int | ||
73 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) | ||
74 | { | 43 | { |
75 | unsigned int bits; | 44 | unsigned int bits; |
76 | char *cp; | 45 | char *cp; |
@@ -85,12 +54,7 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) | |||
85 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) | 54 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) |
86 | bits = 10 * bits + *cp - '0'; | 55 | bits = 10 * bits + *cp - '0'; |
87 | 56 | ||
88 | /* Get public exponent. */ | 57 | if (!key_read(ret, bits, &cp)) |
89 | if (!auth_rsa_read_bignum(&cp, e)) | ||
90 | return 0; | ||
91 | |||
92 | /* Get public modulus. */ | ||
93 | if (!auth_rsa_read_bignum(&cp, n)) | ||
94 | return 0; | 58 | return 0; |
95 | 59 | ||
96 | /* Skip trailing whitespace. */ | 60 | /* Skip trailing whitespace. */ |
@@ -103,63 +67,30 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) | |||
103 | return 1; | 67 | return 1; |
104 | } | 68 | } |
105 | 69 | ||
106 | /* | ||
107 | * Tries to match the host name (which must be in all lowercase) against the | ||
108 | * comma-separated sequence of subpatterns (each possibly preceded by ! to | ||
109 | * indicate negation). Returns true if there is a positive match; zero | ||
110 | * otherwise. | ||
111 | */ | ||
112 | |||
113 | int | 70 | int |
114 | match_hostname(const char *host, const char *pattern, unsigned int len) | 71 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) |
115 | { | 72 | { |
116 | char sub[1024]; | 73 | Key *k = key_new(KEY_RSA); |
117 | int negated; | 74 | int ret = hostfile_read_key(cpp, bitsp, k); |
118 | int got_positive; | 75 | BN_copy(e, k->rsa->e); |
119 | unsigned int i, subi; | 76 | BN_copy(n, k->rsa->n); |
120 | 77 | key_free(k); | |
121 | got_positive = 0; | 78 | return ret; |
122 | for (i = 0; i < len;) { | 79 | } |
123 | /* Check if the subpattern is negated. */ | ||
124 | if (pattern[i] == '!') { | ||
125 | negated = 1; | ||
126 | i++; | ||
127 | } else | ||
128 | negated = 0; | ||
129 | |||
130 | /* | ||
131 | * Extract the subpattern up to a comma or end. Convert the | ||
132 | * subpattern to lowercase. | ||
133 | */ | ||
134 | for (subi = 0; | ||
135 | i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; | ||
136 | subi++, i++) | ||
137 | sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i]; | ||
138 | /* If subpattern too long, return failure (no match). */ | ||
139 | if (subi >= sizeof(sub) - 1) | ||
140 | return 0; | ||
141 | |||
142 | /* If the subpattern was terminated by a comma, skip the comma. */ | ||
143 | if (i < len && pattern[i] == ',') | ||
144 | i++; | ||
145 | |||
146 | /* Null-terminate the subpattern. */ | ||
147 | sub[subi] = '\0'; | ||
148 | 80 | ||
149 | /* Try to match the subpattern against the host name. */ | 81 | int |
150 | if (match_pattern(host, sub)) { | 82 | hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum) |
151 | if (negated) | 83 | { |
152 | return 0; /* Fail */ | 84 | if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) |
153 | else | 85 | return 1; |
154 | got_positive = 1; | 86 | if (bits != BN_num_bits(key->rsa->n)) { |
155 | } | 87 | error("Warning: %s, line %d: keysize mismatch for host %s: " |
88 | "actual %d vs. announced %d.", | ||
89 | filename, linenum, host, BN_num_bits(key->rsa->n), bits); | ||
90 | error("Warning: replace %d with %d in %s, line %d.", | ||
91 | bits, BN_num_bits(key->rsa->n), filename, linenum); | ||
156 | } | 92 | } |
157 | 93 | return 1; | |
158 | /* | ||
159 | * Return success if got a positive match. If there was a negative | ||
160 | * match, we have already returned zero and never get here. | ||
161 | */ | ||
162 | return got_positive; | ||
163 | } | 94 | } |
164 | 95 | ||
165 | /* | 96 | /* |
@@ -170,8 +101,7 @@ match_hostname(const char *host, const char *pattern, unsigned int len) | |||
170 | */ | 101 | */ |
171 | 102 | ||
172 | HostStatus | 103 | HostStatus |
173 | check_host_in_hostfile(const char *filename, const char *host, | 104 | check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found) |
174 | BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn) | ||
175 | { | 105 | { |
176 | FILE *f; | 106 | FILE *f; |
177 | char line[8192]; | 107 | char line[8192]; |
@@ -180,6 +110,8 @@ check_host_in_hostfile(const char *filename, const char *host, | |||
180 | char *cp, *cp2; | 110 | char *cp, *cp2; |
181 | HostStatus end_return; | 111 | HostStatus end_return; |
182 | 112 | ||
113 | if (key == NULL) | ||
114 | fatal("no key to look up"); | ||
183 | /* Open the file containing the list of known hosts. */ | 115 | /* Open the file containing the list of known hosts. */ |
184 | f = fopen(filename, "r"); | 116 | f = fopen(filename, "r"); |
185 | if (!f) | 117 | if (!f) |
@@ -221,18 +153,13 @@ check_host_in_hostfile(const char *filename, const char *host, | |||
221 | * Extract the key from the line. This will skip any leading | 153 | * Extract the key from the line. This will skip any leading |
222 | * whitespace. Ignore badly formatted lines. | 154 | * whitespace. Ignore badly formatted lines. |
223 | */ | 155 | */ |
224 | if (!auth_rsa_read_key(&cp, &kbits, ke, kn)) | 156 | if (!hostfile_read_key(&cp, &kbits, found)) |
157 | continue; | ||
158 | if (!hostfile_check_key(kbits, found, host, filename, linenum)) | ||
225 | continue; | 159 | continue; |
226 | 160 | ||
227 | if (kbits != BN_num_bits(kn)) { | ||
228 | error("Warning: %s, line %d: keysize mismatch for host %s: " | ||
229 | "actual %d vs. announced %d.", | ||
230 | filename, linenum, host, BN_num_bits(kn), kbits); | ||
231 | error("Warning: replace %d with %d in %s, line %d.", | ||
232 | kbits, BN_num_bits(kn), filename, linenum); | ||
233 | } | ||
234 | /* Check if the current key is the same as the given key. */ | 161 | /* Check if the current key is the same as the given key. */ |
235 | if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) { | 162 | if (key_equal(key, found)) { |
236 | /* Ok, they match. */ | 163 | /* Ok, they match. */ |
237 | fclose(f); | 164 | fclose(f); |
238 | return HOST_OK; | 165 | return HOST_OK; |
@@ -260,41 +187,28 @@ check_host_in_hostfile(const char *filename, const char *host, | |||
260 | */ | 187 | */ |
261 | 188 | ||
262 | int | 189 | int |
263 | add_host_to_hostfile(const char *filename, const char *host, | 190 | add_host_to_hostfile(const char *filename, const char *host, Key *key) |
264 | BIGNUM * e, BIGNUM * n) | ||
265 | { | 191 | { |
266 | FILE *f; | 192 | FILE *f; |
267 | char *buf; | 193 | int success = 0; |
268 | unsigned int bits; | 194 | |
195 | if (key == NULL) | ||
196 | return 1; | ||
269 | 197 | ||
270 | /* Open the file for appending. */ | 198 | /* Open the file for appending. */ |
271 | f = fopen(filename, "a"); | 199 | f = fopen(filename, "a"); |
272 | if (!f) | 200 | if (!f) |
273 | return 0; | 201 | return 0; |
274 | 202 | ||
275 | /* size of modulus 'n' */ | 203 | fprintf(f, "%s ", host); |
276 | bits = BN_num_bits(n); | 204 | if (key_write(key, f)) { |
277 | 205 | fprintf(f, "\n"); | |
278 | /* Print the host name and key to the file. */ | 206 | success = 1; |
279 | fprintf(f, "%s %u ", host, bits); | 207 | } else { |
280 | buf = BN_bn2dec(e); | 208 | error("add_host_to_hostfile: saving key failed"); |
281 | if (buf == NULL) { | ||
282 | error("add_host_to_hostfile: BN_bn2dec(e) failed"); | ||
283 | fclose(f); | ||
284 | return 0; | ||
285 | } | 209 | } |
286 | fprintf(f, "%s ", buf); | ||
287 | free(buf); | ||
288 | buf = BN_bn2dec(n); | ||
289 | if (buf == NULL) { | ||
290 | error("add_host_to_hostfile: BN_bn2dec(n) failed"); | ||
291 | fclose(f); | ||
292 | return 0; | ||
293 | } | ||
294 | fprintf(f, "%s\n", buf); | ||
295 | free(buf); | ||
296 | 210 | ||
297 | /* Close the file. */ | 211 | /* Close the file. */ |
298 | fclose(f); | 212 | fclose(f); |
299 | return 1; | 213 | return success; |
300 | } | 214 | } |