From fd4948255560039b51c2d61f0a62784ed8b6f5a6 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Tue, 12 Dec 2023 23:30:26 +0100
Subject: [PATCH 2/4] CVE-2023-48795: Server side mitigations

Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>

Conflict: NA
Reference: https://gitlab.com/libssh/libssh-mirror/-/commit/fd4948255560039b51c2d61f0a62784ed8b6f5a6
---
 include/libssh/kex.h |  1 +
 src/kex.c            | 46 ++++++++++++++++++++++++++++++++++----------
 src/server.c         |  8 +++++++-
 3 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/include/libssh/kex.h b/include/libssh/kex.h
index 2ace69b6..40da4ef2 100644
--- a/include/libssh/kex.h
+++ b/include/libssh/kex.h
@@ -36,6 +36,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit);
 int ssh_send_kex(ssh_session session);
 void ssh_list_kex(struct ssh_kex_struct *kex);
 int ssh_set_client_kex(ssh_session session);
+int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex);
 int ssh_kex_select_methods(ssh_session session);
 int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
 char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
diff --git a/src/kex.c b/src/kex.c
index 0772cae8..e37c176c 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -738,11 +738,8 @@ int ssh_set_client_kex(ssh_session session)
 {
     struct ssh_kex_struct *client = &session->next_crypto->client_kex;
     const char *wanted;
-    char *kex = NULL;
-    char *kex_tmp = NULL;
     int ok;
     int i;
-    size_t kex_len, len;
 
     /* Skip if already set, for example for the rekey or when we do the guessing
      * it could have been already used to make some protocol decisions. */
@@ -791,11 +788,33 @@ int ssh_set_client_kex(ssh_session session)
         return SSH_OK;
     }
 
-    /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */
-    kex = client->methods[SSH_KEX];
+    ok = ssh_kex_append_extensions(session, client);
+    if (ok != SSH_OK){
+        return ok;
+    }
+
+    return SSH_OK;
+}
+
+int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex)
+{
+    char *kex = NULL;
+    char *kex_tmp = NULL;
+    size_t kex_len, len;
+
+    /* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client
+     * and kex-strict-s-v00@openssh.com for server to the list of kex algorithms
+     */
+    kex = pkex->methods[SSH_KEX];
     len = strlen(kex);
-    /* Comma, comma, nul byte */
-    kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1;
+    if (session->server) {
+        /* Comma, nul byte */
+        kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1;
+    } else {
+        /* Comma, comma, nul byte */
+        kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 +
+                  strlen(KEX_STRICT_CLIENT) + 1;
+    }
     if (kex_len >= MAX_PACKET_LEN) {
         /* Overflow */
         return SSH_ERROR;
@@ -805,9 +824,16 @@ int ssh_set_client_kex(ssh_session session)
         ssh_set_error_oom(session);
         return SSH_ERROR;
     }
-    snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT);
-    client->methods[SSH_KEX] = kex_tmp;
-
+    if (session->server){
+        snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER);
+    } else {
+        snprintf(kex_tmp + len,
+                 kex_len - len,
+                 ",%s,%s",
+                 KEX_EXTENSION_CLIENT,
+                 KEX_STRICT_CLIENT);
+    }
+    pkex->methods[SSH_KEX] = kex_tmp;
     return SSH_OK;
 }
 
diff --git a/src/server.c b/src/server.c
index ed73e7fb..35e84465 100644
--- a/src/server.c
+++ b/src/server.c
@@ -195,7 +195,13 @@ int server_set_kex(ssh_session session)
         }
     }
 
-    return 0;
+    /* Do not append the extensions during rekey */
+    if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
+        return SSH_OK;
+    }
+
+    rc = ssh_kex_append_extensions(session, server);
+    return rc;
 }
 
 int ssh_server_init_kex(ssh_session session) {
-- 
2.33.0

