129c4e7d94
Resolves: #1666342
262 lines
10 KiB
Diff
262 lines
10 KiB
Diff
From d028b2495d0bb2b7ae9b0af42b4377af4a964b00 Mon Sep 17 00:00:00 2001
|
|
From: Jakub Jelen <jjelen@redhat.com>
|
|
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 <jjelen@redhat.com>
|
|
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
|
(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 <jjelen@redhat.com>
|
|
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 <jjelen@redhat.com>
|
|
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
|
(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 <jjelen@redhat.com>
|
|
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 <jjelen@redhat.com>
|
|
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
|
(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
|
|
|