Annotation of src/usr.bin/ssh/hostfile.c, Revision 1.14
1.1 deraadt 1: /*
1.8 deraadt 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: */
1.1 deraadt 15:
16: #include "includes.h"
1.14 ! markus 17: RCSID("$OpenBSD: hostfile.c,v 1.5 2000/02/17 18:41:57 markus Exp $");
1.1 deraadt 18:
19: #include "packet.h"
1.14 ! markus 20: #include "match.h"
1.1 deraadt 21: #include "ssh.h"
1.14 ! markus 22: #include <ssl/rsa.h>
! 23: #include <ssl/dsa.h>
! 24: #include "key.h"
! 25: #include "hostfile.h"
1.1 deraadt 26:
1.9 markus 27: /*
1.14 ! markus 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.
1.9 markus 30: */
1.1 deraadt 31:
1.2 provos 32: int
1.14 ! markus 33: hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
1.1 deraadt 34: {
1.7 markus 35: unsigned int bits;
36: char *cp;
37:
38: /* Skip leading whitespace. */
1.9 markus 39: for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
40: ;
1.1 deraadt 41:
1.7 markus 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:
1.14 ! markus 48: if (!key_read(ret, bits, &cp))
1.7 markus 49: return 0;
50:
51: /* Skip trailing whitespace. */
1.9 markus 52: for (; *cp == ' ' || *cp == '\t'; cp++)
53: ;
1.7 markus 54:
55: /* Return results. */
56: *cpp = cp;
57: *bitsp = bits;
58: return 1;
1.1 deraadt 59: }
60:
1.14 ! markus 61: int
! 62: auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
! 63: {
! 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: }
1.1 deraadt 71:
1.2 provos 72: int
1.14 ! markus 73: hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
1.1 deraadt 74: {
1.14 ! markus 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);
1.1 deraadt 83: }
1.14 ! markus 84: return 1;
1.1 deraadt 85: }
86:
1.9 markus 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: */
1.1 deraadt 93:
1.2 provos 94: HostStatus
1.14 ! markus 95: check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found)
1.1 deraadt 96: {
1.7 markus 97: FILE *f;
98: char line[8192];
99: int linenum = 0;
1.12 markus 100: unsigned int kbits, hostlen;
1.7 markus 101: char *cp, *cp2;
102: HostStatus end_return;
103:
1.14 ! markus 104: if (key == NULL)
! 105: fatal("no key to look up");
1.7 markus 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:
1.9 markus 114: /*
115: * Return value when the loop terminates. This is set to
116: * HOST_CHANGED if we have seen a different key for the host and have
117: * not found the proper one.
118: */
1.7 markus 119: end_return = HOST_NEW;
120:
121: /* Go trough the file. */
122: while (fgets(line, sizeof(line), f)) {
123: cp = line;
124: linenum++;
125:
1.9 markus 126: /* Skip any leading whitespace, comments and empty lines. */
127: for (; *cp == ' ' || *cp == '\t'; cp++)
128: ;
1.7 markus 129: if (!*cp || *cp == '#' || *cp == '\n')
130: continue;
131:
132: /* Find the end of the host name portion. */
1.9 markus 133: for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
134: ;
1.7 markus 135:
136: /* Check if the host name matches. */
137: if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
138: continue;
139:
140: /* Got a match. Skip host name. */
141: cp = cp2;
142:
1.9 markus 143: /*
144: * Extract the key from the line. This will skip any leading
145: * whitespace. Ignore badly formatted lines.
146: */
1.14 ! markus 147: if (!hostfile_read_key(&cp, &kbits, found))
! 148: continue;
! 149: if (!hostfile_check_key(kbits, found, host, filename, linenum))
1.7 markus 150: continue;
151:
152: /* Check if the current key is the same as the given key. */
1.14 ! markus 153: if (key_equal(key, found)) {
1.7 markus 154: /* Ok, they match. */
155: fclose(f);
156: return HOST_OK;
157: }
1.9 markus 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.
162: */
1.7 markus 163: end_return = HOST_CHANGED;
1.1 deraadt 164: }
1.7 markus 165: /* Clear variables and close the file. */
166: fclose(f);
167:
1.9 markus 168: /*
169: * Return either HOST_NEW or HOST_CHANGED, depending on whether we
170: * saw a different key for the host.
171: */
1.7 markus 172: return end_return;
1.1 deraadt 173: }
174:
1.9 markus 175: /*
176: * Appends an entry to the host file. Returns false if the entry could not
177: * be appended.
178: */
1.1 deraadt 179:
1.2 provos 180: int
1.14 ! markus 181: add_host_to_hostfile(const char *filename, const char *host, Key *key)
1.1 deraadt 182: {
1.7 markus 183: FILE *f;
1.14 ! markus 184: int success = 0;
! 185:
! 186: if (key == NULL)
! 187: return 1;
1.7 markus 188:
189: /* Open the file for appending. */
190: f = fopen(filename, "a");
191: if (!f)
192: return 0;
193:
1.14 ! markus 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");
1.7 markus 200: }
201:
202: /* Close the file. */
203: fclose(f);
1.14 ! markus 204: return success;
1.1 deraadt 205: }