]> andersk Git - openssh.git/blob - hostfile.c
- OpenBSD CVS update
[openssh.git] / hostfile.c
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"
17 RCSID("$OpenBSD: hostfile.c,v 1.14 2000/03/23 22:15:33 markus Exp $");
18
19 #ifdef HAVE_OPENSSL
20 #include <openssl/bn.h>
21 #include <openssl/rsa.h>
22 #include <openssl/dsa.h>
23 #endif
24 #ifdef HAVE_SSL
25 #include <ssl/bn.h>
26 #include <ssl/rsa.h>
27 #include <ssl/dsa.h>
28 #endif
29
30 #include "packet.h"
31 #include "match.h"
32 #include "ssh.h"
33 #include "key.h"
34 #include "hostfile.h"
35
36 /*
37  * Parses an RSA (number of bits, e, n) or DSA key from a string.  Moves the
38  * pointer over the key.  Skips any whitespace at the beginning and at end.
39  */
40
41 int
42 hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
43 {
44         unsigned int bits;
45         char *cp;
46
47         /* Skip leading whitespace. */
48         for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
49                 ;
50
51         /* Get number of bits. */
52         if (*cp < '0' || *cp > '9')
53                 return 0;       /* Bad bit count... */
54         for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
55                 bits = 10 * bits + *cp - '0';
56
57         if (!key_read(ret, bits, &cp))
58                 return 0;
59
60         /* Skip trailing whitespace. */
61         for (; *cp == ' ' || *cp == '\t'; cp++)
62                 ;
63
64         /* Return results. */
65         *cpp = cp;
66         *bitsp = bits;
67         return 1;
68 }
69
70 int
71 auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
72 {
73         Key *k = key_new(KEY_RSA);
74         int ret = hostfile_read_key(cpp, bitsp, k);
75         BN_copy(e, k->rsa->e);
76         BN_copy(n, k->rsa->n);
77         key_free(k);
78         return ret;
79 }
80
81 int
82 hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
83 {
84         if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
85                 return 1;
86         if (bits != BN_num_bits(key->rsa->n)) {
87                 error("Warning: %s, line %d: keysize mismatch for host %s: "
88                     "actual %d vs. announced %d.",
89                     filename, linenum, host, BN_num_bits(key->rsa->n), bits);
90                 error("Warning: replace %d with %d in %s, line %d.",
91                     bits, BN_num_bits(key->rsa->n), filename, linenum);
92         }
93         return 1;
94 }
95
96 /*
97  * Checks whether the given host (which must be in all lowercase) is already
98  * in the list of our known hosts. Returns HOST_OK if the host is known and
99  * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
100  * if the host is known but used to have a different host key.
101  */
102
103 HostStatus
104 check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found)
105 {
106         FILE *f;
107         char line[8192];
108         int linenum = 0;
109         unsigned int kbits, hostlen;
110         char *cp, *cp2;
111         HostStatus end_return;
112
113         if (key == NULL)
114                 fatal("no key to look up");
115         /* Open the file containing the list of known hosts. */
116         f = fopen(filename, "r");
117         if (!f)
118                 return HOST_NEW;
119
120         /* Cache the length of the host name. */
121         hostlen = strlen(host);
122
123         /*
124          * Return value when the loop terminates.  This is set to
125          * HOST_CHANGED if we have seen a different key for the host and have
126          * not found the proper one.
127          */
128         end_return = HOST_NEW;
129
130         /* Go trough the file. */
131         while (fgets(line, sizeof(line), f)) {
132                 cp = line;
133                 linenum++;
134
135                 /* Skip any leading whitespace, comments and empty lines. */
136                 for (; *cp == ' ' || *cp == '\t'; cp++)
137                         ;
138                 if (!*cp || *cp == '#' || *cp == '\n')
139                         continue;
140
141                 /* Find the end of the host name portion. */
142                 for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
143                         ;
144
145                 /* Check if the host name matches. */
146                 if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
147                         continue;
148
149                 /* Got a match.  Skip host name. */
150                 cp = cp2;
151
152                 /*
153                  * Extract the key from the line.  This will skip any leading
154                  * whitespace.  Ignore badly formatted lines.
155                  */
156                 if (!hostfile_read_key(&cp, &kbits, found))
157                         continue;
158                 if (!hostfile_check_key(kbits, found, host, filename, linenum))
159                         continue;
160
161                 /* Check if the current key is the same as the given key. */
162                 if (key_equal(key, found)) {
163                         /* Ok, they match. */
164                         fclose(f);
165                         return HOST_OK;
166                 }
167                 /*
168                  * They do not match.  We will continue to go through the
169                  * file; however, we note that we will not return that it is
170                  * new.
171                  */
172                 end_return = HOST_CHANGED;
173         }
174         /* Clear variables and close the file. */
175         fclose(f);
176
177         /*
178          * Return either HOST_NEW or HOST_CHANGED, depending on whether we
179          * saw a different key for the host.
180          */
181         return end_return;
182 }
183
184 /*
185  * Appends an entry to the host file.  Returns false if the entry could not
186  * be appended.
187  */
188
189 int
190 add_host_to_hostfile(const char *filename, const char *host, Key *key)
191 {
192         FILE *f;
193         int success = 0;
194
195         if (key == NULL)
196                 return 1;
197
198         /* Open the file for appending. */
199         f = fopen(filename, "a");
200         if (!f)
201                 return 0;
202
203         fprintf(f, "%s ", host);
204         if (key_write(key, f)) {
205                 fprintf(f, "\n");
206                 success = 1;
207         } else {
208                 error("add_host_to_hostfile: saving key failed");
209         }
210
211         /* Close the file. */
212         fclose(f);
213         return success;
214 }
This page took 0.572968 seconds and 5 git commands to generate.