summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2016-02-29 12:15:15 +0000
committerColin Watson <cjwatson@debian.org>2016-02-29 12:15:15 +0000
commitc52a95cc4754e6630c96fe65ae0c65eb41d2c590 (patch)
tree793395934013923b7b2426382c0676edcd4be3d4 /kex.c
parenteeff4de96f5d7365750dc56912c2c62b5c28db6b (diff)
parent72b061d4ba0f909501c595d709ea76e06b01e5c9 (diff)
Import openssh_7.2p1.orig.tar.gz
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c168
1 files changed, 134 insertions, 34 deletions
diff --git a/kex.c b/kex.c
index b777b7d50..d371f47c4 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.109 2015/07/30 00:01:34 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.117 2016/02/08 10:57:07 djm 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 *
@@ -49,7 +49,6 @@
49#include "misc.h" 49#include "misc.h"
50#include "dispatch.h" 50#include "dispatch.h"
51#include "monitor.h" 51#include "monitor.h"
52#include "roaming.h"
53 52
54#include "ssherr.h" 53#include "ssherr.h"
55#include "sshbuf.h" 54#include "sshbuf.h"
@@ -67,6 +66,19 @@ extern const EVP_MD *evp_ssh_sha256(void);
67static int kex_choose_conf(struct ssh *); 66static int kex_choose_conf(struct ssh *);
68static int kex_input_newkeys(int, u_int32_t, void *); 67static int kex_input_newkeys(int, u_int32_t, void *);
69 68
69static const char *proposal_names[PROPOSAL_MAX] = {
70 "KEX algorithms",
71 "host key algorithms",
72 "ciphers ctos",
73 "ciphers stoc",
74 "MACs ctos",
75 "MACs stoc",
76 "compression ctos",
77 "compression stoc",
78 "languages ctos",
79 "languages stoc",
80};
81
70struct kexalg { 82struct kexalg {
71 char *name; 83 char *name;
72 u_int type; 84 u_int type;
@@ -267,7 +279,7 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
267 for (i = 0; i < PROPOSAL_MAX; i++) { 279 for (i = 0; i < PROPOSAL_MAX; i++) {
268 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) 280 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
269 goto out; 281 goto out;
270 debug2("kex_parse_kexinit: %s", proposal[i]); 282 debug2("%s: %s", proposal_names[i], proposal[i]);
271 } 283 }
272 /* first kex follows / reserved */ 284 /* first kex follows / reserved */
273 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ 285 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
@@ -302,7 +314,14 @@ kex_prop_free(char **proposal)
302static int 314static int
303kex_protocol_error(int type, u_int32_t seq, void *ctxt) 315kex_protocol_error(int type, u_int32_t seq, void *ctxt)
304{ 316{
305 error("Hm, kex protocol error: type %d seq %u", type, seq); 317 struct ssh *ssh = active_state; /* XXX */
318 int r;
319
320 error("kex protocol error: type %d seq %u", type, seq);
321 if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
322 (r = sshpkt_put_u32(ssh, seq)) != 0 ||
323 (r = sshpkt_send(ssh)) != 0)
324 return r;
306 return 0; 325 return 0;
307} 326}
308 327
@@ -314,6 +333,20 @@ kex_reset_dispatch(struct ssh *ssh)
314 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); 333 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
315} 334}
316 335
336static int
337kex_send_ext_info(struct ssh *ssh)
338{
339 int r;
340
341 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
342 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
343 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
344 (r = sshpkt_put_cstring(ssh, "rsa-sha2-256,rsa-sha2-512")) != 0 ||
345 (r = sshpkt_send(ssh)) != 0)
346 return r;
347 return 0;
348}
349
317int 350int
318kex_send_newkeys(struct ssh *ssh) 351kex_send_newkeys(struct ssh *ssh)
319{ 352{
@@ -326,9 +359,51 @@ kex_send_newkeys(struct ssh *ssh)
326 debug("SSH2_MSG_NEWKEYS sent"); 359 debug("SSH2_MSG_NEWKEYS sent");
327 debug("expecting SSH2_MSG_NEWKEYS"); 360 debug("expecting SSH2_MSG_NEWKEYS");
328 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); 361 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
362 if (ssh->kex->ext_info_c)
363 if ((r = kex_send_ext_info(ssh)) != 0)
364 return r;
329 return 0; 365 return 0;
330} 366}
331 367
368int
369kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
370{
371 struct ssh *ssh = ctxt;
372 struct kex *kex = ssh->kex;
373 u_int32_t i, ninfo;
374 char *name, *val, *found;
375 int r;
376
377 debug("SSH2_MSG_EXT_INFO received");
378 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
379 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
380 return r;
381 for (i = 0; i < ninfo; i++) {
382 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
383 return r;
384 if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
385 free(name);
386 return r;
387 }
388 debug("%s: %s=<%s>", __func__, name, val);
389 if (strcmp(name, "server-sig-algs") == 0) {
390 found = match_list("rsa-sha2-256", val, NULL);
391 if (found) {
392 kex->rsa_sha2 = 256;
393 free(found);
394 }
395 found = match_list("rsa-sha2-512", val, NULL);
396 if (found) {
397 kex->rsa_sha2 = 512;
398 free(found);
399 }
400 }
401 free(name);
402 free(val);
403 }
404 return sshpkt_get_end(ssh);
405}
406
332static int 407static int
333kex_input_newkeys(int type, u_int32_t seq, void *ctxt) 408kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
334{ 409{
@@ -468,7 +543,7 @@ kex_free_newkeys(struct newkeys *newkeys)
468 newkeys->enc.key = NULL; 543 newkeys->enc.key = NULL;
469 } 544 }
470 if (newkeys->enc.iv) { 545 if (newkeys->enc.iv) {
471 explicit_bzero(newkeys->enc.iv, newkeys->enc.block_size); 546 explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
472 free(newkeys->enc.iv); 547 free(newkeys->enc.iv);
473 newkeys->enc.iv = NULL; 548 newkeys->enc.iv = NULL;
474 } 549 }
@@ -511,6 +586,8 @@ kex_free(struct kex *kex)
511 free(kex->client_version_string); 586 free(kex->client_version_string);
512 free(kex->server_version_string); 587 free(kex->server_version_string);
513 free(kex->failed_choice); 588 free(kex->failed_choice);
589 free(kex->hostkey_alg);
590 free(kex->name);
514 free(kex); 591 free(kex);
515} 592}
516 593
@@ -529,6 +606,25 @@ kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
529 return 0; 606 return 0;
530} 607}
531 608
609/*
610 * Request key re-exchange, returns 0 on success or a ssherr.h error
611 * code otherwise. Must not be called if KEX is incomplete or in-progress.
612 */
613int
614kex_start_rekex(struct ssh *ssh)
615{
616 if (ssh->kex == NULL) {
617 error("%s: no kex", __func__);
618 return SSH_ERR_INTERNAL_ERROR;
619 }
620 if (ssh->kex->done == 0) {
621 error("%s: requested twice", __func__);
622 return SSH_ERR_INTERNAL_ERROR;
623 }
624 ssh->kex->done = 0;
625 return kex_send_kexinit(ssh);
626}
627
532static int 628static int
533choose_enc(struct sshenc *enc, char *client, char *server) 629choose_enc(struct sshenc *enc, char *client, char *server)
534{ 630{
@@ -593,6 +689,7 @@ choose_kex(struct kex *k, char *client, char *server)
593 689
594 k->name = match_list(client, server, NULL); 690 k->name = match_list(client, server, NULL);
595 691
692 debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
596 if (k->name == NULL) 693 if (k->name == NULL)
597 return SSH_ERR_NO_KEX_ALG_MATCH; 694 return SSH_ERR_NO_KEX_ALG_MATCH;
598 if ((kexalg = kex_alg_by_name(k->name)) == NULL) 695 if ((kexalg = kex_alg_by_name(k->name)) == NULL)
@@ -606,15 +703,16 @@ choose_kex(struct kex *k, char *client, char *server)
606static int 703static int
607choose_hostkeyalg(struct kex *k, char *client, char *server) 704choose_hostkeyalg(struct kex *k, char *client, char *server)
608{ 705{
609 char *hostkeyalg = match_list(client, server, NULL); 706 k->hostkey_alg = match_list(client, server, NULL);
610 707
611 if (hostkeyalg == NULL) 708 debug("kex: host key algorithm: %s",
709 k->hostkey_alg ? k->hostkey_alg : "(no match)");
710 if (k->hostkey_alg == NULL)
612 return SSH_ERR_NO_HOSTKEY_ALG_MATCH; 711 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
613 k->hostkey_type = sshkey_type_from_name(hostkeyalg); 712 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
614 if (k->hostkey_type == KEY_UNSPEC) 713 if (k->hostkey_type == KEY_UNSPEC)
615 return SSH_ERR_INTERNAL_ERROR; 714 return SSH_ERR_INTERNAL_ERROR;
616 k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg); 715 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
617 free(hostkeyalg);
618 return 0; 716 return 0;
619} 717}
620 718
@@ -653,8 +751,11 @@ kex_choose_conf(struct ssh *ssh)
653 u_int mode, ctos, need, dh_need, authlen; 751 u_int mode, ctos, need, dh_need, authlen;
654 int r, first_kex_follows; 752 int r, first_kex_follows;
655 753
656 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 || 754 debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
657 (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) 755 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
756 goto out;
757 debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
758 if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
658 goto out; 759 goto out;
659 760
660 if (kex->server) { 761 if (kex->server) {
@@ -665,18 +766,30 @@ kex_choose_conf(struct ssh *ssh)
665 sprop=peer; 766 sprop=peer;
666 } 767 }
667 768
668 /* Check whether server offers roaming */ 769 /* Check whether client supports ext_info_c */
669 if (!kex->server) { 770 if (kex->server) {
670 char *roaming = match_list(KEX_RESUME, 771 char *ext;
671 peer[PROPOSAL_KEX_ALGS], NULL);
672 772
673 if (roaming) { 773 ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
674 kex->roaming = 1; 774 if (ext) {
675 free(roaming); 775 kex->ext_info_c = 1;
776 free(ext);
676 } 777 }
677 } 778 }
678 779
679 /* Algorithm Negotiation */ 780 /* Algorithm Negotiation */
781 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
782 sprop[PROPOSAL_KEX_ALGS])) != 0) {
783 kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
784 peer[PROPOSAL_KEX_ALGS] = NULL;
785 goto out;
786 }
787 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
788 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
789 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
790 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
791 goto out;
792 }
680 for (mode = 0; mode < MODE_MAX; mode++) { 793 for (mode = 0; mode < MODE_MAX; mode++) {
681 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { 794 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
682 r = SSH_ERR_ALLOC_FAIL; 795 r = SSH_ERR_ALLOC_FAIL;
@@ -709,24 +822,12 @@ kex_choose_conf(struct ssh *ssh)
709 peer[ncomp] = NULL; 822 peer[ncomp] = NULL;
710 goto out; 823 goto out;
711 } 824 }
712 debug("kex: %s %s %s %s", 825 debug("kex: %s cipher: %s MAC: %s compression: %s",
713 ctos ? "client->server" : "server->client", 826 ctos ? "client->server" : "server->client",
714 newkeys->enc.name, 827 newkeys->enc.name,
715 authlen == 0 ? newkeys->mac.name : "<implicit>", 828 authlen == 0 ? newkeys->mac.name : "<implicit>",
716 newkeys->comp.name); 829 newkeys->comp.name);
717 } 830 }
718 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
719 sprop[PROPOSAL_KEX_ALGS])) != 0) {
720 kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
721 peer[PROPOSAL_KEX_ALGS] = NULL;
722 goto out;
723 }
724 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
725 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
726 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
727 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
728 goto out;
729 }
730 need = dh_need = 0; 831 need = dh_need = 0;
731 for (mode = 0; mode < MODE_MAX; mode++) { 832 for (mode = 0; mode < MODE_MAX; mode++) {
732 newkeys = kex->newkeys[mode]; 833 newkeys = kex->newkeys[mode];
@@ -812,8 +913,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
812 digest = NULL; 913 digest = NULL;
813 r = 0; 914 r = 0;
814 out: 915 out:
815 if (digest) 916 free(digest);
816 free(digest);
817 ssh_digest_free(hashctx); 917 ssh_digest_free(hashctx);
818 return r; 918 return r;
819} 919}