Compare commits
11 Commits
64d5fa9ff4
...
08844dd288
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08844dd288 | ||
|
|
48f3e4f7d0 | ||
|
|
db93d81b44 | ||
|
|
c4b6eda4ed | ||
|
|
126561a533 | ||
|
|
a0c264f32f | ||
|
|
f8d47b0f15 | ||
|
|
84d63c959c | ||
|
|
ccbe676899 | ||
|
|
8519fb8886 | ||
|
|
4bc4363bda |
@ -0,0 +1,97 @@
|
|||||||
|
From 80d3ea5b413d269ec77aebbb0aabbe738ba31796 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Cosgrove <will@panic.com>
|
||||||
|
Date: Wed, 4 Sep 2019 12:16:52 -0700
|
||||||
|
Subject: [PATCH] packet.c: improved packet parsing in packet_queue_listener
|
||||||
|
(#404)
|
||||||
|
|
||||||
|
* improved bounds checking in packet_queue_listener
|
||||||
|
|
||||||
|
file: packet.c
|
||||||
|
|
||||||
|
notes:
|
||||||
|
improved parsing packet in packet_queue_listener
|
||||||
|
---
|
||||||
|
src/packet.c | 63 +++++++++++++++++++++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 43 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/packet.c b/src/packet.c
|
||||||
|
index 2e01bfc..c83a68d 100644
|
||||||
|
--- a/src/packet.c
|
||||||
|
+++ b/src/packet.c
|
||||||
|
@@ -85,30 +85,53 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- (void) datalen;
|
||||||
|
-
|
||||||
|
if(listen_state->state == libssh2_NB_state_idle) {
|
||||||
|
- unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
|
||||||
|
- listen_state->sender_channel = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
+ unsigned long offset = (sizeof("forwarded-tcpip") - 1) + 5;
|
||||||
|
+ size_t temp_len = 0;
|
||||||
|
+ struct string_buf buf;
|
||||||
|
+ buf.data = data;
|
||||||
|
+ buf.dataptr = buf.data;
|
||||||
|
+ buf.len = datalen;
|
||||||
|
+
|
||||||
|
+ if(datalen < offset) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
|
||||||
|
+ "Unexpected packet size");
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- listen_state->initial_window_size = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- listen_state->packet_size = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
+ buf.dataptr += offset;
|
||||||
|
|
||||||
|
- listen_state->host_len = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- listen_state->host = s;
|
||||||
|
- s += listen_state->host_len;
|
||||||
|
- listen_state->port = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(listen_state->sender_channel))) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting channel");
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(listen_state->initial_window_size))) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting window size");
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(listen_state->packet_size))) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting packet");
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_string(&buf, &(listen_state->host), &temp_len)) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting host");
|
||||||
|
+ }
|
||||||
|
+ listen_state->host_len = (uint32_t)temp_len;
|
||||||
|
|
||||||
|
- listen_state->shost_len = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- listen_state->shost = s;
|
||||||
|
- s += listen_state->shost_len;
|
||||||
|
- listen_state->sport = _libssh2_ntohu32(s);
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(listen_state->port))) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting port");
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_string(&buf, &(listen_state->shost), &temp_len)) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting shost");
|
||||||
|
+ }
|
||||||
|
+ listen_state->shost_len = (uint32_t)temp_len;
|
||||||
|
+
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(listen_state->sport))) {
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting sport");
|
||||||
|
+ }
|
||||||
|
|
||||||
|
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||||
|
"Remote received connection from %s:%ld to %s:%ld",
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
88
0001-packet.c-improved-parsing-in-packet_x11_open-410.patch
Normal file
88
0001-packet.c-improved-parsing-in-packet_x11_open-410.patch
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
From 336bd86d2ca4030b808d76e56a0387914982e289 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Will Cosgrove <will@panic.com>
|
||||||
|
Date: Fri, 13 Sep 2019 09:45:34 -0700
|
||||||
|
Subject: [PATCH] packet.c: improved parsing in packet_x11_open (#410)
|
||||||
|
|
||||||
|
Use new API to parse data in packet_x11_open() for better bounds checking.
|
||||||
|
---
|
||||||
|
src/packet.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++--------------
|
||||||
|
1 file changed, 49 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/packet.c b/src/packet.c
|
||||||
|
index c83a68d..9897f77 100644
|
||||||
|
--- a/src/packet.c
|
||||||
|
+++ b/src/packet.c
|
||||||
|
@@ -295,21 +295,56 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
LIBSSH2_CHANNEL *channel = x11open_state->channel;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
- (void) datalen;
|
||||||
|
-
|
||||||
|
if(x11open_state->state == libssh2_NB_state_idle) {
|
||||||
|
- unsigned char *s = data + (sizeof("x11") - 1) + 5;
|
||||||
|
- x11open_state->sender_channel = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- x11open_state->initial_window_size = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- x11open_state->packet_size = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- x11open_state->shost_len = _libssh2_ntohu32(s);
|
||||||
|
- s += 4;
|
||||||
|
- x11open_state->shost = s;
|
||||||
|
- s += x11open_state->shost_len;
|
||||||
|
- x11open_state->sport = _libssh2_ntohu32(s);
|
||||||
|
+
|
||||||
|
+ unsigned long offset = (sizeof("x11") - 1) + 5;
|
||||||
|
+ size_t temp_len = 0;
|
||||||
|
+ struct string_buf buf;
|
||||||
|
+ buf.data = data;
|
||||||
|
+ buf.dataptr = buf.data;
|
||||||
|
+ buf.len = datalen;
|
||||||
|
+
|
||||||
|
+ if(datalen < offset) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected data length");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ buf.dataptr += offset;
|
||||||
|
+
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(x11open_state->sender_channel))) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected sender channel size");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(x11open_state->initial_window_size))) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected window size");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(x11open_state->packet_size))) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected window size");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
+ if(_libssh2_get_string(&buf, &(x11open_state->shost), &temp_len)) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected host size");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
+ x11open_state->shost_len = (uint32_t)temp_len;
|
||||||
|
+
|
||||||
|
+ if(_libssh2_get_u32(&buf, &(x11open_state->sport))) {
|
||||||
|
+ _libssh2_error(session, LIBSSH2_ERROR_INVAL,
|
||||||
|
+ "unexpected port size");
|
||||||
|
+ failure_code = SSH_OPEN_CONNECT_FAILED;
|
||||||
|
+ goto x11_exit;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
_libssh2_debug(session, LIBSSH2_TRACE_CONN,
|
||||||
|
"X11 Connection Received from %s:%ld on channel %lu",
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
||||||
469
backport-CVE-2023-48795.patch
Normal file
469
backport-CVE-2023-48795.patch
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
From d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Buckley <michael@buckleyisms.com>
|
||||||
|
Date: Thu, 30 Nov 2023 15:08:02 -0800
|
||||||
|
Subject: [PATCH] src: add 'strict KEX' to fix CVE-2023-48795 "Terrapin
|
||||||
|
Attack"
|
||||||
|
|
||||||
|
Refs:
|
||||||
|
https://terrapin-attack.com/
|
||||||
|
https://seclists.org/oss-sec/2023/q4/292
|
||||||
|
https://osv.dev/list?ecosystem=&q=CVE-2023-48795
|
||||||
|
https://github.com/advisories/GHSA-45x7-px36-x8w8
|
||||||
|
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795
|
||||||
|
|
||||||
|
Fixes #1290
|
||||||
|
Closes #1291
|
||||||
|
|
||||||
|
Reference:https://github.com/libssh2/libssh2/commit/d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a
|
||||||
|
Conflict:src: silence compiler warnings 3 (change types)
|
||||||
|
Configurable session read timeout (#892)
|
||||||
|
scp: option to not quote paths (#803)
|
||||||
|
|
||||||
|
---
|
||||||
|
src/kex.c | 63 +++++++++++++++++++++++------------
|
||||||
|
src/libssh2_priv.h | 18 +++++++---
|
||||||
|
src/packet.c | 83 +++++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
src/packet.h | 2 +-
|
||||||
|
src/session.c | 3 ++
|
||||||
|
src/transport.c | 12 ++++++-
|
||||||
|
6 files changed, 149 insertions(+), 32 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/kex.c b/src/kex.c
|
||||||
|
index 214e6cf..47f6bf4 100644
|
||||||
|
--- a/src/kex.c
|
||||||
|
+++ b/src/kex.c
|
||||||
|
@@ -3315,6 +3315,13 @@ kex_method_ssh_curve25519_sha256 = {
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+static const LIBSSH2_KEX_METHOD
|
||||||
|
+kex_method_strict_client_extension = {
|
||||||
|
+ "kex-strict-c-v00@openssh.com",
|
||||||
|
+ NULL,
|
||||||
|
+ 0,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
&kex_method_ecdh_sha2_nistp256,
|
||||||
|
@@ -3329,6 +3336,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
|
||||||
|
&kex_method_diffie_helman_group_exchange_sha1,
|
||||||
|
&kex_method_diffie_helman_group14_sha1,
|
||||||
|
&kex_method_diffie_helman_group1_sha1,
|
||||||
|
+ &kex_method_strict_client_extension,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -3563,13 +3571,13 @@ static int kexinit(LIBSSH2_SESSION * session)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* kex_agree_instr
|
||||||
|
+/* _libssh2_kex_agree_instr
|
||||||
|
* Kex specific variant of strstr()
|
||||||
|
* Needle must be precede by BOL or ',', and followed by ',' or EOL
|
||||||
|
*/
|
||||||
|
-static unsigned char *
|
||||||
|
-kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
|
||||||
|
- const unsigned char *needle, unsigned long needle_len)
|
||||||
|
+unsigned char *
|
||||||
|
+_libssh2_kex_agree_instr(unsigned char *haystack, size_t haystack_len,
|
||||||
|
+ const unsigned char *needle, size_t needle_len)
|
||||||
|
{
|
||||||
|
unsigned char *s;
|
||||||
|
|
||||||
|
@@ -3637,7 +3645,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
|
||||||
|
while(s && *s) {
|
||||||
|
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
|
||||||
|
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
|
||||||
|
- if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
|
||||||
|
+ if(_libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
|
||||||
|
const LIBSSH2_HOSTKEY_METHOD *method =
|
||||||
|
(const LIBSSH2_HOSTKEY_METHOD *)
|
||||||
|
kex_get_method_by_name((char *) s, method_len,
|
||||||
|
@@ -3671,9 +3679,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
|
||||||
|
- s = kex_agree_instr(hostkey, hostkey_len,
|
||||||
|
- (unsigned char *) (*hostkeyp)->name,
|
||||||
|
- strlen((*hostkeyp)->name));
|
||||||
|
+ s = _libssh2_kex_agree_instr(hostkey, hostkey_len,
|
||||||
|
+ (unsigned char *) (*hostkeyp)->name,
|
||||||
|
+ strlen((*hostkeyp)->name));
|
||||||
|
if(s) {
|
||||||
|
/* So far so good, but does it suit our purposes? (Encrypting vs
|
||||||
|
Signing) */
|
||||||
|
@@ -3707,6 +3715,12 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
|
||||||
|
{
|
||||||
|
const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
|
||||||
|
unsigned char *s;
|
||||||
|
+ const unsigned char *strict =
|
||||||
|
+ (unsigned char *)"kex-strict-s-v00@openssh.com";
|
||||||
|
+
|
||||||
|
+ if(_libssh2_kex_agree_instr(kex, kex_len, strict, 28)) {
|
||||||
|
+ session->kex_strict = 1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if(session->kex_prefs) {
|
||||||
|
s = (unsigned char *) session->kex_prefs;
|
||||||
|
@@ -3714,7 +3728,7 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
|
||||||
|
while(s && *s) {
|
||||||
|
unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
|
||||||
|
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
|
||||||
|
- q = kex_agree_instr(kex, kex_len, s, method_len);
|
||||||
|
+ q = _libssh2_kex_agree_instr(kex, kex_len, s, method_len);
|
||||||
|
if(q) {
|
||||||
|
const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
|
||||||
|
kex_get_method_by_name((char *) s, method_len,
|
||||||
|
@@ -3748,9 +3762,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(*kexp && (*kexp)->name) {
|
||||||
|
- s = kex_agree_instr(kex, kex_len,
|
||||||
|
- (unsigned char *) (*kexp)->name,
|
||||||
|
- strlen((*kexp)->name));
|
||||||
|
+ s = _libssh2_kex_agree_instr(kex, kex_len,
|
||||||
|
+ (unsigned char *) (*kexp)->name,
|
||||||
|
+ strlen((*kexp)->name));
|
||||||
|
if(s) {
|
||||||
|
/* We've agreed on a key exchange method,
|
||||||
|
* Can we agree on a hostkey that works with this kex?
|
||||||
|
@@ -3794,7 +3808,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
|
||||||
|
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
|
||||||
|
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
|
||||||
|
|
||||||
|
- if(kex_agree_instr(crypt, crypt_len, s, method_len)) {
|
||||||
|
+ if(_libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
|
||||||
|
const LIBSSH2_CRYPT_METHOD *method =
|
||||||
|
(const LIBSSH2_CRYPT_METHOD *)
|
||||||
|
kex_get_method_by_name((char *) s, method_len,
|
||||||
|
@@ -3816,9 +3830,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(*cryptp && (*cryptp)->name) {
|
||||||
|
- s = kex_agree_instr(crypt, crypt_len,
|
||||||
|
- (unsigned char *) (*cryptp)->name,
|
||||||
|
- strlen((*cryptp)->name));
|
||||||
|
+ s = _libssh2_kex_agree_instr(crypt, crypt_len,
|
||||||
|
+ (unsigned char *) (*cryptp)->name,
|
||||||
|
+ strlen((*cryptp)->name));
|
||||||
|
if(s) {
|
||||||
|
endpoint->crypt = *cryptp;
|
||||||
|
return 0;
|
||||||
|
@@ -3849,7 +3863,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
|
||||||
|
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
|
||||||
|
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
|
||||||
|
|
||||||
|
- if(kex_agree_instr(mac, mac_len, s, method_len)) {
|
||||||
|
+ if(_libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
|
||||||
|
const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
|
||||||
|
kex_get_method_by_name((char *) s, method_len,
|
||||||
|
(const LIBSSH2_COMMON_METHOD **)
|
||||||
|
@@ -3870,8 +3884,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(*macp && (*macp)->name) {
|
||||||
|
- s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name,
|
||||||
|
- strlen((*macp)->name));
|
||||||
|
+ s = _libssh2_kex_agree_instr(mac, mac_len,
|
||||||
|
+ (unsigned char *) (*macp)->name,
|
||||||
|
+ strlen((*macp)->name));
|
||||||
|
if(s) {
|
||||||
|
endpoint->mac = *macp;
|
||||||
|
return 0;
|
||||||
|
@@ -3902,7 +3917,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
|
||||||
|
unsigned char *p = (unsigned char *) strchr((char *) s, ',');
|
||||||
|
size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
|
||||||
|
|
||||||
|
- if(kex_agree_instr(comp, comp_len, s, method_len)) {
|
||||||
|
+ if(_libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
|
||||||
|
const LIBSSH2_COMP_METHOD *method =
|
||||||
|
(const LIBSSH2_COMP_METHOD *)
|
||||||
|
kex_get_method_by_name((char *) s, method_len,
|
||||||
|
@@ -3924,8 +3939,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(*compp && (*compp)->name) {
|
||||||
|
- s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name,
|
||||||
|
- strlen((*compp)->name));
|
||||||
|
+ s = _libssh2_kex_agree_instr(comp, comp_len,
|
||||||
|
+ (unsigned char *) (*compp)->name,
|
||||||
|
+ strlen((*compp)->name));
|
||||||
|
if(s) {
|
||||||
|
endpoint->comp = *compp;
|
||||||
|
return 0;
|
||||||
|
@@ -4097,6 +4113,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
|
||||||
|
session->local.kexinit = key_state->oldlocal;
|
||||||
|
session->local.kexinit_len = key_state->oldlocal_len;
|
||||||
|
key_state->state = libssh2_NB_state_idle;
|
||||||
|
+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
|
||||||
|
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||||
|
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
return -1;
|
||||||
|
@@ -4122,6 +4139,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
|
||||||
|
session->local.kexinit = key_state->oldlocal;
|
||||||
|
session->local.kexinit_len = key_state->oldlocal_len;
|
||||||
|
key_state->state = libssh2_NB_state_idle;
|
||||||
|
+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
|
||||||
|
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||||
|
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
return -1;
|
||||||
|
@@ -4170,6 +4188,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
|
||||||
|
session->remote.kexinit = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
|
||||||
|
session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
|
||||||
|
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
|
||||||
|
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
|
||||||
|
index 33c5ad3..2106786 100644
|
||||||
|
--- a/src/libssh2_priv.h
|
||||||
|
+++ b/src/libssh2_priv.h
|
||||||
|
@@ -629,6 +629,9 @@ struct _LIBSSH2_SESSION
|
||||||
|
unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH];
|
||||||
|
int server_hostkey_sha256_valid;
|
||||||
|
|
||||||
|
+ /* Whether to use the OpenSSH Strict KEX extension */
|
||||||
|
+ int kex_strict;
|
||||||
|
+
|
||||||
|
/* (remote as source of data -- packet_read ) */
|
||||||
|
libssh2_endpoint_data remote;
|
||||||
|
|
||||||
|
@@ -798,6 +801,7 @@ struct _LIBSSH2_SESSION
|
||||||
|
int fullpacket_macstate;
|
||||||
|
size_t fullpacket_payload_len;
|
||||||
|
int fullpacket_packet_type;
|
||||||
|
+ uint32_t fullpacket_required_type;
|
||||||
|
|
||||||
|
/* State variables used in libssh2_sftp_init() */
|
||||||
|
libssh2_nonblocking_states sftpInit_state;
|
||||||
|
@@ -845,10 +849,11 @@ struct _LIBSSH2_SESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
/* session.state bits */
|
||||||
|
-#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
|
||||||
|
-#define LIBSSH2_STATE_NEWKEYS 0x00000002
|
||||||
|
-#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
|
||||||
|
-#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
|
||||||
|
+#define LIBSSH2_STATE_INITIAL_KEX 0x00000001
|
||||||
|
+#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000002
|
||||||
|
+#define LIBSSH2_STATE_NEWKEYS 0x00000004
|
||||||
|
+#define LIBSSH2_STATE_AUTHENTICATED 0x00000008
|
||||||
|
+#define LIBSSH2_STATE_KEX_ACTIVE 0x00000010
|
||||||
|
|
||||||
|
/* session.flag helpers */
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
@@ -1065,6 +1070,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
|
||||||
|
int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
|
||||||
|
key_exchange_state_t * state);
|
||||||
|
|
||||||
|
+unsigned char *_libssh2_kex_agree_instr(unsigned char *haystack,
|
||||||
|
+ size_t haystack_len,
|
||||||
|
+ const unsigned char *needle,
|
||||||
|
+ size_t needle_len);
|
||||||
|
+
|
||||||
|
/* Let crypt.c/hostkey.c expose their method structs */
|
||||||
|
const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
|
||||||
|
const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
|
||||||
|
diff --git a/src/packet.c b/src/packet.c
|
||||||
|
index d4524a8..1f45cd2 100644
|
||||||
|
--- a/src/packet.c
|
||||||
|
+++ b/src/packet.c
|
||||||
|
@@ -467,14 +467,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
* layer when it has received a packet.
|
||||||
|
*
|
||||||
|
* The input pointer 'data' is pointing to allocated data that this function
|
||||||
|
- * is asked to deal with so on failure OR success, it must be freed fine.
|
||||||
|
- * The only exception is when the return code is LIBSSH2_ERROR_EAGAIN.
|
||||||
|
+ * will be freed unless return the code is LIBSSH2_ERROR_EAGAIN.
|
||||||
|
*
|
||||||
|
* This function will always be called with 'datalen' greater than zero.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
_libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
- size_t datalen, int macstate)
|
||||||
|
+ size_t datalen, int macstate, uint32_t seq)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
unsigned char *message = NULL;
|
||||||
|
@@ -517,6 +516,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if(session->state & LIBSSH2_STATE_INITIAL_KEX) {
|
||||||
|
+ if(msg == SSH_MSG_KEXINIT) {
|
||||||
|
+ if(!session->kex_strict) {
|
||||||
|
+ if(datalen < 17) {
|
||||||
|
+ LIBSSH2_FREE(session, data);
|
||||||
|
+ session->packAdd_state = libssh2_NB_state_idle;
|
||||||
|
+ return _libssh2_error(session,
|
||||||
|
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Data too short extracting kex");
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ const unsigned char *strict =
|
||||||
|
+ (unsigned char *)"kex-strict-s-v00@openssh.com";
|
||||||
|
+ struct string_buf buf;
|
||||||
|
+ unsigned char *algs = NULL;
|
||||||
|
+ size_t algs_len = 0;
|
||||||
|
+
|
||||||
|
+ buf.data = (unsigned char *)data;
|
||||||
|
+ buf.dataptr = buf.data;
|
||||||
|
+ buf.len = datalen;
|
||||||
|
+ buf.dataptr += 17; /* advance past type and cookie */
|
||||||
|
+
|
||||||
|
+ if(_libssh2_get_string(&buf, &algs, &algs_len)) {
|
||||||
|
+ LIBSSH2_FREE(session, data);
|
||||||
|
+ session->packAdd_state = libssh2_NB_state_idle;
|
||||||
|
+ return _libssh2_error(session,
|
||||||
|
+ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
|
||||||
|
+ "Algs too short");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(algs_len == 0 ||
|
||||||
|
+ _libssh2_kex_agree_instr(algs, algs_len, strict, 28)) {
|
||||||
|
+ session->kex_strict = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(session->kex_strict && seq) {
|
||||||
|
+ LIBSSH2_FREE(session, data);
|
||||||
|
+ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
||||||
|
+ session->packAdd_state = libssh2_NB_state_idle;
|
||||||
|
+ libssh2_session_disconnect(session, "strict KEX violation: "
|
||||||
|
+ "KEXINIT was not the first packet");
|
||||||
|
+
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
+ "strict KEX violation: "
|
||||||
|
+ "KEXINIT was not the first packet");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(session->kex_strict && session->fullpacket_required_type &&
|
||||||
|
+ session->fullpacket_required_type != msg) {
|
||||||
|
+ LIBSSH2_FREE(session, data);
|
||||||
|
+ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
|
||||||
|
+ session->packAdd_state = libssh2_NB_state_idle;
|
||||||
|
+ libssh2_session_disconnect(session, "strict KEX violation: "
|
||||||
|
+ "unexpected packet type");
|
||||||
|
+
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
+ "strict KEX violation: "
|
||||||
|
+ "unexpected packet type");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if(session->packAdd_state == libssh2_NB_state_allocated) {
|
||||||
|
/* A couple exceptions to the packet adding rule: */
|
||||||
|
switch(msg) {
|
||||||
|
@@ -1116,6 +1179,15 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+ else if(session->kex_strict &&
|
||||||
|
+ (session->state & LIBSSH2_STATE_INITIAL_KEX)) {
|
||||||
|
+ libssh2_session_disconnect(session, "strict KEX violation: "
|
||||||
|
+ "unexpected packet type");
|
||||||
|
+
|
||||||
|
+ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
+ "strict KEX violation: "
|
||||||
|
+ "unexpected packet type");
|
||||||
|
+ }
|
||||||
|
packet = _libssh2_list_next(&packet->node);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
@@ -1177,7 +1249,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
|
||||||
|
}
|
||||||
|
|
||||||
|
while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
|
||||||
|
- int ret = _libssh2_transport_read(session);
|
||||||
|
+ int ret;
|
||||||
|
+ session->fullpacket_required_type = packet_type;
|
||||||
|
+ ret = _libssh2_transport_read(session);
|
||||||
|
+ session->fullpacket_required_type = 0;
|
||||||
|
if(ret == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return ret;
|
||||||
|
else if(ret < 0) {
|
||||||
|
diff --git a/src/packet.h b/src/packet.h
|
||||||
|
index d66b15b..8ff231c 100644
|
||||||
|
--- a/src/packet.h
|
||||||
|
+++ b/src/packet.h
|
||||||
|
@@ -71,6 +71,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session,
|
||||||
|
int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
unsigned long data_len);
|
||||||
|
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
|
- size_t datalen, int macstate);
|
||||||
|
+ size_t datalen, int macstate, uint32_t seq);
|
||||||
|
|
||||||
|
#endif /* LIBSSH2_PACKET_H */
|
||||||
|
diff --git a/src/session.c b/src/session.c
|
||||||
|
index e439acd..75120cf 100644
|
||||||
|
--- a/src/session.c
|
||||||
|
+++ b/src/session.c
|
||||||
|
@@ -500,6 +500,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
|
||||||
|
session->abstract = abstract;
|
||||||
|
session->api_timeout = 0; /* timeout-free API by default */
|
||||||
|
session->api_block_mode = 1; /* blocking API by default */
|
||||||
|
+ session->state = LIBSSH2_STATE_INITIAL_KEX;
|
||||||
|
+ session->fullpacket_required_type = 0;
|
||||||
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
|
||||||
|
"New session resource allocated");
|
||||||
|
_libssh2_init_if_needed();
|
||||||
|
@@ -1171,6 +1173,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
|
||||||
|
const char *desc, const char *lang)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
+ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
|
||||||
|
session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
|
||||||
|
BLOCK_ADJUST(rc, session,
|
||||||
|
session_disconnect(session, reason, desc, lang));
|
||||||
|
diff --git a/src/transport.c b/src/transport.c
|
||||||
|
index 35e7df3..1fc8829 100644
|
||||||
|
--- a/src/transport.c
|
||||||
|
+++ b/src/transport.c
|
||||||
|
@@ -168,6 +168,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
||||||
|
struct transportpacket *p = &session->packet;
|
||||||
|
int rc;
|
||||||
|
int compressed;
|
||||||
|
+ uint32_t seq = session->remote.seqno;
|
||||||
|
|
||||||
|
if(session->fullpacket_state == libssh2_NB_state_idle) {
|
||||||
|
session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
|
||||||
|
@@ -240,7 +241,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
||||||
|
if(session->fullpacket_state == libssh2_NB_state_created) {
|
||||||
|
rc = _libssh2_packet_add(session, p->payload,
|
||||||
|
session->fullpacket_payload_len,
|
||||||
|
- session->fullpacket_macstate);
|
||||||
|
+ session->fullpacket_macstate, seq);
|
||||||
|
if(rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return rc;
|
||||||
|
if(rc) {
|
||||||
|
@@ -251,6 +252,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
|
||||||
|
|
||||||
|
session->fullpacket_state = libssh2_NB_state_idle;
|
||||||
|
|
||||||
|
+ if(session->kex_strict &&
|
||||||
|
+ session->fullpacket_packet_type == SSH_MSG_NEWKEYS) {
|
||||||
|
+ session->remote.seqno = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return session->fullpacket_packet_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -885,6 +891,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
||||||
|
|
||||||
|
session->local.seqno++;
|
||||||
|
|
||||||
|
+ if(session->kex_strict && data[0] == SSH_MSG_NEWKEYS) {
|
||||||
|
+ session->local.seqno = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = LIBSSH2_SEND(session, p->outbuf, total_length,
|
||||||
|
LIBSSH2_SOCKET_SEND_FLAGS(session));
|
||||||
|
if(ret < 0)
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -1,118 +1,119 @@
|
|||||||
From 43f24eb152b8ec62473d2de6108d7c0b267b2419 Mon Sep 17 00:00:00 2001
|
From 43f24eb152b8ec62473d2de6108d7c0b267b2419 Mon Sep 17 00:00:00 2001
|
||||||
From: Will Cosgrove <will@panic.com>
|
From: Will Cosgrove <will@panic.com>
|
||||||
Date: Tue, 27 Aug 2019 10:58:52 -0700
|
Date: Tue, 27 Aug 2019 10:58:52 -0700
|
||||||
Subject: [PATCH] kex.c: improve bounds checking in kex_agree_methods() (#399)
|
Subject: [PATCH] kex.c: improve bounds checking in kex_agree_methods() (#399)
|
||||||
|
|
||||||
file: kex.c
|
file: kex.c
|
||||||
|
|
||||||
notes:
|
notes:
|
||||||
use _libssh2_get_string instead of kex_string_pair which does additional checks
|
use _libssh2_get_string instead of kex_string_pair which does additional checks
|
||||||
---
|
---
|
||||||
src/kex.c | 65 ++++++++++++++++++++-----------------------------------
|
src/kex.c | 65 ++++++++++++++++++++-----------------------------------
|
||||||
1 file changed, 24 insertions(+), 41 deletions(-)
|
1 file changed, 24 insertions(+), 41 deletions(-)
|
||||||
|
|
||||||
diff --git a/src/kex.c b/src/kex.c
|
diff --git a/src/kex.c b/src/kex.c
|
||||||
index df9a4fdd6..7b111feaa 100644
|
index df9a4fdd6..7b111feaa 100644
|
||||||
--- a/src/kex.c
|
--- a/src/kex.c
|
||||||
+++ b/src/kex.c
|
+++ b/src/kex.c
|
||||||
@@ -3937,35 +3937,10 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
|
@@ -3937,35 +3937,10 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
-
|
-
|
||||||
/* TODO: When in server mode we need to turn this logic on its head
|
/* TODO: When in server mode we need to turn this logic on its head
|
||||||
* The Client gets to make the final call on "agreed methods"
|
* The Client gets to make the final call on "agreed methods"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
-/*
|
-/*
|
||||||
- * kex_string_pair() extracts a string from the packet and makes sure it fits
|
- * kex_string_pair() extracts a string from the packet and makes sure it fits
|
||||||
- * within the given packet.
|
- * within the given packet.
|
||||||
- */
|
- */
|
||||||
-static int kex_string_pair(unsigned char **sp, /* parsing position */
|
-static int kex_string_pair(unsigned char **sp, /* parsing position */
|
||||||
- unsigned char *data, /* start pointer to packet */
|
- unsigned char *data, /* start pointer to packet */
|
||||||
- size_t data_len, /* size of total packet */
|
- size_t data_len, /* size of total packet */
|
||||||
- size_t *lenp, /* length of the string */
|
- size_t *lenp, /* length of the string */
|
||||||
- unsigned char **strp) /* pointer to string start */
|
- unsigned char **strp) /* pointer to string start */
|
||||||
-{
|
-{
|
||||||
- unsigned char *s = *sp;
|
- unsigned char *s = *sp;
|
||||||
- *lenp = _libssh2_ntohu32(s);
|
- *lenp = _libssh2_ntohu32(s);
|
||||||
-
|
-
|
||||||
- /* the length of the string must fit within the current pointer and the
|
- /* the length of the string must fit within the current pointer and the
|
||||||
- end of the packet */
|
- end of the packet */
|
||||||
- if(*lenp > (data_len - (s - data) -4))
|
- if(*lenp > (data_len - (s - data) -4))
|
||||||
- return 1;
|
- return 1;
|
||||||
- *strp = s + 4;
|
- *strp = s + 4;
|
||||||
- s += 4 + *lenp;
|
- s += 4 + *lenp;
|
||||||
-
|
-
|
||||||
- *sp = s;
|
- *sp = s;
|
||||||
- return 0;
|
- return 0;
|
||||||
-}
|
-}
|
||||||
-
|
-
|
||||||
/* kex_agree_methods
|
/* kex_agree_methods
|
||||||
* Decide which specific method to use of the methods offered by each party
|
* Decide which specific method to use of the methods offered by each party
|
||||||
*/
|
*/
|
||||||
@@ -3976,40 +3951,48 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
|
@@ -3976,40 +3951,48 @@ static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
*mac_cs, *mac_sc;
|
*mac_cs, *mac_sc;
|
||||||
size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
|
size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
|
||||||
size_t comp_sc_len, mac_cs_len, mac_sc_len;
|
size_t comp_sc_len, mac_cs_len, mac_sc_len;
|
||||||
- unsigned char *s = data;
|
- unsigned char *s = data;
|
||||||
+ struct string_buf buf;
|
+ struct string_buf buf;
|
||||||
|
|
||||||
- /* Skip packet_type, we know it already */
|
- /* Skip packet_type, we know it already */
|
||||||
- s++;
|
- s++;
|
||||||
+ if(data_len < 17)
|
+ if(data_len < 17)
|
||||||
+ return -1;
|
+ return -1;
|
||||||
+
|
+
|
||||||
+ buf.data = (unsigned char *)data;
|
+ buf.data = (unsigned char *)data;
|
||||||
+ buf.len = data_len;
|
+ buf.len = data_len;
|
||||||
+ buf.dataptr = buf.data;
|
+ buf.dataptr = buf.data;
|
||||||
+ buf.dataptr++; /* advance past packet type */
|
+ buf.dataptr++; /* advance past packet type */
|
||||||
|
|
||||||
/* Skip cookie, don't worry, it's preserved in the kexinit field */
|
/* Skip cookie, don't worry, it's preserved in the kexinit field */
|
||||||
- s += 16;
|
- s += 16;
|
||||||
+ buf.dataptr += 16;
|
+ buf.dataptr += 16;
|
||||||
|
|
||||||
/* Locate each string */
|
/* Locate each string */
|
||||||
- if(kex_string_pair(&s, data, data_len, &kex_len, &kex))
|
- if(kex_string_pair(&s, data, data_len, &kex_len, &kex))
|
||||||
+ if(_libssh2_get_string(&buf, &kex, &kex_len))
|
+ if(_libssh2_get_string(&buf, &kex, &kex_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &hostkey_len, &hostkey))
|
- if(kex_string_pair(&s, data, data_len, &hostkey_len, &hostkey))
|
||||||
+ if(_libssh2_get_string(&buf, &hostkey, &hostkey_len))
|
+ if(_libssh2_get_string(&buf, &hostkey, &hostkey_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &crypt_cs_len, &crypt_cs))
|
- if(kex_string_pair(&s, data, data_len, &crypt_cs_len, &crypt_cs))
|
||||||
+ if(_libssh2_get_string(&buf, &crypt_cs, &crypt_cs_len))
|
+ if(_libssh2_get_string(&buf, &crypt_cs, &crypt_cs_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &crypt_sc_len, &crypt_sc))
|
- if(kex_string_pair(&s, data, data_len, &crypt_sc_len, &crypt_sc))
|
||||||
+ if(_libssh2_get_string(&buf, &crypt_sc, &crypt_sc_len))
|
+ if(_libssh2_get_string(&buf, &crypt_sc, &crypt_sc_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &mac_cs_len, &mac_cs))
|
- if(kex_string_pair(&s, data, data_len, &mac_cs_len, &mac_cs))
|
||||||
+ if(_libssh2_get_string(&buf, &mac_cs, &mac_cs_len))
|
+ if(_libssh2_get_string(&buf, &mac_cs, &mac_cs_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &mac_sc_len, &mac_sc))
|
- if(kex_string_pair(&s, data, data_len, &mac_sc_len, &mac_sc))
|
||||||
+ if(_libssh2_get_string(&buf, &mac_sc, &mac_sc_len))
|
+ if(_libssh2_get_string(&buf, &mac_sc, &mac_sc_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &comp_cs_len, &comp_cs))
|
- if(kex_string_pair(&s, data, data_len, &comp_cs_len, &comp_cs))
|
||||||
+ if(_libssh2_get_string(&buf, &comp_cs, &comp_cs_len))
|
+ if(_libssh2_get_string(&buf, &comp_cs, &comp_cs_len))
|
||||||
return -1;
|
return -1;
|
||||||
- if(kex_string_pair(&s, data, data_len, &comp_sc_len, &comp_sc))
|
- if(kex_string_pair(&s, data, data_len, &comp_sc_len, &comp_sc))
|
||||||
+ if(_libssh2_get_string(&buf, &comp_sc, &comp_sc_len))
|
+ if(_libssh2_get_string(&buf, &comp_sc, &comp_sc_len))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If the server sent an optimistic packet, assume that it guessed wrong.
|
/* If the server sent an optimistic packet, assume that it guessed wrong.
|
||||||
* If the guess is determined to be right (by kex_agree_kex_hostkey)
|
* If the guess is determined to be right (by kex_agree_kex_hostkey)
|
||||||
* This flag will be reset to zero so that it's not ignored */
|
* This flag will be reset to zero so that it's not ignored */
|
||||||
- session->burn_optimistic_kexinit = *(s++);
|
- session->burn_optimistic_kexinit = *(s++);
|
||||||
- /* Next uint32 in packet is all zeros (reserved) */
|
- /* Next uint32 in packet is all zeros (reserved) */
|
||||||
+ if(_libssh2_check_length(&buf, 1)) {
|
+ if(_libssh2_check_length(&buf, 1)) {
|
||||||
+ session->burn_optimistic_kexinit = *(buf.dataptr++);
|
+ session->burn_optimistic_kexinit = *(buf.dataptr++);
|
||||||
+ }
|
+ }
|
||||||
+ else {
|
+ else {
|
||||||
+ return -1;
|
+ return -1;
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
- if(data_len < (unsigned) (s - data))
|
- if(data_len < (unsigned) (s - data))
|
||||||
- return -1; /* short packet */
|
- return -1; /* short packet */
|
||||||
+ /* Next uint32 in packet is all zeros (reserved) */
|
+ /* Next uint32 in packet is all zeros (reserved) */
|
||||||
|
|
||||||
if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
|
if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
50
libssh2.spec
50
libssh2.spec
@ -1,19 +1,23 @@
|
|||||||
Name: libssh2
|
Name: libssh2
|
||||||
Version: 1.9.0
|
Version: 1.9.0
|
||||||
Release: 4
|
Release: 8
|
||||||
Summary: A library implementing the SSH2 protocol
|
Summary: A library implementing the SSH2 protocol
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: https://www.libssh2.org/
|
URL: https://www.libssh2.org/
|
||||||
Source0: https://libssh2.org/download/libssh2-%{version}.tar.gz
|
Source0: https://libssh2.org/download/libssh2-%{version}.tar.gz
|
||||||
|
|
||||||
Patch9000: 0001-libssh2-CVE-2019-17498.patch
|
Patch0: 0001-libssh2-CVE-2019-17498.patch
|
||||||
Patch9001: 0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch
|
Patch1: 0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch
|
||||||
Patch9002: fix-use-of-uninitialized-value-476-478.patch
|
Patch2: fix-use-of-uninitialized-value-476-478.patch
|
||||||
Patch9003: fix-heap-buffer-overflow-in-kex_agree_methods.patch
|
Patch3: fix-heap-buffer-overflow-in-kex_agree_methods.patch
|
||||||
|
Patch4: 0001-packet.c-improved-parsing-in-packet_x11_open-410.patch
|
||||||
|
Patch5: 0001-packet.c-improved-packet-parsing-in-packet_queue_lis.patch
|
||||||
|
Patch6: backport-CVE-2023-48795.patch
|
||||||
|
|
||||||
BuildRequires: coreutils findutils /usr/bin/man zlib-devel
|
BuildRequires: coreutils findutils /usr/bin/man zlib-devel
|
||||||
BuildRequires: gcc make sed openssl-devel > 1:1.0.1 openssh-server
|
BuildRequires: gcc make sed openssl-devel > 1:1.0.1 openssh-server
|
||||||
BuildRequires: glibc-langpack-en
|
BuildRequires: glibc-langpack-en
|
||||||
|
Requires: %{name}-help = %{version}-%{release}
|
||||||
|
|
||||||
%description
|
%description
|
||||||
libssh2 is a library implementing the SSH2 protocol as defined by
|
libssh2 is a library implementing the SSH2 protocol as defined by
|
||||||
@ -89,17 +93,41 @@ LC_ALL=en_US.UTF-8 make -C tests check
|
|||||||
%{_mandir}/man3/libssh2_*.3*
|
%{_mandir}/man3/libssh2_*.3*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Sat June 4 2020 songzifeng<songzifeng1@huawei.com> - 1.9.0-4
|
* Mon Apr 08 2024 renmingshuai<renmingshuai@huawei.com> - 1.9.0-8
|
||||||
- Type:bugfix
|
- Type:CVE
|
||||||
- Id:NA
|
- CVE:CVE-2023-48795
|
||||||
- SUG:NA
|
- SUG:NA
|
||||||
- DESC: fix heap buffer overflow in kex.c
|
- DESC:fix CVE-2023-48795
|
||||||
|
|
||||||
|
* Thu Sep 08 2022 licihua<licihua@huawei.com> - 1.9.0-7
|
||||||
|
- Type:bugfix
|
||||||
|
- CVE:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:define libssh-help version
|
||||||
|
|
||||||
|
* Mon Nov 09 2020 xihaochen<xihaochen@huawei.com> - 1.9.0-6
|
||||||
|
- Type:requirement
|
||||||
|
- CVE:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:add libssh2-help dependency for libssh2
|
||||||
|
|
||||||
|
* Thu Sep 24 2020 yuboyun<yuboyun@huawei.com> - 1.9.0-5
|
||||||
|
- Type:bugfix
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix heap-buffer-overflow in _libssh2_ntohu32 and wild-addr-read in _libssh2_ntohu32
|
||||||
|
|
||||||
|
* Thu Jun 4 2020 songzifeng<songzifeng1@huawei.com> - 1.9.0-4
|
||||||
|
- Type:bugfix
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix heap buffer overflow in kex.c
|
||||||
|
|
||||||
* Sat May 30 2020 songzifeng<songzifeng1@huawei.com> - 1.9.0-3
|
* Sat May 30 2020 songzifeng<songzifeng1@huawei.com> - 1.9.0-3
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- Id:NA
|
- ID:NA
|
||||||
- SUG:NA
|
- SUG:NA
|
||||||
- DESC: fix use of uninitialized value in transport.c
|
- DESC:fix use of uninitialized value in transport.c
|
||||||
|
|
||||||
* Sat Dec 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 1.9.0-2
|
* Sat Dec 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 1.9.0-2
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user