diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-12-27 03:25:24 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-12-27 14:38:22 +1100 |
commit | 0a843d9a0e805f14653a555f5c7a8ba99d62c12d (patch) | |
tree | 481f36e9fd1918be5449e369a97c086a1a8d2432 /sshd.c | |
parent | 434b587afe41c19391821e7392005068fda76248 (diff) |
upstream: move client/server SSH-* banners to buffers under
ssh->kex and factor out the banner exchange. This eliminates some common code
from the client and server.
Also be more strict about handling \r characters - these should only
be accepted immediately before \n (pointed out by Jann Horn).
Inspired by a patch from Markus Schmidt.
(lots of) feedback and ok markus@
OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 118 |
1 files changed, 4 insertions, 114 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -180,13 +180,6 @@ char **rexec_argv; | |||
180 | int listen_socks[MAX_LISTEN_SOCKS]; | 180 | int listen_socks[MAX_LISTEN_SOCKS]; |
181 | int num_listen_socks = 0; | 181 | int num_listen_socks = 0; |
182 | 182 | ||
183 | /* | ||
184 | * the client's version string, passed by sshd2 in compat mode. if != NULL, | ||
185 | * sshd will skip the version-number exchange | ||
186 | */ | ||
187 | char *client_version_string = NULL; | ||
188 | char *server_version_string = NULL; | ||
189 | |||
190 | /* Daemon's agent connection */ | 183 | /* Daemon's agent connection */ |
191 | int auth_sock = -1; | 184 | int auth_sock = -1; |
192 | int have_agent = 0; | 185 | int have_agent = 0; |
@@ -363,108 +356,6 @@ grace_alarm_handler(int sig) | |||
363 | ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); | 356 | ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); |
364 | } | 357 | } |
365 | 358 | ||
366 | static void | ||
367 | sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) | ||
368 | { | ||
369 | u_int i; | ||
370 | int remote_major, remote_minor; | ||
371 | char *s; | ||
372 | char buf[256]; /* Must not be larger than remote_version. */ | ||
373 | char remote_version[256]; /* Must be at least as big as buf. */ | ||
374 | |||
375 | xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", | ||
376 | PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, | ||
377 | *options.version_addendum == '\0' ? "" : " ", | ||
378 | options.version_addendum); | ||
379 | |||
380 | /* Send our protocol version identification. */ | ||
381 | if (atomicio(vwrite, sock_out, server_version_string, | ||
382 | strlen(server_version_string)) | ||
383 | != strlen(server_version_string)) { | ||
384 | logit("Could not write ident string to %s port %d", | ||
385 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
386 | cleanup_exit(255); | ||
387 | } | ||
388 | |||
389 | /* Read other sides version identification. */ | ||
390 | memset(buf, 0, sizeof(buf)); | ||
391 | for (i = 0; i < sizeof(buf) - 1; i++) { | ||
392 | if (atomicio(read, sock_in, &buf[i], 1) != 1) { | ||
393 | logit("Did not receive identification string " | ||
394 | "from %s port %d", | ||
395 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
396 | cleanup_exit(255); | ||
397 | } | ||
398 | if (buf[i] == '\r') { | ||
399 | buf[i] = 0; | ||
400 | /* Kludge for F-Secure Macintosh < 1.0.2 */ | ||
401 | if (i == 12 && | ||
402 | strncmp(buf, "SSH-1.5-W1.0", 12) == 0) | ||
403 | break; | ||
404 | continue; | ||
405 | } | ||
406 | if (buf[i] == '\n') { | ||
407 | buf[i] = 0; | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | buf[sizeof(buf) - 1] = 0; | ||
412 | client_version_string = xstrdup(buf); | ||
413 | |||
414 | /* | ||
415 | * Check that the versions match. In future this might accept | ||
416 | * several versions and set appropriate flags to handle them. | ||
417 | */ | ||
418 | if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", | ||
419 | &remote_major, &remote_minor, remote_version) != 3) { | ||
420 | s = "Protocol mismatch.\n"; | ||
421 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
422 | logit("Bad protocol version identification '%.100s' " | ||
423 | "from %s port %d", client_version_string, | ||
424 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); | ||
425 | close(sock_in); | ||
426 | close(sock_out); | ||
427 | cleanup_exit(255); | ||
428 | } | ||
429 | debug("Client protocol version %d.%d; client software version %.100s", | ||
430 | remote_major, remote_minor, remote_version); | ||
431 | |||
432 | ssh->compat = compat_datafellows(remote_version); | ||
433 | |||
434 | if ((ssh->compat & SSH_BUG_PROBE) != 0) { | ||
435 | logit("probed from %s port %d with %s. Don't panic.", | ||
436 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
437 | client_version_string); | ||
438 | cleanup_exit(255); | ||
439 | } | ||
440 | if ((ssh->compat & SSH_BUG_SCANNER) != 0) { | ||
441 | logit("scanned from %s port %d with %s. Don't panic.", | ||
442 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
443 | client_version_string); | ||
444 | cleanup_exit(255); | ||
445 | } | ||
446 | if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { | ||
447 | logit("Client version \"%.100s\" uses unsafe RSA signature " | ||
448 | "scheme; disabling use of RSA keys", remote_version); | ||
449 | } | ||
450 | |||
451 | chop(server_version_string); | ||
452 | debug("Local version string %.200s", server_version_string); | ||
453 | |||
454 | if (remote_major != 2 && | ||
455 | !(remote_major == 1 && remote_minor == 99)) { | ||
456 | s = "Protocol major versions differ.\n"; | ||
457 | (void) atomicio(vwrite, sock_out, s, strlen(s)); | ||
458 | close(sock_in); | ||
459 | close(sock_out); | ||
460 | logit("Protocol major versions differ for %s port %d: " | ||
461 | "%.200s vs. %.200s", | ||
462 | ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), | ||
463 | server_version_string, client_version_string); | ||
464 | cleanup_exit(255); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | /* Destroy the host and server keys. They will no longer be needed. */ | 359 | /* Destroy the host and server keys. They will no longer be needed. */ |
469 | void | 360 | void |
470 | destroy_sensitive_data(void) | 361 | destroy_sensitive_data(void) |
@@ -2115,7 +2006,9 @@ main(int ac, char **av) | |||
2115 | if (!debug_flag) | 2006 | if (!debug_flag) |
2116 | alarm(options.login_grace_time); | 2007 | alarm(options.login_grace_time); |
2117 | 2008 | ||
2118 | sshd_exchange_identification(ssh, sock_in, sock_out); | 2009 | if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) |
2010 | cleanup_exit(255); /* error already logged */ | ||
2011 | |||
2119 | packet_set_nonblocking(); | 2012 | packet_set_nonblocking(); |
2120 | 2013 | ||
2121 | /* allocate authentication context */ | 2014 | /* allocate authentication context */ |
@@ -2303,9 +2196,6 @@ do_ssh2_kex(void) | |||
2303 | # endif | 2196 | # endif |
2304 | #endif | 2197 | #endif |
2305 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; | 2198 | kex->kex[KEX_C25519_SHA256] = kexc25519_server; |
2306 | kex->server = 1; | ||
2307 | kex->client_version_string=client_version_string; | ||
2308 | kex->server_version_string=server_version_string; | ||
2309 | kex->load_host_public_key=&get_hostkey_public_by_type; | 2199 | kex->load_host_public_key=&get_hostkey_public_by_type; |
2310 | kex->load_host_private_key=&get_hostkey_private_by_type; | 2200 | kex->load_host_private_key=&get_hostkey_private_by_type; |
2311 | kex->host_key_index=&get_hostkey_index; | 2201 | kex->host_key_index=&get_hostkey_index; |