summaryrefslogtreecommitdiff
path: root/hostfile.c
diff options
context:
space:
mode:
authorAlistair Delva <adelva@google.com>2020-08-21 00:00:13 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-08-21 00:00:13 +0000
commited358b3546c776c1c677fd88eb8f716cf6187510 (patch)
tree3c6134bcb2cda4b9dccc57b4a8b997a945aab62d /hostfile.c
parent22246b08952d746a7cc5a292570636cf4277598f (diff)
parent44a1065de8a58c51a021243a28bfa01e87822e4f (diff)
Merge changes I934c73d4,I28cdc9a0,I9e734da9,I3c079d86
* changes: UPSTREAM: depend UPSTREAM: upstream: avoid possible NULL deref; from Pedro Martelletto Revert "upstream: fix compilation with DEBUG_KEXDH; bz#3160 ok dtucker@" Merge upstream-master into master
Diffstat (limited to 'hostfile.c')
-rw-r--r--hostfile.c91
1 files changed, 36 insertions, 55 deletions
diff --git a/hostfile.c b/hostfile.c
index b235795e..a4a35597 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.64 2015/02/16 22:08:57 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.79 2020/03/06 18:25:12 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -49,7 +49,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <unistd.h>
#include "xmalloc.h"
@@ -123,14 +122,13 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
u_char salt[256], result[256];
char uu_salt[512], uu_result[512];
static char encoded[1024];
- u_int i, len;
+ u_int len;
len = ssh_digest_bytes(SSH_DIGEST_SHA1);
if (name_from_hostfile == NULL) {
/* Create new salt */
- for (i = 0; i < len; i++)
- salt[i] = arc4random();
+ arc4random_buf(salt, len);
} else {
/* Extract salt from known host entry */
if (extract_salt(name_from_hostfile, src_len, salt,
@@ -164,13 +162,12 @@ int
hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret)
{
char *cp;
- int r;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
- if ((r = sshkey_read(ret, &cp)) != 0)
+ if (sshkey_read(ret, &cp) != 0)
return 0;
/* Skip trailing whitespace. */
@@ -242,7 +239,8 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
struct hostkey_entry *tmp;
if (l->status == HKF_STATUS_INVALID) {
- error("%s:%ld: parse error in hostkeys file",
+ /* XXX make this verbose() in the future */
+ debug("%s:%ld: parse error in hostkeys file",
l->path, l->linenum);
return 0;
}
@@ -251,7 +249,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
l->marker == MRK_NONE ? "" :
(l->marker == MRK_CA ? "ca " : "revoked "),
sshkey_type(l->key), l->path, l->linenum);
- if ((tmp = reallocarray(hostkeys->entries,
+ if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries,
hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL)
return SSH_ERR_ALLOC_FAIL;
hostkeys->entries = tmp;
@@ -300,8 +298,7 @@ free_hostkeys(struct hostkeys *hostkeys)
explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
}
free(hostkeys->entries);
- explicit_bzero(hostkeys, sizeof(*hostkeys));
- free(hostkeys);
+ freezero(hostkeys, sizeof(*hostkeys));
}
static int
@@ -315,7 +312,7 @@ check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k)
continue;
if (sshkey_equal_public(k, hostkeys->entries[i].key))
return -1;
- if (is_cert &&
+ if (is_cert && k != NULL &&
sshkey_equal_public(k->cert->signature_key,
hostkeys->entries[i].key))
return -1;
@@ -346,16 +343,11 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
HostStatus end_return = HOST_NEW;
int want_cert = sshkey_is_cert(k);
HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE;
- int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2;
if (found != NULL)
*found = NULL;
for (i = 0; i < hostkeys->num_entries; i++) {
- if (proto == 1 && hostkeys->entries[i].key->type != KEY_RSA1)
- continue;
- if (proto == 2 && hostkeys->entries[i].key->type == KEY_RSA1)
- continue;
if (hostkeys->entries[i].marker != want_marker)
continue;
if (k == NULL) {
@@ -419,19 +411,24 @@ write_host_entry(FILE *f, const char *host, const char *ip,
const struct sshkey *key, int store_hash)
{
int r, success = 0;
- char *hashed_host = NULL;
+ char *hashed_host = NULL, *lhost;
+
+ lhost = xstrdup(host);
+ lowercase(lhost);
if (store_hash) {
- if ((hashed_host = host_hash(host, NULL, 0)) == NULL) {
+ if ((hashed_host = host_hash(lhost, NULL, 0)) == NULL) {
error("%s: host_hash failed", __func__);
+ free(lhost);
return 0;
}
fprintf(f, "%s ", hashed_host);
} else if (ip != NULL)
- fprintf(f, "%s,%s ", host, ip);
- else
- fprintf(f, "%s ", host);
-
+ fprintf(f, "%s,%s ", lhost, ip);
+ else {
+ fprintf(f, "%s ", lhost);
+ }
+ free(lhost);
if ((r = sshkey_write(key, f)) == 0)
success = 1;
else
@@ -485,13 +482,6 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx)
return 0;
}
- /* XXX might need a knob for this later */
- /* Don't remove RSA1 keys */
- if (l->key->type == KEY_RSA1) {
- fprintf(ctx->out, "%s\n", l->line);
- return 0;
- }
-
/*
* If this line contains one of the keys that we will be
* adding later, then don't change it and mark the key for
@@ -552,8 +542,8 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
/*
* Prepare temporary file for in-place deletion.
*/
- if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) < 0 ||
- (r = asprintf(&back, "%s.old", filename)) < 0) {
+ if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) == -1 ||
+ (r = asprintf(&back, "%s.old", filename)) == -1) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -575,6 +565,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
/* Remove all entries for the specified host from the file */
if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip,
HKF_WANT_PARSE_KEY)) != 0) {
+ oerrno = errno;
error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
goto fail;
}
@@ -662,7 +653,7 @@ match_maybe_hashed(const char *host, const char *names, int *was_hashed)
return nlen == strlen(hashed_host) &&
strncmp(hashed_host, names, nlen) == 0;
}
- return match_hostname(host, names, nlen) == 1;
+ return match_hostname(host, names) == 1;
}
int
@@ -670,14 +661,14 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
const char *host, const char *ip, u_int options)
{
FILE *f;
- char line[8192], oline[8192], ktype[128];
+ char *line = NULL, ktype[128];
u_long linenum = 0;
char *cp, *cp2;
u_int kbits;
int hashed;
int s, r = 0;
struct hostkey_foreach_line lineinfo;
- size_t l;
+ size_t linesize = 0, l;
memset(&lineinfo, 0, sizeof(lineinfo));
if (host == NULL && (options & HKF_WANT_MATCH) != 0)
@@ -686,15 +677,16 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
return SSH_ERR_SYSTEM_ERROR;
debug3("%s: reading file \"%s\"", __func__, path);
- while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) {
+ while (getline(&line, &linesize, f) != -1) {
+ linenum++;
line[strcspn(line, "\n")] = '\0';
- strlcpy(oline, line, sizeof(oline));
+ free(lineinfo.line);
sshkey_free(lineinfo.key);
memset(&lineinfo, 0, sizeof(lineinfo));
lineinfo.path = path;
lineinfo.linenum = linenum;
- lineinfo.line = oline;
+ lineinfo.line = xstrdup(line);
lineinfo.marker = MRK_NONE;
lineinfo.status = HKF_STATUS_OK;
lineinfo.keytype = KEY_UNSPEC;
@@ -784,20 +776,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
break;
}
if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) {
-#ifdef WITH_SSH1
- sshkey_free(lineinfo.key);
- lineinfo.key = sshkey_new(KEY_RSA1);
- if (lineinfo.key == NULL) {
- error("%s: sshkey_new fail", __func__);
- r = SSH_ERR_ALLOC_FAIL;
- break;
- }
- if (!hostfile_read_key(&cp, &kbits,
- lineinfo.key))
- goto bad;
-#else
goto bad;
-#endif
}
lineinfo.keytype = lineinfo.key->type;
lineinfo.comment = cp;
@@ -810,15 +789,15 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
memcpy(ktype, lineinfo.rawkey, l);
ktype[l] = '\0';
lineinfo.keytype = sshkey_type_from_name(ktype);
-#ifdef WITH_SSH1
+
/*
- * Assume RSA1 if the first component is a short
+ * Assume legacy RSA1 if the first component is a short
* decimal number.
*/
if (lineinfo.keytype == KEY_UNSPEC && l < 8 &&
strspn(ktype, "0123456789") == l)
- lineinfo.keytype = KEY_RSA1;
-#endif
+ goto bad;
+
/*
* Check that something other than whitespace follows
* the key type. This won't catch all corruption, but
@@ -846,6 +825,8 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
break;
}
sshkey_free(lineinfo.key);
+ free(lineinfo.line);
+ free(line);
fclose(f);
return r;
}