diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index a18ef04c..452c1e2e 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -851,6 +851,7 @@ LIBSSH_API char *ssh_string_to_char(ssh_string str); #define SSH_STRING_FREE_CHAR(x) \ do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0) LIBSSH_API void ssh_string_free_char(char *s); +LIBSSH_API int ssh_string_cmp(ssh_string s1, ssh_string s2); LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo, int verify); diff --git a/src/libssh.map b/src/libssh.map index bde93738..7876ad9a 100644 --- a/src/libssh.map +++ b/src/libssh.map @@ -491,5 +491,6 @@ LIBSSH_AFTER_4_10_0 ssh_get_supported_methods; sshsig_sign; sshsig_verify; + ssh_string_cmp; } LIBSSH_4_10_0; diff --git a/src/string.c b/src/string.c index b2240fca..fdcce7cc 100644 --- a/src/string.c +++ b/src/string.c @@ -27,8 +27,8 @@ #include #ifndef _WIN32 -#include #include +#include #endif #include "libssh/priv.h" @@ -244,6 +244,56 @@ struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) return new; } +/** + * @brief Compare two SSH strings. + * + * @param[in] s1 The first SSH string to compare. + * @param[in] s2 The second SSH string to compare. + * + * @return 0 if the strings are equal, + * < 0 if s1 is less than s2, + * > 0 if s1 is greater than s2. + */ +int ssh_string_cmp(struct ssh_string_struct *s1, struct ssh_string_struct *s2) +{ + size_t len1, len2, min_len; + int cmp; + + /* Both are NULL */ + if (s1 == NULL && s2 == NULL) { + return 0; + } + + /* Only one is NULL - NULL is considered "less than" non-NULL */ + if (s1 == NULL) { + return -1; + } else if (s2 == NULL) { + return 1; + } + + /* Get lengths */ + len1 = ssh_string_len(s1); + len2 = ssh_string_len(s2); + min_len = MIN(len1, len2); + + /* Compare data up to the shorter length */ + if (min_len > 0) { + cmp = memcmp(s1->data, s2->data, min_len); + if (cmp != 0) { + return cmp; + } + } + + /* If common prefix is equal, compare lengths */ + if (len1 < len2) { + return -1; + } else if (len1 > len2) { + return 1; + } + + return 0; +} + /** * @brief Destroy the data in a string so it couldn't appear in a core dump. *