From 0870c8db28be9eb457ee3d4f9a168959d9507efd Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@0xbadc0de.be>
Date: Tue, 12 Dec 2023 23:30:26 +0100
Subject: [PATCH] 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>

Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/0870c8db28be9eb457ee3d4f9a168959d9507efd]
CVE: CVE-2023-48795
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
---
 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 a626d105..2b1a74d5 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, int server_kex);
 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 2ed90235..b03e6484 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -766,11 +766,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;
 
     ok = ssh_get_random(client->cookie, 16, 0);
     if (!ok) {
@@ -802,11 +799,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;
@@ -816,9 +835,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 bc98da4f..f3d24a7b 100644
--- a/src/server.c
+++ b/src/server.c
@@ -158,7 +158,13 @@ static 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.25.1

