diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
commit | 95def09838fc61b37b6ea7cd5c234a465b4b129b (patch) | |
tree | 042744f76f40a326b873cb1c3690a6d7d966bc3e /hostfile.c | |
parent | 4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff) |
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates
- [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
[ssh.h sshd.8 sshd.c]
syslog changes:
* Unified Logmessage for all auth-types, for success and for failed
* Standard connections get only ONE line in the LOG when level==LOG:
Auth-attempts are logged only, if authentication is:
a) successfull or
b) with passwd or
c) we had more than AUTH_FAIL_LOG failues
* many log() became verbose()
* old behaviour with level=VERBOSE
- [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
messages. allows use of s/key in windows (ttssh, securecrt) and
ssh-1.2.27 clients without 'ssh -v', ok: niels@
- [sshd.8]
-V, for fallback to openssh in SSH2 compatibility mode
- [sshd.c]
fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'hostfile.c')
-rw-r--r-- | hostfile.c | 457 |
1 files changed, 224 insertions, 233 deletions
diff --git a/hostfile.c b/hostfile.c index de21c904e..61046f071 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -1,20 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | 2 | * | |
3 | hostfile.c | 3 | * hostfile.c |
4 | 4 | * | |
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> | 5 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
6 | 6 | * | |
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 7 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
8 | All rights reserved | 8 | * All rights reserved |
9 | 9 | * | |
10 | Created: Thu Jun 29 07:10:56 1995 ylo | 10 | * Created: Thu Jun 29 07:10:56 1995 ylo |
11 | 11 | * | |
12 | Functions for manipulating the known hosts files. | 12 | * Functions for manipulating the known hosts files. |
13 | 13 | * | |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$Id: hostfile.c,v 1.4 1999/11/17 06:29:08 damien Exp $"); | 17 | RCSID("$Id: hostfile.c,v 1.5 1999/11/24 13:26:22 damien Exp $"); |
18 | 18 | ||
19 | #include "packet.h" | 19 | #include "packet.h" |
20 | #include "ssh.h" | 20 | #include "ssh.h" |
@@ -26,140 +26,136 @@ RCSID("$Id: hostfile.c,v 1.4 1999/11/17 06:29:08 damien Exp $"); | |||
26 | modify the buffer containing the number. */ | 26 | modify the buffer containing the number. */ |
27 | 27 | ||
28 | int | 28 | int |
29 | auth_rsa_read_bignum(char **cpp, BIGNUM *value) | 29 | auth_rsa_read_bignum(char **cpp, BIGNUM * value) |
30 | { | 30 | { |
31 | char *cp = *cpp; | 31 | char *cp = *cpp; |
32 | int len, old; | 32 | int len, old; |
33 | |||
34 | /* Skip any leading whitespace. */ | ||
35 | for (; *cp == ' ' || *cp == '\t'; cp++); | ||
33 | 36 | ||
34 | /* Skip any leading whitespace. */ | 37 | /* Check that it begins with a hex digit. */ |
35 | for (; *cp == ' ' || *cp == '\t'; cp++) | 38 | if (*cp < '0' || *cp > '9') |
36 | ; | 39 | return 0; |
37 | 40 | ||
38 | /* Check that it begins with a hex digit. */ | 41 | /* Save starting position. */ |
39 | if (*cp < '0' || *cp > '9') | 42 | *cpp = cp; |
40 | return 0; | ||
41 | 43 | ||
42 | /* Save starting position. */ | 44 | /* Move forward until all hex digits skipped. */ |
43 | *cpp = cp; | 45 | for (; *cp >= '0' && *cp <= '9'; cp++); |
44 | 46 | ||
45 | /* Move forward until all hex digits skipped. */ | 47 | /* Compute the length of the hex number. */ |
46 | for (; *cp >= '0' && *cp <= '9'; cp++) | 48 | len = cp - *cpp; |
47 | ; | ||
48 | 49 | ||
49 | /* Compute the length of the hex number. */ | 50 | /* Save the old terminating character, and replace it by \0. */ |
50 | len = cp - *cpp; | 51 | old = *cp; |
52 | *cp = 0; | ||
51 | 53 | ||
52 | /* Save the old terminating character, and replace it by \0. */ | ||
53 | old = *cp; | ||
54 | *cp = 0; | ||
55 | 54 | ||
56 | 55 | /* Parse the number. */ | |
57 | /* Parse the number. */ | 56 | if (BN_dec2bn(&value, *cpp) == 0) |
58 | if (BN_dec2bn(&value, *cpp) == 0) | 57 | return 0; |
59 | return 0; | ||
60 | 58 | ||
61 | /* Restore old terminating character. */ | 59 | /* Restore old terminating character. */ |
62 | *cp = old; | 60 | *cp = old; |
63 | 61 | ||
64 | /* Move beyond the number and return success. */ | 62 | /* Move beyond the number and return success. */ |
65 | *cpp = cp; | 63 | *cpp = cp; |
66 | return 1; | 64 | return 1; |
67 | } | 65 | } |
68 | 66 | ||
69 | /* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer | 67 | /* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer |
70 | over the key. Skips any whitespace at the beginning and at end. */ | 68 | over the key. Skips any whitespace at the beginning and at end. */ |
71 | 69 | ||
72 | int | 70 | int |
73 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n) | 71 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) |
74 | { | 72 | { |
75 | unsigned int bits; | 73 | unsigned int bits; |
76 | char *cp; | 74 | char *cp; |
77 | 75 | ||
78 | /* Skip leading whitespace. */ | 76 | /* Skip leading whitespace. */ |
79 | for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) | 77 | for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++); |
80 | ; | 78 | |
81 | 79 | /* Get number of bits. */ | |
82 | /* Get number of bits. */ | 80 | if (*cp < '0' || *cp > '9') |
83 | if (*cp < '0' || *cp > '9') | 81 | return 0; /* Bad bit count... */ |
84 | return 0; /* Bad bit count... */ | 82 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) |
85 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) | 83 | bits = 10 * bits + *cp - '0'; |
86 | bits = 10 * bits + *cp - '0'; | 84 | |
87 | 85 | /* Get public exponent. */ | |
88 | /* Get public exponent. */ | 86 | if (!auth_rsa_read_bignum(&cp, e)) |
89 | if (!auth_rsa_read_bignum(&cp, e)) | 87 | return 0; |
90 | return 0; | 88 | |
91 | 89 | /* Get public modulus. */ | |
92 | /* Get public modulus. */ | 90 | if (!auth_rsa_read_bignum(&cp, n)) |
93 | if (!auth_rsa_read_bignum(&cp, n)) | 91 | return 0; |
94 | return 0; | 92 | |
95 | 93 | /* Skip trailing whitespace. */ | |
96 | /* Skip trailing whitespace. */ | 94 | for (; *cp == ' ' || *cp == '\t'; cp++); |
97 | for (; *cp == ' ' || *cp == '\t'; cp++) | 95 | |
98 | ; | 96 | /* Return results. */ |
99 | 97 | *cpp = cp; | |
100 | /* Return results. */ | 98 | *bitsp = bits; |
101 | *cpp = cp; | 99 | return 1; |
102 | *bitsp = bits; | ||
103 | return 1; | ||
104 | } | 100 | } |
105 | 101 | ||
106 | /* Tries to match the host name (which must be in all lowercase) against the | 102 | /* Tries to match the host name (which must be in all lowercase) against the |
107 | comma-separated sequence of subpatterns (each possibly preceded by ! to | 103 | comma-separated sequence of subpatterns (each possibly preceded by ! to |
108 | indicate negation). Returns true if there is a positive match; zero | 104 | indicate negation). Returns true if there is a positive match; zero |
109 | otherwise. */ | 105 | otherwise. */ |
110 | 106 | ||
111 | int | 107 | int |
112 | match_hostname(const char *host, const char *pattern, unsigned int len) | 108 | match_hostname(const char *host, const char *pattern, unsigned int len) |
113 | { | 109 | { |
114 | char sub[1024]; | 110 | char sub[1024]; |
115 | int negated; | 111 | int negated; |
116 | int got_positive; | 112 | int got_positive; |
117 | unsigned int i, subi; | 113 | unsigned int i, subi; |
118 | 114 | ||
119 | got_positive = 0; | 115 | got_positive = 0; |
120 | for (i = 0; i < len;) | 116 | for (i = 0; i < len;) { |
121 | { | 117 | /* Check if the subpattern is negated. */ |
122 | /* Check if the subpattern is negated. */ | 118 | if (pattern[i] == '!') { |
123 | if (pattern[i] == '!') | 119 | negated = 1; |
124 | { | 120 | i++; |
125 | negated = 1; | 121 | } else |
126 | i++; | 122 | negated = 0; |
123 | |||
124 | /* Extract the subpattern up to a comma or end. Convert | ||
125 | the subpattern to lowercase. */ | ||
126 | for (subi = 0; | ||
127 | i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; | ||
128 | subi++, i++) | ||
129 | sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i]; | ||
130 | /* If subpattern too long, return failure (no match). */ | ||
131 | if (subi >= sizeof(sub) - 1) | ||
132 | return 0; | ||
133 | |||
134 | /* If the subpattern was terminated by a comma, skip the | ||
135 | comma. */ | ||
136 | if (i < len && pattern[i] == ',') | ||
137 | i++; | ||
138 | |||
139 | /* Null-terminate the subpattern. */ | ||
140 | sub[subi] = '\0'; | ||
141 | |||
142 | /* Try to match the subpattern against the host name. */ | ||
143 | if (match_pattern(host, sub)) { | ||
144 | if (negated) | ||
145 | return 0; /* Fail if host matches | ||
146 | any negated subpattern. */ | ||
147 | else | ||
148 | got_positive = 1; | ||
149 | } | ||
127 | } | 150 | } |
128 | else | 151 | |
129 | negated = 0; | 152 | /* Return success if got a positive match. If there was a |
130 | 153 | negative match, we have already returned zero and never get | |
131 | /* Extract the subpattern up to a comma or end. Convert the subpattern | 154 | here. */ |
132 | to lowercase. */ | 155 | return got_positive; |
133 | for (subi = 0; | ||
134 | i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; | ||
135 | subi++, i++) | ||
136 | sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i]; | ||
137 | /* If subpattern too long, return failure (no match). */ | ||
138 | if (subi >= sizeof(sub) - 1) | ||
139 | return 0; | ||
140 | |||
141 | /* If the subpattern was terminated by a comma, skip the comma. */ | ||
142 | if (i < len && pattern[i] == ',') | ||
143 | i++; | ||
144 | |||
145 | /* Null-terminate the subpattern. */ | ||
146 | sub[subi] = '\0'; | ||
147 | |||
148 | /* Try to match the subpattern against the host name. */ | ||
149 | if (match_pattern(host, sub)) { | ||
150 | if (negated) | ||
151 | return 0; /* Fail if host matches any negated subpattern. */ | ||
152 | else | ||
153 | got_positive = 1; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /* Return success if got a positive match. If there was a negative match, | ||
158 | we have already returned zero and never get here. */ | ||
159 | return got_positive; | ||
160 | } | 156 | } |
161 | 157 | ||
162 | /* Checks whether the given host (which must be in all lowercase) is | 158 | /* Checks whether the given host (which must be in all lowercase) is |
163 | already in the list of our known hosts. | 159 | already in the list of our known hosts. |
164 | Returns HOST_OK if the host is known and has the specified key, | 160 | Returns HOST_OK if the host is known and has the specified key, |
165 | HOST_NEW if the host is not known, and HOST_CHANGED if the host is known | 161 | HOST_NEW if the host is not known, and HOST_CHANGED if the host is known |
@@ -167,87 +163,82 @@ match_hostname(const char *host, const char *pattern, unsigned int len) | |||
167 | 163 | ||
168 | HostStatus | 164 | HostStatus |
169 | check_host_in_hostfile(const char *filename, const char *host, | 165 | check_host_in_hostfile(const char *filename, const char *host, |
170 | BIGNUM *e, BIGNUM *n, BIGNUM *ke, BIGNUM *kn) | 166 | BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn) |
171 | { | 167 | { |
172 | FILE *f; | 168 | FILE *f; |
173 | char line[8192]; | 169 | char line[8192]; |
174 | int linenum = 0; | 170 | int linenum = 0; |
175 | unsigned int bits, kbits, hostlen; | 171 | unsigned int bits, kbits, hostlen; |
176 | char *cp, *cp2; | 172 | char *cp, *cp2; |
177 | HostStatus end_return; | 173 | HostStatus end_return; |
178 | 174 | ||
179 | /* Open the file containing the list of known hosts. */ | 175 | /* Open the file containing the list of known hosts. */ |
180 | f = fopen(filename, "r"); | 176 | f = fopen(filename, "r"); |
181 | if (!f) | 177 | if (!f) |
182 | return HOST_NEW; | 178 | return HOST_NEW; |
183 | 179 | ||
184 | /* Cache the length of the host name. */ | 180 | /* Cache the length of the host name. */ |
185 | hostlen = strlen(host); | 181 | hostlen = strlen(host); |
186 | 182 | ||
187 | /* Return value when the loop terminates. This is set to HOST_CHANGED if | 183 | /* Return value when the loop terminates. This is set to |
188 | we have seen a different key for the host and have not found the proper | 184 | HOST_CHANGED if we have seen a different key for the host and |
189 | one. */ | 185 | have not found the proper one. */ |
190 | end_return = HOST_NEW; | 186 | end_return = HOST_NEW; |
191 | 187 | ||
192 | /* size of modulus 'n' */ | 188 | /* size of modulus 'n' */ |
193 | bits = BN_num_bits(n); | 189 | bits = BN_num_bits(n); |
194 | 190 | ||
195 | /* Go trough the file. */ | 191 | /* Go trough the file. */ |
196 | while (fgets(line, sizeof(line), f)) | 192 | while (fgets(line, sizeof(line), f)) { |
197 | { | 193 | cp = line; |
198 | cp = line; | 194 | linenum++; |
199 | linenum++; | 195 | |
200 | 196 | /* Skip any leading whitespace. */ | |
201 | /* Skip any leading whitespace. */ | 197 | for (; *cp == ' ' || *cp == '\t'; cp++); |
202 | for (; *cp == ' ' || *cp == '\t'; cp++) | 198 | |
203 | ; | 199 | /* Ignore comment lines and empty lines. */ |
204 | 200 | if (!*cp || *cp == '#' || *cp == '\n') | |
205 | /* Ignore comment lines and empty lines. */ | 201 | continue; |
206 | if (!*cp || *cp == '#' || *cp == '\n') | 202 | |
207 | continue; | 203 | /* Find the end of the host name portion. */ |
208 | 204 | for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++); | |
209 | /* Find the end of the host name portion. */ | 205 | |
210 | for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) | 206 | /* Check if the host name matches. */ |
211 | ; | 207 | if (!match_hostname(host, cp, (unsigned int) (cp2 - cp))) |
212 | 208 | continue; | |
213 | /* Check if the host name matches. */ | 209 | |
214 | if (!match_hostname(host, cp, (unsigned int)(cp2 - cp))) | 210 | /* Got a match. Skip host name. */ |
215 | continue; | 211 | cp = cp2; |
216 | 212 | ||
217 | /* Got a match. Skip host name. */ | 213 | /* Extract the key from the line. This will skip any |
218 | cp = cp2; | 214 | leading whitespace. Ignore badly formatted lines. */ |
219 | 215 | if (!auth_rsa_read_key(&cp, &kbits, ke, kn)) | |
220 | /* Extract the key from the line. This will skip any leading | 216 | continue; |
221 | whitespace. Ignore badly formatted lines. */ | 217 | |
222 | if (!auth_rsa_read_key(&cp, &kbits, ke, kn)) | 218 | if (kbits != BN_num_bits(kn)) { |
223 | continue; | 219 | error("Warning: error in %s, line %d: keysize mismatch for host %s: " |
224 | 220 | "actual size %d vs. announced %d.", | |
225 | if (kbits != BN_num_bits(kn)) { | 221 | filename, linenum, host, BN_num_bits(kn), kbits); |
226 | error("Warning: error in %s, line %d: keysize mismatch for host %s: " | 222 | error("Warning: replace %d with %d in %s, line %d.", |
227 | "actual size %d vs. announced %d.", | 223 | kbits, BN_num_bits(kn), filename, linenum); |
228 | filename, linenum, host, BN_num_bits(kn), kbits); | 224 | } |
229 | error("Warning: replace %d with %d in %s, line %d.", | 225 | /* Check if the current key is the same as the given key. */ |
230 | kbits, BN_num_bits(kn), filename, linenum); | 226 | if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) { |
231 | } | 227 | /* Ok, they match. */ |
232 | 228 | fclose(f); | |
233 | /* Check if the current key is the same as the given key. */ | 229 | return HOST_OK; |
234 | if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) | 230 | } |
235 | { | 231 | /* They do not match. We will continue to go through the |
236 | /* Ok, they match. */ | 232 | file; however, we note that we will not return that it |
237 | fclose(f); | 233 | is new. */ |
238 | return HOST_OK; | 234 | end_return = HOST_CHANGED; |
239 | } | 235 | } |
240 | 236 | /* Clear variables and close the file. */ | |
241 | /* They do not match. We will continue to go through the file; however, | 237 | fclose(f); |
242 | we note that we will not return that it is new. */ | 238 | |
243 | end_return = HOST_CHANGED; | 239 | /* Return either HOST_NEW or HOST_CHANGED, depending on whether we |
244 | } | 240 | saw a different key for the host. */ |
245 | /* Clear variables and close the file. */ | 241 | return end_return; |
246 | fclose(f); | ||
247 | |||
248 | /* Return either HOST_NEW or HOST_CHANGED, depending on whether we saw a | ||
249 | different key for the host. */ | ||
250 | return end_return; | ||
251 | } | 242 | } |
252 | 243 | ||
253 | /* Appends an entry to the host file. Returns false if the entry | 244 | /* Appends an entry to the host file. Returns false if the entry |
@@ -255,40 +246,40 @@ check_host_in_hostfile(const char *filename, const char *host, | |||
255 | 246 | ||
256 | int | 247 | int |
257 | add_host_to_hostfile(const char *filename, const char *host, | 248 | add_host_to_hostfile(const char *filename, const char *host, |
258 | BIGNUM *e, BIGNUM *n) | 249 | BIGNUM * e, BIGNUM * n) |
259 | { | 250 | { |
260 | FILE *f; | 251 | FILE *f; |
261 | char *buf; | 252 | char *buf; |
262 | unsigned int bits; | 253 | unsigned int bits; |
263 | 254 | ||
264 | /* Open the file for appending. */ | 255 | /* Open the file for appending. */ |
265 | f = fopen(filename, "a"); | 256 | f = fopen(filename, "a"); |
266 | if (!f) | 257 | if (!f) |
267 | return 0; | 258 | return 0; |
268 | 259 | ||
269 | /* size of modulus 'n' */ | 260 | /* size of modulus 'n' */ |
270 | bits = BN_num_bits(n); | 261 | bits = BN_num_bits(n); |
271 | 262 | ||
272 | /* Print the host name and key to the file. */ | 263 | /* Print the host name and key to the file. */ |
273 | fprintf(f, "%s %u ", host, bits); | 264 | fprintf(f, "%s %u ", host, bits); |
274 | buf = BN_bn2dec(e); | 265 | buf = BN_bn2dec(e); |
275 | if (buf == NULL) { | 266 | if (buf == NULL) { |
276 | error("add_host_to_hostfile: BN_bn2dec(e) failed"); | 267 | error("add_host_to_hostfile: BN_bn2dec(e) failed"); |
277 | fclose(f); | 268 | fclose(f); |
278 | return 0; | 269 | return 0; |
279 | } | 270 | } |
280 | fprintf(f, "%s ", buf); | 271 | fprintf(f, "%s ", buf); |
281 | free (buf); | 272 | free(buf); |
282 | buf = BN_bn2dec(n); | 273 | buf = BN_bn2dec(n); |
283 | if (buf == NULL) { | 274 | if (buf == NULL) { |
284 | error("add_host_to_hostfile: BN_bn2dec(n) failed"); | 275 | error("add_host_to_hostfile: BN_bn2dec(n) failed"); |
285 | fclose(f); | 276 | fclose(f); |
286 | return 0; | 277 | return 0; |
287 | } | 278 | } |
288 | fprintf(f, "%s\n", buf); | 279 | fprintf(f, "%s\n", buf); |
289 | free (buf); | 280 | free(buf); |
290 | 281 | ||
291 | /* Close the file. */ | 282 | /* Close the file. */ |
292 | fclose(f); | 283 | fclose(f); |
293 | return 1; | 284 | return 1; |
294 | } | 285 | } |