1- From d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a Mon Sep 17 00:00:00 2001
1+ From 3a80751dce7b7d98b9d9006fb37213a1e4af7ac5 Mon Sep 17 00:00:00 2001
22From: Michael Buckley <
[email protected] >
33Date: Thu, 30 Nov 2023 15:08:02 -0800
44Subject: [PATCH] src: add 'strict KEX' to fix CVE-2023-48795 "Terrapin Attack"
@@ -15,6 +15,8 @@ Closes #1291
1515
1616Upstream: https://github.com/libssh2/libssh2/commit/d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a
1717Signed-off-by: Fabrice Fontaine <
[email protected] >
18+ [Dario: make the patch to be applied with fuzz factor 0]
19+ Signed-off-by: Dario Binacchi <
[email protected] >
1820---
1921 src/kex.c | 63 +++++++++++++++++++++++------------
2022 src/libssh2_priv.h | 18 +++++++---
2527 6 files changed, 149 insertions(+), 32 deletions(-)
2628
2729diff --git a/src/kex.c b/src/kex.c
28- index 8e7b7f0af3..a7b301e157 100644
30+ index d4034a0a953e..b4b748cac4ee 100644
2931--- a/src/kex.c
3032+++ b/src/kex.c
31- @@ -3032 ,6 +3032 ,13 @@ kex_method_extension_negotiation = {
33+ @@ -3037 ,6 +3037 ,13 @@ kex_method_extension_negotiation = {
3234 0,
3335 };
3436
@@ -42,15 +44,15 @@ index 8e7b7f0af3..a7b301e157 100644
4244 static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
4345 #if LIBSSH2_ED25519
4446 &kex_method_ssh_curve25519_sha256,
45- @@ -3050 ,6 +3057 ,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
47+ @@ -3055 ,6 +3062 ,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
4648 &kex_method_diffie_helman_group1_sha1,
4749 &kex_method_diffie_helman_group_exchange_sha1,
4850 &kex_method_extension_negotiation,
4951+ &kex_method_strict_client_extension,
5052 NULL
5153 };
5254
53- @@ -3302 ,13 +3310 ,13 @@ static int kexinit(LIBSSH2_SESSION * session)
55+ @@ -3307 ,13 +3315 ,13 @@ static int kexinit(LIBSSH2_SESSION * session)
5456 return 0;
5557 }
5658
@@ -68,7 +70,7 @@ index 8e7b7f0af3..a7b301e157 100644
6870 {
6971 unsigned char *s;
7072 unsigned char *end_haystack;
71- @@ -3393 ,7 +3401 ,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
73+ @@ -3398 ,7 +3406 ,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
7274 while(s && *s) {
7375 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
7476 size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
@@ -77,7 +79,7 @@ index 8e7b7f0af3..a7b301e157 100644
7779 const LIBSSH2_HOSTKEY_METHOD *method =
7880 (const LIBSSH2_HOSTKEY_METHOD *)
7981 kex_get_method_by_name((char *) s, method_len,
80- @@ -3427 ,9 +3435 ,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
82+ @@ -3432 ,9 +3440 ,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
8183 }
8284
8385 while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
@@ -90,7 +92,7 @@ index 8e7b7f0af3..a7b301e157 100644
9092 if(s) {
9193 /* So far so good, but does it suit our purposes? (Encrypting vs
9294 Signing) */
93- @@ -3463 ,6 +3471 ,12 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
95+ @@ -3468 ,6 +3476 ,12 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
9496 {
9597 const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
9698 unsigned char *s;
@@ -103,7 +105,7 @@ index 8e7b7f0af3..a7b301e157 100644
103105
104106 if(session->kex_prefs) {
105107 s = (unsigned char *) session->kex_prefs;
106- @@ -3470 ,7 +3484 ,7 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
108+ @@ -3475 ,7 +3489 ,7 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
107109 while(s && *s) {
108110 unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
109111 size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
@@ -112,7 +114,7 @@ index 8e7b7f0af3..a7b301e157 100644
112114 if(q) {
113115 const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
114116 kex_get_method_by_name((char *) s, method_len,
115- @@ -3504 ,9 +3518 ,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
117+ @@ -3509 ,9 +3523 ,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
116118 }
117119
118120 while(*kexp && (*kexp)->name) {
@@ -125,7 +127,7 @@ index 8e7b7f0af3..a7b301e157 100644
125127 if(s) {
126128 /* We've agreed on a key exchange method,
127129 * Can we agree on a hostkey that works with this kex?
128- @@ -3550 ,7 +3564 ,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
130+ @@ -3555 ,7 +3569 ,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
129131 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
130132 size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
131133
@@ -134,7 +136,7 @@ index 8e7b7f0af3..a7b301e157 100644
134136 const LIBSSH2_CRYPT_METHOD *method =
135137 (const LIBSSH2_CRYPT_METHOD *)
136138 kex_get_method_by_name((char *) s, method_len,
137- @@ -3572 ,9 +3586 ,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
139+ @@ -3577 ,9 +3591 ,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
138140 }
139141
140142 while(*cryptp && (*cryptp)->name) {
@@ -147,7 +149,7 @@ index 8e7b7f0af3..a7b301e157 100644
147149 if(s) {
148150 endpoint->crypt = *cryptp;
149151 return 0;
150- @@ -3614 ,7 +3628 ,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
152+ @@ -3619 ,7 +3633 ,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
151153 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
152154 size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
153155
@@ -156,7 +158,7 @@ index 8e7b7f0af3..a7b301e157 100644
156158 const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
157159 kex_get_method_by_name((char *) s, method_len,
158160 (const LIBSSH2_COMMON_METHOD **)
159- @@ -3635 ,8 +3649 ,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
161+ @@ -3640 ,8 +3654 ,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
160162 }
161163
162164 while(*macp && (*macp)->name) {
@@ -168,7 +170,7 @@ index 8e7b7f0af3..a7b301e157 100644
168170 if(s) {
169171 endpoint->mac = *macp;
170172 return 0;
171- @@ -3667 ,7 +3682 ,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
173+ @@ -3672 ,7 +3687 ,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
172174 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
173175 size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
174176
@@ -177,7 +179,7 @@ index 8e7b7f0af3..a7b301e157 100644
177179 const LIBSSH2_COMP_METHOD *method =
178180 (const LIBSSH2_COMP_METHOD *)
179181 kex_get_method_by_name((char *) s, method_len,
180- @@ -3689 ,8 +3704 ,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
182+ @@ -3694 ,8 +3709 ,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
181183 }
182184
183185 while(*compp && (*compp)->name) {
@@ -189,23 +191,23 @@ index 8e7b7f0af3..a7b301e157 100644
189191 if(s) {
190192 endpoint->comp = *compp;
191193 return 0;
192- @@ -3871 ,6 +3887 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
194+ @@ -3876 ,6 +3892 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
193195 session->local.kexinit = key_state->oldlocal;
194196 session->local.kexinit_len = key_state->oldlocal_len;
195197 key_state->state = libssh2_NB_state_idle;
196198+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
197199 session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
198200 session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
199201 return -1;
200- @@ -3896 ,6 +3913 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
202+ @@ -3901 ,6 +3918 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
201203 session->local.kexinit = key_state->oldlocal;
202204 session->local.kexinit_len = key_state->oldlocal_len;
203205 key_state->state = libssh2_NB_state_idle;
204206+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
205207 session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
206208 session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
207209 return -1;
208- @@ -3944 ,6 +3962 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
210+ @@ -3949 ,6 +3967 ,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
209211 session->remote.kexinit = NULL;
210212 }
211213
@@ -214,10 +216,10 @@ index 8e7b7f0af3..a7b301e157 100644
214216 session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
215217
216218diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
217- index 7660366954..18d9ab2130 100644
219+ index 82c3afe250b0..ee1d8b5c2b9b 100644
218220--- a/src/libssh2_priv.h
219221+++ b/src/libssh2_priv.h
220- @@ -736 ,6 +736 ,9 @@ struct _LIBSSH2_SESSION
222+ @@ -699 ,6 +699 ,9 @@ struct _LIBSSH2_SESSION
221223 /* key signing algorithm preferences -- NULL yields server order */
222224 char *sign_algo_prefs;
223225
@@ -227,15 +229,15 @@ index 7660366954..18d9ab2130 100644
227229 /* (remote as source of data -- packet_read ) */
228230 libssh2_endpoint_data remote;
229231
230- @@ -908 ,6 +911 ,7 @@ struct _LIBSSH2_SESSION
232+ @@ -870 ,6 +873 ,7 @@ struct _LIBSSH2_SESSION
231233 int fullpacket_macstate;
232234 size_t fullpacket_payload_len;
233235 int fullpacket_packet_type;
234236+ uint32_t fullpacket_required_type;
235237
236238 /* State variables used in libssh2_sftp_init() */
237239 libssh2_nonblocking_states sftpInit_state;
238- @@ -948 ,10 +952 ,11 @@ struct _LIBSSH2_SESSION
240+ @@ -910 ,10 +914 ,11 @@ struct _LIBSSH2_SESSION
239241 };
240242
241243 /* session.state bits */
@@ -251,7 +253,7 @@ index 7660366954..18d9ab2130 100644
251253
252254 /* session.flag helpers */
253255 #ifdef MSG_NOSIGNAL
254- @@ -1182 ,6 +1187 ,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
256+ @@ -1144 ,6 +1149 ,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
255257 int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
256258 key_exchange_state_t * state);
257259
@@ -264,10 +266,10 @@ index 7660366954..18d9ab2130 100644
264266 const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
265267 const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
266268diff --git a/src/packet.c b/src/packet.c
267- index eccb8c56a8..6da14e9fa1 100644
269+ index b5b41981a108..35d4d39eff87 100644
268270--- a/src/packet.c
269271+++ b/src/packet.c
270- @@ -624 ,14 +624 ,13 @@ packet_authagent_open(LIBSSH2_SESSION * session,
272+ @@ -605 ,14 +605 ,13 @@ authagent_exit:
271273 * layer when it has received a packet.
272274 *
273275 * The input pointer 'data' is pointing to allocated data that this function
@@ -284,7 +286,7 @@ index eccb8c56a8..6da14e9fa1 100644
284286 {
285287 int rc = 0;
286288 unsigned char *message = NULL;
287- @@ -676 ,6 +675 ,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
289+ @@ -657 ,6 +656 ,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
288290 break;
289291 }
290292
@@ -355,7 +357,7 @@ index eccb8c56a8..6da14e9fa1 100644
355357 if(session->packAdd_state == libssh2_NB_state_allocated) {
356358 /* A couple exceptions to the packet adding rule: */
357359 switch(msg) {
358- @@ -1364 ,6 +1427 ,15 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
360+ @@ -1341 ,6 +1404 ,15 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
359361
360362 return 0;
361363 }
@@ -371,7 +373,7 @@ index eccb8c56a8..6da14e9fa1 100644
371373 packet = _libssh2_list_next(&packet->node);
372374 }
373375 return -1;
374- @@ -1425 ,7 +1497 ,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
376+ @@ -1402 ,7 +1474 ,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
375377 }
376378
377379 while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
@@ -384,22 +386,22 @@ index eccb8c56a8..6da14e9fa1 100644
384386 return ret;
385387 else if(ret < 0) {
386388diff --git a/src/packet.h b/src/packet.h
387- index 1d90b8af12..955351e5f6 100644
389+ index 79018bcf1d55..6ea100a5cfb3 100644
388390--- a/src/packet.h
389391+++ b/src/packet.h
390- @@ -72 ,6 +72 ,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session,
392+ @@ -71 ,6 +71 ,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session,
391393 int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
392394 unsigned long data_len);
393395 int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
394396- size_t datalen, int macstate);
395397+ size_t datalen, int macstate, uint32_t seq);
396398
397- #endif /* LIBSSH2_PACKET_H */
399+ #endif /* __LIBSSH2_PACKET_H */
398400diff --git a/src/session.c b/src/session.c
399- index 35e7929fe7..9d89ade8ec 100644
401+ index a4d602bad002..f4bafb57b2a6 100644
400402--- a/src/session.c
401403+++ b/src/session.c
402- @@ -469 ,6 +469 ,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
404+ @@ -464 ,6 +464 ,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
403405 session->abstract = abstract;
404406 session->api_timeout = 0; /* timeout-free API by default */
405407 session->api_block_mode = 1; /* blocking API by default */
@@ -408,7 +410,7 @@ index 35e7929fe7..9d89ade8ec 100644
408410 session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT;
409411 session->flag.quote_paths = 1; /* default behavior is to quote paths
410412 for the scp subsystem */
411- @@ -1223 ,6 +1225 ,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
413+ @@ -1186 ,6 +1188 ,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
412414 const char *desc, const char *lang)
413415 {
414416 int rc;
@@ -417,18 +419,18 @@ index 35e7929fe7..9d89ade8ec 100644
417419 BLOCK_ADJUST(rc, session,
418420 session_disconnect(session, reason, desc, lang));
419421diff --git a/src/transport.c b/src/transport.c
420- index 21be9d2b80..a8bb588a4b 100644
422+ index 6d902d3372b4..3b30ff848726 100644
421423--- a/src/transport.c
422424+++ b/src/transport.c
423- @@ -186 ,6 +186 ,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
425+ @@ -187 ,6 +187 ,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
424426 struct transportpacket *p = &session->packet;
425427 int rc;
426428 int compressed;
427429+ uint32_t seq = session->remote.seqno;
428430
429431 if(session->fullpacket_state == libssh2_NB_state_idle) {
430432 session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
431- @@ -317 ,7 +318 ,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
433+ @@ -318 ,7 +319 ,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
432434 if(session->fullpacket_state == libssh2_NB_state_created) {
433435 rc = _libssh2_packet_add(session, p->payload,
434436 session->fullpacket_payload_len,
@@ -437,7 +439,7 @@ index 21be9d2b80..a8bb588a4b 100644
437439 if(rc == LIBSSH2_ERROR_EAGAIN)
438440 return rc;
439441 if(rc) {
440- @@ -328 ,6 +329 ,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
442+ @@ -329 ,6 +330 ,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
441443
442444 session->fullpacket_state = libssh2_NB_state_idle;
443445
@@ -449,7 +451,7 @@ index 21be9d2b80..a8bb588a4b 100644
449451 return session->fullpacket_packet_type;
450452 }
451453
452- @@ -1093 ,6 +1099 ,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
454+ @@ -1091 ,6 +1097 ,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
453455
454456 session->local.seqno++;
455457
@@ -460,3 +462,6 @@ index 21be9d2b80..a8bb588a4b 100644
460462 ret = LIBSSH2_SEND(session, p->outbuf, total_length,
461463 LIBSSH2_SOCKET_SEND_FLAGS(session));
462464 if(ret < 0)
465+ - -
466+ 2.43.0
467+
0 commit comments