diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 110 |
1 files changed, 82 insertions, 28 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.136 2018/02/07 02:06:50 jsing Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.141 2018/07/09 13:37:10 sf Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -174,7 +174,7 @@ kex_names_cat(const char *a, const char *b) | |||
174 | size_t len; | 174 | size_t len; |
175 | 175 | ||
176 | if (a == NULL || *a == '\0') | 176 | if (a == NULL || *a == '\0') |
177 | return NULL; | 177 | return strdup(b); |
178 | if (b == NULL || *b == '\0') | 178 | if (b == NULL || *b == '\0') |
179 | return strdup(a); | 179 | return strdup(a); |
180 | if (strlen(b) > 1024*1024) | 180 | if (strlen(b) > 1024*1024) |
@@ -209,27 +209,88 @@ kex_names_cat(const char *a, const char *b) | |||
209 | * specified names should be removed. | 209 | * specified names should be removed. |
210 | */ | 210 | */ |
211 | int | 211 | int |
212 | kex_assemble_names(const char *def, char **list) | 212 | kex_assemble_names(char **listp, const char *def, const char *all) |
213 | { | 213 | { |
214 | char *ret; | 214 | char *cp, *tmp, *patterns; |
215 | char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL; | ||
216 | int r = SSH_ERR_INTERNAL_ERROR; | ||
215 | 217 | ||
216 | if (list == NULL || *list == NULL || **list == '\0') { | 218 | if (listp == NULL || *listp == NULL || **listp == '\0') { |
217 | *list = strdup(def); | 219 | if ((*listp = strdup(def)) == NULL) |
220 | return SSH_ERR_ALLOC_FAIL; | ||
218 | return 0; | 221 | return 0; |
219 | } | 222 | } |
220 | if (**list == '+') { | 223 | |
221 | if ((ret = kex_names_cat(def, *list + 1)) == NULL) | 224 | list = *listp; |
222 | return SSH_ERR_ALLOC_FAIL; | 225 | *listp = NULL; |
223 | free(*list); | 226 | if (*list == '+') { |
224 | *list = ret; | 227 | /* Append names to default list */ |
225 | } else if (**list == '-') { | 228 | if ((tmp = kex_names_cat(def, list + 1)) == NULL) { |
226 | if ((ret = match_filter_list(def, *list + 1)) == NULL) | 229 | r = SSH_ERR_ALLOC_FAIL; |
227 | return SSH_ERR_ALLOC_FAIL; | 230 | goto fail; |
228 | free(*list); | 231 | } |
229 | *list = ret; | 232 | free(list); |
233 | list = tmp; | ||
234 | } else if (*list == '-') { | ||
235 | /* Remove names from default list */ | ||
236 | if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) { | ||
237 | r = SSH_ERR_ALLOC_FAIL; | ||
238 | goto fail; | ||
239 | } | ||
240 | free(list); | ||
241 | /* filtering has already been done */ | ||
242 | return 0; | ||
243 | } else { | ||
244 | /* Explicit list, overrides default - just use "list" as is */ | ||
230 | } | 245 | } |
231 | 246 | ||
232 | return 0; | 247 | /* |
248 | * The supplied names may be a pattern-list. For the -list case, | ||
249 | * the patterns are applied above. For the +list and explicit list | ||
250 | * cases we need to do it now. | ||
251 | */ | ||
252 | ret = NULL; | ||
253 | if ((patterns = opatterns = strdup(list)) == NULL) { | ||
254 | r = SSH_ERR_ALLOC_FAIL; | ||
255 | goto fail; | ||
256 | } | ||
257 | /* Apply positive (i.e. non-negated) patterns from the list */ | ||
258 | while ((cp = strsep(&patterns, ",")) != NULL) { | ||
259 | if (*cp == '!') { | ||
260 | /* negated matches are not supported here */ | ||
261 | r = SSH_ERR_INVALID_ARGUMENT; | ||
262 | goto fail; | ||
263 | } | ||
264 | free(matching); | ||
265 | if ((matching = match_filter_whitelist(all, cp)) == NULL) { | ||
266 | r = SSH_ERR_ALLOC_FAIL; | ||
267 | goto fail; | ||
268 | } | ||
269 | if ((tmp = kex_names_cat(ret, matching)) == NULL) { | ||
270 | r = SSH_ERR_ALLOC_FAIL; | ||
271 | goto fail; | ||
272 | } | ||
273 | free(ret); | ||
274 | ret = tmp; | ||
275 | } | ||
276 | if (ret == NULL || *ret == '\0') { | ||
277 | /* An empty name-list is an error */ | ||
278 | /* XXX better error code? */ | ||
279 | r = SSH_ERR_INVALID_ARGUMENT; | ||
280 | goto fail; | ||
281 | } | ||
282 | |||
283 | /* success */ | ||
284 | *listp = ret; | ||
285 | ret = NULL; | ||
286 | r = 0; | ||
287 | |||
288 | fail: | ||
289 | free(matching); | ||
290 | free(opatterns); | ||
291 | free(list); | ||
292 | free(ret); | ||
293 | return r; | ||
233 | } | 294 | } |
234 | 295 | ||
235 | /* put algorithm proposal into buffer */ | 296 | /* put algorithm proposal into buffer */ |
@@ -342,6 +403,7 @@ kex_send_ext_info(struct ssh *ssh) | |||
342 | 403 | ||
343 | if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) | 404 | if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) |
344 | return SSH_ERR_ALLOC_FAIL; | 405 | return SSH_ERR_ALLOC_FAIL; |
406 | /* XXX filter algs list by allowed pubkey/hostbased types */ | ||
345 | if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || | 407 | if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || |
346 | (r = sshpkt_put_u32(ssh, 1)) != 0 || | 408 | (r = sshpkt_put_u32(ssh, 1)) != 0 || |
347 | (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || | 409 | (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || |
@@ -378,7 +440,7 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) | |||
378 | { | 440 | { |
379 | struct kex *kex = ssh->kex; | 441 | struct kex *kex = ssh->kex; |
380 | u_int32_t i, ninfo; | 442 | u_int32_t i, ninfo; |
381 | char *name, *found; | 443 | char *name; |
382 | u_char *val; | 444 | u_char *val; |
383 | size_t vlen; | 445 | size_t vlen; |
384 | int r; | 446 | int r; |
@@ -401,16 +463,8 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) | |||
401 | return SSH_ERR_INVALID_FORMAT; | 463 | return SSH_ERR_INVALID_FORMAT; |
402 | } | 464 | } |
403 | debug("%s: %s=<%s>", __func__, name, val); | 465 | debug("%s: %s=<%s>", __func__, name, val); |
404 | found = match_list("rsa-sha2-256", val, NULL); | 466 | kex->server_sig_algs = val; |
405 | if (found) { | 467 | val = NULL; |
406 | kex->rsa_sha2 = 256; | ||
407 | free(found); | ||
408 | } | ||
409 | found = match_list("rsa-sha2-512", val, NULL); | ||
410 | if (found) { | ||
411 | kex->rsa_sha2 = 512; | ||
412 | free(found); | ||
413 | } | ||
414 | } else | 468 | } else |
415 | debug("%s: %s (unrecognised)", __func__, name); | 469 | debug("%s: %s (unrecognised)", __func__, name); |
416 | free(name); | 470 | free(name); |