diff options
author | djm@openbsd.org <djm@openbsd.org> | 2020-09-18 05:23:03 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-09-18 15:25:01 +1000 |
commit | b3855ff053f5078ec3d3c653cdaedefaa5fc362d (patch) | |
tree | ea3e00e58cde7d1a35b138608030ad05c9160b85 | |
parent | f93b187ab900c7d12875952cc63350fe4de8a0a8 (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.c | 41 |
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 */ | ||
106 | static char * | ||
107 | first_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 | |||
105 | static char * | 117 | static char * |
106 | order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) | 118 | order_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); |