summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2019-06-05 06:41:44 +0100
committerColin Watson <cjwatson@debian.org>2019-06-09 22:09:07 +0100
commit865a97e05b6aab1619e1c8eeb33ccb8f9a9e48d3 (patch)
tree7bb2128eb663180bacfabca88f26d26bf0733824 /kex.c
parentba627ba172d6649919baedff5ba2789610da382a (diff)
parent7d50f9e5be88179325983a1f58c9d51bb58f025a (diff)
New upstream release (8.0p1)
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c402
1 files changed, 357 insertions, 45 deletions
diff --git a/kex.c b/kex.c
index fb5bfaea5..bbb7a2340 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.141 2018/07/09 13:37:10 sf Exp $ */ 1/* $OpenBSD: kex.c,v 1.150 2019/01/21 12:08:13 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 *
@@ -25,19 +25,25 @@
25 25
26#include "includes.h" 26#include "includes.h"
27 27
28 28#include <sys/types.h>
29#include <errno.h>
29#include <signal.h> 30#include <signal.h>
30#include <stdarg.h> 31#include <stdarg.h>
31#include <stdio.h> 32#include <stdio.h>
32#include <stdlib.h> 33#include <stdlib.h>
33#include <string.h> 34#include <string.h>
35#include <unistd.h>
36#include <poll.h>
34 37
35#ifdef WITH_OPENSSL 38#ifdef WITH_OPENSSL
36#include <openssl/crypto.h> 39#include <openssl/crypto.h>
37#include <openssl/dh.h> 40#include <openssl/dh.h>
38#endif 41#endif
39 42
43#include "ssh.h"
40#include "ssh2.h" 44#include "ssh2.h"
45#include "atomicio.h"
46#include "version.h"
41#include "packet.h" 47#include "packet.h"
42#include "compat.h" 48#include "compat.h"
43#include "cipher.h" 49#include "cipher.h"
@@ -49,6 +55,7 @@
49#include "misc.h" 55#include "misc.h"
50#include "dispatch.h" 56#include "dispatch.h"
51#include "monitor.h" 57#include "monitor.h"
58#include "xmalloc.h"
52 59
53#include "ssherr.h" 60#include "ssherr.h"
54#include "sshbuf.h" 61#include "sshbuf.h"
@@ -106,26 +113,33 @@ static const struct kexalg kexalgs[] = {
106#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) 113#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
107 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, 114 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
108 { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, 115 { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
116 { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0,
117 SSH_DIGEST_SHA512 },
109#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ 118#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
110 { NULL, -1, -1, -1}, 119 { NULL, -1, -1, -1},
111}; 120};
112static const struct kexalg kexalg_prefixes[] = { 121static const struct kexalg gss_kexalgs[] = {
113#ifdef GSSAPI 122#ifdef GSSAPI
114 { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, 123 { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
115 { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 124 { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
116 { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, 125 { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
126 { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
127 { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
128 { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256,
129 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
130 { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
117#endif 131#endif
118 { NULL, -1, -1, -1 }, 132 { NULL, -1, -1, -1 },
119}; 133};
120 134
121char * 135static char *
122kex_alg_list(char sep) 136kex_alg_list_internal(char sep, const struct kexalg *algs)
123{ 137{
124 char *ret = NULL, *tmp; 138 char *ret = NULL, *tmp;
125 size_t nlen, rlen = 0; 139 size_t nlen, rlen = 0;
126 const struct kexalg *k; 140 const struct kexalg *k;
127 141
128 for (k = kexalgs; k->name != NULL; k++) { 142 for (k = algs; k->name != NULL; k++) {
129 if (ret != NULL) 143 if (ret != NULL)
130 ret[rlen++] = sep; 144 ret[rlen++] = sep;
131 nlen = strlen(k->name); 145 nlen = strlen(k->name);
@@ -140,6 +154,18 @@ kex_alg_list(char sep)
140 return ret; 154 return ret;
141} 155}
142 156
157char *
158kex_alg_list(char sep)
159{
160 return kex_alg_list_internal(sep, kexalgs);
161}
162
163char *
164kex_gss_alg_list(char sep)
165{
166 return kex_alg_list_internal(sep, gss_kexalgs);
167}
168
143static const struct kexalg * 169static const struct kexalg *
144kex_alg_by_name(const char *name) 170kex_alg_by_name(const char *name)
145{ 171{
@@ -149,7 +175,7 @@ kex_alg_by_name(const char *name)
149 if (strcmp(k->name, name) == 0) 175 if (strcmp(k->name, name) == 0)
150 return k; 176 return k;
151 } 177 }
152 for (k = kexalg_prefixes; k->name != NULL; k++) { 178 for (k = gss_kexalgs; k->name != NULL; k++) {
153 if (strncmp(k->name, name, strlen(k->name)) == 0) 179 if (strncmp(k->name, name, strlen(k->name)) == 0)
154 return k; 180 return k;
155 } 181 }
@@ -309,6 +335,29 @@ kex_assemble_names(char **listp, const char *def, const char *all)
309 return r; 335 return r;
310} 336}
311 337
338/* Validate GSS KEX method name list */
339int
340kex_gss_names_valid(const char *names)
341{
342 char *s, *cp, *p;
343
344 if (names == NULL || *names == '\0')
345 return 0;
346 s = cp = xstrdup(names);
347 for ((p = strsep(&cp, ",")); p && *p != '\0';
348 (p = strsep(&cp, ","))) {
349 if (strncmp(p, "gss-", 4) != 0
350 || kex_alg_by_name(p) == NULL) {
351 error("Unsupported KEX algorithm \"%.100s\"", p);
352 free(s);
353 return 0;
354 }
355 }
356 debug3("gss kex names ok: [%s]", names);
357 free(s);
358 return 1;
359}
360
312/* put algorithm proposal into buffer */ 361/* put algorithm proposal into buffer */
313int 362int
314kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) 363kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
@@ -503,6 +552,7 @@ kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
503 if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) 552 if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
504 return r; 553 return r;
505 kex->done = 1; 554 kex->done = 1;
555 kex->flags &= ~KEX_INITIAL;
506 sshbuf_reset(kex->peer); 556 sshbuf_reset(kex->peer);
507 /* sshbuf_reset(kex->my); */ 557 /* sshbuf_reset(kex->my); */
508 kex->flags &= ~KEX_INIT_SENT; 558 kex->flags &= ~KEX_INIT_SENT;
@@ -593,31 +643,20 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
593 return SSH_ERR_INTERNAL_ERROR; 643 return SSH_ERR_INTERNAL_ERROR;
594} 644}
595 645
596int 646struct kex *
597kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) 647kex_new(void)
598{ 648{
599 struct kex *kex; 649 struct kex *kex;
600 int r;
601 650
602 *kexp = NULL; 651 if ((kex = calloc(1, sizeof(*kex))) == NULL ||
603 if ((kex = calloc(1, sizeof(*kex))) == NULL) 652 (kex->peer = sshbuf_new()) == NULL ||
604 return SSH_ERR_ALLOC_FAIL; 653 (kex->my = sshbuf_new()) == NULL ||
605 if ((kex->peer = sshbuf_new()) == NULL || 654 (kex->client_version = sshbuf_new()) == NULL ||
606 (kex->my = sshbuf_new()) == NULL) { 655 (kex->server_version = sshbuf_new()) == NULL) {
607 r = SSH_ERR_ALLOC_FAIL;
608 goto out;
609 }
610 if ((r = kex_prop2buf(kex->my, proposal)) != 0)
611 goto out;
612 kex->done = 0;
613 kex_reset_dispatch(ssh);
614 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
615 r = 0;
616 *kexp = kex;
617 out:
618 if (r != 0)
619 kex_free(kex); 656 kex_free(kex);
620 return r; 657 return NULL;
658 }
659 return kex;
621} 660}
622 661
623void 662void
@@ -656,6 +695,9 @@ kex_free(struct kex *kex)
656{ 695{
657 u_int mode; 696 u_int mode;
658 697
698 if (kex == NULL)
699 return;
700
659#ifdef WITH_OPENSSL 701#ifdef WITH_OPENSSL
660 DH_free(kex->dh); 702 DH_free(kex->dh);
661#ifdef OPENSSL_HAS_ECC 703#ifdef OPENSSL_HAS_ECC
@@ -668,12 +710,13 @@ kex_free(struct kex *kex)
668 } 710 }
669 sshbuf_free(kex->peer); 711 sshbuf_free(kex->peer);
670 sshbuf_free(kex->my); 712 sshbuf_free(kex->my);
713 sshbuf_free(kex->client_version);
714 sshbuf_free(kex->server_version);
715 sshbuf_free(kex->client_pub);
671 free(kex->session_id); 716 free(kex->session_id);
672#ifdef GSSAPI 717#ifdef GSSAPI
673 free(kex->gss_host); 718 free(kex->gss_host);
674#endif /* GSSAPI */ 719#endif /* GSSAPI */
675 free(kex->client_version_string);
676 free(kex->server_version_string);
677 free(kex->failed_choice); 720 free(kex->failed_choice);
678 free(kex->hostkey_alg); 721 free(kex->hostkey_alg);
679 free(kex->name); 722 free(kex->name);
@@ -681,11 +724,24 @@ kex_free(struct kex *kex)
681} 724}
682 725
683int 726int
727kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
728{
729 int r;
730
731 if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
732 return r;
733 ssh->kex->flags = KEX_INITIAL;
734 kex_reset_dispatch(ssh);
735 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
736 return 0;
737}
738
739int
684kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) 740kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
685{ 741{
686 int r; 742 int r;
687 743
688 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) 744 if ((r = kex_ready(ssh, proposal)) != 0)
689 return r; 745 return r;
690 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ 746 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
691 kex_free(ssh->kex); 747 kex_free(ssh->kex);
@@ -858,7 +914,7 @@ kex_choose_conf(struct ssh *ssh)
858 } 914 }
859 915
860 /* Check whether client supports ext_info_c */ 916 /* Check whether client supports ext_info_c */
861 if (kex->server) { 917 if (kex->server && (kex->flags & KEX_INITIAL)) {
862 char *ext; 918 char *ext;
863 919
864 ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); 920 ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
@@ -1016,6 +1072,14 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1016 u_int i, j, mode, ctos; 1072 u_int i, j, mode, ctos;
1017 int r; 1073 int r;
1018 1074
1075 /* save initial hash as session id */
1076 if (kex->session_id == NULL) {
1077 kex->session_id_len = hashlen;
1078 kex->session_id = malloc(kex->session_id_len);
1079 if (kex->session_id == NULL)
1080 return SSH_ERR_ALLOC_FAIL;
1081 memcpy(kex->session_id, hash, kex->session_id_len);
1082 }
1019 for (i = 0; i < NKEYS; i++) { 1083 for (i = 0; i < NKEYS; i++) {
1020 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, 1084 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1021 shared_secret, &keys[i])) != 0) { 1085 shared_secret, &keys[i])) != 0) {
@@ -1034,29 +1098,277 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1034 return 0; 1098 return 0;
1035} 1099}
1036 1100
1037#ifdef WITH_OPENSSL
1038int 1101int
1039kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, 1102kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1040 const BIGNUM *secret)
1041{ 1103{
1042 struct sshbuf *shared_secret; 1104 struct kex *kex = ssh->kex;
1043 int r;
1044 1105
1045 if ((shared_secret = sshbuf_new()) == NULL) 1106 *pubp = NULL;
1046 return SSH_ERR_ALLOC_FAIL; 1107 *prvp = NULL;
1047 if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0) 1108 if (kex->load_host_public_key == NULL ||
1048 r = kex_derive_keys(ssh, hash, hashlen, shared_secret); 1109 kex->load_host_private_key == NULL)
1049 sshbuf_free(shared_secret); 1110 return SSH_ERR_INVALID_ARGUMENT;
1050 return r; 1111 *pubp = kex->load_host_public_key(kex->hostkey_type,
1112 kex->hostkey_nid, ssh);
1113 *prvp = kex->load_host_private_key(kex->hostkey_type,
1114 kex->hostkey_nid, ssh);
1115 if (*pubp == NULL)
1116 return SSH_ERR_NO_HOSTKEY_LOADED;
1117 return 0;
1051} 1118}
1052#endif
1053 1119
1120int
1121kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1122{
1123 struct kex *kex = ssh->kex;
1124
1125 if (kex->verify_host_key == NULL)
1126 return SSH_ERR_INVALID_ARGUMENT;
1127 if (server_host_key->type != kex->hostkey_type ||
1128 (kex->hostkey_type == KEY_ECDSA &&
1129 server_host_key->ecdsa_nid != kex->hostkey_nid))
1130 return SSH_ERR_KEY_TYPE_MISMATCH;
1131 if (kex->verify_host_key(server_host_key, ssh) == -1)
1132 return SSH_ERR_SIGNATURE_INVALID;
1133 return 0;
1134}
1054 1135
1055#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 1136#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
1056void 1137void
1057dump_digest(char *msg, u_char *digest, int len) 1138dump_digest(const char *msg, const u_char *digest, int len)
1058{ 1139{
1059 fprintf(stderr, "%s\n", msg); 1140 fprintf(stderr, "%s\n", msg);
1060 sshbuf_dump_data(digest, len, stderr); 1141 sshbuf_dump_data(digest, len, stderr);
1061} 1142}
1062#endif 1143#endif
1144
1145/*
1146 * Send a plaintext error message to the peer, suffixed by \r\n.
1147 * Only used during banner exchange, and there only for the server.
1148 */
1149static void
1150send_error(struct ssh *ssh, char *msg)
1151{
1152 char *crnl = "\r\n";
1153
1154 if (!ssh->kex->server)
1155 return;
1156
1157 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1158 msg, strlen(msg)) != strlen(msg) ||
1159 atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1160 crnl, strlen(crnl)) != strlen(crnl))
1161 error("%s: write: %.100s", __func__, strerror(errno));
1162}
1163
1164/*
1165 * Sends our identification string and waits for the peer's. Will block for
1166 * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1167 * Returns on 0 success or a ssherr.h code on failure.
1168 */
1169int
1170kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1171 int debian_banner, const char *version_addendum)
1172{
1173 int remote_major, remote_minor, mismatch;
1174 size_t len, i, n;
1175 int r, expect_nl;
1176 u_char c;
1177 struct sshbuf *our_version = ssh->kex->server ?
1178 ssh->kex->server_version : ssh->kex->client_version;
1179 struct sshbuf *peer_version = ssh->kex->server ?
1180 ssh->kex->client_version : ssh->kex->server_version;
1181 char *our_version_string = NULL, *peer_version_string = NULL;
1182 char *cp, *remote_version = NULL;
1183
1184 /* Prepare and send our banner */
1185 sshbuf_reset(our_version);
1186 if (version_addendum != NULL && *version_addendum == '\0')
1187 version_addendum = NULL;
1188 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
1189 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
1190 debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM,
1191 version_addendum == NULL ? "" : " ",
1192 version_addendum == NULL ? "" : version_addendum)) != 0) {
1193 error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
1194 goto out;
1195 }
1196
1197 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1198 sshbuf_mutable_ptr(our_version),
1199 sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1200 error("%s: write: %.100s", __func__, strerror(errno));
1201 r = SSH_ERR_SYSTEM_ERROR;
1202 goto out;
1203 }
1204 if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1205 error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r));
1206 goto out;
1207 }
1208 our_version_string = sshbuf_dup_string(our_version);
1209 if (our_version_string == NULL) {
1210 error("%s: sshbuf_dup_string failed", __func__);
1211 r = SSH_ERR_ALLOC_FAIL;
1212 goto out;
1213 }
1214 debug("Local version string %.100s", our_version_string);
1215
1216 /* Read other side's version identification. */
1217 for (n = 0; ; n++) {
1218 if (n >= SSH_MAX_PRE_BANNER_LINES) {
1219 send_error(ssh, "No SSH identification string "
1220 "received.");
1221 error("%s: No SSH version received in first %u lines "
1222 "from server", __func__, SSH_MAX_PRE_BANNER_LINES);
1223 r = SSH_ERR_INVALID_FORMAT;
1224 goto out;
1225 }
1226 sshbuf_reset(peer_version);
1227 expect_nl = 0;
1228 for (i = 0; ; i++) {
1229 if (timeout_ms > 0) {
1230 r = waitrfd(ssh_packet_get_connection_in(ssh),
1231 &timeout_ms);
1232 if (r == -1 && errno == ETIMEDOUT) {
1233 send_error(ssh, "Timed out waiting "
1234 "for SSH identification string.");
1235 error("Connection timed out during "
1236 "banner exchange");
1237 r = SSH_ERR_CONN_TIMEOUT;
1238 goto out;
1239 } else if (r == -1) {
1240 error("%s: %s",
1241 __func__, strerror(errno));
1242 r = SSH_ERR_SYSTEM_ERROR;
1243 goto out;
1244 }
1245 }
1246
1247 len = atomicio(read, ssh_packet_get_connection_in(ssh),
1248 &c, 1);
1249 if (len != 1 && errno == EPIPE) {
1250 error("%s: Connection closed by remote host",
1251 __func__);
1252 r = SSH_ERR_CONN_CLOSED;
1253 goto out;
1254 } else if (len != 1) {
1255 error("%s: read: %.100s",
1256 __func__, strerror(errno));
1257 r = SSH_ERR_SYSTEM_ERROR;
1258 goto out;
1259 }
1260 if (c == '\r') {
1261 expect_nl = 1;
1262 continue;
1263 }
1264 if (c == '\n')
1265 break;
1266 if (c == '\0' || expect_nl) {
1267 error("%s: banner line contains invalid "
1268 "characters", __func__);
1269 goto invalid;
1270 }
1271 if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1272 error("%s: sshbuf_put: %s",
1273 __func__, ssh_err(r));
1274 goto out;
1275 }
1276 if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1277 error("%s: banner line too long", __func__);
1278 goto invalid;
1279 }
1280 }
1281 /* Is this an actual protocol banner? */
1282 if (sshbuf_len(peer_version) > 4 &&
1283 memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1284 break;
1285 /* If not, then just log the line and continue */
1286 if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1287 error("%s: sshbuf_dup_string failed", __func__);
1288 r = SSH_ERR_ALLOC_FAIL;
1289 goto out;
1290 }
1291 /* Do not accept lines before the SSH ident from a client */
1292 if (ssh->kex->server) {
1293 error("%s: client sent invalid protocol identifier "
1294 "\"%.256s\"", __func__, cp);
1295 free(cp);
1296 goto invalid;
1297 }
1298 debug("%s: banner line %zu: %s", __func__, n, cp);
1299 free(cp);
1300 }
1301 peer_version_string = sshbuf_dup_string(peer_version);
1302 if (peer_version_string == NULL)
1303 error("%s: sshbuf_dup_string failed", __func__);
1304 /* XXX must be same size for sscanf */
1305 if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1306 error("%s: calloc failed", __func__);
1307 r = SSH_ERR_ALLOC_FAIL;
1308 goto out;
1309 }
1310
1311 /*
1312 * Check that the versions match. In future this might accept
1313 * several versions and set appropriate flags to handle them.
1314 */
1315 if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1316 &remote_major, &remote_minor, remote_version) != 3) {
1317 error("Bad remote protocol version identification: '%.100s'",
1318 peer_version_string);
1319 invalid:
1320 send_error(ssh, "Invalid SSH identification string.");
1321 r = SSH_ERR_INVALID_FORMAT;
1322 goto out;
1323 }
1324 debug("Remote protocol version %d.%d, remote software version %.100s",
1325 remote_major, remote_minor, remote_version);
1326 ssh->compat = compat_datafellows(remote_version);
1327
1328 mismatch = 0;
1329 switch (remote_major) {
1330 case 2:
1331 break;
1332 case 1:
1333 if (remote_minor != 99)
1334 mismatch = 1;
1335 break;
1336 default:
1337 mismatch = 1;
1338 break;
1339 }
1340 if (mismatch) {
1341 error("Protocol major versions differ: %d vs. %d",
1342 PROTOCOL_MAJOR_2, remote_major);
1343 send_error(ssh, "Protocol major versions differ.");
1344 r = SSH_ERR_NO_PROTOCOL_VERSION;
1345 goto out;
1346 }
1347
1348 if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1349 logit("probed from %s port %d with %s. Don't panic.",
1350 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1351 peer_version_string);
1352 r = SSH_ERR_CONN_CLOSED; /* XXX */
1353 goto out;
1354 }
1355 if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1356 logit("scanned from %s port %d with %s. Don't panic.",
1357 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1358 peer_version_string);
1359 r = SSH_ERR_CONN_CLOSED; /* XXX */
1360 goto out;
1361 }
1362 if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
1363 logit("Remote version \"%.100s\" uses unsafe RSA signature "
1364 "scheme; disabling use of RSA keys", remote_version);
1365 }
1366 /* success */
1367 r = 0;
1368 out:
1369 free(our_version_string);
1370 free(peer_version_string);
1371 free(remote_version);
1372 return r;
1373}
1374