|
|
f806d6 |
diff -up openssh-8.0p1/hostfile.c.cve-2020-14145 openssh-8.0p1/hostfile.c
|
|
|
f806d6 |
--- openssh-8.0p1/hostfile.c.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200
|
|
|
f806d6 |
+++ openssh-8.0p1/hostfile.c 2021-05-17 16:53:38.694577251 +0200
|
|
|
f806d6 |
@@ -409,6 +409,18 @@ lookup_key_in_hostkeys_by_type(struct ho
|
|
|
f806d6 |
found) == HOST_FOUND);
|
|
|
f806d6 |
}
|
|
|
f806d6 |
|
|
|
f806d6 |
+int
|
|
|
f806d6 |
+lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker)
|
|
|
f806d6 |
+{
|
|
|
f806d6 |
+ u_int i;
|
|
|
f806d6 |
+
|
|
|
f806d6 |
+ for (i = 0; i < hostkeys->num_entries; i++) {
|
|
|
f806d6 |
+ if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker)
|
|
|
f806d6 |
+ return 1;
|
|
|
f806d6 |
+ }
|
|
|
f806d6 |
+ return 0;
|
|
|
f806d6 |
+}
|
|
|
f806d6 |
+
|
|
|
f806d6 |
static int
|
|
|
f806d6 |
write_host_entry(FILE *f, const char *host, const char *ip,
|
|
|
f806d6 |
const struct sshkey *key, int store_hash)
|
|
|
f806d6 |
diff -up openssh-8.0p1/hostfile.h.cve-2020-14145 openssh-8.0p1/hostfile.h
|
|
|
f806d6 |
--- openssh-8.0p1/hostfile.h.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200
|
|
|
f806d6 |
+++ openssh-8.0p1/hostfile.h 2021-05-17 16:53:38.694577251 +0200
|
|
|
f806d6 |
@@ -39,6 +39,7 @@ HostStatus check_key_in_hostkeys(struct
|
|
|
f806d6 |
const struct hostkey_entry **);
|
|
|
f806d6 |
int lookup_key_in_hostkeys_by_type(struct hostkeys *, int,
|
|
|
f806d6 |
const struct hostkey_entry **);
|
|
|
f806d6 |
+int lookup_marker_in_hostkeys(struct hostkeys *, int);
|
|
|
f806d6 |
|
|
|
f806d6 |
int hostfile_read_key(char **, u_int *, struct sshkey *);
|
|
|
f806d6 |
int add_host_to_hostfile(const char *, const char *,
|
|
|
f806d6 |
diff -up openssh-8.0p1/sshconnect2.c.cve-2020-14145 openssh-8.0p1/sshconnect2.c
|
|
|
f806d6 |
--- openssh-8.0p1/sshconnect2.c.cve-2020-14145 2021-05-17 16:53:38.610576561 +0200
|
|
|
f806d6 |
+++ openssh-8.0p1/sshconnect2.c 2021-05-17 16:54:58.169230103 +0200
|
|
|
f806d6 |
@@ -98,12 +98,25 @@ verify_host_key_callback(struct sshkey *
|
|
|
f806d6 |
return 0;
|
|
|
f806d6 |
}
|
|
|
f806d6 |
|
|
|
f806d6 |
+/* Returns the first item from a comma-separated algorithm list */
|
|
|
f806d6 |
+static char *
|
|
|
f806d6 |
+first_alg(const char *algs)
|
|
|
f806d6 |
+{
|
|
|
f806d6 |
+ char *ret, *cp;
|
|
|
f806d6 |
+
|
|
|
f806d6 |
+ ret = xstrdup(algs);
|
|
|
f806d6 |
+ if ((cp = strchr(ret, ',')) != NULL)
|
|
|
f806d6 |
+ *cp = '\0';
|
|
|
f806d6 |
+ return ret;
|
|
|
f806d6 |
+}
|
|
|
f806d6 |
+
|
|
|
f806d6 |
static char *
|
|
|
f806d6 |
order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
|
|
|
f806d6 |
{
|
|
|
f806d6 |
- char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
|
|
|
f806d6 |
+ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL;
|
|
|
f806d6 |
+ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL;
|
|
|
f806d6 |
size_t maxlen;
|
|
|
f806d6 |
- struct hostkeys *hostkeys;
|
|
|
f806d6 |
+ struct hostkeys *hostkeys = NULL;
|
|
|
f806d6 |
int ktype;
|
|
|
f806d6 |
u_int i;
|
|
|
f806d6 |
|
|
|
f806d6 |
@@ -115,6 +128,26 @@ order_hostkeyalgs(char *host, struct soc
|
|
|
f806d6 |
for (i = 0; i < options.num_system_hostfiles; i++)
|
|
|
f806d6 |
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
|
|
|
f806d6 |
|
|
|
f806d6 |
+ /*
|
|
|
f806d6 |
+ * If a plain public key exists that matches the type of the best
|
|
|
f806d6 |
+ * preference HostkeyAlgorithms, then use the whole list as is.
|
|
|
f806d6 |
+ * Note that we ignore whether the best preference algorithm is a
|
|
|
f806d6 |
+ * certificate type, as sshconnect.c will downgrade certs to
|
|
|
f806d6 |
+ * plain keys if necessary.
|
|
|
f806d6 |
+ */
|
|
|
f806d6 |
+ best = first_alg(options.hostkeyalgorithms);
|
|
|
f806d6 |
+ if (lookup_key_in_hostkeys_by_type(hostkeys,
|
|
|
f806d6 |
+ sshkey_type_plain(sshkey_type_from_name(best)), NULL)) {
|
|
|
f806d6 |
+ debug3("%s: have matching best-preference key type %s, "
|
|
|
f806d6 |
+ "using HostkeyAlgorithms verbatim", __func__, best);
|
|
|
f806d6 |
+ ret = xstrdup(options.hostkeyalgorithms);
|
|
|
f806d6 |
+ goto out;
|
|
|
f806d6 |
+ }
|
|
|
f806d6 |
+
|
|
|
f806d6 |
+ /*
|
|
|
f806d6 |
+ * Otherwise, prefer the host key algorithms that match known keys
|
|
|
f806d6 |
+ * while keeping the ordering of HostkeyAlgorithms as much as possible.
|
|
|
f806d6 |
+ */
|
|
|
f806d6 |
oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
|
|
|
f806d6 |
maxlen = strlen(avail) + 1;
|
|
|
f806d6 |
first = xmalloc(maxlen);
|
|
|
f806d6 |
@@ -131,11 +164,23 @@ order_hostkeyalgs(char *host, struct soc
|
|
|
f806d6 |
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
|
|
|
f806d6 |
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
|
|
|
f806d6 |
fatal("%s: unknown alg %s", __func__, alg);
|
|
|
f806d6 |
+ /*
|
|
|
f806d6 |
+ * If we have a @cert-authority marker in known_hosts then
|
|
|
f806d6 |
+ * prefer all certificate algorithms.
|
|
|
f806d6 |
+ */
|
|
|
f806d6 |
+ if (sshkey_type_is_cert(ktype) &&
|
|
|
f806d6 |
+ lookup_marker_in_hostkeys(hostkeys, MRK_CA)) {
|
|
|
f806d6 |
+ ALG_APPEND(first, alg);
|
|
|
f806d6 |
+ continue;
|
|
|
f806d6 |
+ }
|
|
|
f806d6 |
+ /* If the key appears in known_hosts then prefer it */
|
|
|
f806d6 |
if (lookup_key_in_hostkeys_by_type(hostkeys,
|
|
|
f806d6 |
- sshkey_type_plain(ktype), NULL))
|
|
|
f806d6 |
+ sshkey_type_plain(ktype), NULL)) {
|
|
|
f806d6 |
ALG_APPEND(first, alg);
|
|
|
f806d6 |
- else
|
|
|
f806d6 |
- ALG_APPEND(last, alg);
|
|
|
f806d6 |
+ continue;
|
|
|
f806d6 |
+ }
|
|
|
f806d6 |
+ /* Otherwise, put it last */
|
|
|
f806d6 |
+ ALG_APPEND(last, alg);
|
|
|
f806d6 |
}
|
|
|
f806d6 |
#undef ALG_APPEND
|
|
|
f806d6 |
xasprintf(&ret, "%s%s%s", first,
|
|
|
f806d6 |
@@ -143,6 +188,8 @@ order_hostkeyalgs(char *host, struct soc
|
|
|
f806d6 |
if (*first != '\0')
|
|
|
f806d6 |
debug3("%s: prefer hostkeyalgs: %s", __func__, first);
|
|
|
f806d6 |
|
|
|
f806d6 |
+ out:
|
|
|
f806d6 |
+ free(best);
|
|
|
f806d6 |
free(first);
|
|
|
f806d6 |
free(last);
|
|
|
f806d6 |
free(hostname);
|