diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index e669d5a65..000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,31 +0,0 @@ -**What**: - - - -**Why**: - - - -**How did you test it**: - - - -**Checklist**: - - - - - -- [ ] Tests -- [ ] PR merge commit message adjusted diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index 808dfd75a..b72900665 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -56,7 +56,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . push: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index f0543cfe5..b122911a5 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -51,7 +51,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build and push Container image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . push: ${{ github.event_name != 'pull_request' && (github.ref_type == 'tag' || github.ref_name == 'main') }} diff --git a/.github/workflows/release-pontos-manually.yml b/.github/workflows/release-pontos-manually.yml deleted file mode 100644 index a717c35e4..000000000 --- a/.github/workflows/release-pontos-manually.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Manually release gvmd with pontos - -on: - workflow_dispatch: - inputs: - branch: - description: "Branch" - required: true - default: "main" - -jobs: - build-and-release: - name: Build and release with pontos - runs-on: "ubuntu-latest" - steps: - - name: Release with release action - uses: greenbone/actions/release@v2 - with: - conventional-commits: true - ref: ${{ github.event.inputs.branch }} - github-user: ${{ secrets.GREENBONE_BOT }} - github-user-mail: ${{ secrets.GREENBONE_BOT_MAIL }} - github-user-token: ${{ secrets.GREENBONE_BOT_TOKEN }} - gpg-key: ${{ secrets.GPG_KEY }} - gpg-fingerprint: ${{ secrets.GPG_FINGERPRINT }} - gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/release-pontos.yml b/.github/workflows/release-pontos.yml new file mode 100644 index 000000000..85da7c555 --- /dev/null +++ b/.github/workflows/release-pontos.yml @@ -0,0 +1,34 @@ +name: Release gvmd with pontos + +on: + pull_request: + types: [closed] + workflow_dispatch: + +jobs: + build-and-release: + name: Create a new release with pontos + # If the event is a workflow_dispatch or the label 'make release' is set and PR is closed because of a merge + if: (github.event_name == 'workflow_dispatch') || (contains( github.event.pull_request.labels.*.name, 'make release') && github.event.pull_request.merged == true) + runs-on: "ubuntu-latest" + steps: + - name: Setting the Reference + run: | + if [[ "${{ github.event_name }}" = "workflow_dispatch" ]]; then + echo "RELEASE_REF=${{ github.ref_name }}" >> $GITHUB_ENV + else + echo "RELEASE_REF=${{ github.base_ref }}" >> $GITHUB_ENV + fi + - name: Release with release action + uses: greenbone/actions/release@v2 + with: + python-version: "3.10" + conventional-commits: true + github-user: ${{ secrets.GREENBONE_BOT }} + github-user-mail: ${{ secrets.GREENBONE_BOT_MAIL }} + github-user-token: ${{ secrets.GREENBONE_BOT_TOKEN }} + gpg-key: ${{ secrets.GPG_KEY }} + gpg-fingerprint: ${{ secrets.GPG_FINGERPRINT }} + gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }} + strategy: calendar + ref: ${{ env.RELEASE_REF }} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e815c7de..67b95dbde 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,7 +45,7 @@ find_package (PostgreSQL REQUIRED) if (NOT PostgreSQL_FOUND) message (SEND_ERROR "The PostgreSQL library is required.") endif (NOT PostgreSQL_FOUND) -string (REGEX MATCH "^[ \t]*\([0-9]+\)\\.\([0-9]+\)\(.*\)" TEMP ${PostgreSQL_VERSION_STRING}) +string (REGEX MATCH "^[ \t]*\([0-9]+\)\\.\([0-9]+\)\(.*\)" TEMP "${PostgreSQL_VERSION_STRING}") if (NOT CMAKE_MATCH_1) message (SEND_ERROR "Error matching PostgreSQL version.") elseif ((CMAKE_MATCH_1 EQUAL 9 AND CMAKE_MATCH_2 LESS 6) @@ -127,7 +127,7 @@ add_executable (manage-utils-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -154,7 +154,7 @@ add_executable (manage-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -181,7 +181,7 @@ add_executable (manage-sql-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -208,7 +208,7 @@ add_executable (gmp-tickets-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tls_certificates.c) add_test (gmp-tickets-test gmp-tickets-test) @@ -234,7 +234,7 @@ add_executable (utils-test sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) @@ -263,7 +263,7 @@ add_executable (gvmd sql_pg.c manage_pg.c lsc_user.c lsc_crypt.c utils.c gmp.c gmp_base.c gmp_configs.c gmp_delete.c gmp_get.c - gmp_license.c + gmp_license.c gmp_logout.c gmp_port_lists.c gmp_report_formats.c gmp_tickets.c gmp_tls_certificates.c) diff --git a/src/gmp.c b/src/gmp.c index e2411b820..caa4acf48 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -89,6 +89,7 @@ #include "gmp_get.h" #include "gmp_configs.h" #include "gmp_license.h" +#include "gmp_logout.h" #include "gmp_port_lists.h" #include "gmp_report_formats.h" #include "gmp_tickets.h" @@ -4322,6 +4323,7 @@ typedef enum CLIENT_GET_VERSION_AUTHENTIC, CLIENT_GET_VULNS, CLIENT_HELP, + CLIENT_LOGOUT, CLIENT_MODIFY_ALERT, CLIENT_MODIFY_ALERT_ACTIVE, CLIENT_MODIFY_ALERT_COMMENT, @@ -5696,6 +5698,13 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, &help_data->type); set_client_state (CLIENT_HELP); } + else if (strcasecmp ("LOGOUT", element_name) == 0) + { + logout_start (gmp_parser, + attribute_names, + attribute_values); + set_client_state (CLIENT_LOGOUT); + } else if (strcasecmp ("MODIFY_ALERT", element_name) == 0) { modify_alert_data->event_data = make_array (); @@ -7684,6 +7693,10 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, set_read_over (gmp_parser); break; + case CLIENT_LOGOUT: + logout_element_start (gmp_parser, element_name, + attribute_names, attribute_values); + break; case CLIENT_MODIFY_LICENSE: modify_license_element_start (gmp_parser, element_name, attribute_names, attribute_values); @@ -22197,7 +22210,14 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, } set_client_state (CLIENT_AUTHENTIC); break; - + case CLIENT_LOGOUT: + { + if (logout_element_end (gmp_parser, error, element_name)) + { + set_client_state (CLIENT_TOP); + } + break; + } case CLIENT_MODIFY_ALERT: { event_t event; diff --git a/src/gmp_logout.c b/src/gmp_logout.c new file mode 100644 index 000000000..8cc221610 --- /dev/null +++ b/src/gmp_logout.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2021-2022 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file gmp_logout.c + * @brief GVM GMP layer: Logout handling + * + * This includes functions for GMP handling of the user logout. + */ + +#include "gmp_logout.h" +#include "manage.h" + +typedef struct +{ + context_data_t *context; ///< XML parser context. +} logout_t; + +static logout_t logout_data; + +/* + * @brief Reset command data. + */ +static void +logout_reset () +{ + if (logout_data.context->first) + { + free_entity (logout_data.context->first->data); + g_slist_free_1 (logout_data.context->first); + } + g_free (logout_data.context); + memset (&logout_data, 0, sizeof (logout_t)); +} + +/** + * @brief Start a command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +logout_start (gmp_parser_t *gmp_parser, + const gchar **attribute_names, + const gchar **attribute_values) +{ + memset (&logout_data, 0, sizeof (logout_t)); + logout_data.context = g_malloc0 (sizeof (context_data_t)); + logout_element_start (gmp_parser, "logout", + attribute_names, attribute_values); +} + +/** + * @brief Start element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] name Element name. + * @param[in] attribute_names All attribute names. + * @param[in] attribute_values All attribute values. + */ +void +logout_element_start (gmp_parser_t *gmp_parser, + const gchar *name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + xml_handle_start_element (logout_data.context, name, + attribute_names, attribute_values); +} + +/** + * @brief Execute command. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + */ +static void +logout_run (gmp_parser_t *gmp_parser, + GError **error) +{ + logout_user (); + SEND_TO_CLIENT_OR_FAIL (""); + logout_reset (); +} + +/** + * @brief End element. + * + * @param[in] gmp_parser GMP parser. + * @param[in] error Error parameter. + * @param[in] name Element name. + * + * @return 0 success, 1 command finished. + */ +int +logout_element_end (gmp_parser_t *gmp_parser, + GError **error, + const gchar *name) +{ + xml_handle_end_element (logout_data.context, name); + if (logout_data.context->done) + { + logout_run (gmp_parser, error); + return 1; + } + return 0; +} diff --git a/src/gmp_logout.h b/src/gmp_logout.h new file mode 100644 index 000000000..2be7900e7 --- /dev/null +++ b/src/gmp_logout.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2021-2022 Greenbone Networks GmbH + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "gmp_base.h" + +#include +#include + +void +logout_start (gmp_parser_t *, + const gchar **, + const gchar **); + +void +logout_element_start (gmp_parser_t *, const gchar *, + const gchar **, const gchar **); + +int +logout_element_end (gmp_parser_t *, GError **, const gchar *); diff --git a/src/gvmd.c b/src/gvmd.c index 80fe5919a..9adf06c4f 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -1822,6 +1822,7 @@ gvmd (int argc, char** argv, char *env[]) { /* Process options. */ + static int auth_timeout = 15; static gboolean check_alerts = FALSE; static gboolean migrate_database = FALSE; static gboolean encrypt_all_credentials = FALSE; @@ -1895,6 +1896,11 @@ gvmd (int argc, char** argv, char *env[]) GOptionContext *option_context; static GOptionEntry option_entries[] = { + { "auth-timeout", '\0', 0, G_OPTION_ARG_INT, + &auth_timeout, + "Sets the authentication timeout time for the cached authentication." + " Defaults to 15 minutes.", + "" }, { "broker-address", '\0', 0, G_OPTION_ARG_STRING, &broker_address, "Sets the address for the publish-subscribe message (MQTT) broker." @@ -2266,6 +2272,9 @@ gvmd (int argc, char** argv, char *env[]) client_watch_interval = 0; } + /* Set authentication cache timeout */ + set_auth_timeout (auth_timeout); + /* Set broker address */ set_broker_address (broker_address ? broker_address diff --git a/src/manage.c b/src/manage.c index 6b2d6d2af..db2b77a50 100644 --- a/src/manage.c +++ b/src/manage.c @@ -162,6 +162,12 @@ */ #define MAX_HOSTS_DEFAULT "20" +/** + * @brief Number of minutes until the authentication cache is deleted + * if the session is idle. + */ +static int auth_timeout = 0; + /** * @brief Address of the broker used for publish-subscribe messaging (MQTT). */ @@ -5997,6 +6003,31 @@ manage_gvmd_data_feed_dirs_exist () && report_formats_feed_dir_exists (); } +/** + * @brief Get the authentication cache timeout. + * + * @return The current timeout in minutes. + */ +int +get_auth_timeout () +{ + return auth_timeout; +} + +/** + * @brief Set the authentication cache timeout. + * + * @param new_timeout The new timeout in minutes. + */ +void +set_auth_timeout (int new_timeout) +{ + if (new_timeout < 1) + auth_timeout = 1; + else + auth_timeout = new_timeout; +} + /** * @brief Get the publish-subscribe messaging (MQTT) broker address. * diff --git a/src/manage.h b/src/manage.h index 903ed7053..62031f9a7 100644 --- a/src/manage.h +++ b/src/manage.h @@ -199,6 +199,8 @@ extern credentials_t current_credentials; int authenticate (credentials_t*); +void +logout_user (); /* Database. */ @@ -3614,6 +3616,12 @@ manage_gvmd_data_feed_dir_exists (const char *); gboolean manage_gvmd_data_feed_dirs_exist (); +int +get_auth_timeout (); + +void +set_auth_timeout (int); + const gchar * get_broker_address (); diff --git a/src/manage_pg.c b/src/manage_pg.c index d38ea0927..95fd82230 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -3008,7 +3008,7 @@ db_extension_available (const char *name) } /** - * @brief Clean up old SQL functions now incliuded in the pg-gvm extension. + * @brief Clean up old SQL functions now included in the pg-gvm extension. */ void cleanup_old_sql_functions () diff --git a/src/manage_sql.c b/src/manage_sql.c index 093604dc7..fe7f998da 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -16653,6 +16653,8 @@ manage_reset_currents () { global_current_report = 0; current_scanner_task = (task_t) 0; + sql ("RESET \"gvmd.user.id\";"); + sql ("RESET \"gvmd.tz_override\";"); free_credentials (¤t_credentials); } @@ -16924,8 +16926,8 @@ auth_cache_find (const char *username, const char *password, int method) quoted_username = sql_quote (username); hash = sql_string ("SELECT hash FROM auth_cache WHERE username = '%s'" - " AND method = %i AND creation_time >= m_now () - 300;", - quoted_username, method); + " AND method = %i AND creation_time >= m_now () - %d;", + quoted_username, method, get_auth_timeout()*60); g_free (quoted_username); if (!hash) return -1; @@ -16968,7 +16970,33 @@ auth_cache_insert (const char *username, const char *password, int method) sql ("INSERT INTO auth_cache (username, hash, method, creation_time)" " VALUES ('%s', '%s', %i, m_now ());", quoted_username, hash, method); /* Cleanup cache */ - sql ("DELETE FROM auth_cache WHERE creation_time < m_now () - 300"); + sql ("DELETE FROM auth_cache WHERE creation_time < m_now () - %d", + get_auth_timeout()*60); +} + +/** + * @brief Delete the credentials of a user from the authentication + * cache. + * + * @param[in] username Username. + */ +static void +auth_cache_delete (const char *username) +{ + sql ("DELETE from auth_cache WHERE username = '%s'", username); +} + +/** + * @brief Refresh the authentication of a user in the authentication + * cache. + * + * @param[in] username Username. + */ +static void +auth_cache_refresh (const char *username) +{ + sql ("UPDATE auth_cache SET creation_time = m_now() WHERE username = '%s'", + username); } /** @@ -16999,7 +17027,10 @@ authenticate_any_method (const gchar *username, const gchar *password, *auth_method = AUTHENTICATION_METHOD_LDAP_CONNECT; /* Search the LDAP authentication cache first. */ if (auth_cache_find (username, password, 0) == 0) - return 0; + { + auth_cache_refresh (username); + return 0; + } manage_get_ldap_info (NULL, &host, &authdn, &allow_plaintext, &cacert); info = ldap_auth_info_new (host, authdn, allow_plaintext); @@ -17021,7 +17052,10 @@ authenticate_any_method (const gchar *username, const gchar *password, *auth_method = AUTHENTICATION_METHOD_RADIUS_CONNECT; if (auth_cache_find (username, password, 1) == 0) - return 0; + { + auth_cache_refresh (username); + return 0; + } manage_get_radius_info (NULL, &host, &key); ret = radius_authenticate (host, key, username, password); @@ -17032,6 +17066,11 @@ authenticate_any_method (const gchar *username, const gchar *password, return ret; } *auth_method = AUTHENTICATION_METHOD_FILE; + if (auth_cache_find (username, password, 2) == 0) + { + auth_cache_refresh (username); + return 0; + } hash = manage_user_hash (username); ret = manage_authentication_verify(hash, password); switch(ret){ @@ -17043,9 +17082,11 @@ authenticate_any_method (const gchar *username, const gchar *password, hash = manage_authentication_hash(password); sql ("UPDATE users SET password = '%s', modification_time = m_now () WHERE name = '%s';", hash, username); + auth_cache_insert (username, password, 2); ret = 0; break; case GMA_SUCCESS: + auth_cache_insert (username, password, 2); ret = 0; break; default: @@ -17131,6 +17172,18 @@ authenticate (credentials_t* credentials) return 1; } +/** + * @brief Perform actions necessary at user logout + * + * @param[in] username Username. + */ +void +logout_user () +{ + auth_cache_delete(current_credentials.username); + manage_reset_currents (); +} + /** * @brief Return number of resources of a certain type for current user. * diff --git a/tools/gvm-lsc-deb-creator b/tools/gvm-lsc-deb-creator index 236c541e9..8970a3ec2 100755 --- a/tools/gvm-lsc-deb-creator +++ b/tools/gvm-lsc-deb-creator @@ -161,7 +161,7 @@ COPYRIGHT_FILE="${DOC_DATA_DIR}/copyright" # Create data archive cd "${DATA_DIR}" -tar -C "${DATA_DIR}" -acfz "../data.tar.gz" "${HOME_SUBDIR}" "${DOC_SUBDIR}" +tar -C "${DATA_DIR}" -z -cf "../data.tar.gz" "${HOME_SUBDIR}" "${DOC_SUBDIR}" #