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}"
#