Deleted Added
full compact
hostfile.c (57429) hostfile.c (58582)
1/*
2 *
3 * hostfile.c
4 *
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 *
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
9 *
10 * Created: Thu Jun 29 07:10:56 1995 ylo
11 *
12 * Functions for manipulating the known hosts files.
13 *
14 */
15
16#include "includes.h"
1/*
2 *
3 * hostfile.c
4 *
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 *
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
9 *
10 * Created: Thu Jun 29 07:10:56 1995 ylo
11 *
12 * Functions for manipulating the known hosts files.
13 *
14 */
15
16#include "includes.h"
17RCSID("$OpenBSD: hostfile.c,v 1.13 2000/02/18 10:20:20 markus Exp $");
17RCSID("$OpenBSD: hostfile.c,v 1.14 2000/03/23 22:15:33 markus Exp $");
18
19#include "packet.h"
18
19#include "packet.h"
20#include "match.h"
20#include "ssh.h"
21#include "ssh.h"
22#include <ssl/rsa.h>
23#include <ssl/dsa.h>
24#include "key.h"
25#include "hostfile.h"
21
22/*
26
27/*
23 * Reads a multiple-precision integer in decimal from the buffer, and advances
24 * the pointer. The integer must already be initialized. This function is
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 * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
29 * pointer over the key. Skips any whitespace at the beginning and at end.
28 */
29
30int
30 */
31
32int
31auth_rsa_read_bignum(char **cpp, BIGNUM * value)
33hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
32{
34{
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
72int
73auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
74{
75 unsigned int bits;
76 char *cp;
77
78 /* Skip leading whitespace. */
79 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
80 ;
81
82 /* Get number of bits. */
83 if (*cp < '0' || *cp > '9')
84 return 0; /* Bad bit count... */
85 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
86 bits = 10 * bits + *cp - '0';
87
35 unsigned int bits;
36 char *cp;
37
38 /* Skip leading whitespace. */
39 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
40 ;
41
42 /* Get number of bits. */
43 if (*cp < '0' || *cp > '9')
44 return 0; /* Bad bit count... */
45 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
46 bits = 10 * bits + *cp - '0';
47
88 /* Get public exponent. */
89 if (!auth_rsa_read_bignum(&cp, e))
48 if (!key_read(ret, bits, &cp))
90 return 0;
91
49 return 0;
50
92 /* Get public modulus. */
93 if (!auth_rsa_read_bignum(&cp, n))
94 return 0;
95
96 /* Skip trailing whitespace. */
97 for (; *cp == ' ' || *cp == '\t'; cp++)
98 ;
99
100 /* Return results. */
101 *cpp = cp;
102 *bitsp = bits;
103 return 1;
104}
105
51 /* Skip trailing whitespace. */
52 for (; *cp == ' ' || *cp == '\t'; cp++)
53 ;
54
55 /* Return results. */
56 *cpp = cp;
57 *bitsp = bits;
58 return 1;
59}
60
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
113int
61int
114match_hostname(const char *host, const char *pattern, unsigned int len)
62auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
115{
63{
116 char sub[1024];
117 int negated;
118 int got_positive;
119 unsigned int i, subi;
64 Key *k = key_new(KEY_RSA);
65 int ret = hostfile_read_key(cpp, bitsp, k);
66 BN_copy(e, k->rsa->e);
67 BN_copy(n, k->rsa->n);
68 key_free(k);
69 return ret;
70}
120
71
121 got_positive = 0;
122 for (i = 0; i < len;) {
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
149 /* Try to match the subpattern against the host name. */
150 if (match_pattern(host, sub)) {
151 if (negated)
152 return 0; /* Fail */
153 else
154 got_positive = 1;
155 }
72int
73hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
74{
75 if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
76 return 1;
77 if (bits != BN_num_bits(key->rsa->n)) {
78 error("Warning: %s, line %d: keysize mismatch for host %s: "
79 "actual %d vs. announced %d.",
80 filename, linenum, host, BN_num_bits(key->rsa->n), bits);
81 error("Warning: replace %d with %d in %s, line %d.",
82 bits, BN_num_bits(key->rsa->n), filename, linenum);
156 }
83 }
157
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;
84 return 1;
163}
164
165/*
166 * Checks whether the given host (which must be in all lowercase) is already
167 * in the list of our known hosts. Returns HOST_OK if the host is known and
168 * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
169 * if the host is known but used to have a different host key.
170 */
171
172HostStatus
85}
86
87/*
88 * Checks whether the given host (which must be in all lowercase) is already
89 * in the list of our known hosts. Returns HOST_OK if the host is known and
90 * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
91 * if the host is known but used to have a different host key.
92 */
93
94HostStatus
173check_host_in_hostfile(const char *filename, const char *host,
174 BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn)
95check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found)
175{
176 FILE *f;
177 char line[8192];
178 int linenum = 0;
179 unsigned int kbits, hostlen;
180 char *cp, *cp2;
181 HostStatus end_return;
182
96{
97 FILE *f;
98 char line[8192];
99 int linenum = 0;
100 unsigned int kbits, hostlen;
101 char *cp, *cp2;
102 HostStatus end_return;
103
104 if (key == NULL)
105 fatal("no key to look up");
183 /* Open the file containing the list of known hosts. */
184 f = fopen(filename, "r");
185 if (!f)
186 return HOST_NEW;
187
188 /* Cache the length of the host name. */
189 hostlen = strlen(host);
190

--- 25 unchanged lines hidden (view full) ---

216
217 /* Got a match. Skip host name. */
218 cp = cp2;
219
220 /*
221 * Extract the key from the line. This will skip any leading
222 * whitespace. Ignore badly formatted lines.
223 */
106 /* Open the file containing the list of known hosts. */
107 f = fopen(filename, "r");
108 if (!f)
109 return HOST_NEW;
110
111 /* Cache the length of the host name. */
112 hostlen = strlen(host);
113

--- 25 unchanged lines hidden (view full) ---

139
140 /* Got a match. Skip host name. */
141 cp = cp2;
142
143 /*
144 * Extract the key from the line. This will skip any leading
145 * whitespace. Ignore badly formatted lines.
146 */
224 if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
147 if (!hostfile_read_key(&cp, &kbits, found))
225 continue;
148 continue;
149 if (!hostfile_check_key(kbits, found, host, filename, linenum))
150 continue;
226
151
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. */
152 /* Check if the current key is the same as the given key. */
235 if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) {
153 if (key_equal(key, found)) {
236 /* Ok, they match. */
237 fclose(f);
238 return HOST_OK;
239 }
240 /*
241 * They do not match. We will continue to go through the
242 * file; however, we note that we will not return that it is
243 * new.

--- 11 unchanged lines hidden (view full) ---

255}
256
257/*
258 * Appends an entry to the host file. Returns false if the entry could not
259 * be appended.
260 */
261
262int
154 /* Ok, they match. */
155 fclose(f);
156 return HOST_OK;
157 }
158 /*
159 * They do not match. We will continue to go through the
160 * file; however, we note that we will not return that it is
161 * new.

--- 11 unchanged lines hidden (view full) ---

173}
174
175/*
176 * Appends an entry to the host file. Returns false if the entry could not
177 * be appended.
178 */
179
180int
263add_host_to_hostfile(const char *filename, const char *host,
264 BIGNUM * e, BIGNUM * n)
181add_host_to_hostfile(const char *filename, const char *host, Key *key)
265{
266 FILE *f;
182{
183 FILE *f;
267 char *buf;
268 unsigned int bits;
184 int success = 0;
269
185
186 if (key == NULL)
187 return 1;
188
270 /* Open the file for appending. */
271 f = fopen(filename, "a");
272 if (!f)
273 return 0;
274
189 /* Open the file for appending. */
190 f = fopen(filename, "a");
191 if (!f)
192 return 0;
193
275 /* size of modulus 'n' */
276 bits = BN_num_bits(n);
277
278 /* Print the host name and key to the file. */
279 fprintf(f, "%s %u ", host, bits);
280 buf = BN_bn2dec(e);
281 if (buf == NULL) {
282 error("add_host_to_hostfile: BN_bn2dec(e) failed");
283 fclose(f);
284 return 0;
194 fprintf(f, "%s ", host);
195 if (key_write(key, f)) {
196 fprintf(f, "\n");
197 success = 1;
198 } else {
199 error("add_host_to_hostfile: saving key failed");
285 }
200 }
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
297 /* Close the file. */
298 fclose(f);
201
202 /* Close the file. */
203 fclose(f);
299 return 1;
204 return success;
300}
205}