From 1a02364b5107a4125ea3cb76fcdb6beabaebf3be Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 22 Dec 2023 10:32:40 +0100
Subject: [PATCH] Fix regression in IPv6 addresses in hostname parsing

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4f997aee7c7d7ea346b3e8ba505da0b7601ff318)

CVE: CVE-2023-6004
Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/1a02364b5107a4125ea3cb76fcdb6beabaebf3be]
Signed-off-by: nikhil r <nikhil.r@kpit.com>
Comment: Removed 1 hunk from config_parser.c as the function was intoduced in
later version

---
 include/libssh/config_parser.h | 11 ++++++++---
 src/config.c                   |  4 ++--
 src/config_parser.c            | 16 +++++++++++-----
 src/options.c                  | 10 ++--------
 4 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h
index a7dd42a2c..ca353432b 100644
--- a/include/libssh/config_parser.h
+++ b/include/libssh/config_parser.h
@@ -26,6 +26,8 @@
 #ifndef CONFIG_PARSER_H_
 #define CONFIG_PARSER_H_
 
+#include <stdbool.h>
+
 char *ssh_config_get_cmd(char **str);
 
 char *ssh_config_get_token(char **str);
@@ -45,13 +47,16 @@ int ssh_config_get_yesno(char **str, int notfound);
  *                       be stored or NULL if we do not care about the result.
  * @param[out]  port     Pointer to the location, where the new port will
  *                       be stored or NULL if we do not care about the result.
+ * @param[in]   ignore_port Set to true if the we should not attempt to parse
+ *                       port number.
  *
  * @returns     SSH_OK if the provided string is in format of SSH URI,
  *              SSH_ERROR on failure
  */
 int ssh_config_parse_uri(const char *tok,
-        char **username,
-        char **hostname,
-        char **port);
+                         char **username,
+                         char **hostname,
+                         char **port,
+                         bool ignore_port);
 
 #endif /* LIBSSH_CONFIG_H_ */
diff --git a/src/config_parser.c b/src/config_parser.c
index b8b94611a..d4b2d2c3b 100644
--- a/src/config_parser.c
+++ b/src/config_parser.c
@@ -162,9 +162,10 @@ int ssh_config_get_yesno(char **str, int notfound)
 }
 
 int ssh_config_parse_uri(const char *tok,
-        char **username,
-        char **hostname,
-        char **port)
+                         char **username,
+                         char **hostname,
+                         char **port,
+                         bool ignore_port)
 {
     char *endp = NULL;
     long port_n;
@@ -210,12 +211,17 @@ int ssh_config_parse_uri(const char *tok,
         if (endp == NULL) {
             goto error;
         }
-    } else {
-        /* Hostnames or aliases expand to the last colon or to the end */
+    } else if (!ignore_port) {
+        /* Hostnames or aliases expand to the last colon (if port is requested)
+         * or to the end */
         endp = strrchr(tok, ':');
         if (endp == NULL) {
             endp = strchr(tok, '\0');
         }
+    } else {
+        /* If no port is requested, expand to the end of line
+         * (to accommodate the IPv6 addresses) */
+        endp = strchr(tok, '\0');
     }
     if (tok == endp) {
         /* Zero-length hostnames are not valid */
diff --git a/src/options.c b/src/options.c
index 385114555..b3ecffe15 100644
--- a/src/options.c
+++ b/src/options.c
@@ -416,17 +416,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
                 ssh_set_error_invalid(session);
                 return -1;
             } else {
-                char *username = NULL, *hostname = NULL, *port = NULL;
-                rc = ssh_config_parse_uri(value, &username, &hostname, &port);
+                char *username = NULL, *hostname = NULL;
+                rc = ssh_config_parse_uri(value, &username, &hostname, NULL, true);
                 if (rc != SSH_OK) {
                     return -1;
                 }
-                if (port != NULL) {
-                    SAFE_FREE(username);
-                    SAFE_FREE(hostname);
-                    SAFE_FREE(port);
-                    return -1;
-                }
                 if (username != NULL) {
                     SAFE_FREE(session->opts.username);
                    session->opts.username = username;
