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} |