From c6180409677c765e6b9ae2b18a3a7a9671ac1dbe Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Tue, 10 Oct 2023 12:44:16 +0200 Subject: [PATCH] CVE-2023-6004: misc: Add function to check allowed characters of a hostname The hostname can be a domain name or an ip address. The colon has to be allowed because of IPv6 even it is prohibited in domain names. Signed-off-by: Norbert Pocs Reviewed-by: Andreas Schneider Reviewed-by: Jakub Jelen CVE: CVE-2023-6004 Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/c6180409677c765e6b9ae2b18a3a7a9671ac1dbe] Signed-off-by: nikhil r Comment: Refreshed hunk 1 from misc.h and hunk 2 from misc.c --- include/libssh/misc.h | 3 ++ src/misc.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/include/libssh/misc.h b/include/libssh/misc.h index 924da5336..0924ba7fb 100644 --- a/include/libssh/misc.h +++ b/include/libssh/misc.h @@ -89,4 +89,6 @@ int ssh_match_group(const char *group, const char *object); int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len); +int ssh_check_hostname_syntax(const char *hostname); + #endif /* MISC_H_ */ diff --git a/src/misc.c b/src/misc.c index 7c478a773..be6ee836e 100644 --- a/src/misc.c +++ b/src/misc.c @@ -94,6 +94,8 @@ #define ZLIB_STRING "" #endif +#define ARPA_DOMAIN_MAX_LEN 63 + /** * @defgroup libssh_misc The SSH helper functions. * @ingroup libssh @@ -1292,4 +1294,69 @@ error: return SSH_ERROR; } +/** + * @brief Checks syntax of a domain name + * + * The check is made based on the RFC1035 section 2.3.1 + * Allowed characters are: hyphen, period, digits (0-9) and letters (a-zA-Z) + * + * The label should be no longer than 63 characters + * The label should start with a letter and end with a letter or number + * The label in this implementation can start with a number to allow virtual + * URLs to pass. Note that this will make IPv4 addresses to pass + * this check too. + * + * @param hostname The domain name to be checked, has to be null terminated + * + * @return SSH_OK if the hostname passes syntax check + * SSH_ERROR otherwise or if hostname is NULL or empty string + */ +int ssh_check_hostname_syntax(const char *hostname) +{ + char *it = NULL, *s = NULL, *buf = NULL; + size_t it_len; + char c; + + if (hostname == NULL || strlen(hostname) == 0) { + return SSH_ERROR; + } + + /* strtok_r writes into the string, keep the input clean */ + s = strdup(hostname); + if (s == NULL) { + return SSH_ERROR; + } + + it = strtok_r(s, ".", &buf); + /* if the token has 0 length */ + if (it == NULL) { + free(s); + return SSH_ERROR; + } + do { + it_len = strlen(it); + if (it_len > ARPA_DOMAIN_MAX_LEN || + /* the first char must be a letter, but some virtual urls start + * with a number */ + isalnum(it[0]) == 0 || + isalnum(it[it_len - 1]) == 0) { + free(s); + return SSH_ERROR; + } + while (*it != '\0') { + c = *it; + /* the "." is allowed too, but tokenization removes it from the + * string */ + if (isalnum(c) == 0 && c != '-') { + free(s); + return SSH_ERROR; + } + it++; + } + } while ((it = strtok_r(NULL, ".", &buf)) != NULL); + + free(s); + + return SSH_OK; +} /** @} */