1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-26 01:03:15 +03:00

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 <norbertpocs0@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
Norbert Pocs
2023-10-10 12:44:16 +02:00
committed by Andreas Schneider
parent b83368b2ed
commit 0ff85b034a
2 changed files with 70 additions and 0 deletions

View File

@@ -122,6 +122,8 @@ char *ssh_strreplace(const char *src, const char *pattern, const char *repl);
ssize_t ssh_readn(int fd, void *buf, size_t nbytes);
ssize_t ssh_writen(int fd, const void *buf, size_t nbytes);
int ssh_check_hostname_syntax(const char *hostname);
#ifdef __cplusplus
}
#endif

View File

@@ -94,6 +94,8 @@
#define ZLIB_STRING ""
#endif
#define ARPA_DOMAIN_MAX_LEN 63
/**
* @defgroup libssh_misc The SSH helper functions
* @ingroup libssh
@@ -2087,4 +2089,70 @@ ssize_t ssh_writen(int fd, const void *buf, size_t nbytes)
return total_bytes_written;
}
/**
* @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;
}
/** @} */