source: trunk/third/openssh/hostfile.c @ 18759

Revision 18759, 6.6 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Functions for manipulating the known hosts files.
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose.  Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 *
13 *
14 * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
15 * Copyright (c) 1999 Niels Provos.  All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "includes.h"
39RCSID("$OpenBSD: hostfile.c,v 1.30 2002/07/24 16:11:18 markus Exp $");
40
41#include "packet.h"
42#include "match.h"
43#include "key.h"
44#include "hostfile.h"
45#include "log.h"
46
47/*
48 * Parses an RSA (number of bits, e, n) or DSA key from a string.  Moves the
49 * pointer over the key.  Skips any whitespace at the beginning and at end.
50 */
51
52int
53hostfile_read_key(char **cpp, u_int *bitsp, Key *ret)
54{
55        char *cp;
56
57        /* Skip leading whitespace. */
58        for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
59                ;
60
61        if (key_read(ret, &cp) != 1)
62                return 0;
63
64        /* Skip trailing whitespace. */
65        for (; *cp == ' ' || *cp == '\t'; cp++)
66                ;
67
68        /* Return results. */
69        *cpp = cp;
70        *bitsp = key_size(ret);
71        return 1;
72}
73
74static int
75hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
76{
77        if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
78                return 1;
79        if (bits != BN_num_bits(key->rsa->n)) {
80                log("Warning: %s, line %d: keysize mismatch for host %s: "
81                    "actual %d vs. announced %d.",
82                    filename, linenum, host, BN_num_bits(key->rsa->n), bits);
83                log("Warning: replace %d with %d in %s, line %d.",
84                    bits, BN_num_bits(key->rsa->n), filename, linenum);
85        }
86        return 1;
87}
88
89/*
90 * Checks whether the given host (which must be in all lowercase) is already
91 * in the list of our known hosts. Returns HOST_OK if the host is known and
92 * has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
93 * if the host is known but used to have a different host key.
94 *
95 * If no 'key' has been specified and a key of type 'keytype' is known
96 * for the specified host, then HOST_FOUND is returned.
97 */
98
99static HostStatus
100check_host_in_hostfile_by_key_or_type(const char *filename,
101    const char *host, Key *key, int keytype, Key *found, int *numret)
102{
103        FILE *f;
104        char line[8192];
105        int linenum = 0;
106        u_int kbits;
107        char *cp, *cp2;
108        HostStatus end_return;
109
110        debug3("check_host_in_hostfile: filename %s", filename);
111
112        /* Open the file containing the list of known hosts. */
113        f = fopen(filename, "r");
114        if (!f)
115                return HOST_NEW;
116
117        /*
118         * Return value when the loop terminates.  This is set to
119         * HOST_CHANGED if we have seen a different key for the host and have
120         * not found the proper one.
121         */
122        end_return = HOST_NEW;
123
124        /* Go through the file. */
125        while (fgets(line, sizeof(line), f)) {
126                cp = line;
127                linenum++;
128
129                /* Skip any leading whitespace, comments and empty lines. */
130                for (; *cp == ' ' || *cp == '\t'; cp++)
131                        ;
132                if (!*cp || *cp == '#' || *cp == '\n')
133                        continue;
134
135                /* Find the end of the host name portion. */
136                for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
137                        ;
138
139                /* Check if the host name matches. */
140                if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1)
141                        continue;
142
143                /* Got a match.  Skip host name. */
144                cp = cp2;
145
146                /*
147                 * Extract the key from the line.  This will skip any leading
148                 * whitespace.  Ignore badly formatted lines.
149                 */
150                if (!hostfile_read_key(&cp, &kbits, found))
151                        continue;
152
153                if (numret != NULL)
154                        *numret = linenum;
155
156                if (key == NULL) {
157                        /* we found a key of the requested type */
158                        if (found->type == keytype)
159                                return HOST_FOUND;
160                        continue;
161                }
162
163                if (!hostfile_check_key(kbits, found, host, filename, linenum))
164                        continue;
165
166                /* Check if the current key is the same as the given key. */
167                if (key_equal(key, found)) {
168                        /* Ok, they match. */
169                        debug3("check_host_in_hostfile: match line %d", linenum);
170                        fclose(f);
171                        return HOST_OK;
172                }
173                /*
174                 * They do not match.  We will continue to go through the
175                 * file; however, we note that we will not return that it is
176                 * new.
177                 */
178                end_return = HOST_CHANGED;
179        }
180        /* Clear variables and close the file. */
181        fclose(f);
182
183        /*
184         * Return either HOST_NEW or HOST_CHANGED, depending on whether we
185         * saw a different key for the host.
186         */
187        return end_return;
188}
189
190HostStatus
191check_host_in_hostfile(const char *filename, const char *host, Key *key,
192    Key *found, int *numret)
193{
194        if (key == NULL)
195                fatal("no key to look up");
196        return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
197            found, numret));
198}
199
200int
201lookup_key_in_hostfile_by_type(const char *filename, const char *host,
202    int keytype, Key *found, int *numret)
203{
204        return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
205            keytype, found, numret) == HOST_FOUND);
206}
207
208/*
209 * Appends an entry to the host file.  Returns false if the entry could not
210 * be appended.
211 */
212
213int
214add_host_to_hostfile(const char *filename, const char *host, Key *key)
215{
216        FILE *f;
217        int success = 0;
218        if (key == NULL)
219                return 1;       /* XXX ? */
220        f = fopen(filename, "a");
221        if (!f)
222                return 0;
223        fprintf(f, "%s ", host);
224        if (key_write(key, f)) {
225                success = 1;
226        } else {
227                error("add_host_to_hostfile: saving key in %s failed", filename);
228        }
229        fprintf(f, "\n");
230        fclose(f);
231        return success;
232}
Note: See TracBrowser for help on using the repository browser.