diff --git a/.gitignore b/.gitignore index 332b72232..bef7e4064 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ tags +.ccls diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac1b41f5..f5d38dcf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,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 d88411289..4852cef54 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 @@ -433,6 +439,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 a5256cc9f..27999305f 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. * @@ -2040,6 +2088,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..b5a5b918f --- /dev/null +++ b/src/manage_authentication.c @@ -0,0 +1,105 @@ +#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}; + +/** + * @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) +{ + 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; + // 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]; + 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; +} + +/** + * @brief creates a hash based on the settings set by + * manage_authentication_setup and the password. + * + * @param[in] password - 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) +{ + 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..9cbbffd2b --- /dev/null +++ b/src/manage_authentication.h @@ -0,0 +1,23 @@ +#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, +}; + +enum manage_authentication_rc +manage_authentication_setup (const char *pepper, unsigned int pepper_size, + unsigned int count, char *prefix); +char * +manage_authentication_hash (const char *password); + +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 d18bfe206..169cdf7bd 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" @@ -16829,7 +16830,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; } @@ -16848,7 +16864,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 */ @@ -16917,7 +16933,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; } @@ -50384,7 +50420,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, @@ -50633,7 +50669,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 */ @@ -51738,7 +51774,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;