summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-09-18 05:23:03 +0000
committerDamien Miller <djm@mindrot.org>2020-09-18 15:25:01 +1000
commitb3855ff053f5078ec3d3c653cdaedefaa5fc362d (patch)
treeea3e00e58cde7d1a35b138608030ad05c9160b85
parentf93b187ab900c7d12875952cc63350fe4de8a0a8 (diff)
upstream: tweak the client hostkey preference ordering algorithm to
prefer the default ordering if the user has a key that matches the best-preference default algorithm. feedback and ok markus@ OpenBSD-Commit-ID: a92dd7d7520ddd95c0a16786a7519e6d0167d35f
-rw-r--r--sshconnect2.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 347e348c6..f64aae66a 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.325 2020/08/27 01:06:18 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.326 2020/09/18 05:23:03 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -102,12 +102,25 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
102 return 0; 102 return 0;
103} 103}
104 104
105/* Returns the first item from a comma-separated algorithm list */
106static char *
107first_alg(const char *algs)
108{
109 char *ret, *cp;
110
111 ret = xstrdup(algs);
112 if ((cp = strchr(ret, ',')) != NULL)
113 *cp = '\0';
114 return ret;
115}
116
105static char * 117static char *
106order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) 118order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
107{ 119{
108 char *oavail, *avail, *first, *last, *alg, *hostname, *ret; 120 char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL;
121 char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL;
109 size_t maxlen; 122 size_t maxlen;
110 struct hostkeys *hostkeys; 123 struct hostkeys *hostkeys = NULL;
111 int ktype; 124 int ktype;
112 u_int i; 125 u_int i;
113 126
@@ -119,6 +132,26 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
119 for (i = 0; i < options.num_system_hostfiles; i++) 132 for (i = 0; i < options.num_system_hostfiles; i++)
120 load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]); 133 load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
121 134
135 /*
136 * If a plain public key exists that matches the type of the best
137 * preference HostkeyAlgorithms, then use the whole list as is.
138 * Note that we ignore whether the best preference algorithm is a
139 * certificate type, as sshconnect.c will downgrade certs to
140 * plain keys if necessary.
141 */
142 best = first_alg(options.hostkeyalgorithms);
143 if (lookup_key_in_hostkeys_by_type(hostkeys,
144 sshkey_type_plain(sshkey_type_from_name(best)), NULL)) {
145 debug3("%s: have matching best-preference key type %s, "
146 "using HostkeyAlgorithms verbatim", __func__, best);
147 ret = xstrdup(options.hostkeyalgorithms);
148 goto out;
149 }
150
151 /*
152 * Otherwise, prefer the host key algorithms that match known keys
153 * while keeping the ordering of HostkeyAlgorithms as much as possible.
154 */
122 oavail = avail = xstrdup(options.hostkeyalgorithms); 155 oavail = avail = xstrdup(options.hostkeyalgorithms);
123 maxlen = strlen(avail) + 1; 156 maxlen = strlen(avail) + 1;
124 first = xmalloc(maxlen); 157 first = xmalloc(maxlen);
@@ -159,6 +192,8 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
159 if (*first != '\0') 192 if (*first != '\0')
160 debug3("%s: prefer hostkeyalgs: %s", __func__, first); 193 debug3("%s: prefer hostkeyalgs: %s", __func__, first);
161 194
195 out:
196 free(best);
162 free(first); 197 free(first);
163 free(last); 198 free(last);
164 free(hostname); 199 free(hostname);