aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2019-01-07 18:49:58 +0100
committerAndreas Schneider <asn@cryptomilk.org>2019-01-09 17:22:48 +0100
commit0acfd81f85f8c41547ac700782fa96a000abdc79 (patch)
treefb71cbe071cbab8c5ac02c1869164846f73af6fc
parentd028b2495d0bb2b7ae9b0af42b4377af4a964b00 (diff)
downloadlibssh-0acfd81f85f8c41547ac700782fa96a000abdc79.tar.gz
libssh-0acfd81f85f8c41547ac700782fa96a000abdc79.tar.xz
libssh-0acfd81f85f8c41547ac700782fa96a000abdc79.zip
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)
-rw-r--r--include/libssh/session.h7
-rw-r--r--src/kex.c24
-rw-r--r--src/server.c2
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);
}