From 129c4e7d94cb9e38f4e5c93b742276f8bbab2708 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Tue, 15 Jan 2019 16:40:16 +0100 Subject: [PATCH] Fix rsa-sha2 extension handling Resolves: #1666342 --- libssh-0.8.6-fix-rsa-sha2-ext.patch | 261 ++++++++++++++++++++++++++++ libssh.spec | 7 +- 2 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 libssh-0.8.6-fix-rsa-sha2-ext.patch diff --git a/libssh-0.8.6-fix-rsa-sha2-ext.patch b/libssh-0.8.6-fix-rsa-sha2-ext.patch new file mode 100644 index 0000000..3fe8438 --- /dev/null +++ b/libssh-0.8.6-fix-rsa-sha2-ext.patch @@ -0,0 +1,261 @@ +From d028b2495d0bb2b7ae9b0af42b4377af4a964b00 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 8 Jan 2019 11:32:10 +0100 +Subject: [PATCH 1/3] dh: Make sure we do not access uninitialized memory + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit ca62632170c311923026f978c57d2e0a0be3e0e1) +--- + src/dh.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/dh.c b/src/dh.c +index 90c1813c..cc12fd46 100644 +--- a/src/dh.c ++++ b/src/dh.c +@@ -1274,6 +1274,10 @@ int ssh_get_server_publickey(ssh_session session, ssh_key *key) + + ssh_key ssh_dh_get_current_server_publickey(ssh_session session) + { ++ if (session->current_crypto == NULL) { ++ return NULL; ++ } ++ + return session->current_crypto->server_pubkey; + } + +-- +2.20.1 + + +From 0acfd81f85f8c41547ac700782fa96a000abdc79 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 7 Jan 2019 18:49:58 +0100 +Subject: [PATCH 2/3] server: Correctly handle extensions + +If the server had an RSA host key, it provided unconditionally SHA2 +signatures without consulting the client proposed list of supported host +keys. + +This commit implements more fine-grained detection of the extension +to provide the client with valid signatures according to RFC 8332 +Section 3.1. + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 27fe60954c29e548c30af239d92ab4faaf8cf788) +--- + include/libssh/session.h | 7 ++++--- + src/kex.c | 24 ++++++++++++++++++++---- + src/server.c | 2 +- + 3 files changed, 25 insertions(+), 8 deletions(-) + +diff --git a/include/libssh/session.h b/include/libssh/session.h +index 8b963066..23633cc2 100644 +--- a/include/libssh/session.h ++++ b/include/libssh/session.h +@@ -87,10 +87,11 @@ enum ssh_pending_call_e { + #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 + + /* extensions flags */ ++/* negotiation enabled */ ++#define SSH_EXT_NEGOTIATION 0x01 + /* server-sig-algs extension */ +-#define SSH_EXT_SIG_RSA_SHA256 0x01 +-#define SSH_EXT_SIG_RSA_SHA512 0x02 +-#define SSH_EXT_ALL SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512 ++#define SSH_EXT_SIG_RSA_SHA256 0x02 ++#define SSH_EXT_SIG_RSA_SHA512 0x04 + + /* members that are common to ssh_session and ssh_bind */ + struct ssh_common_struct { +diff --git a/src/kex.c b/src/kex.c +index 35a5a602..d9d0c7e5 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -526,13 +526,29 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){ + ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX], + KEX_EXTENSION_CLIENT); + if (ok) { ++ const char *hostkeys = NULL; ++ ++ /* The client supports extension negotiation */ ++ session->extensions |= SSH_EXT_NEGOTIATION; + /* +- * Enable all the supported extensions and when the time comes +- * (after NEWKEYS) send them to the client. ++ * RFC 8332 Section 3.1: Use for Server Authentication ++ * Check what algorithms were provided in the SSH_HOSTKEYS list ++ * by the client and enable the respective extensions to provide ++ * correct signature in the next packet if RSA is negotiated + */ ++ hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS]; ++ ok = ssh_match_group(hostkeys, "rsa-sha2-512"); ++ if (ok) { ++ session->extensions |= SSH_EXT_SIG_RSA_SHA512; ++ } ++ ok = ssh_match_group(hostkeys, "rsa-sha2-256"); ++ if (ok) { ++ session->extensions |= SSH_EXT_SIG_RSA_SHA256; ++ } + SSH_LOG(SSH_LOG_DEBUG, "The client supports extension " +- "negotiation: enabling all extensions"); +- session->extensions = SSH_EXT_ALL; ++ "negotiation. Enabled signature algorithms: %s%s", ++ session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "", ++ session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : ""); + } + + /* +diff --git a/src/server.c b/src/server.c +index 8197fd86..02471e91 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -523,7 +523,7 @@ static void ssh_server_connection_callback(ssh_session session){ + * our supported extensions now. This is the first message after + * sending NEWKEYS message and after turning on crypto. + */ +- if (session->extensions && ++ if (session->extensions & SSH_EXT_NEGOTIATION && + session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { + ssh_server_send_extensions(session); + } +-- +2.20.1 + + +From bfc39d578db2412d2ae379a105c3cb658f48748c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 8 Jan 2019 14:27:39 +0100 +Subject: [PATCH 3/3] kex: List also the SHA2 extension when ordering hostkey + algorithms + +By default, the list of already stored known host types is preferred, +but this selection so far ignored the SHA2 extension and excluded these +keys in the KEXINIT list leading to not using this extension if not +explicitly enabled from configuration. + +This commit extends the default list with the SHA2 signatures algoritms +and compares only base types so they can be listed in the KEXINIT list. + +This adjust the tests to expect the full list of algorithms to pass. + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 531b80a60bcb89c0ea09e85e36e240755407febf) +--- + src/kex.c | 36 +++++++++++--------- + tests/unittests/torture_knownhosts_parsing.c | 10 +++--- + 2 files changed, 26 insertions(+), 20 deletions(-) + +diff --git a/src/kex.c b/src/kex.c +index d9d0c7e5..44d60f59 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -38,6 +38,7 @@ + #include "libssh/curve25519.h" + #include "libssh/knownhosts.h" + #include "libssh/misc.h" ++#include "libssh/pki.h" + + #ifdef HAVE_LIBGCRYPT + # define BLOWFISH "blowfish-cbc," +@@ -619,6 +620,8 @@ char *ssh_client_select_hostkeys(ssh_session session) + "ecdsa-sha2-nistp521", + "ecdsa-sha2-nistp384", + "ecdsa-sha2-nistp256", ++ "rsa-sha2-512", ++ "rsa-sha2-256", + "ssh-rsa", + #ifdef HAVE_DSA + "ssh-dss", +@@ -644,29 +647,30 @@ char *ssh_client_select_hostkeys(ssh_session session) + + for (i = 0; preferred_hostkeys[i] != NULL; ++i) { + bool found = false; ++ /* This is a signature type: We list also the SHA2 extensions */ ++ enum ssh_keytypes_e base_preferred = ++ ssh_key_type_from_signature_name(preferred_hostkeys[i]); + + for (it = ssh_list_get_iterator(algo_list); + it != NULL; + it = it->next) { + const char *algo = ssh_iterator_value(const char *, it); +- int cmp; +- int ok; ++ /* This is always key type so we do not have to care for the ++ * SHA2 extension */ ++ enum ssh_keytypes_e base_algo = ssh_key_type_from_name(algo); + +- cmp = strcmp(preferred_hostkeys[i], algo); +- if (cmp == 0) { +- ok = ssh_verify_existing_algo(SSH_HOSTKEYS, algo); +- if (ok) { +- if (needcomma) { +- strncat(methods_buffer, +- ",", +- sizeof(methods_buffer) - strlen(methods_buffer) - 1); +- } ++ if (base_preferred == base_algo) { ++ /* Matching the keys already verified it is a known type */ ++ if (needcomma) { + strncat(methods_buffer, +- algo, ++ ",", + sizeof(methods_buffer) - strlen(methods_buffer) - 1); +- needcomma = 1; +- found = true; + } ++ strncat(methods_buffer, ++ preferred_hostkeys[i], ++ sizeof(methods_buffer) - strlen(methods_buffer) - 1); ++ needcomma = 1; ++ found = true; + } + } + /* Collect the rest of the algorithms in other buffer, that will +@@ -728,10 +732,10 @@ int ssh_set_client_kex(ssh_session session) + + memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **)); + /* first check if we have specific host key methods */ +- if(session->opts.wanted_methods[SSH_HOSTKEYS] == NULL){ ++ if (session->opts.wanted_methods[SSH_HOSTKEYS] == NULL) { + /* Only if no override */ + session->opts.wanted_methods[SSH_HOSTKEYS] = +- ssh_client_select_hostkeys(session); ++ ssh_client_select_hostkeys(session); + } + + for (i = 0; i < KEX_METHODS_SIZE; i++) { +diff --git a/tests/unittests/torture_knownhosts_parsing.c b/tests/unittests/torture_knownhosts_parsing.c +index 148c5da8..a7a0d99d 100644 +--- a/tests/unittests/torture_knownhosts_parsing.c ++++ b/tests/unittests/torture_knownhosts_parsing.c +@@ -310,8 +310,9 @@ torture_knownhosts_algorithms(void **state) + const char *knownhosts_file = *state; + char *algo_list = NULL; + ssh_session session; +- const char *expect = "ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521," +- "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256" ++ const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa," ++ "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," ++ "ecdsa-sha2-nistp256" + #ifdef HAVE_DSA + ",ssh-dss" + #endif +@@ -339,8 +340,9 @@ torture_knownhosts_algorithms_global(void **state) + const char *knownhosts_file = *state; + char *algo_list = NULL; + ssh_session session; +- const char *expect = "ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521," +- "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256" ++ const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa," ++ "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," ++ "ecdsa-sha2-nistp256" + #ifdef HAVE_DSA + ",ssh-dss" + #endif +-- +2.20.1 + diff --git a/libssh.spec b/libssh.spec index ad7842d..25465b0 100644 --- a/libssh.spec +++ b/libssh.spec @@ -1,6 +1,6 @@ Name: libssh Version: 0.8.6 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A library implementing the SSH protocol License: LGPLv2+ URL: http://www.libssh.org @@ -9,6 +9,8 @@ Source0: https://www.libssh.org/files/0.8/%{name}-%{version}.tar.xz Source1: https://www.libssh.org/files/0.8/%{name}-%{version}.tar.xz.asc Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring +Patch0: libssh-0.8.6-fix-rsa-sha2-ext.patch + BuildRequires: cmake BuildRequires: doxygen BuildRequires: gcc-c++ @@ -104,6 +106,9 @@ popd %{_libdir}/libssh_threads.so %changelog +* Tue Jan 15 2019 Anderson Sasaki - 0.8.6-2 +- Fix rsa-sha2 extension handling (#1666342) + * Thu Jan 03 2019 Anderson Sasaki - 0.8.6-1 - Update to version 0.8.6 https://www.libssh.org/2018/12/24/libssh-0-8-6-xmas-edition/