From 7bc8c3085921c3f9ef77a347c91d9bea529350b9 Mon Sep 17 00:00:00 2001 From: djm Date: Sun, 18 Jan 2015 21:48:09 +0000 Subject: [PATCH] convert load_hostkeys() (hostkey ordering and known_host matching) to use the new hostkey_foreach() iterator; ok markus --- usr.bin/ssh/hostfile.c | 141 +++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 89 deletions(-) diff --git a/usr.bin/ssh/hostfile.c b/usr.bin/ssh/hostfile.c index 1389c82dd0c..dfba67e99e8 100644 --- a/usr.bin/ssh/hostfile.c +++ b/usr.bin/ssh/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.60 2015/01/18 21:40:23 djm Exp $ */ +/* $OpenBSD: hostfile.c,v 1.61 2015/01/18 21:48:09 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -241,100 +241,64 @@ init_hostkeys(void) return ret; } -void -load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) -{ - FILE *f; - char line[8192]; - u_long linenum = 0, num_loaded = 0; - char *cp, *cp2, *hashed_host; - HostkeyMarker marker; - struct sshkey *key; - u_int kbits; - - if ((f = fopen(path, "r")) == NULL) - return; - debug3("%s: loading entries for host \"%.100s\" from file \"%s\"", - __func__, host, path); - while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { - cp = line; +struct load_callback_ctx { + const char *host; + u_long num_loaded; + struct hostkeys *hostkeys; +}; - /* Skip any leading whitespace, comments and empty lines. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '#' || *cp == '\n') - continue; +static int +record_hostkey(struct hostkey_foreach_line *l, void *_ctx) +{ + struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx; + struct hostkeys *hostkeys = ctx->hostkeys; + struct hostkey_entry *tmp; - if ((marker = check_markers(&cp)) == MRK_ERROR) { - verbose("%s: invalid marker at %s:%lu", - __func__, path, linenum); - continue; - } + if (l->status == HKF_STATUS_INVALID) { + error("%s:%ld: parse error in hostkeys file", + l->path, l->linenum); + return 0; + } - /* Find the end of the host name portion. */ - for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) - ; + debug3("%s: found %skey type %s in file %s:%lu", __func__, + l->marker == MRK_NONE ? "" : + (l->marker == MRK_CA ? "ca " : "revoked "), + sshkey_type(l->key), l->path, l->linenum); + if ((tmp = reallocarray(hostkeys->entries, + hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL) + return SSH_ERR_ALLOC_FAIL; + hostkeys->entries = tmp; + hostkeys->entries[hostkeys->num_entries].host = xstrdup(ctx->host); + hostkeys->entries[hostkeys->num_entries].file = xstrdup(l->path); + hostkeys->entries[hostkeys->num_entries].line = l->linenum; + hostkeys->entries[hostkeys->num_entries].key = l->key; + l->key = NULL; /* steal it */ + hostkeys->entries[hostkeys->num_entries].marker = l->marker; + hostkeys->num_entries++; + ctx->num_loaded++; - /* Check if the host name matches. */ - if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { - if (*cp != HASH_DELIM) - continue; - hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); - if (hashed_host == NULL) { - debug("Invalid hashed host line %lu of %s", - linenum, path); - continue; - } - if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) - continue; - } + return 0; +} - /* Got a match. Skip host name. */ - cp = cp2; +void +load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) +{ + int r; + struct load_callback_ctx ctx; - /* - * Extract the key from the line. This will skip any leading - * whitespace. Ignore badly formatted lines. - */ - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { - error("%s: sshkey_new failed", __func__); - break; - } - if (!hostfile_read_key(&cp, &kbits, key)) { - sshkey_free(key); -#ifdef WITH_SSH1 - if ((key = sshkey_new(KEY_RSA1)) == NULL) { - error("%s: sshkey_new failed", __func__); - break; - } - if (!hostfile_read_key(&cp, &kbits, key)) { - sshkey_free(key); - continue; - } -#else - continue; -#endif - } - if (!hostfile_check_key(kbits, key, host, path, linenum)) - continue; + ctx.host = host; + ctx.num_loaded = 0; + ctx.hostkeys = hostkeys; - debug3("%s: found %skey type %s in file %s:%lu", __func__, - marker == MRK_NONE ? "" : - (marker == MRK_CA ? "ca " : "revoked "), - sshkey_type(key), path, linenum); - hostkeys->entries = xrealloc(hostkeys->entries, - hostkeys->num_entries + 1, sizeof(*hostkeys->entries)); - hostkeys->entries[hostkeys->num_entries].host = xstrdup(host); - hostkeys->entries[hostkeys->num_entries].file = xstrdup(path); - hostkeys->entries[hostkeys->num_entries].line = linenum; - hostkeys->entries[hostkeys->num_entries].key = key; - hostkeys->entries[hostkeys->num_entries].marker = marker; - hostkeys->num_entries++; - num_loaded++; + if ((r = hostkeys_foreach(path, record_hostkey, &ctx, host, + HKF_WANT_MATCH_HOST|HKF_WANT_PARSE_KEY)) != 0) { + if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT) + debug("%s: hostkeys_foreach failed for %s: %s", + __func__, path, ssh_err(r)); } - debug3("%s: loaded %lu keys", __func__, num_loaded); - fclose(f); - return; + if (ctx.num_loaded != 0) + debug3("%s: loaded %lu keys from %s", __func__, + ctx.num_loaded, host); } void @@ -467,7 +431,6 @@ lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, * Appends an entry to the host file. Returns false if the entry could not * be appended. */ - int add_host_to_hostfile(const char *filename, const char *host, const struct sshkey *key, int store_hash) @@ -484,7 +447,7 @@ add_host_to_hostfile(const char *filename, const char *host, if (store_hash) { if ((hashed_host = host_hash(host, NULL, 0)) == NULL) { - error("add_host_to_hostfile: host_hash failed"); + error("%s: host_hash failed", __func__); fclose(f); return 0; } -- 2.20.1