diff --git a/0001-libssh2-CVE-2019-17498.patch b/0001-libssh2-CVE-2019-17498.patch deleted file mode 100644 index 4c9170842896aeaee9880209acfc70d863627ade..0000000000000000000000000000000000000000 --- a/0001-libssh2-CVE-2019-17498.patch +++ /dev/null @@ -1,116 +0,0 @@ -From ae6b894e43dabed9a93c1b5e47ab564de3f00d6c Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -Date: Sat, 21 Dec 2019 19:31:58 +0800 -Subject: [PATCH] packet.c: improve message parsing (#402) - ---- - src/packet.c | 66 +++++++++++++++++++++++++----------------------------------- - 1 file changed, 27 insertions(+), 39 deletions(-) - -diff --git a/src/packet.c b/src/packet.c -index 38ab629..52eed32 100644 ---- a/src/packet.c -+++ b/src/packet.c -@@ -419,8 +419,8 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - size_t datalen, int macstate) - { - int rc = 0; -- char *message = NULL; -- char *language = NULL; -+ unsigned char *message = NULL; -+ unsigned char *language = NULL; - size_t message_len = 0; - size_t language_len = 0; - LIBSSH2_CHANNEL *channelp = NULL; -@@ -472,32 +472,21 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - - case SSH_MSG_DISCONNECT: - if(datalen >= 5) { -- size_t reason = _libssh2_ntohu32(data + 1); -+ uint32_t reason = 0; -+ struct string_buf buf; -+ buf.data = (unsigned char *)data; -+ buf.dataptr = buf.data; -+ buf.len = datalen; -+ buf.dataptr++; /* advance past type */ - -- if(datalen >= 9) { -- message_len = _libssh2_ntohu32(data + 5); -+ _libssh2_get_u32(&buf, &reason); -+ _libssh2_get_string(&buf, &message, &message_len); -+ _libssh2_get_string(&buf, &language, &language_len); - -- if(message_len < datalen-13) { -- /* 9 = packet_type(1) + reason(4) + message_len(4) */ -- message = (char *) data + 9; -- -- language_len = -- _libssh2_ntohu32(data + 9 + message_len); -- language = (char *) data + 9 + message_len + 4; -- -- if(language_len > (datalen-13-message_len)) { -- /* bad input, clear info */ -- language = message = NULL; -- language_len = message_len = 0; -- } -- } -- else -- /* bad size, clear it */ -- message_len = 0; -- } - if(session->ssh_msg_disconnect) { -- LIBSSH2_DISCONNECT(session, reason, message, -- message_len, language, language_len); -+ LIBSSH2_DISCONNECT(session, reason, (const char *)message, -+ message_len, (const char *)language, -+ language_len); - } - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "Disconnect(%d): %s(%s)", reason, -@@ -539,22 +528,21 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - int always_display = data[1]; - - if(datalen >= 6) { -- message_len = _libssh2_ntohu32(data + 2); -- -- if(message_len <= (datalen - 10)) { -- /* 6 = packet_type(1) + display(1) + message_len(4) */ -- message = (char *) data + 6; -- language_len = _libssh2_ntohu32(data + 6 + -- message_len); -- -- if(language_len <= (datalen - 10 - message_len)) -- language = (char *) data + 10 + message_len; -- } -+ struct string_buf buf; -+ buf.data = (unsigned char *)data; -+ buf.dataptr = buf.data; -+ buf.len = datalen; -+ buf.dataptr += 2; /* advance past type & always display */ -+ -+ _libssh2_get_string(&buf, &message, &message_len); -+ _libssh2_get_string(&buf, &language, &language_len); - } - - if(session->ssh_msg_debug) { -- LIBSSH2_DEBUG(session, always_display, message, -- message_len, language, language_len); -+ LIBSSH2_DEBUG(session, always_display, -+ (const char *)message, -+ message_len, (const char *)language, -+ language_len); - } - } - /* -@@ -579,7 +567,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, - uint32_t len = 0; - unsigned char want_reply = 0; - len = _libssh2_ntohu32(data + 1); -- if(datalen >= (6 + len)) { -+ if((len <= (UINT_MAX - 6)) && (datalen >= (6 + len))) { - want_reply = data[5 + len]; - _libssh2_debug(session, - LIBSSH2_TRACE_CONN, --- -1.8.3.1 - diff --git a/0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch b/0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch deleted file mode 100644 index 50e5a343a155b912901316d1c4bed32ae3185b4f..0000000000000000000000000000000000000000 --- a/0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c2304e1ed951644bbe559348030bbb2844b348de Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -Date: Sat, 21 Dec 2019 19:35:22 +0800 -Subject: [PATCH] misc.c: _libssh2_ntohu32 cast bit shifting (#401) - ---- - src/misc.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/misc.c b/src/misc.c -index bd084c8..b307260 100644 ---- a/src/misc.c -+++ b/src/misc.c -@@ -196,7 +196,10 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length, - unsigned int - _libssh2_ntohu32(const unsigned char *buf) - { -- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -+ return (((unsigned int)buf[0] << 24) -+ | ((unsigned int)buf[1] << 16) -+ | ((unsigned int)buf[2] << 8) -+ | ((unsigned int)buf[3])); - } - - --- -1.8.3.1 - diff --git a/0001-packet.c-improved-packet-parsing-in-packet_queue_lis.patch b/0001-packet.c-improved-packet-parsing-in-packet_queue_lis.patch deleted file mode 100644 index 383a759daa116ace423e47baca311c2572e17c80..0000000000000000000000000000000000000000 --- a/0001-packet.c-improved-packet-parsing-in-packet_queue_lis.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 80d3ea5b413d269ec77aebbb0aabbe738ba31796 Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -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 - diff --git a/0001-packet.c-improved-parsing-in-packet_x11_open-410.patch b/0001-packet.c-improved-parsing-in-packet_x11_open-410.patch deleted file mode 100644 index 4c76ad3ffc72aecb2b532942bdd4a9e97e653ecf..0000000000000000000000000000000000000000 --- a/0001-packet.c-improved-parsing-in-packet_x11_open-410.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 336bd86d2ca4030b808d76e56a0387914982e289 Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -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 - diff --git a/backport-RSA-SHA2-256-512-key-upgrade-support-RFC-8332.patch b/backport-RSA-SHA2-256-512-key-upgrade-support-RFC-8332.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccb5d3f9ac85b1479427fa1d8c59ce67c600298f --- /dev/null +++ b/backport-RSA-SHA2-256-512-key-upgrade-support-RFC-8332.patch @@ -0,0 +1,1025 @@ +From 64a555d6f5aafed504a10e5b756e85c91b1d56ce Mon Sep 17 00:00:00 2001 +From: Will Cosgrove +Date: Thu, 6 Jan 2022 09:50:58 -0800 +Subject: [PATCH] RSA SHA2 256/512 key upgrade support RFC 8332 #536 (#626) + +Notes: +* Host Key RSA 256/512 support #536 +* Client side key hash upgrading for RFC 8332 +* Support for server-sig-algs, ext-info-c server messages +* Customizing preferred server-sig-algs via the preference LIBSSH2_METHOD_SIGN_ALGO + +Credit: Anders Borum, Will Cosgrove +--- + docs/HACKING-CRYPTO | 37 ++++++++ + docs/libssh2_session_methods.3 | 7 +- + include/libssh2.h | 1 + + src/crypto.h | 32 +++++++ + src/hostkey.c | 198 ++++++++++++++++++++++++++++++++++++++++- + src/kex.c | 22 +++++ + src/libgcrypt.c | 18 ++++ + src/libgcrypt.h | 1 + + src/libssh2_priv.h | 8 ++ + src/mbedtls.c | 19 ++++ + src/mbedtls.h | 1 + + src/openssl.c | 94 +++++++++++++++++-- + src/openssl.h | 2 + + src/packet.c | 69 ++++++++++++++ + src/userauth.c | 159 +++++++++++++++++++++++++++++++-- + src/wincng.c | 18 ++++ + src/wincng.h | 1 + + 19 files changed, 685 insertions(+), 21 deletions(-) + +diff --git a/docs/HACKING-CRYPTO b/docs/HACKING-CRYPTO +index ca94772..85d813a 100644 +--- a/docs/HACKING-CRYPTO ++++ b/docs/HACKING-CRYPTO +@@ -637,6 +637,32 @@ Note: this procedure is not used if macro _libssh2_rsa_sha1_signv() is defined. + void _libssh2_rsa_free(libssh2_rsa_ctx *rsactx); + Releases the RSA computation context at rsactx. + ++LIBSSH2_RSA_SHA2 ++#define as 1 if the crypto library supports RSA SHA2 256/512, else 0. ++If defined as 0, the rest of this section can be omitted. ++ ++int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, ++ libssh2_rsa_ctx * rsactx, ++ const unsigned char *hash, ++ size_t hash_len, ++ unsigned char **signature, ++ size_t *signature_len); ++RSA signs the (hash, hashlen) SHA-2 hash bytes based on hash length and stores ++the allocated signature at (signature, signature_len). ++Signature buffer must be allocated from the given session. ++Returns 0 if OK, else -1. ++This procedure is already prototyped in crypto.h. ++Note: this procedure is not used if macro _libssh2_rsa_sha1_signv() is defined. ++ ++int _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsa, ++ size_t hash_len, ++ const unsigned char *sig, ++ unsigned long sig_len, ++ const unsigned char *m, unsigned long m_len); ++Verify (sig, sig_len) signature of (m, m_len) using an SHA-2 hash based on ++hash length and the RSA context. ++Return 0 if OK, else -1. ++This procedure is already prototyped in crypto.h. + + 7.2) DSA + LIBSSH2_DSA +@@ -900,3 +926,14 @@ If this is not needed, it should be defined as an empty macro. + int _libssh2_random(unsigned char *buf, int len); + Store len random bytes at buf. + Returns 0 if OK, else -1. ++ ++const char * _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len); ++ ++This function is for implementing key hash upgrading as defined in RFC 8332. ++ ++Based on the incoming key_method value, this function will return a ++list of supported algorithms that can upgrade the original key method algorithm ++as a comma seperated list, if there is no upgrade option this function should ++return NULL. +diff --git a/docs/libssh2_session_methods.3 b/docs/libssh2_session_methods.3 +index cc4f6d4..0e7f79f 100644 +--- a/docs/libssh2_session_methods.3 ++++ b/docs/libssh2_session_methods.3 +@@ -1,4 +1,4 @@ +-.TH libssh2_session_methods 3 "1 Jun 2007" "libssh2 0.15" "libssh2 manual" ++.TH libssh2_session_methods 3 "8 Nov 2021" "libssh2 1.11" "libssh2 manual" + .SH NAME + libssh2_session_methods - return the currently active algorithms + .SH SYNOPSIS +@@ -8,13 +8,14 @@ const char * + libssh2_session_methods(LIBSSH2_SESSION *session, int method_type); + + .SH DESCRIPTION +-\fIsession\fP - Session instance as returned by ++\fIsession\fP - Session instance as returned by + .BR libssh2_session_init_ex(3) + + \fImethod_type\fP - one of the method type constants: LIBSSH2_METHOD_KEX, + LIBSSH2_METHOD_HOSTKEY, LIBSSH2_METHOD_CRYPT_CS, LIBSSH2_METHOD_CRYPT_SC, + LIBSSH2_METHOD_MAC_CS, LIBSSH2_METHOD_MAC_SC, LIBSSH2_METHOD_COMP_CS, +-LIBSSH2_METHOD_COMP_SC, LIBSSH2_METHOD_LANG_CS, LIBSSH2_METHOD_LANG_SC. ++LIBSSH2_METHOD_COMP_SC, LIBSSH2_METHOD_LANG_CS, LIBSSH2_METHOD_LANG_SC, ++LIBSSH2_METHOD_SIGN_ALGO. + + Returns the actual method negotiated for a particular transport parameter. + .SH RETURN VALUE +diff --git a/include/libssh2.h b/include/libssh2.h +index d064b31..b9ae809 100644 +--- a/include/libssh2.h ++++ b/include/libssh2.h +@@ -356,6 +356,7 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE + #define LIBSSH2_METHOD_COMP_SC 7 + #define LIBSSH2_METHOD_LANG_CS 8 + #define LIBSSH2_METHOD_LANG_SC 9 ++#define LIBSSH2_METHOD_SIGN_ALGO 10 + + /* flags */ + #define LIBSSH2_FLAG_SIGPIPE 1 +diff --git a/src/crypto.h b/src/crypto.h +index f512d60..809aef7 100644 +--- a/src/crypto.h ++++ b/src/crypto.h +@@ -93,6 +93,19 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, + size_t hash_len, + unsigned char **signature, + size_t *signature_len); ++#if LIBSSH2_RSA_SHA2 ++int _libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, ++ libssh2_rsa_ctx * rsactx, ++ const unsigned char *hash, ++ size_t hash_len, ++ unsigned char **signature, ++ size_t *signature_len); ++int _libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsa, ++ size_t hash_len, ++ const unsigned char *sig, ++ unsigned long sig_len, ++ const unsigned char *m, unsigned long m_len); ++#endif + int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa, + LIBSSH2_SESSION * session, + const char *filedata, +@@ -245,4 +258,23 @@ int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session, + size_t privatekeydata_len, + const char *passphrase); + ++ ++/** ++ * @function _libssh2_supported_key_sign_algorithms ++ * @abstract Returns supported algorithms used for upgrading public ++ * key signing RFC 8332 ++ * @discussion Based on the incoming key_method value, this function ++ * will return supported algorithms that can upgrade the key method ++ * @related _libssh2_key_sign_algorithm() ++ * @param key_method current key method, usually the default key sig method ++ * @param key_method_len length of the key method buffer ++ * @result comma seperated list of supported upgrade options per RFC 8332, if ++ * there is no upgrade option return NULL ++ */ ++ ++const char * ++_libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len); ++ + #endif /* __LIBSSH2_CRYPTO_H */ +diff --git a/src/hostkey.c b/src/hostkey.c +index c0e2c63..f005d90 100644 +--- a/src/hostkey.c ++++ b/src/hostkey.c +@@ -64,8 +64,8 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, + void **abstract) + { + libssh2_rsa_ctx *rsactx; +- unsigned char *e, *n; +- size_t e_len, n_len; ++ unsigned char *e, *n, *type; ++ size_t e_len, n_len, type_len; + struct string_buf buf; + + if(*abstract) { +@@ -83,8 +83,27 @@ hostkey_method_ssh_rsa_init(LIBSSH2_SESSION * session, + buf.dataptr = buf.data; + buf.len = hostkey_data_len; + +- if(_libssh2_match_string(&buf, "ssh-rsa")) ++ if(_libssh2_get_string(&buf, &type, &type_len)) { + return -1; ++ } ++ ++ /* we accept one of 3 header types */ ++ if(type_len == 7 && strncmp("ssh-rsa", (char *)type, 7) == 0) { ++ /* ssh-rsa */ ++ } ++#if LIBSSH2_RSA_SHA2 ++ else if(type_len == 12 && strncmp("rsa-sha2-256", (char *)type, 12) == 0) { ++ /* rsa-sha2-256 */ ++ } ++ else if(type_len == 12 && strncmp("rsa-sha2-512", (char *)type, 12) == 0) { ++ /* rsa-sha2-512 */ ++ } ++#endif ++ else { ++ _libssh2_debug(session, LIBSSH2_TRACE_ERROR, ++ "unexpected rsa type: %.*s", type_len, type); ++ return -1; ++ } + + if(_libssh2_get_string(&buf, &e, &e_len)) + return -1; +@@ -228,6 +247,146 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session, + } + + /* ++ * hostkey_method_ssh_rsa_sha2_256_sig_verify ++ * ++ * Verify signature created by remote ++ */ ++#if LIBSSH2_RSA_SHA2 ++ ++static int ++hostkey_method_ssh_rsa_sha2_256_sig_verify(LIBSSH2_SESSION * session, ++ const unsigned char *sig, ++ size_t sig_len, ++ const unsigned char *m, ++ size_t m_len, void **abstract) ++{ ++ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); ++ (void) session; ++ ++ /* Skip past keyname_len(4) + keyname(12){"rsa-sha2-256"} + ++ signature_len(4) */ ++ if(sig_len < 20) ++ return -1; ++ ++ sig += 20; ++ sig_len -= 20; ++ return _libssh2_rsa_sha2_verify(rsactx, SHA256_DIGEST_LENGTH, sig, sig_len, ++ m, m_len); ++} ++ ++/* ++ * hostkey_method_ssh_rsa_sha2_256_signv ++ * ++ * Construct a signature from an array of vectors ++ */ ++ ++static int ++hostkey_method_ssh_rsa_sha2_256_signv(LIBSSH2_SESSION * session, ++ unsigned char **signature, ++ size_t *signature_len, ++ int veccount, ++ const struct iovec datavec[], ++ void **abstract) ++{ ++ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); ++ ++#ifdef _libssh2_rsa_sha2_256_signv ++ return _libssh2_rsa_sha2_256_signv(session, signature, signature_len, ++ veccount, datavec, rsactx); ++#else ++ int ret; ++ int i; ++ unsigned char hash[SHA256_DIGEST_LENGTH]; ++ libssh2_sha256_ctx ctx; ++ ++ libssh2_sha256_init(&ctx); ++ for(i = 0; i < veccount; i++) { ++ libssh2_sha256_update(ctx, datavec[i].iov_base, datavec[i].iov_len); ++ } ++ libssh2_sha256_final(ctx, hash); ++ ++ ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA256_DIGEST_LENGTH, ++ signature, signature_len); ++ if(ret) { ++ return -1; ++ } ++ ++ return 0; ++#endif ++} ++ ++/* ++ * hostkey_method_ssh_rsa_sha2_512_sig_verify ++ * ++ * Verify signature created by remote ++ */ ++ ++static int ++hostkey_method_ssh_rsa_sha2_512_sig_verify(LIBSSH2_SESSION * session, ++ const unsigned char *sig, ++ size_t sig_len, ++ const unsigned char *m, ++ size_t m_len, void **abstract) ++{ ++ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); ++ (void) session; ++ ++ /* Skip past keyname_len(4) + keyname(12){"rsa-sha2-512"} + ++ signature_len(4) */ ++ if(sig_len < 20) ++ return -1; ++ ++ sig += 20; ++ sig_len -= 20; ++ return _libssh2_rsa_sha2_verify(rsactx, SHA512_DIGEST_LENGTH, sig, ++ sig_len, m, m_len); ++} ++ ++ ++/* ++ * hostkey_method_ssh_rsa_sha2_512_signv ++ * ++ * Construct a signature from an array of vectors ++ */ ++static int ++hostkey_method_ssh_rsa_sha2_512_signv(LIBSSH2_SESSION * session, ++ unsigned char **signature, ++ size_t *signature_len, ++ int veccount, ++ const struct iovec datavec[], ++ void **abstract) ++{ ++ libssh2_rsa_ctx *rsactx = (libssh2_rsa_ctx *) (*abstract); ++ ++#ifdef _libssh2_rsa_sha2_512_signv ++ return _libssh2_rsa_sha2_512_signv(session, signature, signature_len, ++ veccount, datavec, rsactx); ++#else ++ int ret; ++ int i; ++ unsigned char hash[SHA512_DIGEST_LENGTH]; ++ libssh2_sha512_ctx ctx; ++ ++ libssh2_sha512_init(&ctx); ++ for(i = 0; i < veccount; i++) { ++ libssh2_sha512_update(ctx, datavec[i].iov_base, datavec[i].iov_len); ++ } ++ libssh2_sha512_final(ctx, hash); ++ ++ ret = _libssh2_rsa_sha2_sign(session, rsactx, hash, SHA512_DIGEST_LENGTH, ++ signature, signature_len); ++ if(ret) { ++ return -1; ++ } ++ ++ return 0; ++#endif ++} ++ ++#endif /* LIBSSH2_RSA_SHA2 */ ++ ++ ++/* + * hostkey_method_ssh_rsa_dtor + * + * Shutdown the hostkey +@@ -260,6 +419,35 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa = { + NULL, /* encrypt */ + hostkey_method_ssh_rsa_dtor, + }; ++ ++#if LIBSSH2_RSA_SHA2 ++ ++static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_256 = { ++ "rsa-sha2-256", ++ SHA256_DIGEST_LENGTH, ++ hostkey_method_ssh_rsa_init, ++ hostkey_method_ssh_rsa_initPEM, ++ hostkey_method_ssh_rsa_initPEMFromMemory, ++ hostkey_method_ssh_rsa_sha2_256_sig_verify, ++ hostkey_method_ssh_rsa_sha2_256_signv, ++ NULL, /* encrypt */ ++ hostkey_method_ssh_rsa_dtor, ++}; ++ ++static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ssh_rsa_sha2_512 = { ++ "rsa-sha2-512", ++ SHA512_DIGEST_LENGTH, ++ hostkey_method_ssh_rsa_init, ++ hostkey_method_ssh_rsa_initPEM, ++ hostkey_method_ssh_rsa_initPEMFromMemory, ++ hostkey_method_ssh_rsa_sha2_512_sig_verify, ++ hostkey_method_ssh_rsa_sha2_512_signv, ++ NULL, /* encrypt */ ++ hostkey_method_ssh_rsa_dtor, ++}; ++ ++#endif /* LIBSSH2_RSA_SHA2 */ ++ + #endif /* LIBSSH2_RSA */ + + #if LIBSSH2_DSA +@@ -1041,6 +1229,10 @@ static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = { + &hostkey_method_ssh_ed25519, + #endif + #if LIBSSH2_RSA ++#if LIBSSH2_RSA_SHA2 ++ &hostkey_method_ssh_rsa_sha2_512, ++ &hostkey_method_ssh_rsa_sha2_256, ++#endif /* LIBSSH2_RSA_SHA2 */ + &hostkey_method_ssh_rsa, + #endif /* LIBSSH2_RSA */ + #if LIBSSH2_DSA +diff --git a/src/kex.c b/src/kex.c +index c300ecb..8f02808 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -3026,6 +3026,17 @@ kex_method_ssh_curve25519_sha256 = { + }; + #endif + ++/* this kex method signals that client can receive extensions ++ * as described in https://datatracker.ietf.org/doc/html/rfc8308 ++*/ ++ ++static const LIBSSH2_KEX_METHOD ++kex_method_extension_negotiation = { ++ "ext-info-c", ++ NULL, ++ 0, ++}; ++ + static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { + #if LIBSSH2_ED25519 + &kex_method_ssh_curve25519_sha256, +@@ -3043,6 +3054,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = { + &kex_method_diffie_helman_group14_sha1, + &kex_method_diffie_helman_group1_sha1, + &kex_method_diffie_helman_group_exchange_sha1, ++ &kex_method_extension_negotiation, + NULL + }; + +@@ -3978,6 +3990,11 @@ libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type, + mlist = NULL; + break; + ++ case LIBSSH2_METHOD_SIGN_ALGO: ++ prefvar = &session->sign_algo_prefs; ++ mlist = NULL; ++ break; ++ + default: + return _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "Invalid parameter specified for method_type"); +@@ -4073,6 +4090,11 @@ LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session, + _libssh2_comp_methods(session); + break; + ++ case LIBSSH2_METHOD_SIGN_ALGO: ++ /* no built-in supported list due to backend support */ ++ mlist = NULL; ++ break; ++ + default: + return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED, + "Unknown method type"); +diff --git a/src/libgcrypt.c b/src/libgcrypt.c +index 0aff176..f6e9b64 100644 +--- a/src/libgcrypt.c ++++ b/src/libgcrypt.c +@@ -664,4 +664,22 @@ _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) + *dhctx = NULL; + } + ++/* _libssh2_supported_key_sign_algorithms ++ * ++ * Return supported key hash algo upgrades, see crypto.h ++ * ++ */ ++ ++const char * ++_libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len) ++{ ++ (void)session; ++ (void)key_method; ++ (void)key_method_len; ++ ++ return NULL; ++} ++ + #endif /* LIBSSH2_LIBGCRYPT */ +diff --git a/src/libgcrypt.h b/src/libgcrypt.h +index 298c65e..95876b9 100644 +--- a/src/libgcrypt.h ++++ b/src/libgcrypt.h +@@ -55,6 +55,7 @@ + #define LIBSSH2_3DES 1 + + #define LIBSSH2_RSA 1 ++#define LIBSSH2_RSA_SHA2 0 + #define LIBSSH2_DSA 1 + #define LIBSSH2_ECDSA 0 + #define LIBSSH2_ED25519 0 +diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h +index da488b7..aff791e 100644 +--- a/src/libssh2_priv.h ++++ b/src/libssh2_priv.h +@@ -640,6 +640,13 @@ struct _LIBSSH2_SESSION + unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH]; + int server_hostkey_sha256_valid; + ++ /* public key algorithms accepted as comma separated list */ ++ char *server_sign_algorithms; ++ size_t server_sign_algorithms_len; ++ ++ /* key signing algorithm preferences -- NULL yields server order */ ++ char *sign_algo_prefs; ++ + /* (remote as source of data -- packet_read ) */ + libssh2_endpoint_data remote; + +@@ -1006,6 +1013,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) + #define SSH_MSG_DEBUG 4 + #define SSH_MSG_SERVICE_REQUEST 5 + #define SSH_MSG_SERVICE_ACCEPT 6 ++#define SSH_MSG_EXT_INFO 7 + + #define SSH_MSG_KEXINIT 20 + #define SSH_MSG_NEWKEYS 21 +diff --git a/src/mbedtls.c b/src/mbedtls.c +index 4629ce4..dc76ef5 100644 +--- a/src/mbedtls.c ++++ b/src/mbedtls.c +@@ -1247,5 +1247,24 @@ _libssh2_mbedtls_ecdsa_free(libssh2_ecdsa_ctx *ctx) + mbedtls_free(ctx); + } + ++ ++/* _libssh2_supported_key_sign_algorithms ++ * ++ * Return supported key hash algo upgrades, see crypto.h ++ * ++ */ ++ ++const char * ++_libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len) ++{ ++ (void)session; ++ (void)key_method; ++ (void)key_method_len; ++ ++ return NULL; ++} ++ + #endif /* LIBSSH2_ECDSA */ + #endif /* LIBSSH2_MBEDTLS */ +diff --git a/src/mbedtls.h b/src/mbedtls.h +index 671932c..0450113 100644 +--- a/src/mbedtls.h ++++ b/src/mbedtls.h +@@ -71,6 +71,7 @@ + #define LIBSSH2_3DES 1 + + #define LIBSSH2_RSA 1 ++#define LIBSSH2_RSA_SHA2 0 + #define LIBSSH2_DSA 0 + #ifdef MBEDTLS_ECDSA_C + # define LIBSSH2_ECDSA 1 +diff --git a/src/openssl.c b/src/openssl.c +index 7a6810f..72a85b3 100644 +--- a/src/openssl.c ++++ b/src/openssl.c +@@ -154,21 +154,57 @@ _libssh2_rsa_new(libssh2_rsa_ctx ** rsa, + } + + int +-_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, ++_libssh2_rsa_sha2_verify(libssh2_rsa_ctx * rsactx, ++ size_t hash_len, + const unsigned char *sig, + unsigned long sig_len, + const unsigned char *m, unsigned long m_len) + { +- unsigned char hash[SHA_DIGEST_LENGTH]; + int ret; ++ int nid_type; ++ unsigned char *hash = malloc(hash_len); ++ if(hash == NULL) ++ return -1; ++ ++ if(hash_len == SHA_DIGEST_LENGTH) { ++ nid_type = NID_sha1; ++ ret = _libssh2_sha1(m, m_len, hash); ++ } ++ else if(hash_len == SHA256_DIGEST_LENGTH) { ++ nid_type = NID_sha256; ++ ret = _libssh2_sha256(m, m_len, hash); ++ ++ } ++ else if(hash_len == SHA512_DIGEST_LENGTH) { ++ nid_type = NID_sha512; ++ ret = _libssh2_sha512(m, m_len, hash); ++ } ++ else ++ ret = -1; /* unsupported digest */ + +- if(_libssh2_sha1(m, m_len, hash)) ++ if(ret != 0) { ++ free(hash); + return -1; /* failure */ +- ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, ++ } ++ ++ ret = RSA_verify(nid_type, hash, hash_len, + (unsigned char *) sig, sig_len, rsactx); ++ ++ free(hash); ++ + return (ret == 1) ? 0 : -1; + } + ++int ++_libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, ++ const unsigned char *sig, ++ unsigned long sig_len, ++ const unsigned char *m, unsigned long m_len) ++{ ++ return _libssh2_rsa_sha2_verify(rsactx, SHA_DIGEST_LENGTH, sig, sig_len, m, ++ m_len); ++} ++ + #if LIBSSH2_DSA + int + _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx, +@@ -1876,7 +1912,7 @@ _libssh2_ed25519_new_public(libssh2_ed25519_ctx ** ed_ctx, + + + int +-_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, ++_libssh2_rsa_sha2_sign(LIBSSH2_SESSION * session, + libssh2_rsa_ctx * rsactx, + const unsigned char *hash, + size_t hash_len, +@@ -1893,7 +1929,17 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, + return -1; + } + +- ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); ++ if(hash_len == SHA_DIGEST_LENGTH) ++ ret = RSA_sign(NID_sha1, hash, hash_len, sig, &sig_len, rsactx); ++ else if(hash_len == SHA256_DIGEST_LENGTH) ++ ret = RSA_sign(NID_sha256, hash, hash_len, sig, &sig_len, rsactx); ++ else if(hash_len == SHA512_DIGEST_LENGTH) ++ ret = RSA_sign(NID_sha512, hash, hash_len, sig, &sig_len, rsactx); ++ else { ++ _libssh2_error(session, LIBSSH2_ERROR_PROTO, ++ "Unsupported hash digest length"); ++ ret = -1; ++ } + + if(!ret) { + LIBSSH2_FREE(session, sig); +@@ -1906,6 +1952,19 @@ _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, + return 0; + } + ++ ++int ++_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, ++ libssh2_rsa_ctx * rsactx, ++ const unsigned char *hash, ++ size_t hash_len, ++ unsigned char **signature, size_t *signature_len) ++{ ++ return _libssh2_rsa_sha2_sign(session, rsactx, hash, hash_len, ++ signature, signature_len); ++} ++ ++ + #if LIBSSH2_DSA + int + _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, +@@ -3283,4 +3342,27 @@ _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx) + *dhctx = NULL; + } + ++/* _libssh2_supported_key_sign_algorithms ++ * ++ * Return supported key hash algo upgrades, see crypto.h ++ * ++ */ ++ ++const char * ++_libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len) ++{ ++ (void)session; ++ ++#if LIBSSH2_RSA_SHA2 ++ if(key_method_len == 7 && ++ memcmp(key_method, "ssh-rsa", key_method_len) == 0) { ++ return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; ++ } ++#endif ++ ++ return NULL; ++} ++ + #endif /* LIBSSH2_OPENSSL */ +diff --git a/src/openssl.h b/src/openssl.h +index 658b040..2a002b4 100644 +--- a/src/openssl.h ++++ b/src/openssl.h +@@ -64,8 +64,10 @@ + + #ifdef OPENSSL_NO_RSA + # define LIBSSH2_RSA 0 ++# define LIBSSH2_RSA_SHA2 0 + #else + # define LIBSSH2_RSA 1 ++# define LIBSSH2_RSA_SHA2 1 + #endif + + #ifdef OPENSSL_NO_DSA +diff --git a/src/packet.c b/src/packet.c +index 04937d6..686be5c 100644 +--- a/src/packet.c ++++ b/src/packet.c +@@ -616,6 +616,75 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, + return 0; + + /* ++ byte SSH_MSG_EXT_INFO ++ uint32 nr-extensions ++ [repeat "nr-extensions" times] ++ string extension-name [RFC8308] ++ string extension-value (binary) ++ */ ++ ++ case SSH_MSG_EXT_INFO: ++ if(datalen >= 5) { ++ uint32_t nr_extensions = 0; ++ struct string_buf buf; ++ buf.data = (unsigned char *)data; ++ buf.dataptr = buf.data; ++ buf.len = datalen; ++ buf.dataptr += 1; /* advance past type */ ++ ++ if(_libssh2_get_u32(&buf, &nr_extensions) != 0) { ++ rc = _libssh2_error(session, LIBSSH2_ERROR_PROTO, ++ "Invalid extension info received"); ++ } ++ ++ while(rc == 0 && nr_extensions > 0) { ++ ++ size_t name_len = 0; ++ size_t value_len = 0; ++ unsigned char *name = NULL; ++ unsigned char *value = NULL; ++ ++ nr_extensions -= 1; ++ ++ _libssh2_get_string(&buf, &name, &name_len); ++ _libssh2_get_string(&buf, &value, &value_len); ++ ++ if(name != NULL && value != NULL) { ++ _libssh2_debug(session, ++ LIBSSH2_TRACE_KEX, ++ "Server to Client extension %.*s: %.*s", ++ name_len, name, value_len, value); ++ } ++ ++ if(name_len == 15 && ++ memcmp(name, "server-sig-algs", 15) == 0) { ++ if(session->server_sign_algorithms) { ++ LIBSSH2_FREE(session, ++ session->server_sign_algorithms); ++ } ++ ++ session->server_sign_algorithms = ++ LIBSSH2_ALLOC(session, ++ value_len); ++ ++ if(session->server_sign_algorithms) { ++ session->server_sign_algorithms_len = value_len; ++ memcpy(session->server_sign_algorithms, ++ value, value_len); ++ } ++ else { ++ rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "memory for server sign algo"); ++ } ++ } ++ } ++ } ++ ++ LIBSSH2_FREE(session, data); ++ session->packAdd_state = libssh2_NB_state_idle; ++ return rc; ++ ++ /* + byte SSH_MSG_GLOBAL_REQUEST + string request name in US-ASCII only + boolean want reply +diff --git a/src/userauth.c b/src/userauth.c +index 4442eee..988dc17 100644 +--- a/src/userauth.c ++++ b/src/userauth.c +@@ -1086,6 +1086,148 @@ static int plain_method_len(const char *method, size_t method_len) + return method_len; + } + ++/** ++ * @function _libssh2_key_sign_algorithm ++ * @abstract Upgrades the algorithm used for public key signing RFC 8332 ++ * @discussion Based on the incoming key_method value, this function ++ * will upgrade the key method input based on user preferences, ++ * server support algos and crypto backend support ++ * @related _libssh2_supported_key_sign_algorithms() ++ * @param key_method current key method, usually the default key sig method ++ * @param key_method_len length of the key method buffer ++ * @result error code or zero on success ++ */ ++ ++static int ++_libssh2_key_sign_algorithm(LIBSSH2_SESSION *session, ++ unsigned char **key_method, ++ size_t *key_method_len) ++{ ++ const char *s = NULL; ++ const char *a = NULL; ++ const char *match = NULL; ++ const char *p = NULL; ++ const char *f = NULL; ++ char *i = NULL; ++ int p_len = 0; ++ int f_len = 0; ++ int rc = 0; ++ int match_len = 0; ++ char *filtered_algs = NULL; ++ ++ const char *supported_algs = ++ _libssh2_supported_key_sign_algorithms(session, ++ *key_method, ++ *key_method_len); ++ ++ if(supported_algs == NULL || session->server_sign_algorithms == NULL) { ++ /* no upgrading key algorithm supported, do nothing */ ++ return LIBSSH2_ERROR_NONE; ++ } ++ ++ filtered_algs = LIBSSH2_ALLOC(session, strlen(supported_algs) + 1); ++ if(!filtered_algs) { ++ rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "Unable to allocate filtered algs"); ++ return rc; ++ } ++ ++ s = session->server_sign_algorithms; ++ i = filtered_algs; ++ ++ /* this walks the server algo list and the supported algo list and creates ++ a filtered list that includes matches */ ++ ++ while(s && *s) { ++ p = strchr(s, ','); ++ p_len = p ? (p - s) : (int) strlen(s); ++ a = supported_algs; ++ ++ while(a && *a) { ++ f = strchr(a, ','); ++ f_len = f ? (f - a) : (int) strlen(a); ++ ++ if(f_len == p_len && memcmp(a, s, p_len)) { ++ ++ if(i != filtered_algs) { ++ memcpy(i, ",", 1); ++ i += 1; ++ } ++ ++ memcpy(i, s, p_len); ++ i += p_len; ++ } ++ ++ a = f ? (f + 1) : NULL; ++ } ++ ++ s = p ? (p + 1) : NULL; ++ } ++ ++ filtered_algs[i - filtered_algs] = '\0'; ++ ++ if(session->sign_algo_prefs) { ++ s = session->sign_algo_prefs; ++ } ++ else { ++ s = supported_algs; ++ } ++ ++ /* now that we have the possible supported algos, match based on the prefs ++ or what is supported by the crypto backend, look for a match */ ++ ++ while(s && *s && !match) { ++ p = strchr(s, ','); ++ p_len = p ? (p - s) : (int) strlen(s); ++ a = filtered_algs; ++ ++ while(a && *a && !match) { ++ f = strchr(a, ','); ++ f_len = f ? (f - a) : (int) strlen(a); ++ ++ if(f_len == p_len && memcmp(a, s, p_len)) { ++ /* found a match, upgrade key method */ ++ match = s; ++ match_len = p_len; ++ } ++ else { ++ a = f ? (f + 1) : NULL; ++ } ++ } ++ ++ s = p ? (p + 1) : NULL; ++ } ++ ++ if(match != NULL) { ++ if(*key_method) ++ LIBSSH2_FREE(session, *key_method); ++ ++ *key_method = LIBSSH2_ALLOC(session, match_len); ++ if(key_method) { ++ memcpy(*key_method, match, match_len); ++ *key_method_len = match_len; ++ ++ _libssh2_debug(session, LIBSSH2_TRACE_KEX, ++ "Signing using %.*s", match_len, match); ++ } ++ else { ++ *key_method_len = 0; ++ rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, ++ "Unable to allocate key method upgrade"); ++ } ++ } ++ else { ++ /* no match was found */ ++ rc = _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE, ++ "No signing signature matched"); ++ } ++ ++ if(filtered_algs) ++ LIBSSH2_FREE(session, filtered_algs); ++ ++ return rc; ++} ++ + int + _libssh2_userauth_publickey(LIBSSH2_SESSION *session, + const char *username, +@@ -1144,15 +1286,14 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, + memcpy(session->userauth_pblc_method, pubkeydata + 4, + session->userauth_pblc_method_len); + } +- /* +- * The length of the method name read from plaintext prefix in the +- * file must match length embedded in the key. +- * TODO: The data should match too but we don't check that. Should we? +- */ +- else if(session->userauth_pblc_method_len != +- _libssh2_ntohu32(pubkeydata)) +- return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, +- "Invalid public key"); ++ ++ /* upgrade key key signing algo needed */ ++ rc = _libssh2_key_sign_algorithm(session, ++ &session->userauth_pblc_method, ++ &session->userauth_pblc_method_len); ++ ++ if(rc) ++ return rc; + + /* + * 45 = packet_type(1) + username_len(4) + servicename_len(4) + +diff --git a/src/wincng.c b/src/wincng.c +index 9ae8dde..58e2251 100644 +--- a/src/wincng.c ++++ b/src/wincng.c +@@ -2591,4 +2591,22 @@ fb: + return _libssh2_wincng_bignum_mod_exp(secret, f, dhctx->bn, p); + } + ++/* _libssh2_supported_key_sign_algorithms ++ * ++ * Return supported key hash algo upgrades, see crypto.h ++ * ++ */ ++ ++const char * ++_libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, ++ unsigned char *key_method, ++ size_t key_method_len) ++{ ++ (void)session; ++ (void)key_method; ++ (void)key_method_len; ++ ++ return NULL; ++} ++ + #endif /* LIBSSH2_WINCNG */ +diff --git a/src/wincng.h b/src/wincng.h +index eaf6f90..538cc43 100644 +--- a/src/wincng.h ++++ b/src/wincng.h +@@ -63,6 +63,7 @@ + #define LIBSSH2_3DES 1 + + #define LIBSSH2_RSA 1 ++#define LIBSSH2_RSA_SHA2 0 + #define LIBSSH2_DSA 1 + #define LIBSSH2_ECDSA 0 + #define LIBSSH2_ED25519 0 +-- +1.8.3.1 + diff --git a/fix-heap-buffer-overflow-in-kex_agree_methods.patch b/fix-heap-buffer-overflow-in-kex_agree_methods.patch deleted file mode 100644 index 47b2674c52dc203f76360bb158e36ffe97c3c4b0..0000000000000000000000000000000000000000 --- a/fix-heap-buffer-overflow-in-kex_agree_methods.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 43f24eb152b8ec62473d2de6108d7c0b267b2419 Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -Date: Tue, 27 Aug 2019 10:58:52 -0700 -Subject: [PATCH] kex.c: improve bounds checking in kex_agree_methods() (#399) - -file: kex.c - -notes: -use _libssh2_get_string instead of kex_string_pair which does additional checks ---- - src/kex.c | 65 ++++++++++++++++++++----------------------------------- - 1 file changed, 24 insertions(+), 41 deletions(-) - -diff --git a/src/kex.c b/src/kex.c -index df9a4fdd6..7b111feaa 100644 ---- a/src/kex.c -+++ b/src/kex.c -@@ -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 - * 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 -- * within the given packet. -- */ --static int kex_string_pair(unsigned char **sp, /* parsing position */ -- unsigned char *data, /* start pointer to packet */ -- size_t data_len, /* size of total packet */ -- size_t *lenp, /* length of the string */ -- unsigned char **strp) /* pointer to string start */ --{ -- unsigned char *s = *sp; -- *lenp = _libssh2_ntohu32(s); -- -- /* the length of the string must fit within the current pointer and the -- end of the packet */ -- if(*lenp > (data_len - (s - data) -4)) -- return 1; -- *strp = s + 4; -- s += 4 + *lenp; -- -- *sp = s; -- return 0; --} -- - /* kex_agree_methods - * 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, - *mac_cs, *mac_sc; - 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; -- unsigned char *s = data; -+ struct string_buf buf; - -- /* Skip packet_type, we know it already */ -- s++; -+ if(data_len < 17) -+ return -1; -+ -+ buf.data = (unsigned char *)data; -+ buf.len = data_len; -+ buf.dataptr = buf.data; -+ buf.dataptr++; /* advance past packet type */ - - /* Skip cookie, don't worry, it's preserved in the kexinit field */ -- s += 16; -+ buf.dataptr += 16; - - /* Locate each string */ -- if(kex_string_pair(&s, data, data_len, &kex_len, &kex)) -+ if(_libssh2_get_string(&buf, &kex, &kex_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &hostkey_len, &hostkey)) -+ if(_libssh2_get_string(&buf, &hostkey, &hostkey_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &crypt_cs_len, &crypt_cs)) -+ if(_libssh2_get_string(&buf, &crypt_cs, &crypt_cs_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &crypt_sc_len, &crypt_sc)) -+ if(_libssh2_get_string(&buf, &crypt_sc, &crypt_sc_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &mac_cs_len, &mac_cs)) -+ if(_libssh2_get_string(&buf, &mac_cs, &mac_cs_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &mac_sc_len, &mac_sc)) -+ if(_libssh2_get_string(&buf, &mac_sc, &mac_sc_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &comp_cs_len, &comp_cs)) -+ if(_libssh2_get_string(&buf, &comp_cs, &comp_cs_len)) - return -1; -- if(kex_string_pair(&s, data, data_len, &comp_sc_len, &comp_sc)) -+ if(_libssh2_get_string(&buf, &comp_sc, &comp_sc_len)) - return -1; - - /* 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) - * This flag will be reset to zero so that it's not ignored */ -- session->burn_optimistic_kexinit = *(s++); -- /* Next uint32 in packet is all zeros (reserved) */ -+ if(_libssh2_check_length(&buf, 1)) { -+ session->burn_optimistic_kexinit = *(buf.dataptr++); -+ } -+ else { -+ return -1; -+ } - -- if(data_len < (unsigned) (s - data)) -- return -1; /* short packet */ -+ /* Next uint32 in packet is all zeros (reserved) */ - - if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) { - return -1; - diff --git a/fix-use-of-uninitialized-value-476-478.patch b/fix-use-of-uninitialized-value-476-478.patch deleted file mode 100644 index 040094dbc8fb98e563022c7a542ff142784a3d30..0000000000000000000000000000000000000000 --- a/fix-use-of-uninitialized-value-476-478.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0b44e558f311671f6e6d14c559bc1c9bda59b8df Mon Sep 17 00:00:00 2001 -From: Will Cosgrove -Date: Thu, 28 May 2020 14:20:08 -0700 -Subject: [PATCH 2/2] transport.c: moving total_num check from #476 (#478) - -file: transport.c - -notes: -moving total_num zero length check from #476 up to the prior bounds check which already includes a total_num check. Makes it slightly more readable. - -credit: -Will Cosgrove ---- - src/transport.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/transport.c b/src/transport.c -index adf96c2..11e5614 100644 ---- a/src/transport.c -+++ b/src/transport.c -@@ -465,7 +465,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) - * or less (including length, padding length, payload, - * padding, and MAC.)." - */ -- if(total_num > LIBSSH2_PACKET_MAXPAYLOAD) { -+ if(total_num > LIBSSH2_PACKET_MAXPAYLOAD || total_num == 0) { - return LIBSSH2_ERROR_OUT_OF_BOUNDARY; - } - --- -1.8.3.1 - diff --git a/libssh2-1.10.0.tar.gz b/libssh2-1.10.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..675581d990ecaf32f5c078542b66efe956255393 Binary files /dev/null and b/libssh2-1.10.0.tar.gz differ diff --git a/libssh2-1.9.0.tar.gz b/libssh2-1.9.0.tar.gz deleted file mode 100644 index 55c3ddff2a2d1afd4771e5b0505feb278a773f3d..0000000000000000000000000000000000000000 Binary files a/libssh2-1.9.0.tar.gz and /dev/null differ diff --git a/libssh2.spec b/libssh2.spec index 6bb48379117afef0a44a406f6ee59de9d9c68824..6ed9405a3452076a7a636f031bb82d812b93bc10 100644 --- a/libssh2.spec +++ b/libssh2.spec @@ -1,21 +1,16 @@ Name: libssh2 -Version: 1.9.0 -Release: 6 +Version: 1.10.0 +Release: 1 Summary: A library implementing the SSH2 protocol License: BSD URL: https://www.libssh2.org/ Source0: https://libssh2.org/download/libssh2-%{version}.tar.gz -Patch0: 0001-libssh2-CVE-2019-17498.patch -Patch1: 0001-libssh2-misc.c-_libssh2_ntohu32-cast-bit-shifting-40.patch -Patch2: fix-use-of-uninitialized-value-476-478.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 +Patch0: backport-RSA-SHA2-256-512-key-upgrade-support-RFC-8332.patch BuildRequires: coreutils findutils /usr/bin/man zlib-devel BuildRequires: gcc make sed openssl-devel > 1:1.0.1 openssh-server -BuildRequires: glibc-langpack-en +BuildRequires: glibc-langpack-en groff %description libssh2 is a library implementing the SSH2 protocol as defined by @@ -91,6 +86,12 @@ LC_ALL=en_US.UTF-8 make -C tests check %{_mandir}/man3/libssh2_*.3* %changelog +* Tue Mar 21 2022 yanglu - 1.10.0-1 +- Type:requirement +- ID:NA +- SUG:NA +- DESC:update libssh2 to 1.10.0 + * Thu Sep 24 2020 yuboyun - 1.9.0-6 - Type:bugfix - ID:NA