From dcf3ec0e092fd496c5460db097efc6dc91dd3c48 Mon Sep 17 00:00:00 2001 From: Philipp Eder Date: Fri, 7 May 2021 13:53:56 +0200 Subject: [PATCH 1/4] Use pba authentication instead of authutils To be able to verify new password hashes and update old ones gvmd is using passwordbasedauthentication of gvm-libs. To configure: - pepper - counts - algorithm authentication_settings_t is introduced. manage_option_setup is using authentication_settings_t to translate it to PBASettings for password based authentication. To configure it from a user perspective use `--hashcount` and `--pepper`. Once a pepper is set you must reuse it; otherwise the login are not working due to incorrect salt. (cherry picked from commit ef9d161f39a9b967dbeb8d4f751152d11fc2d5ac) # Conflicts: # .gitignore --- .gitignore | 5 +++ CHANGELOG.md | 1 + src/CMakeLists.txt | 7 ++++ src/gvmd.c | 56 ++++++++++++++++++++++++++++++++ src/manage_authentication.c | 63 +++++++++++++++++++++++++++++++++++ src/manage_authentication.h | 65 +++++++++++++++++++++++++++++++++++++ src/manage_sql.c | 48 +++++++++++++++++++++++---- 7 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 src/manage_authentication.c create mode 100644 src/manage_authentication.h diff --git a/.gitignore b/.gitignore index 567609b12..a522b8421 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ build/ +<<<<<<< HEAD +======= +tags +.ccls +>>>>>>> ef9d161f3... Use pba authentication instead of authutils diff --git a/CHANGELOG.md b/CHANGELOG.md index 79359fc9e..96fbcee0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Improve report counts performance [#1438](https://github.com/greenbone/gvmd/pull/1438) - Clean up log config, add gvm-libs log domains [#1502](https://github.com/greenbone/gvmd/pull/1502) - Sort missing severity as lowest value in GMP get [#1508](https://github.com/greenbone/gvmd/pull/1508) +- Use passwordbasedauthentication of gvm-libs instead of auth_utils [#1505](https://github.com/greenbone/gvmd/pull/1505) ### Fixed - Also create owner WITH clause for single resources [#1406](https://github.com/greenbone/gvmd/pull/1406) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c17f62081..95146af1c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,6 +104,7 @@ add_executable (manage-utils-test manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -127,6 +128,7 @@ add_executable (manage-test manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -150,6 +152,7 @@ add_executable (manage-sql-test manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -173,6 +176,7 @@ add_executable (gmp-tickets-test manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -195,6 +199,7 @@ add_executable (utils-test manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -219,6 +224,7 @@ add_executable (gvmd manage_acl.c manage_configs.c manage_get.c manage_port_lists.c manage_preferences.c manage_report_formats.c + manage_authentication.c manage_sql.c manage_sql_nvts.c manage_sql_secinfo.c manage_sql_port_lists.c manage_sql_configs.c manage_sql_report_formats.c @@ -430,6 +436,7 @@ set (C_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gvmd.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_port_lists.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_preferences.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_report_formats.c" + "${CMAKE_CURRENT_SOURCE_DIR}/manage_authentication.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_configs.c" "${CMAKE_CURRENT_SOURCE_DIR}/manage_sql_nvts.c" diff --git a/src/gvmd.c b/src/gvmd.c index 5a051e14b..bc5a035a6 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -102,6 +102,7 @@ #include "manage.h" #include "manage_sql_nvts.h" #include "manage_sql_secinfo.h" +#include "manage_authentication.h" #include "gmpd.h" #include "utils.h" @@ -1674,6 +1675,53 @@ manager_listen (const char *address_str_unix, const char *address_str_tls, return 0; } +/** + * @brief parse_authentication_goption_arg is used to parse authentication + * parameter. + * + * @param[in] opt the parameter (e.g. --pepper). + * @param[in] arg the value of the parameter. + * @param[in] data the pointer of the data to set (unused). + * @param[in] err used to set error string on failure. + * + * @return TRUE success, FALSE on failure. + **/ +static gboolean +parse_authentication_goption_arg (const gchar *opt, const gchar *arg, + gpointer data, GError **err) +{ + if (strcmp (opt, "--pepper") == 0) + { + if (manage_authentication_setup(arg, strlen(arg), 0, NULL) != GMA_SUCCESS) + { + g_set_error ( + err, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Unable to set given pepper (%s)", + arg); + return FALSE; + } + } + else if (strcmp (opt, "--hashcount") == 0) + { + if (manage_authentication_setup(NULL, 0, strtol(arg, NULL, 0), NULL) != GMA_SUCCESS) + { + g_set_error ( + err, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Unable to set hash_count (%s)", + arg); + return FALSE; + } + } + else + { + g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION, + "Unknown authentication option: %s.", opt); + return FALSE; + } + + return TRUE; +} + /** * @brief Entry point to the manager. * @@ -2042,6 +2090,14 @@ gvmd (int argc, char** argv) &verify_scanner, "Verify scanner and exit.", "" }, + { "pepper", '\0', 0, G_OPTION_ARG_CALLBACK, + parse_authentication_goption_arg, + "Use to statically enhance salt of password hashes (maximal 4 character).", + "" }, + { "hashcount", '\0', 0, G_OPTION_ARG_CALLBACK, + parse_authentication_goption_arg, + "Use to enhance the computational cost of creating a password hash.", + "" }, { "version", '\0', 0, G_OPTION_ARG_NONE, &print_version, "Print version and exit.", diff --git a/src/manage_authentication.c b/src/manage_authentication.c new file mode 100644 index 000000000..1db01870d --- /dev/null +++ b/src/manage_authentication.c @@ -0,0 +1,63 @@ +#include "manage_authentication.h" +#include + +#include +#include + +// prefer stack rather than heap so that we use the defaults on usage failure +// rather than having to check and fail. +struct PBASettings settings = {{0}, COUNT_DEFAULT, PREFIX_DEFAULT}; + +enum manage_authentication_rc +manage_authentication_setup (const char *pepper, unsigned int pepper_size, + unsigned int count, char *prefix) +{ + struct PBASettings *tmp = pba_init (pepper, pepper_size, count, prefix); + enum manage_authentication_rc rc = GMA_ERR; + unsigned int i; + + if (tmp == NULL) + goto exit; + // ovly override pepper when pepper is initially set otherwise keep + // previous pepper + for (i = 0; pepper != NULL && i < MAX_PEPPER_SIZE; i++) + settings.pepper[i] = tmp->pepper[i]; + settings.count = count > 0 ? tmp->count : settings.count; + settings.prefix = prefix != NULL ? tmp->prefix : settings.prefix; + pba_finalize(tmp); + rc = GMA_SUCCESS; + +exit: + return rc; +} + +char * +manage_authentication_hash (const char *password) +{ + return pba_hash(&settings, password); +} + +enum manage_authentication_rc +manage_authentication_verify (const char *hash, const char *password) +{ + enum pba_rc pba_rc = pba_verify_hash(&settings, hash, password); + enum manage_authentication_rc rc; + switch (pba_rc){ + case VALID: + rc = GMA_SUCCESS; + break; + case INVALID: + rc = GMA_HASH_INVALID; + break; + case UPDATE_RECOMMENDED: + rc = GMA_HASH_VALID_BUT_DATED; + break; + default: + rc = GMA_ERR; + break; + + } + + return rc; +} + diff --git a/src/manage_authentication.h b/src/manage_authentication.h new file mode 100644 index 000000000..df0a20c51 --- /dev/null +++ b/src/manage_authentication.h @@ -0,0 +1,65 @@ +#ifndef _GVMD_MANAGE_AUTHENTICATION_H +#define _GVMD_MANAGE_AUTHENTICATION_H + + +enum manage_authentication_rc +{ + GMA_SUCCESS, + GMA_HASH_VALID_BUT_DATED, + GMA_HASH_INVALID, + GMA_ERR, +}; + +/** + * @brief manage_authentication_setup sets the pepper, count and prefix used + * by the authentication implementation. + * + * When pepper is a NULL pointer, prefix is a NULL pointer or count is 0 then + * the previous setting of that setting will be kept. + * + * This is mainly to allow easier configuration within gvmd.c so that it can + * used parameterized without restore the same information there. + * + * The initial defaults are set to no-pepper, COUNT_DEFAULT and PREFIX_DEFAULT + * of gvm-libs. + * + * @param[in] pepper - a static hidden addition to the randomely generated salt + * @param[in] pepper_size - the size of pepper; it must not larger then + * MAX_PEPPER_SIZE + * @param[in] count - the amount of rounds used to calculate the hash; if 0 then + * COUNT_DEFAULT will be used + * @param[in] prefix - the used algorithm, if NULL pointer then the most secure + * available algorithm will be used. + * + * @return GMA_SUCCESS when the settings are set or GMA_ERR if there was a + * failure. + */ +enum manage_authentication_rc +manage_authentication_setup (const char *pepper, unsigned int pepper_size, + unsigned int count, char *prefix); +/** + * @brief creates a hash based on the settings set by + * manage_authentication_setup and the password. + * + * @param[in] passwod - the password to be hashed + * @return the hash or a NULL pointer on a failure. + * */ +char * +manage_authentication_hash (const char *password); +/** + * @brief manage_authentication_verify verifies given password with given hash. + * + * @param[in] password - the clear text password to be verified + * @param[in] hash - the stored hash to verify the password against. + * + * @return GMA_SUCCESS when password is valid, + * GMA_HASH_VALID_BUT_DATED when password is valid but a new hash + * should ne created and stored. + * GMA_HASH_INVALID when password is invalid + * GMA_ERR when an unexpected error occurs. + **/ +enum manage_authentication_rc +manage_authentication_verify (const char *hash, const char *password); + +#endif + diff --git a/src/manage_sql.c b/src/manage_sql.c index 44fe1c54c..230bd296a 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -38,6 +38,7 @@ #include "manage_sql_tickets.h" #include "manage_sql_tls_certificates.h" #include "manage_acl.h" +#include "manage_authentication.h" #include "lsc_user.h" #include "sql.h" #include "utils.h" @@ -16917,7 +16918,22 @@ auth_cache_find (const char *username, const char *password, int method) if (!hash) return -1; - ret = gvm_authenticate_classic (username, password, hash); + // verify for VALID or OUTDATED but don't update + ret = manage_authentication_verify(hash, password); + switch(ret){ + case GMA_HASH_INVALID: + ret = 1; + break; + case GMA_HASH_VALID_BUT_DATED: + ret = 0; + break; + case GMA_SUCCESS: + ret = 0; + break; + default: + ret = -1; + break; + } g_free (hash); return ret; } @@ -16936,7 +16952,7 @@ auth_cache_insert (const char *username, const char *password, int method) char *hash, *quoted_username; quoted_username = sql_quote (username); - hash = get_password_hashes (password); + hash = manage_authentication_hash(password); sql ("INSERT INTO auth_cache (username, hash, method, creation_time)" " VALUES ('%s', '%s', %i, m_now ());", quoted_username, hash, method); /* Cleanup cache */ @@ -17005,7 +17021,27 @@ authenticate_any_method (const gchar *username, const gchar *password, } *auth_method = AUTHENTICATION_METHOD_FILE; hash = manage_user_hash (username); - ret = gvm_authenticate_classic (username, password, hash); + ret = manage_authentication_verify(hash, password); + switch(ret){ + case GMA_HASH_INVALID: + ret = 1; + break; + case GMA_HASH_VALID_BUT_DATED: + g_free(hash); + hash = manage_authentication_hash(password); + sql ("UPDATE users SET password = '%s', modification_time = m_now () WHERE name = '%s';", + hash, username); + ret = 0; + break; + case GMA_SUCCESS: + ret = 0; + break; + default: + ret = -1; + break; + } + + g_free (hash); return ret; } @@ -51637,7 +51673,7 @@ set_password (const gchar *name, const gchar *uuid, const gchar *password, g_free (errstr); return -1; } - hash = get_password_hashes (password); + hash = manage_authentication_hash (password); sql ("UPDATE users SET password = '%s', modification_time = m_now ()" " WHERE uuid = '%s';", hash, @@ -51886,7 +51922,7 @@ create_user (const gchar * name, const gchar * password, const gchar *comment, /* Get the password hashes. */ - hash = get_password_hashes (password); + hash = manage_authentication_hash (password); /* Get the quoted comment */ @@ -52992,7 +53028,7 @@ modify_user (const gchar * user_id, gchar **name, const gchar *new_name, /* Get the password hashes. */ if (password) - hash = get_password_hashes (password); + hash = manage_authentication_hash (password); else hash = NULL; From d468da810d353de7c7d76cf58cd4e4bf82728fa7 Mon Sep 17 00:00:00 2001 From: Philipp Eder Date: Fri, 7 May 2021 15:45:01 +0200 Subject: [PATCH 2/4] Move doxygen comments from header into implementation (cherry picked from commit 6a406e815d3f1f64a6d28d2cd2795bb6abb89a0a) --- src/manage_authentication.c | 43 ++++++++++++++++++++++++++++++++++++ src/manage_authentication.h | 44 +------------------------------------ 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/manage_authentication.c b/src/manage_authentication.c index 1db01870d..22ff9e3d2 100644 --- a/src/manage_authentication.c +++ b/src/manage_authentication.c @@ -8,6 +8,30 @@ // rather than having to check and fail. struct PBASettings settings = {{0}, COUNT_DEFAULT, PREFIX_DEFAULT}; +/** + * @brief manage_authentication_setup sets the pepper, count and prefix used + * by the authentication implementation. + * + * When pepper is a NULL pointer, prefix is a NULL pointer or count is 0 then + * the previous setting of that setting will be kept. + * + * This is mainly to allow easier configuration within gvmd.c so that it can + * used parameterized without restore the same information there. + * + * The initial defaults are set to no-pepper, COUNT_DEFAULT and PREFIX_DEFAULT + * of gvm-libs. + * + * @param[in] pepper - a static hidden addition to the randomely generated salt + * @param[in] pepper_size - the size of pepper; it must not larger then + * MAX_PEPPER_SIZE + * @param[in] count - the amount of rounds used to calculate the hash; if 0 then + * COUNT_DEFAULT will be used + * @param[in] prefix - the used algorithm, if NULL pointer then the most secure + * available algorithm will be used. + * + * @return GMA_SUCCESS when the settings are set or GMA_ERR if there was a + * failure. + */ enum manage_authentication_rc manage_authentication_setup (const char *pepper, unsigned int pepper_size, unsigned int count, char *prefix) @@ -31,12 +55,31 @@ manage_authentication_setup (const char *pepper, unsigned int pepper_size, return rc; } +/** + * @brief creates a hash based on the settings set by + * manage_authentication_setup and the password. + * + * @param[in] passwod - the password to be hashed + * @return the hash or a NULL pointer on a failure. + * */ char * manage_authentication_hash (const char *password) { return pba_hash(&settings, password); } +/** + * @brief manage_authentication_verify verifies given password with given hash. + * + * @param[in] password - the clear text password to be verified + * @param[in] hash - the stored hash to verify the password against. + * + * @return GMA_SUCCESS when password is valid, + * GMA_HASH_VALID_BUT_DATED when password is valid but a new hash + * should ne created and stored. + * GMA_HASH_INVALID when password is invalid + * GMA_ERR when an unexpected error occurs. + **/ enum manage_authentication_rc manage_authentication_verify (const char *hash, const char *password) { diff --git a/src/manage_authentication.h b/src/manage_authentication.h index df0a20c51..9cbbffd2b 100644 --- a/src/manage_authentication.h +++ b/src/manage_authentication.h @@ -10,54 +10,12 @@ enum manage_authentication_rc GMA_ERR, }; -/** - * @brief manage_authentication_setup sets the pepper, count and prefix used - * by the authentication implementation. - * - * When pepper is a NULL pointer, prefix is a NULL pointer or count is 0 then - * the previous setting of that setting will be kept. - * - * This is mainly to allow easier configuration within gvmd.c so that it can - * used parameterized without restore the same information there. - * - * The initial defaults are set to no-pepper, COUNT_DEFAULT and PREFIX_DEFAULT - * of gvm-libs. - * - * @param[in] pepper - a static hidden addition to the randomely generated salt - * @param[in] pepper_size - the size of pepper; it must not larger then - * MAX_PEPPER_SIZE - * @param[in] count - the amount of rounds used to calculate the hash; if 0 then - * COUNT_DEFAULT will be used - * @param[in] prefix - the used algorithm, if NULL pointer then the most secure - * available algorithm will be used. - * - * @return GMA_SUCCESS when the settings are set or GMA_ERR if there was a - * failure. - */ enum manage_authentication_rc manage_authentication_setup (const char *pepper, unsigned int pepper_size, unsigned int count, char *prefix); -/** - * @brief creates a hash based on the settings set by - * manage_authentication_setup and the password. - * - * @param[in] passwod - the password to be hashed - * @return the hash or a NULL pointer on a failure. - * */ char * manage_authentication_hash (const char *password); -/** - * @brief manage_authentication_verify verifies given password with given hash. - * - * @param[in] password - the clear text password to be verified - * @param[in] hash - the stored hash to verify the password against. - * - * @return GMA_SUCCESS when password is valid, - * GMA_HASH_VALID_BUT_DATED when password is valid but a new hash - * should ne created and stored. - * GMA_HASH_INVALID when password is invalid - * GMA_ERR when an unexpected error occurs. - **/ + enum manage_authentication_rc manage_authentication_verify (const char *hash, const char *password); From 1690b38580c3b892bae49dcea07d648239bc61a4 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Fri, 7 May 2021 16:04:31 +0200 Subject: [PATCH 3/4] Fix typos in comments (cherry picked from commit 778bfa5ce70a053f20494324b7d759f5df03a87e) --- src/manage_authentication.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/manage_authentication.c b/src/manage_authentication.c index 22ff9e3d2..b5a5b918f 100644 --- a/src/manage_authentication.c +++ b/src/manage_authentication.c @@ -42,7 +42,7 @@ manage_authentication_setup (const char *pepper, unsigned int pepper_size, if (tmp == NULL) goto exit; - // ovly override pepper when pepper is initially set otherwise keep + // only override pepper when pepper is initially set otherwise keep // previous pepper for (i = 0; pepper != NULL && i < MAX_PEPPER_SIZE; i++) settings.pepper[i] = tmp->pepper[i]; @@ -59,7 +59,7 @@ manage_authentication_setup (const char *pepper, unsigned int pepper_size, * @brief creates a hash based on the settings set by * manage_authentication_setup and the password. * - * @param[in] passwod - the password to be hashed + * @param[in] password - the password to be hashed * @return the hash or a NULL pointer on a failure. * */ char * @@ -103,4 +103,3 @@ manage_authentication_verify (const char *hash, const char *password) return rc; } - From 0fd892afdc7dd7d746fdc2cff47baa5029a52c93 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Fri, 7 May 2021 16:56:39 +0200 Subject: [PATCH 4/4] Resolve conflict in .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index a522b8421..bef7e4064 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ build/ -<<<<<<< HEAD -======= tags .ccls ->>>>>>> ef9d161f3... Use pba authentication instead of authutils