1 /* $NetBSD: kex.c,v 1.40 2026/04/08 18:58:40 christos Exp $ */ 2 /* $OpenBSD: kex.c,v 1.193 2026/03/05 05:40:35 djm Exp $ */ 3 4 /* 5 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "includes.h" 29 __RCSID("$NetBSD: kex.c,v 1.40 2026/04/08 18:58:40 christos Exp $"); 30 31 #include <sys/param.h> /* MAX roundup */ 32 #include <sys/types.h> 33 #include <errno.h> 34 #include <signal.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #ifdef WITH_OPENSSL 42 #include <openssl/crypto.h> 43 #include <openssl/dh.h> 44 #endif 45 46 #include "ssh.h" 47 #include "ssh2.h" 48 #include "atomicio.h" 49 #include "version.h" 50 #include "packet.h" 51 #include "compat.h" 52 #include "cipher.h" 53 #include "sshkey.h" 54 #include "kex.h" 55 #include "log.h" 56 #include "mac.h" 57 #include "match.h" 58 #include "misc.h" 59 #include "dispatch.h" 60 #include "myproposal.h" 61 62 #include "ssherr.h" 63 #include "sshbuf.h" 64 #include "digest.h" 65 #include "xmalloc.h" 66 67 /* prototype */ 68 static int kex_choose_conf(struct ssh *, uint32_t seq); 69 static int kex_input_newkeys(int, uint32_t, struct ssh *); 70 71 static const char * const proposal_names[PROPOSAL_MAX] = { 72 "KEX algorithms", 73 "host key algorithms", 74 "ciphers ctos", 75 "ciphers stoc", 76 "MACs ctos", 77 "MACs stoc", 78 "compression ctos", 79 "compression stoc", 80 "languages ctos", 81 "languages stoc", 82 }; 83 84 /* 85 * Fill out a proposal array with dynamically allocated values, which may 86 * be modified as required for compatibility reasons. 87 * Any of the options may be NULL, in which case the default is used. 88 * Array contents must be freed by calling kex_proposal_free_entries. 89 */ 90 void 91 kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], 92 const char *kexalgos, const char *ciphers, const char *macs, 93 const char *comp, const char *hkalgs) 94 { 95 const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER }; 96 const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; 97 const char **defprop = ssh->kex->server ? defpropserver : defpropclient; 98 u_int i; 99 char *cp; 100 101 if (prop == NULL) 102 fatal_f("proposal missing"); 103 104 /* Append EXT_INFO signalling to KexAlgorithms */ 105 if (kexalgos == NULL) 106 kexalgos = defprop[PROPOSAL_KEX_ALGS]; 107 if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? 108 "ext-info-s,kex-strict-s-v00 (at) openssh.com" : 109 "ext-info-c,kex-strict-c-v00 (at) openssh.com")) == NULL) 110 fatal_f("kex_names_cat"); 111 112 for (i = 0; i < PROPOSAL_MAX; i++) { 113 switch(i) { 114 case PROPOSAL_KEX_ALGS: 115 prop[i] = compat_kex_proposal(ssh, cp); 116 break; 117 case PROPOSAL_ENC_ALGS_CTOS: 118 case PROPOSAL_ENC_ALGS_STOC: 119 prop[i] = xstrdup(ciphers ? ciphers : defprop[i]); 120 break; 121 case PROPOSAL_MAC_ALGS_CTOS: 122 case PROPOSAL_MAC_ALGS_STOC: 123 prop[i] = xstrdup(macs ? macs : defprop[i]); 124 break; 125 case PROPOSAL_COMP_ALGS_CTOS: 126 case PROPOSAL_COMP_ALGS_STOC: 127 prop[i] = xstrdup(comp ? comp : defprop[i]); 128 break; 129 case PROPOSAL_SERVER_HOST_KEY_ALGS: 130 prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]); 131 break; 132 default: 133 prop[i] = xstrdup(defprop[i]); 134 } 135 } 136 free(cp); 137 } 138 139 void 140 kex_proposal_free_entries(char *prop[PROPOSAL_MAX]) 141 { 142 u_int i; 143 144 for (i = 0; i < PROPOSAL_MAX; i++) 145 free(prop[i]); 146 } 147 148 /* put algorithm proposal into buffer */ 149 int 150 kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) 151 { 152 u_int i; 153 int r; 154 155 sshbuf_reset(b); 156 157 /* 158 * add a dummy cookie, the cookie will be overwritten by 159 * kex_send_kexinit(), each time a kexinit is set 160 */ 161 for (i = 0; i < KEX_COOKIE_LEN; i++) { 162 if ((r = sshbuf_put_u8(b, 0)) != 0) 163 return r; 164 } 165 for (i = 0; i < PROPOSAL_MAX; i++) { 166 if ((r = sshbuf_put_cstring(b, proposal[i])) != 0) 167 return r; 168 } 169 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */ 170 (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */ 171 return r; 172 return 0; 173 } 174 175 /* parse buffer and return algorithm proposal */ 176 int 177 kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) 178 { 179 struct sshbuf *b = NULL; 180 u_char v; 181 u_int i; 182 char **proposal = NULL; 183 int r; 184 185 *propp = NULL; 186 if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL) 187 return SSH_ERR_ALLOC_FAIL; 188 if ((b = sshbuf_fromb(raw)) == NULL) { 189 r = SSH_ERR_ALLOC_FAIL; 190 goto out; 191 } 192 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */ 193 error_fr(r, "consume cookie"); 194 goto out; 195 } 196 /* extract kex init proposal strings */ 197 for (i = 0; i < PROPOSAL_MAX; i++) { 198 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) { 199 error_fr(r, "parse proposal %u", i); 200 goto out; 201 } 202 debug2("%s: %s", proposal_names[i], proposal[i]); 203 } 204 /* first kex follows / reserved */ 205 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ 206 (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */ 207 error_fr(r, "parse"); 208 goto out; 209 } 210 if (first_kex_follows != NULL) 211 *first_kex_follows = v; 212 debug2("first_kex_follows %d ", v); 213 debug2("reserved %u ", i); 214 r = 0; 215 *propp = proposal; 216 out: 217 if (r != 0 && proposal != NULL) 218 kex_prop_free(proposal); 219 sshbuf_free(b); 220 return r; 221 } 222 223 void 224 kex_prop_free(char **proposal) 225 { 226 u_int i; 227 228 if (proposal == NULL) 229 return; 230 for (i = 0; i < PROPOSAL_MAX; i++) 231 free(proposal[i]); 232 free(proposal); 233 } 234 235 int 236 kex_protocol_error(int type, uint32_t seq, struct ssh *ssh) 237 { 238 int r; 239 240 /* If in strict mode, any unexpected message is an error */ 241 if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { 242 ssh_packet_disconnect(ssh, "strict KEX violation: " 243 "unexpected packet type %u (seqnr %u)", type, seq); 244 } 245 error_f("type %u seq %u", type, seq); 246 if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || 247 (r = sshpkt_put_u32(ssh, seq)) != 0 || 248 (r = sshpkt_send(ssh)) != 0) 249 return r; 250 return 0; 251 } 252 253 static void 254 kex_reset_dispatch(struct ssh *ssh) 255 { 256 ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN, 257 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 258 } 259 260 void 261 kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs) 262 { 263 char *alg, *oalgs, *algs, *sigalgs; 264 const char *sigalg; 265 266 /* 267 * NB. allowed algorithms may contain certificate algorithms that 268 * map to a specific plain signature type, e.g. 269 * rsa-sha2-512-cert-v01 (at) openssh.com => rsa-sha2-512 270 * We need to be careful here to match these, retain the mapping 271 * and only add each signature algorithm once. 272 */ 273 if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL) 274 fatal_f("sshkey_alg_list failed"); 275 oalgs = algs = xstrdup(allowed_algs); 276 free(ssh->kex->server_sig_algs); 277 ssh->kex->server_sig_algs = NULL; 278 for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0'; 279 (alg = strsep(&algs, ","))) { 280 if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL) 281 continue; 282 if (!kex_has_any_alg(sigalg, sigalgs)) 283 continue; 284 /* Don't add an algorithm twice. */ 285 if (ssh->kex->server_sig_algs != NULL && 286 kex_has_any_alg(sigalg, ssh->kex->server_sig_algs)) 287 continue; 288 xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg); 289 } 290 free(oalgs); 291 free(sigalgs); 292 if (ssh->kex->server_sig_algs == NULL) 293 ssh->kex->server_sig_algs = xstrdup(""); 294 } 295 296 static int 297 kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) 298 { 299 int r; 300 301 if (ssh->kex->server_sig_algs == NULL && 302 (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) 303 return SSH_ERR_ALLOC_FAIL; 304 if ((r = sshbuf_put_u32(m, 4)) != 0 || 305 (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 || 306 (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 || 307 (r = sshbuf_put_cstring(m, 308 "publickey-hostbound (at) openssh.com")) != 0 || 309 (r = sshbuf_put_cstring(m, "0")) != 0 || 310 (r = sshbuf_put_cstring(m, "ping (at) openssh.com")) != 0 || 311 (r = sshbuf_put_cstring(m, "0")) != 0 || 312 (r = sshbuf_put_cstring(m, "agent-forward")) != 0 || 313 (r = sshbuf_put_cstring(m, "0")) != 0) { 314 error_fr(r, "compose"); 315 return r; 316 } 317 return 0; 318 } 319 320 static int 321 kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m) 322 { 323 int r; 324 325 if ((r = sshbuf_put_u32(m, 1)) != 0 || 326 (r = sshbuf_put_cstring(m, "ext-info-in-auth (at) openssh.com")) != 0 || 327 (r = sshbuf_put_cstring(m, "0")) != 0) { 328 error_fr(r, "compose"); 329 goto out; 330 } 331 /* success */ 332 r = 0; 333 out: 334 return r; 335 } 336 337 static int 338 kex_maybe_send_ext_info(struct ssh *ssh) 339 { 340 int r; 341 struct sshbuf *m = NULL; 342 343 if ((ssh->kex->flags & KEX_INITIAL) == 0) 344 return 0; 345 if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s) 346 return 0; 347 348 /* Compose EXT_INFO packet. */ 349 if ((m = sshbuf_new()) == NULL) 350 fatal_f("sshbuf_new failed"); 351 if (ssh->kex->ext_info_c && 352 (r = kex_compose_ext_info_server(ssh, m)) != 0) 353 goto fail; 354 if (ssh->kex->ext_info_s && 355 (r = kex_compose_ext_info_client(ssh, m)) != 0) 356 goto fail; 357 358 /* Send the actual KEX_INFO packet */ 359 debug("Sending SSH2_MSG_EXT_INFO"); 360 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || 361 (r = sshpkt_putb(ssh, m)) != 0 || 362 (r = sshpkt_send(ssh)) != 0) { 363 error_f("send EXT_INFO"); 364 goto fail; 365 } 366 367 r = 0; 368 369 fail: 370 sshbuf_free(m); 371 return r; 372 } 373 374 int 375 kex_server_update_ext_info(struct ssh *ssh) 376 { 377 int r; 378 379 if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0) 380 return 0; 381 382 debug_f("Sending SSH2_MSG_EXT_INFO"); 383 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || 384 (r = sshpkt_put_u32(ssh, 1)) != 0 || 385 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || 386 (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 || 387 (r = sshpkt_send(ssh)) != 0) { 388 error_f("send EXT_INFO"); 389 return r; 390 } 391 return 0; 392 } 393 394 int 395 kex_send_newkeys(struct ssh *ssh) 396 { 397 int r; 398 399 kex_reset_dispatch(ssh); 400 if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 || 401 (r = sshpkt_send(ssh)) != 0) 402 return r; 403 debug("SSH2_MSG_NEWKEYS sent"); 404 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); 405 if ((r = kex_maybe_send_ext_info(ssh)) != 0) 406 return r; 407 debug("expecting SSH2_MSG_NEWKEYS"); 408 return 0; 409 } 410 411 /* Check whether an ext_info value contains the expected version string */ 412 static int 413 kex_ext_info_check_ver(struct kex *kex, const char *name, 414 const u_char *val, size_t len, const char *want_ver, u_int flag) 415 { 416 if (memchr(val, '\0', len) != NULL) { 417 error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name); 418 return SSH_ERR_INVALID_FORMAT; 419 } 420 debug_f("%s=<%s>", name, val); 421 if (strcmp((const char *)val, want_ver) == 0) 422 kex->flags |= flag; 423 else 424 debug_f("unsupported version of %s extension", name); 425 return 0; 426 } 427 428 static int 429 kex_ext_info_client_parse(struct ssh *ssh, const char *name, 430 const u_char *value, size_t vlen) 431 { 432 int r; 433 434 /* NB. some messages are only accepted in the initial EXT_INFO */ 435 if (strcmp(name, "server-sig-algs") == 0) { 436 /* Ensure no \0 lurking in value */ 437 if (memchr(value, '\0', vlen) != NULL) { 438 error_f("nul byte in %s", name); 439 return SSH_ERR_INVALID_FORMAT; 440 } 441 debug_f("%s=<%s>", name, value); 442 free(ssh->kex->server_sig_algs); 443 ssh->kex->server_sig_algs = xstrdup((const char *)value); 444 } else if (ssh->kex->ext_info_received == 1 && 445 strcmp(name, "publickey-hostbound (at) openssh.com") == 0) { 446 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, 447 "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) { 448 return r; 449 } 450 } else if (ssh->kex->ext_info_received == 1 && 451 strcmp(name, "ping (at) openssh.com") == 0) { 452 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, 453 "0", KEX_HAS_PING)) != 0) { 454 return r; 455 } 456 } else if (ssh->kex->ext_info_received == 1 && 457 strcmp(name, "agent-forward") == 0) { 458 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, 459 "0", KEX_HAS_NEWAGENT)) != 0) { 460 return r; 461 } 462 } else 463 debug_f("%s (unrecognised)", name); 464 465 return 0; 466 } 467 468 static int 469 kex_ext_info_server_parse(struct ssh *ssh, const char *name, 470 const u_char *value, size_t vlen) 471 { 472 int r; 473 474 if (strcmp(name, "ext-info-in-auth (at) openssh.com") == 0) { 475 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, 476 "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) { 477 return r; 478 } 479 } else 480 debug_f("%s (unrecognised)", name); 481 return 0; 482 } 483 484 int 485 kex_input_ext_info(int type, uint32_t seq, struct ssh *ssh) 486 { 487 struct kex *kex = ssh->kex; 488 const int max_ext_info = kex->server ? 1 : 2; 489 uint32_t i, ninfo; 490 char *name; 491 u_char *val; 492 size_t vlen; 493 int r; 494 495 debug("SSH2_MSG_EXT_INFO received"); 496 if (++kex->ext_info_received > max_ext_info) { 497 error("too many SSH2_MSG_EXT_INFO messages sent by peer"); 498 return dispatch_protocol_error(type, seq, ssh); 499 } 500 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); 501 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) 502 return r; 503 if (ninfo >= 1024) { 504 error("SSH2_MSG_EXT_INFO with too many entries, expected " 505 "<=1024, received %u", ninfo); 506 return dispatch_protocol_error(type, seq, ssh); 507 } 508 for (i = 0; i < ninfo; i++) { 509 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) 510 return r; 511 if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) { 512 free(name); 513 return r; 514 } 515 debug3_f("extension %s", name); 516 if (kex->server) { 517 if ((r = kex_ext_info_server_parse(ssh, name, 518 val, vlen)) != 0) 519 return r; 520 } else { 521 if ((r = kex_ext_info_client_parse(ssh, name, 522 val, vlen)) != 0) 523 return r; 524 } 525 free(name); 526 free(val); 527 } 528 return sshpkt_get_end(ssh); 529 } 530 531 static int 532 kex_input_newkeys(int type, uint32_t seq, struct ssh *ssh) 533 { 534 struct kex *kex = ssh->kex; 535 int r, initial = (kex->flags & KEX_INITIAL) != 0; 536 char *cp, **prop; 537 538 debug("SSH2_MSG_NEWKEYS received"); 539 if (kex->ext_info_c && initial) 540 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info); 541 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error); 542 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); 543 if ((r = sshpkt_get_end(ssh)) != 0) 544 return r; 545 if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) 546 return r; 547 if (initial) { 548 /* Remove initial KEX signalling from proposal for rekeying */ 549 if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0) 550 return r; 551 if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS], 552 kex->server ? 553 "ext-info-s,kex-strict-s-v00 (at) openssh.com" : 554 "ext-info-c,kex-strict-c-v00 (at) openssh.com")) == NULL) { 555 error_f("match_filter_denylist failed"); 556 goto fail; 557 } 558 free(prop[PROPOSAL_KEX_ALGS]); 559 prop[PROPOSAL_KEX_ALGS] = cp; 560 if ((r = kex_prop2buf(ssh->kex->my, prop)) != 0) { 561 error_f("kex_prop2buf failed"); 562 fail: 563 kex_proposal_free_entries(prop); 564 free(prop); 565 return SSH_ERR_INTERNAL_ERROR; 566 } 567 kex_proposal_free_entries(prop); 568 free(prop); 569 } 570 kex->done = 1; 571 kex->flags &= ~KEX_INITIAL; 572 sshbuf_reset(kex->peer); 573 kex->flags &= ~KEX_INIT_SENT; 574 return 0; 575 } 576 577 int 578 kex_send_kexinit(struct ssh *ssh) 579 { 580 u_char *cookie; 581 struct kex *kex = ssh->kex; 582 int r; 583 584 if (kex == NULL) { 585 error_f("no kex"); 586 return SSH_ERR_INTERNAL_ERROR; 587 } 588 if (kex->flags & KEX_INIT_SENT) 589 return 0; 590 kex->done = 0; 591 592 /* generate a random cookie */ 593 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) { 594 error_f("bad kex length: %zu < %d", 595 sshbuf_len(kex->my), KEX_COOKIE_LEN); 596 return SSH_ERR_INVALID_FORMAT; 597 } 598 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) { 599 error_f("buffer error"); 600 return SSH_ERR_INTERNAL_ERROR; 601 } 602 arc4random_buf(cookie, KEX_COOKIE_LEN); 603 604 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || 605 (r = sshpkt_putb(ssh, kex->my)) != 0 || 606 (r = sshpkt_send(ssh)) != 0) { 607 error_fr(r, "compose reply"); 608 return r; 609 } 610 debug("SSH2_MSG_KEXINIT sent"); 611 kex->flags |= KEX_INIT_SENT; 612 return 0; 613 } 614 615 int 616 kex_input_kexinit(int type, uint32_t seq, struct ssh *ssh) 617 { 618 struct kex *kex = ssh->kex; 619 const u_char *ptr; 620 u_int i; 621 size_t dlen; 622 int r; 623 624 debug("SSH2_MSG_KEXINIT received"); 625 if (kex == NULL) { 626 error_f("no kex"); 627 return SSH_ERR_INTERNAL_ERROR; 628 } 629 free(kex->name); 630 kex->name = NULL; 631 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); 632 ptr = sshpkt_ptr(ssh, &dlen); 633 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) 634 return r; 635 636 /* discard packet */ 637 for (i = 0; i < KEX_COOKIE_LEN; i++) { 638 if ((r = sshpkt_get_u8(ssh, NULL)) != 0) { 639 error_fr(r, "discard cookie"); 640 return r; 641 } 642 } 643 for (i = 0; i < PROPOSAL_MAX; i++) { 644 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { 645 error_fr(r, "discard proposal"); 646 return r; 647 } 648 } 649 /* 650 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 651 * KEX method has the server move first, but a server might be using 652 * a custom method or one that we otherwise don't support. We should 653 * be prepared to remember first_kex_follows here so we can eat a 654 * packet later. 655 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means 656 * for cases where the server *doesn't* go first. I guess we should 657 * ignore it when it is set for these cases, which is what we do now. 658 */ 659 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ 660 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ 661 (r = sshpkt_get_end(ssh)) != 0) 662 return r; 663 664 if (!(kex->flags & KEX_INIT_SENT)) 665 if ((r = kex_send_kexinit(ssh)) != 0) 666 return r; 667 if ((r = kex_choose_conf(ssh, seq)) != 0) 668 return r; 669 670 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) 671 return (kex->kex[kex->kex_type])(ssh); 672 673 error_f("unknown kex type %u", kex->kex_type); 674 return SSH_ERR_INTERNAL_ERROR; 675 } 676 677 struct kex * 678 kex_new(void) 679 { 680 struct kex *kex; 681 682 if ((kex = calloc(1, sizeof(*kex))) == NULL || 683 (kex->peer = sshbuf_new()) == NULL || 684 (kex->my = sshbuf_new()) == NULL || 685 (kex->client_version = sshbuf_new()) == NULL || 686 (kex->server_version = sshbuf_new()) == NULL || 687 (kex->session_id = sshbuf_new()) == NULL) { 688 kex_free(kex); 689 return NULL; 690 } 691 return kex; 692 } 693 694 void 695 kex_free_newkeys(struct newkeys *newkeys) 696 { 697 if (newkeys == NULL) 698 return; 699 if (newkeys->enc.key) { 700 explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); 701 free(newkeys->enc.key); 702 newkeys->enc.key = NULL; 703 } 704 if (newkeys->enc.iv) { 705 explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len); 706 free(newkeys->enc.iv); 707 newkeys->enc.iv = NULL; 708 } 709 free(newkeys->enc.name); 710 explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); 711 free(newkeys->comp.name); 712 explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); 713 mac_clear(&newkeys->mac); 714 if (newkeys->mac.key) { 715 explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); 716 free(newkeys->mac.key); 717 newkeys->mac.key = NULL; 718 } 719 free(newkeys->mac.name); 720 explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); 721 freezero(newkeys, sizeof(*newkeys)); 722 } 723 724 void 725 kex_free(struct kex *kex) 726 { 727 u_int mode; 728 729 if (kex == NULL) 730 return; 731 732 #ifdef WITH_OPENSSL 733 DH_free(kex->dh); 734 EC_KEY_free(kex->ec_client_key); 735 #endif 736 for (mode = 0; mode < MODE_MAX; mode++) { 737 kex_free_newkeys(kex->newkeys[mode]); 738 kex->newkeys[mode] = NULL; 739 } 740 sshbuf_free(kex->peer); 741 sshbuf_free(kex->my); 742 sshbuf_free(kex->client_version); 743 sshbuf_free(kex->server_version); 744 sshbuf_free(kex->client_pub); 745 sshbuf_free(kex->session_id); 746 sshbuf_free(kex->initial_sig); 747 sshkey_free(kex->initial_hostkey); 748 free(kex->failed_choice); 749 free(kex->hostkey_alg); 750 free(kex->name); 751 free(kex->server_sig_algs); 752 free(kex); 753 } 754 755 int 756 kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) 757 { 758 int r; 759 760 if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) 761 return r; 762 ssh->kex->flags = KEX_INITIAL; 763 kex_reset_dispatch(ssh); 764 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); 765 return 0; 766 } 767 768 int 769 kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) 770 { 771 int r; 772 773 if ((r = kex_ready(ssh, proposal)) != 0) 774 return r; 775 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ 776 kex_free(ssh->kex); 777 ssh->kex = NULL; 778 return r; 779 } 780 return 0; 781 } 782 783 /* 784 * Request key re-exchange, returns 0 on success or a ssherr.h error 785 * code otherwise. Must not be called if KEX is incomplete or in-progress. 786 */ 787 int 788 kex_start_rekex(struct ssh *ssh) 789 { 790 if (ssh->kex == NULL) { 791 error_f("no kex"); 792 return SSH_ERR_INTERNAL_ERROR; 793 } 794 if (ssh->kex->done == 0) { 795 error_f("requested twice"); 796 return SSH_ERR_INTERNAL_ERROR; 797 } 798 ssh->kex->done = 0; 799 return kex_send_kexinit(ssh); 800 } 801 802 static int 803 choose_enc(struct sshenc *enc, char *client, char *server) 804 { 805 char *name = match_list(client, server, NULL); 806 807 if (name == NULL) 808 return SSH_ERR_NO_CIPHER_ALG_MATCH; 809 if ((enc->cipher = cipher_by_name(name)) == NULL) { 810 error_f("unsupported cipher %s", name); 811 free(name); 812 return SSH_ERR_INTERNAL_ERROR; 813 } 814 enc->name = name; 815 enc->enabled = 0; 816 enc->iv = NULL; 817 enc->iv_len = cipher_ivlen(enc->cipher); 818 enc->key = NULL; 819 enc->key_len = cipher_keylen(enc->cipher); 820 enc->block_size = cipher_blocksize(enc->cipher); 821 return 0; 822 } 823 824 static int 825 choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) 826 { 827 char *name = match_list(client, server, NULL); 828 829 if (name == NULL) 830 return SSH_ERR_NO_MAC_ALG_MATCH; 831 if (mac_setup(mac, name) < 0) { 832 error_f("unsupported MAC %s", name); 833 free(name); 834 return SSH_ERR_INTERNAL_ERROR; 835 } 836 mac->name = name; 837 mac->key = NULL; 838 mac->enabled = 0; 839 return 0; 840 } 841 842 static int 843 choose_comp(struct sshcomp *comp, char *client, char *server) 844 { 845 char *name = match_list(client, server, NULL); 846 847 if (name == NULL) 848 return SSH_ERR_NO_COMPRESS_ALG_MATCH; 849 #ifdef WITH_ZLIB 850 if (strcmp(name, "zlib (at) openssh.com") == 0) { 851 comp->type = COMP_DELAYED; 852 } else 853 #endif /* WITH_ZLIB */ 854 if (strcmp(name, "none") == 0) { 855 comp->type = COMP_NONE; 856 } else { 857 error_f("unsupported compression scheme %s", name); 858 free(name); 859 return SSH_ERR_INTERNAL_ERROR; 860 } 861 comp->name = name; 862 return 0; 863 } 864 865 static int 866 choose_kex(struct kex *k, char *client, char *server) 867 { 868 k->name = match_list(client, server, NULL); 869 870 debug("kex: algorithm: %s", k->name ? k->name : "(no match)"); 871 if (k->name == NULL) 872 return SSH_ERR_NO_KEX_ALG_MATCH; 873 if (!kex_name_valid(k->name)) { 874 error_f("unsupported KEX method %s", k->name); 875 return SSH_ERR_INTERNAL_ERROR; 876 } 877 k->kex_type = kex_type_from_name(k->name); 878 k->hash_alg = kex_hash_from_name(k->name); 879 k->ec_nid = kex_nid_from_name(k->name); 880 return 0; 881 } 882 883 static int 884 choose_hostkeyalg(struct kex *k, char *client, char *server) 885 { 886 free(k->hostkey_alg); 887 k->hostkey_alg = match_list(client, server, NULL); 888 889 debug("kex: host key algorithm: %s", 890 k->hostkey_alg ? k->hostkey_alg : "(no match)"); 891 if (k->hostkey_alg == NULL) 892 return SSH_ERR_NO_HOSTKEY_ALG_MATCH; 893 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); 894 if (k->hostkey_type == KEY_UNSPEC) { 895 error_f("unsupported hostkey algorithm %s", k->hostkey_alg); 896 return SSH_ERR_INTERNAL_ERROR; 897 } 898 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); 899 return 0; 900 } 901 902 static int 903 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) 904 { 905 static int check[] = { 906 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 907 }; 908 int *idx; 909 char *p; 910 911 for (idx = &check[0]; *idx != -1; idx++) { 912 if ((p = strchr(my[*idx], ',')) != NULL) 913 *p = '\0'; 914 if ((p = strchr(peer[*idx], ',')) != NULL) 915 *p = '\0'; 916 if (strcmp(my[*idx], peer[*idx]) != 0) { 917 debug2("proposal mismatch: my %s peer %s", 918 my[*idx], peer[*idx]); 919 return (0); 920 } 921 } 922 debug2("proposals match"); 923 return (1); 924 } 925 926 static int 927 kexalgs_contains(char **peer, const char *ext) 928 { 929 return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); 930 } 931 932 static int 933 kex_choose_conf(struct ssh *ssh, uint32_t seq) 934 { 935 struct kex *kex = ssh->kex; 936 struct newkeys *newkeys; 937 char **my = NULL, **peer = NULL; 938 char **cprop, **sprop; 939 int nenc, nmac, ncomp; 940 u_int mode, ctos, need, dh_need, authlen; 941 int log_flag = 0; 942 int r, first_kex_follows; 943 944 debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); 945 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) 946 goto out; 947 debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server"); 948 if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) 949 goto out; 950 951 if (kex->server) { 952 cprop=peer; 953 sprop=my; 954 } else { 955 cprop=my; 956 sprop=peer; 957 } 958 959 /* Check whether peer supports ext_info/kex_strict */ 960 if ((kex->flags & KEX_INITIAL) != 0) { 961 if (kex->server) { 962 kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); 963 kex->kex_strict = kexalgs_contains(peer, 964 "kex-strict-c-v00 (at) openssh.com"); 965 } else { 966 kex->ext_info_s = kexalgs_contains(peer, "ext-info-s"); 967 kex->kex_strict = kexalgs_contains(peer, 968 "kex-strict-s-v00 (at) openssh.com"); 969 } 970 if (kex->kex_strict) { 971 debug3_f("will use strict KEX ordering"); 972 if (seq != 0) 973 ssh_packet_disconnect(ssh, 974 "strict KEX violation: " 975 "KEXINIT was not the first packet"); 976 } 977 } 978 979 /* Check whether client supports rsa-sha2 algorithms */ 980 if (kex->server && (kex->flags & KEX_INITIAL)) { 981 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], 982 "rsa-sha2-256,rsa-sha2-256-cert-v01 (at) openssh.com")) 983 kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; 984 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], 985 "rsa-sha2-512,rsa-sha2-512-cert-v01 (at) openssh.com")) 986 kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; 987 } 988 989 /* Algorithm Negotiation */ 990 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], 991 sprop[PROPOSAL_KEX_ALGS])) != 0) { 992 kex->failed_choice = peer[PROPOSAL_KEX_ALGS]; 993 peer[PROPOSAL_KEX_ALGS] = NULL; 994 goto out; 995 } 996 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 997 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) { 998 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS]; 999 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL; 1000 goto out; 1001 } 1002 for (mode = 0; mode < MODE_MAX; mode++) { 1003 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { 1004 r = SSH_ERR_ALLOC_FAIL; 1005 goto out; 1006 } 1007 kex->newkeys[mode] = newkeys; 1008 ctos = (!kex->server && mode == MODE_OUT) || 1009 (kex->server && mode == MODE_IN); 1010 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 1011 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 1012 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 1013 if ((r = choose_enc(&newkeys->enc, cprop[nenc], 1014 sprop[nenc])) != 0) { 1015 kex->failed_choice = peer[nenc]; 1016 peer[nenc] = NULL; 1017 goto out; 1018 } 1019 authlen = cipher_authlen(newkeys->enc.cipher); 1020 /* ignore mac for authenticated encryption */ 1021 if (authlen == 0 && 1022 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac], 1023 sprop[nmac])) != 0) { 1024 kex->failed_choice = peer[nmac]; 1025 peer[nmac] = NULL; 1026 goto out; 1027 } 1028 if ((r = choose_comp(&newkeys->comp, cprop[ncomp], 1029 sprop[ncomp])) != 0) { 1030 kex->failed_choice = peer[ncomp]; 1031 peer[ncomp] = NULL; 1032 goto out; 1033 } 1034 debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); 1035 if (strcmp(newkeys->enc.name, "none") == 0) { 1036 int auth_flag; 1037 1038 auth_flag = ssh_packet_authentication_state(ssh); 1039 debug("Requesting NONE. Authflag is %d", auth_flag); 1040 if (auth_flag == 1) { 1041 debug("None requested post authentication."); 1042 } else { 1043 fatal("Pre-authentication none cipher requests are not allowed."); 1044 } 1045 } 1046 debug("kex: %s cipher: %s MAC: %s compression: %s", 1047 ctos ? "client->server" : "server->client", 1048 newkeys->enc.name, 1049 authlen == 0 ? newkeys->mac.name : "<implicit>", 1050 newkeys->comp.name); 1051 /* client starts withctos = 0 && log flag = 0 and no log*/ 1052 /* 2nd client pass ctos=1 and flag = 1 so no log*/ 1053 /* server starts with ctos =1 && log_flag = 0 so log */ 1054 /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ 1055 /* -cjr*/ 1056 if (ctos && !log_flag) { 1057 logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", 1058 ssh_remote_ipaddr(ssh), 1059 ssh_remote_port(ssh), 1060 newkeys->enc.name, 1061 authlen == 0 ? newkeys->mac.name : "<implicit>", 1062 newkeys->comp.name); 1063 } 1064 log_flag = 1; 1065 } 1066 need = dh_need = 0; 1067 for (mode = 0; mode < MODE_MAX; mode++) { 1068 newkeys = kex->newkeys[mode]; 1069 need = MAXIMUM(need, newkeys->enc.key_len); 1070 need = MAXIMUM(need, newkeys->enc.block_size); 1071 need = MAXIMUM(need, newkeys->enc.iv_len); 1072 need = MAXIMUM(need, newkeys->mac.key_len); 1073 dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher)); 1074 dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); 1075 dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); 1076 dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); 1077 } 1078 /* XXX need runden? */ 1079 kex->we_need = need; 1080 kex->dh_need = dh_need; 1081 1082 /* ignore the next message if the proposals do not match */ 1083 if (first_kex_follows && !proposals_match(my, peer)) 1084 ssh->dispatch_skip_packets = 1; 1085 r = 0; 1086 out: 1087 kex_prop_free(my); 1088 kex_prop_free(peer); 1089 return r; 1090 } 1091 1092 static int 1093 derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, 1094 const struct sshbuf *shared_secret, u_char **keyp) 1095 { 1096 struct kex *kex = ssh->kex; 1097 struct ssh_digest_ctx *hashctx = NULL; 1098 char c = id; 1099 u_int have; 1100 size_t mdsz; 1101 u_char *digest; 1102 int r; 1103 1104 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) 1105 return SSH_ERR_INVALID_ARGUMENT; 1106 if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) { 1107 r = SSH_ERR_ALLOC_FAIL; 1108 goto out; 1109 } 1110 1111 /* K1 = HASH(K || H || "A" || session_id) */ 1112 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || 1113 ssh_digest_update_buffer(hashctx, shared_secret) != 0 || 1114 ssh_digest_update(hashctx, hash, hashlen) != 0 || 1115 ssh_digest_update(hashctx, &c, 1) != 0 || 1116 ssh_digest_update_buffer(hashctx, kex->session_id) != 0 || 1117 ssh_digest_final(hashctx, digest, mdsz) != 0) { 1118 r = SSH_ERR_LIBCRYPTO_ERROR; 1119 error_f("KEX hash failed"); 1120 goto out; 1121 } 1122 ssh_digest_free(hashctx); 1123 hashctx = NULL; 1124 1125 /* 1126 * expand key: 1127 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) 1128 * Key = K1 || K2 || ... || Kn 1129 */ 1130 for (have = mdsz; need > have; have += mdsz) { 1131 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || 1132 ssh_digest_update_buffer(hashctx, shared_secret) != 0 || 1133 ssh_digest_update(hashctx, hash, hashlen) != 0 || 1134 ssh_digest_update(hashctx, digest, have) != 0 || 1135 ssh_digest_final(hashctx, digest + have, mdsz) != 0) { 1136 error_f("KDF failed"); 1137 r = SSH_ERR_LIBCRYPTO_ERROR; 1138 goto out; 1139 } 1140 ssh_digest_free(hashctx); 1141 hashctx = NULL; 1142 } 1143 #ifdef DEBUG_KEX 1144 fprintf(stderr, "key '%c'== ", c); 1145 dump_digest("key", digest, need); 1146 #endif 1147 *keyp = digest; 1148 digest = NULL; 1149 r = 0; 1150 out: 1151 free(digest); 1152 ssh_digest_free(hashctx); 1153 return r; 1154 } 1155 1156 #define NKEYS 6 1157 int 1158 kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, 1159 const struct sshbuf *shared_secret) 1160 { 1161 struct kex *kex = ssh->kex; 1162 u_char *keys[NKEYS]; 1163 u_int i, j, mode, ctos; 1164 int r; 1165 1166 /* save initial hash as session id */ 1167 if ((kex->flags & KEX_INITIAL) != 0) { 1168 if (sshbuf_len(kex->session_id) != 0) { 1169 error_f("already have session ID at kex"); 1170 return SSH_ERR_INTERNAL_ERROR; 1171 } 1172 if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0) 1173 return r; 1174 } else if (sshbuf_len(kex->session_id) == 0) { 1175 error_f("no session ID in rekex"); 1176 return SSH_ERR_INTERNAL_ERROR; 1177 } 1178 for (i = 0; i < NKEYS; i++) { 1179 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, 1180 shared_secret, &keys[i])) != 0) { 1181 for (j = 0; j < i; j++) 1182 free(keys[j]); 1183 return r; 1184 } 1185 } 1186 for (mode = 0; mode < MODE_MAX; mode++) { 1187 ctos = (!kex->server && mode == MODE_OUT) || 1188 (kex->server && mode == MODE_IN); 1189 kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; 1190 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; 1191 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; 1192 } 1193 return 0; 1194 } 1195 1196 int 1197 kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) 1198 { 1199 struct kex *kex = ssh->kex; 1200 1201 *pubp = NULL; 1202 *prvp = NULL; 1203 if (kex->load_host_public_key == NULL || 1204 kex->load_host_private_key == NULL) { 1205 error_f("missing hostkey loader"); 1206 return SSH_ERR_INVALID_ARGUMENT; 1207 } 1208 *pubp = kex->load_host_public_key(kex->hostkey_type, 1209 kex->hostkey_nid, ssh); 1210 *prvp = kex->load_host_private_key(kex->hostkey_type, 1211 kex->hostkey_nid, ssh); 1212 if (*pubp == NULL) 1213 return SSH_ERR_NO_HOSTKEY_LOADED; 1214 return 0; 1215 } 1216 1217 int 1218 kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) 1219 { 1220 struct kex *kex = ssh->kex; 1221 1222 if (kex->verify_host_key == NULL) { 1223 error_f("missing hostkey verifier"); 1224 return SSH_ERR_INVALID_ARGUMENT; 1225 } 1226 if (server_host_key->type != kex->hostkey_type || 1227 (kex->hostkey_type == KEY_ECDSA && 1228 server_host_key->ecdsa_nid != kex->hostkey_nid)) 1229 return SSH_ERR_KEY_TYPE_MISMATCH; 1230 if (kex->verify_host_key(server_host_key, ssh) == -1) 1231 return SSH_ERR_SIGNATURE_INVALID; 1232 return 0; 1233 } 1234 1235 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 1236 void 1237 dump_digest(const char *msg, const u_char *digest, int len) 1238 { 1239 fprintf(stderr, "%s\n", msg); 1240 sshbuf_dump_data(digest, len, stderr); 1241 } 1242 #endif 1243 1244 /* 1245 * Send a plaintext error message to the peer, suffixed by \r\n. 1246 * Only used during banner exchange, and there only for the server. 1247 */ 1248 static void 1249 send_error(struct ssh *ssh, const char *msg) 1250 { 1251 const char *crnl = "\r\n"; 1252 1253 if (!ssh->kex->server) 1254 return; 1255 1256 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), 1257 __UNCONST(msg), strlen(msg)) != strlen(msg) || 1258 atomicio(vwrite, ssh_packet_get_connection_out(ssh), 1259 __UNCONST(crnl), strlen(crnl)) != strlen(crnl)) 1260 error_f("write: %.100s", strerror(errno)); 1261 } 1262 1263 /* 1264 * Sends our identification string and waits for the peer's. Will block for 1265 * up to timeout_ms (or indefinitely if timeout_ms <= 0). 1266 * Returns on 0 success or a ssherr.h code on failure. 1267 */ 1268 int 1269 kex_exchange_identification(struct ssh *ssh, int timeout_ms, 1270 const char *version_addendum) 1271 { 1272 int remote_major, remote_minor, mismatch, oerrno = 0; 1273 size_t len, n; 1274 int r, expect_nl; 1275 u_char c; 1276 struct sshbuf *our_version = ssh->kex->server ? 1277 ssh->kex->server_version : ssh->kex->client_version; 1278 struct sshbuf *peer_version = ssh->kex->server ? 1279 ssh->kex->client_version : ssh->kex->server_version; 1280 char *our_version_string = NULL, *peer_version_string = NULL; 1281 char *cp, *remote_version = NULL; 1282 1283 /* Prepare and send our banner */ 1284 sshbuf_reset(our_version); 1285 if (version_addendum != NULL && *version_addendum == '\0') 1286 version_addendum = NULL; 1287 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n", 1288 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, 1289 version_addendum == NULL ? "" : " ", 1290 version_addendum == NULL ? "" : version_addendum)) != 0) { 1291 oerrno = errno; 1292 error_fr(r, "sshbuf_putf"); 1293 goto out; 1294 } 1295 1296 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), 1297 sshbuf_mutable_ptr(our_version), 1298 sshbuf_len(our_version)) != sshbuf_len(our_version)) { 1299 oerrno = errno; 1300 debug_f("write: %.100s", strerror(errno)); 1301 r = SSH_ERR_SYSTEM_ERROR; 1302 goto out; 1303 } 1304 if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */ 1305 oerrno = errno; 1306 error_fr(r, "sshbuf_consume_end"); 1307 goto out; 1308 } 1309 our_version_string = sshbuf_dup_string(our_version); 1310 if (our_version_string == NULL) { 1311 error_f("sshbuf_dup_string failed"); 1312 r = SSH_ERR_ALLOC_FAIL; 1313 goto out; 1314 } 1315 debug("Local version string %.100s", our_version_string); 1316 1317 /* Read other side's version identification. */ 1318 for (n = 0; ; n++) { 1319 if (n >= SSH_MAX_PRE_BANNER_LINES) { 1320 send_error(ssh, "No SSH identification string " 1321 "received."); 1322 error_f("No SSH version received in first %u lines " 1323 "from server", SSH_MAX_PRE_BANNER_LINES); 1324 r = SSH_ERR_INVALID_FORMAT; 1325 goto out; 1326 } 1327 sshbuf_reset(peer_version); 1328 expect_nl = 0; 1329 for (;;) { 1330 if (timeout_ms > 0) { 1331 r = waitrfd(ssh_packet_get_connection_in(ssh), 1332 &timeout_ms, NULL); 1333 if (r == -1 && errno == ETIMEDOUT) { 1334 send_error(ssh, "Timed out waiting " 1335 "for SSH identification string."); 1336 error("Connection timed out during " 1337 "banner exchange"); 1338 r = SSH_ERR_CONN_TIMEOUT; 1339 goto out; 1340 } else if (r == -1) { 1341 oerrno = errno; 1342 error_f("%s", strerror(errno)); 1343 r = SSH_ERR_SYSTEM_ERROR; 1344 goto out; 1345 } 1346 } 1347 1348 len = atomicio(read, ssh_packet_get_connection_in(ssh), 1349 &c, 1); 1350 if (len != 1 && errno == EPIPE) { 1351 verbose_f("Connection closed by remote host"); 1352 r = SSH_ERR_CONN_CLOSED; 1353 goto out; 1354 } else if (len != 1) { 1355 oerrno = errno; 1356 error_f("read: %.100s", strerror(errno)); 1357 r = SSH_ERR_SYSTEM_ERROR; 1358 goto out; 1359 } 1360 if (c == '\r') { 1361 expect_nl = 1; 1362 continue; 1363 } 1364 if (c == '\n') 1365 break; 1366 if (c == '\0' || expect_nl) { 1367 verbose_f("banner line contains invalid " 1368 "characters"); 1369 goto invalid; 1370 } 1371 if ((r = sshbuf_put_u8(peer_version, c)) != 0) { 1372 oerrno = errno; 1373 error_fr(r, "sshbuf_put"); 1374 goto out; 1375 } 1376 if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { 1377 verbose_f("banner line too long"); 1378 goto invalid; 1379 } 1380 } 1381 /* Is this an actual protocol banner? */ 1382 if (sshbuf_len(peer_version) > 4 && 1383 memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0) 1384 break; 1385 /* If not, then just log the line and continue */ 1386 if ((cp = sshbuf_dup_string(peer_version)) == NULL) { 1387 error_f("sshbuf_dup_string failed"); 1388 r = SSH_ERR_ALLOC_FAIL; 1389 goto out; 1390 } 1391 /* Do not accept lines before the SSH ident from a client */ 1392 if (ssh->kex->server) { 1393 verbose_f("client sent invalid protocol identifier " 1394 "\"%.256s\"", cp); 1395 free(cp); 1396 goto invalid; 1397 } 1398 debug_f("banner line %zu: %s", n, cp); 1399 free(cp); 1400 } 1401 peer_version_string = sshbuf_dup_string(peer_version); 1402 if (peer_version_string == NULL) 1403 fatal_f("sshbuf_dup_string failed"); 1404 /* XXX must be same size for sscanf */ 1405 if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { 1406 error_f("calloc failed"); 1407 r = SSH_ERR_ALLOC_FAIL; 1408 goto out; 1409 } 1410 1411 /* 1412 * Check that the versions match. In future this might accept 1413 * several versions and set appropriate flags to handle them. 1414 */ 1415 if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n", 1416 &remote_major, &remote_minor, remote_version) != 3) { 1417 error("Bad remote protocol version identification: '%.100s'", 1418 peer_version_string); 1419 invalid: 1420 send_error(ssh, "Invalid SSH identification string."); 1421 r = SSH_ERR_INVALID_FORMAT; 1422 goto out; 1423 } 1424 debug("Remote protocol version %d.%d, remote software version %.100s", 1425 remote_major, remote_minor, remote_version); 1426 compat_banner(ssh, remote_version); 1427 1428 mismatch = 0; 1429 switch (remote_major) { 1430 case 2: 1431 break; 1432 case 1: 1433 if (remote_minor != 99) 1434 mismatch = 1; 1435 break; 1436 default: 1437 mismatch = 1; 1438 break; 1439 } 1440 if (mismatch) { 1441 error("Protocol major versions differ: %d vs. %d", 1442 PROTOCOL_MAJOR_2, remote_major); 1443 send_error(ssh, "Protocol major versions differ."); 1444 r = SSH_ERR_NO_PROTOCOL_VERSION; 1445 goto out; 1446 } 1447 1448 if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { 1449 logit("probed from %s port %d with %s. Don't panic.", 1450 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), 1451 peer_version_string); 1452 r = SSH_ERR_CONN_CLOSED; /* XXX */ 1453 goto out; 1454 } 1455 if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { 1456 logit("scanned from %s port %d with %s. Don't panic.", 1457 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), 1458 peer_version_string); 1459 r = SSH_ERR_CONN_CLOSED; /* XXX */ 1460 goto out; 1461 } 1462 /* success */ 1463 r = 0; 1464 out: 1465 free(our_version_string); 1466 free(peer_version_string); 1467 free(remote_version); 1468 if (r == SSH_ERR_SYSTEM_ERROR) 1469 errno = oerrno; 1470 return r; 1471 } 1472 1473