diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 82 |
1 files changed, 75 insertions, 7 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.112 2015/11/13 04:39:35 djm Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.113 2015/12/04 16:41:28 markus 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 | * |
@@ -334,6 +334,20 @@ kex_reset_dispatch(struct ssh *ssh) | |||
334 | ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); | 334 | ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); |
335 | } | 335 | } |
336 | 336 | ||
337 | static int | ||
338 | kex_send_ext_info(struct ssh *ssh) | ||
339 | { | ||
340 | int r; | ||
341 | |||
342 | if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || | ||
343 | (r = sshpkt_put_u32(ssh, 1)) != 0 || | ||
344 | (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || | ||
345 | (r = sshpkt_put_cstring(ssh, "rsa-sha2-256,rsa-sha2-512")) != 0 || | ||
346 | (r = sshpkt_send(ssh)) != 0) | ||
347 | return r; | ||
348 | return 0; | ||
349 | } | ||
350 | |||
337 | int | 351 | int |
338 | kex_send_newkeys(struct ssh *ssh) | 352 | kex_send_newkeys(struct ssh *ssh) |
339 | { | 353 | { |
@@ -346,9 +360,51 @@ kex_send_newkeys(struct ssh *ssh) | |||
346 | debug("SSH2_MSG_NEWKEYS sent"); | 360 | debug("SSH2_MSG_NEWKEYS sent"); |
347 | debug("expecting SSH2_MSG_NEWKEYS"); | 361 | debug("expecting SSH2_MSG_NEWKEYS"); |
348 | ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); | 362 | ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); |
363 | if (ssh->kex->ext_info_c) | ||
364 | if ((r = kex_send_ext_info(ssh)) != 0) | ||
365 | return r; | ||
349 | return 0; | 366 | return 0; |
350 | } | 367 | } |
351 | 368 | ||
369 | int | ||
370 | kex_input_ext_info(int type, u_int32_t seq, void *ctxt) | ||
371 | { | ||
372 | struct ssh *ssh = ctxt; | ||
373 | struct kex *kex = ssh->kex; | ||
374 | u_int32_t i, ninfo; | ||
375 | char *name, *val, *found; | ||
376 | int r; | ||
377 | |||
378 | debug("SSH2_MSG_EXT_INFO received"); | ||
379 | ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); | ||
380 | if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) | ||
381 | return r; | ||
382 | for (i = 0; i < ninfo; i++) { | ||
383 | if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) | ||
384 | return r; | ||
385 | if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) { | ||
386 | free(name); | ||
387 | return r; | ||
388 | } | ||
389 | debug("%s: %s=<%s>", __func__, name, val); | ||
390 | if (strcmp(name, "server-sig-algs") == 0) { | ||
391 | found = match_list("rsa-sha2-256", val, NULL); | ||
392 | if (found) { | ||
393 | kex->rsa_sha2 = 256; | ||
394 | free(found); | ||
395 | } | ||
396 | found = match_list("rsa-sha2-512", val, NULL); | ||
397 | if (found) { | ||
398 | kex->rsa_sha2 = 512; | ||
399 | free(found); | ||
400 | } | ||
401 | } | ||
402 | free(name); | ||
403 | free(val); | ||
404 | } | ||
405 | return sshpkt_get_end(ssh); | ||
406 | } | ||
407 | |||
352 | static int | 408 | static int |
353 | kex_input_newkeys(int type, u_int32_t seq, void *ctxt) | 409 | kex_input_newkeys(int type, u_int32_t seq, void *ctxt) |
354 | { | 410 | { |
@@ -531,6 +587,8 @@ kex_free(struct kex *kex) | |||
531 | free(kex->client_version_string); | 587 | free(kex->client_version_string); |
532 | free(kex->server_version_string); | 588 | free(kex->server_version_string); |
533 | free(kex->failed_choice); | 589 | free(kex->failed_choice); |
590 | free(kex->hostkey_alg); | ||
591 | free(kex->name); | ||
534 | free(kex); | 592 | free(kex); |
535 | } | 593 | } |
536 | 594 | ||
@@ -627,17 +685,16 @@ choose_kex(struct kex *k, char *client, char *server) | |||
627 | static int | 685 | static int |
628 | choose_hostkeyalg(struct kex *k, char *client, char *server) | 686 | choose_hostkeyalg(struct kex *k, char *client, char *server) |
629 | { | 687 | { |
630 | char *hostkeyalg = match_list(client, server, NULL); | 688 | k->hostkey_alg = match_list(client, server, NULL); |
631 | 689 | ||
632 | debug("kex: host key algorithm: %s", | 690 | debug("kex: host key algorithm: %s", |
633 | hostkeyalg ? hostkeyalg : "(no match)"); | 691 | k->hostkey_alg ? k->hostkey_alg : "(no match)"); |
634 | if (hostkeyalg == NULL) | 692 | if (k->hostkey_alg == NULL) |
635 | return SSH_ERR_NO_HOSTKEY_ALG_MATCH; | 693 | return SSH_ERR_NO_HOSTKEY_ALG_MATCH; |
636 | k->hostkey_type = sshkey_type_from_name(hostkeyalg); | 694 | k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); |
637 | if (k->hostkey_type == KEY_UNSPEC) | 695 | if (k->hostkey_type == KEY_UNSPEC) |
638 | return SSH_ERR_INTERNAL_ERROR; | 696 | return SSH_ERR_INTERNAL_ERROR; |
639 | k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg); | 697 | k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); |
640 | free(hostkeyalg); | ||
641 | return 0; | 698 | return 0; |
642 | } | 699 | } |
643 | 700 | ||
@@ -702,6 +759,17 @@ kex_choose_conf(struct ssh *ssh) | |||
702 | } | 759 | } |
703 | } | 760 | } |
704 | 761 | ||
762 | /* Check whether client supports ext_info_c */ | ||
763 | if (kex->server) { | ||
764 | char *ext; | ||
765 | |||
766 | ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); | ||
767 | if (ext) { | ||
768 | kex->ext_info_c = 1; | ||
769 | free(ext); | ||
770 | } | ||
771 | } | ||
772 | |||
705 | /* Algorithm Negotiation */ | 773 | /* Algorithm Negotiation */ |
706 | if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], | 774 | if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], |
707 | sprop[PROPOSAL_KEX_ALGS])) != 0) { | 775 | sprop[PROPOSAL_KEX_ALGS])) != 0) { |