summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-09-05 09:35:19 +0000
committerDamien Miller <djm@mindrot.org>2019-09-05 20:07:12 +1000
commit76f09bd95917862101b740afb19f4db5ccc752bf (patch)
tree738f704070454ff08cf3b078920dae42bd48981c /kex.c
parent0ea332497b2b2fc3995f72f6bafe9d664c0195b3 (diff)
upstream: sprinkle in some explicit errors here, otherwise the
percolate all the way up to dispatch_run_fatal() and lose all meaninful context to help with bz#3063; ok dtucker@ OpenBSD-Commit-ID: 5b2da83bb1c4a3471444b7910b2120ae36438a0a
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c80
1 files changed, 60 insertions, 20 deletions
diff --git a/kex.c b/kex.c
index ff88dd7e3..1eb27264a 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.151 2019/09/05 09:25:13 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.152 2019/09/05 09:35:19 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 *
@@ -345,18 +345,25 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
345 r = SSH_ERR_ALLOC_FAIL; 345 r = SSH_ERR_ALLOC_FAIL;
346 goto out; 346 goto out;
347 } 347 }
348 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */ 348 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
349 error("%s: consume cookie: %s", __func__, ssh_err(r));
349 goto out; 350 goto out;
351 }
350 /* extract kex init proposal strings */ 352 /* extract kex init proposal strings */
351 for (i = 0; i < PROPOSAL_MAX; i++) { 353 for (i = 0; i < PROPOSAL_MAX; i++) {
352 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) 354 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
355 error("%s: parse proposal %u: %s", __func__,
356 i, ssh_err(r));
353 goto out; 357 goto out;
358 }
354 debug2("%s: %s", proposal_names[i], proposal[i]); 359 debug2("%s: %s", proposal_names[i], proposal[i]);
355 } 360 }
356 /* first kex follows / reserved */ 361 /* first kex follows / reserved */
357 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ 362 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
358 (r = sshbuf_get_u32(b, &i)) != 0) /* reserved */ 363 (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
364 error("%s: parse: %s", __func__, ssh_err(r));
359 goto out; 365 goto out;
366 }
360 if (first_kex_follows != NULL) 367 if (first_kex_follows != NULL)
361 *first_kex_follows = v; 368 *first_kex_follows = v;
362 debug2("first_kex_follows %d ", v); 369 debug2("first_kex_follows %d ", v);
@@ -417,8 +424,10 @@ kex_send_ext_info(struct ssh *ssh)
417 (r = sshpkt_put_u32(ssh, 1)) != 0 || 424 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
418 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || 425 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
419 (r = sshpkt_put_cstring(ssh, algs)) != 0 || 426 (r = sshpkt_put_cstring(ssh, algs)) != 0 ||
420 (r = sshpkt_send(ssh)) != 0) 427 (r = sshpkt_send(ssh)) != 0) {
428 error("%s: compose: %s", __func__, ssh_err(r));
421 goto out; 429 goto out;
430 }
422 /* success */ 431 /* success */
423 r = 0; 432 r = 0;
424 out: 433 out:
@@ -512,23 +521,32 @@ kex_send_kexinit(struct ssh *ssh)
512 struct kex *kex = ssh->kex; 521 struct kex *kex = ssh->kex;
513 int r; 522 int r;
514 523
515 if (kex == NULL) 524 if (kex == NULL) {
525 error("%s: no hex", __func__);
516 return SSH_ERR_INTERNAL_ERROR; 526 return SSH_ERR_INTERNAL_ERROR;
527 }
517 if (kex->flags & KEX_INIT_SENT) 528 if (kex->flags & KEX_INIT_SENT)
518 return 0; 529 return 0;
519 kex->done = 0; 530 kex->done = 0;
520 531
521 /* generate a random cookie */ 532 /* generate a random cookie */
522 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) 533 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
534 error("%s: bad kex length: %zu < %d", __func__,
535 sshbuf_len(kex->my), KEX_COOKIE_LEN);
523 return SSH_ERR_INVALID_FORMAT; 536 return SSH_ERR_INVALID_FORMAT;
524 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) 537 }
538 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
539 error("%s: buffer error", __func__);
525 return SSH_ERR_INTERNAL_ERROR; 540 return SSH_ERR_INTERNAL_ERROR;
541 }
526 arc4random_buf(cookie, KEX_COOKIE_LEN); 542 arc4random_buf(cookie, KEX_COOKIE_LEN);
527 543
528 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || 544 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
529 (r = sshpkt_putb(ssh, kex->my)) != 0 || 545 (r = sshpkt_putb(ssh, kex->my)) != 0 ||
530 (r = sshpkt_send(ssh)) != 0) 546 (r = sshpkt_send(ssh)) != 0) {
547 error("%s: compose reply: %s", __func__, ssh_err(r));
531 return r; 548 return r;
549 }
532 debug("SSH2_MSG_KEXINIT sent"); 550 debug("SSH2_MSG_KEXINIT sent");
533 kex->flags |= KEX_INIT_SENT; 551 kex->flags |= KEX_INIT_SENT;
534 return 0; 552 return 0;
@@ -545,21 +563,28 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
545 int r; 563 int r;
546 564
547 debug("SSH2_MSG_KEXINIT received"); 565 debug("SSH2_MSG_KEXINIT received");
548 if (kex == NULL) 566 if (kex == NULL) {
549 return SSH_ERR_INVALID_ARGUMENT; 567 error("%s: no hex", __func__);
550 568 return SSH_ERR_INTERNAL_ERROR;
569 }
551 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); 570 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
552 ptr = sshpkt_ptr(ssh, &dlen); 571 ptr = sshpkt_ptr(ssh, &dlen);
553 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) 572 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
554 return r; 573 return r;
555 574
556 /* discard packet */ 575 /* discard packet */
557 for (i = 0; i < KEX_COOKIE_LEN; i++) 576 for (i = 0; i < KEX_COOKIE_LEN; i++) {
558 if ((r = sshpkt_get_u8(ssh, NULL)) != 0) 577 if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
578 error("%s: discard cookie: %s", __func__, ssh_err(r));
559 return r; 579 return r;
560 for (i = 0; i < PROPOSAL_MAX; i++) 580 }
561 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) 581 }
582 for (i = 0; i < PROPOSAL_MAX; i++) {
583 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
584 error("%s: discard proposal: %s", __func__, ssh_err(r));
562 return r; 585 return r;
586 }
587 }
563 /* 588 /*
564 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 589 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
565 * KEX method has the server move first, but a server might be using 590 * KEX method has the server move first, but a server might be using
@@ -584,6 +609,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
584 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) 609 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
585 return (kex->kex[kex->kex_type])(ssh); 610 return (kex->kex[kex->kex_type])(ssh);
586 611
612 error("%s: unknown kex type %u", __func__, kex->kex_type);
587 return SSH_ERR_INTERNAL_ERROR; 613 return SSH_ERR_INTERNAL_ERROR;
588} 614}
589 615
@@ -719,6 +745,7 @@ choose_enc(struct sshenc *enc, char *client, char *server)
719 if (name == NULL) 745 if (name == NULL)
720 return SSH_ERR_NO_CIPHER_ALG_MATCH; 746 return SSH_ERR_NO_CIPHER_ALG_MATCH;
721 if ((enc->cipher = cipher_by_name(name)) == NULL) { 747 if ((enc->cipher = cipher_by_name(name)) == NULL) {
748 error("%s: unsupported cipher %s", __func__, name);
722 free(name); 749 free(name);
723 return SSH_ERR_INTERNAL_ERROR; 750 return SSH_ERR_INTERNAL_ERROR;
724 } 751 }
@@ -740,6 +767,7 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
740 if (name == NULL) 767 if (name == NULL)
741 return SSH_ERR_NO_MAC_ALG_MATCH; 768 return SSH_ERR_NO_MAC_ALG_MATCH;
742 if (mac_setup(mac, name) < 0) { 769 if (mac_setup(mac, name) < 0) {
770 error("%s: unsupported MAC %s", __func__, name);
743 free(name); 771 free(name);
744 return SSH_ERR_INTERNAL_ERROR; 772 return SSH_ERR_INTERNAL_ERROR;
745 } 773 }
@@ -763,6 +791,7 @@ choose_comp(struct sshcomp *comp, char *client, char *server)
763 } else if (strcmp(name, "none") == 0) { 791 } else if (strcmp(name, "none") == 0) {
764 comp->type = COMP_NONE; 792 comp->type = COMP_NONE;
765 } else { 793 } else {
794 error("%s: unsupported compression scheme %s", __func__, name);
766 free(name); 795 free(name);
767 return SSH_ERR_INTERNAL_ERROR; 796 return SSH_ERR_INTERNAL_ERROR;
768 } 797 }
@@ -780,8 +809,10 @@ choose_kex(struct kex *k, char *client, char *server)
780 debug("kex: algorithm: %s", k->name ? k->name : "(no match)"); 809 debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
781 if (k->name == NULL) 810 if (k->name == NULL)
782 return SSH_ERR_NO_KEX_ALG_MATCH; 811 return SSH_ERR_NO_KEX_ALG_MATCH;
783 if ((kexalg = kex_alg_by_name(k->name)) == NULL) 812 if ((kexalg = kex_alg_by_name(k->name)) == NULL) {
813 error("%s: unsupported KEX method %s", __func__, k->name);
784 return SSH_ERR_INTERNAL_ERROR; 814 return SSH_ERR_INTERNAL_ERROR;
815 }
785 k->kex_type = kexalg->type; 816 k->kex_type = kexalg->type;
786 k->hash_alg = kexalg->hash_alg; 817 k->hash_alg = kexalg->hash_alg;
787 k->ec_nid = kexalg->ec_nid; 818 k->ec_nid = kexalg->ec_nid;
@@ -798,8 +829,11 @@ choose_hostkeyalg(struct kex *k, char *client, char *server)
798 if (k->hostkey_alg == NULL) 829 if (k->hostkey_alg == NULL)
799 return SSH_ERR_NO_HOSTKEY_ALG_MATCH; 830 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
800 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); 831 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
801 if (k->hostkey_type == KEY_UNSPEC) 832 if (k->hostkey_type == KEY_UNSPEC) {
833 error("%s: unsupported hostkey algorithm %s", __func__,
834 k->hostkey_alg);
802 return SSH_ERR_INTERNAL_ERROR; 835 return SSH_ERR_INTERNAL_ERROR;
836 }
803 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); 837 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
804 return 0; 838 return 0;
805} 839}
@@ -968,6 +1002,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
968 kex->session_id_len) != 0 || 1002 kex->session_id_len) != 0 ||
969 ssh_digest_final(hashctx, digest, mdsz) != 0) { 1003 ssh_digest_final(hashctx, digest, mdsz) != 0) {
970 r = SSH_ERR_LIBCRYPTO_ERROR; 1004 r = SSH_ERR_LIBCRYPTO_ERROR;
1005 error("%s: KEX hash failed", __func__);
971 goto out; 1006 goto out;
972 } 1007 }
973 ssh_digest_free(hashctx); 1008 ssh_digest_free(hashctx);
@@ -984,6 +1019,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
984 ssh_digest_update(hashctx, hash, hashlen) != 0 || 1019 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
985 ssh_digest_update(hashctx, digest, have) != 0 || 1020 ssh_digest_update(hashctx, digest, have) != 0 ||
986 ssh_digest_final(hashctx, digest + have, mdsz) != 0) { 1021 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
1022 error("%s: KDF failed", __func__);
987 r = SSH_ERR_LIBCRYPTO_ERROR; 1023 r = SSH_ERR_LIBCRYPTO_ERROR;
988 goto out; 1024 goto out;
989 } 1025 }
@@ -1047,8 +1083,10 @@ kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1047 *pubp = NULL; 1083 *pubp = NULL;
1048 *prvp = NULL; 1084 *prvp = NULL;
1049 if (kex->load_host_public_key == NULL || 1085 if (kex->load_host_public_key == NULL ||
1050 kex->load_host_private_key == NULL) 1086 kex->load_host_private_key == NULL) {
1087 error("%s: missing hostkey loader", __func__);
1051 return SSH_ERR_INVALID_ARGUMENT; 1088 return SSH_ERR_INVALID_ARGUMENT;
1089 }
1052 *pubp = kex->load_host_public_key(kex->hostkey_type, 1090 *pubp = kex->load_host_public_key(kex->hostkey_type,
1053 kex->hostkey_nid, ssh); 1091 kex->hostkey_nid, ssh);
1054 *prvp = kex->load_host_private_key(kex->hostkey_type, 1092 *prvp = kex->load_host_private_key(kex->hostkey_type,
@@ -1063,8 +1101,10 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1063{ 1101{
1064 struct kex *kex = ssh->kex; 1102 struct kex *kex = ssh->kex;
1065 1103
1066 if (kex->verify_host_key == NULL) 1104 if (kex->verify_host_key == NULL) {
1105 error("%s: missing hostkey verifier", __func__);
1067 return SSH_ERR_INVALID_ARGUMENT; 1106 return SSH_ERR_INVALID_ARGUMENT;
1107 }
1068 if (server_host_key->type != kex->hostkey_type || 1108 if (server_host_key->type != kex->hostkey_type ||
1069 (kex->hostkey_type == KEY_ECDSA && 1109 (kex->hostkey_type == KEY_ECDSA &&
1070 server_host_key->ecdsa_nid != kex->hostkey_nid)) 1110 server_host_key->ecdsa_nid != kex->hostkey_nid))