Annotation of src/usr.bin/ssh/hostfile.c, Revision 1.16
1.1 deraadt 1: /*
1.16 ! markus 2: *
1.8 deraadt 3: * hostfile.c
1.16 ! markus 4: *
1.8 deraadt 5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
1.16 ! markus 6: *
1.8 deraadt 7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
1.16 ! markus 9: *
1.8 deraadt 10: * Created: Thu Jun 29 07:10:56 1995 ylo
1.16 ! markus 11: *
1.8 deraadt 12: * Functions for manipulating the known hosts files.
1.16 ! markus 13: *
1.8 deraadt 14: */
1.1 deraadt 15:
16: #include "includes.h"
1.16 ! markus 17: RCSID("$OpenBSD: hostfile.c,v 1.15 2000/04/12 09:39:10 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.15 markus 22: #include <openssl/rsa.h>
23: #include <openssl/dsa.h>
1.14 markus 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: }