From ebcd6eee3cd04babd9e8f5efbe2377317c95bcc8 Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Wed, 27 Dec 2023 20:32:18 +0100 Subject: [PATCH] misc: Add function to check username syntax Malicious code can be injected using the username with metacharacters, therefore the username must be validated before using it with any %u. Signed-off-by: Norbert Pocs Reviewed-by: Jakub Jelen --- include/libssh/misc.h | 1 + src/misc.c | 32 ++++++++++++++++++++++++++++++++ tests/unittests/torture_misc.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/include/libssh/misc.h b/include/libssh/misc.h index dfbba14c..fc8596f7 100644 --- a/include/libssh/misc.h +++ b/include/libssh/misc.h @@ -123,6 +123,7 @@ 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); +int ssh_check_username_syntax(const char *username); #ifdef __cplusplus } diff --git a/src/misc.c b/src/misc.c index 5cab9d96..c5213561 100644 --- a/src/misc.c +++ b/src/misc.c @@ -2187,4 +2187,36 @@ int ssh_check_hostname_syntax(const char *hostname) return SSH_OK; } +/** + * @brief Checks syntax of a username + * + * This check disallows metacharacters in the username + * + * @param username The username to be checked, has to be null terminated + * + * @return SSH_OK if the username passes syntax check + * SSH_ERROR otherwise or if username is NULL or empty string + */ +int ssh_check_username_syntax(const char *username) +{ + size_t username_len; + + if (username == NULL || *username == '-') { + return SSH_ERROR; + } + + username_len = strlen(username); + if (username_len == 0 || username[username_len - 1] == '\\' || + strpbrk(username, "'`\";&<>|(){}") != NULL) { + return SSH_ERROR; + } + for (size_t i = 0; i < username_len; i++) { + if (isspace(username[i]) != 0 && username[i + 1] == '-') { + return SSH_ERROR; + } + } + + return SSH_OK; +} + /** @} */ diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c index e35d2eac..5a3b4805 100644 --- a/tests/unittests/torture_misc.c +++ b/tests/unittests/torture_misc.c @@ -1058,6 +1058,39 @@ static void torture_ssh_check_hostname_syntax(void **state) assert_int_equal(rc, SSH_ERROR); } +static void torture_ssh_check_username_syntax(void **state) { + int rc; + (void)state; + + rc = ssh_check_username_syntax("username"); + assert_int_equal(rc, SSH_OK); + rc = ssh_check_username_syntax("Alice"); + assert_int_equal(rc, SSH_OK); + rc = ssh_check_username_syntax("Alice and Bob"); + assert_int_equal(rc, SSH_OK); + rc = ssh_check_username_syntax("n4me?"); + assert_int_equal(rc, SSH_OK); + + rc = ssh_check_username_syntax("alice&bob"); + assert_int_equal(rc, SSH_ERROR); + rc = ssh_check_username_syntax("backslash\\"); + assert_int_equal(rc, SSH_ERROR); + rc = ssh_check_username_syntax("&var|()us\"