From d2c21eb296b1630be5f6092c3faafd626512082b Mon Sep 17 00:00:00 2001
From: ozgen
Date: Thu, 14 Aug 2025 10:16:12 +0200
Subject: [PATCH 1/6] Change: extend agent data with new fields from Agent
Controller
---
src/CMakeLists.txt | 2 +-
src/gmp_agents.c | 19 ++--
src/manage_agents.c | 47 ++++++---
src/manage_agents.h | 24 ++++-
src/manage_pg.c | 9 +-
src/manage_sql_agents.c | 155 ++++++++++++++++++++++--------
src/manage_sql_agents.h | 41 +++++---
src/schema_formats/XML/GMP.xml.in | 74 +++++++++++---
8 files changed, 280 insertions(+), 91 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7ec0d31028..d8a51cc487 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -44,7 +44,7 @@ if(ENABLE_AGENTS)
pkg_check_modules(
LIBGVM_AGENT_CONTROLLER
REQUIRED
- libgvm_agent_controller>=22.23
+ libgvm_agent_controller>=22.24
)
else(ENABLE_AGENTS)
message(STATUS "ENABLE_AGENTS flag is not enabled")
diff --git a/src/gmp_agents.c b/src/gmp_agents.c
index ecda646a84..78abca5356 100644
--- a/src/gmp_agents.c
+++ b/src/gmp_agents.c
@@ -147,7 +147,12 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
"%i"
"%s"
"%s"
- "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%i"
""
"%s"
"",
@@ -158,7 +163,12 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
agent_iterator_heartbeat_interval (&agents),
agent_iterator_connection_status (&agents),
iso_if_time (agent_iterator_last_update (&agents)),
- agent_iterator_schedule (&agents),
+ agent_iterator_config (&agents),
+ agent_iterator_updater_version (&agents),
+ agent_iterator_agent_version (&agents),
+ agent_iterator_operating_system (&agents),
+ agent_iterator_architecture (&agents),
+ agent_iterator_update_to_latest (&agents),
agent_scanner_uuid ? agent_scanner_uuid : "",
agent_scanner_name ? agent_scanner_name : "");
@@ -356,11 +366,6 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
update->min_interval = atoi (entity_text (e));
if ((e = entity_child (root, "heartbeat_interval")))
update->heartbeat_interval = atoi (entity_text (e));
- if ((e = entity_child (root, "schedule")))
- {
- update->schedule_config = agent_controller_config_schedule_new ();
- update->schedule_config->schedule = g_strdup (entity_text (e));
- }
if ((e = entity_child (root, "comment")))
comment = g_strdup (entity_text (e));
diff --git a/src/manage_agents.c b/src/manage_agents.c
index fc0544d405..016123be91 100644
--- a/src/manage_agents.c
+++ b/src/manage_agents.c
@@ -91,11 +91,12 @@ convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t lis
dest->heartbeat_interval = src->heartbeat_interval;
dest->connection_status = g_strdup (src->connection_status);
dest->last_update_agent_control = src->last_update;
-
- if (src->schedule_config && src->schedule_config->schedule)
- dest->schedule = g_strdup (src->schedule_config->schedule);
- else
- dest->schedule = g_strdup ("");
+ dest->config = g_strdup (src->config);
+ dest->updater_version = g_strdup (src->updater_version);
+ dest->agent_version = g_strdup (src->agent_version);
+ dest->operating_system = g_strdup (src->operating_system);
+ dest->architecture = g_strdup (src->architecture);
+ dest->update_to_latest = src->update_to_latest;
dest->scanner = scanner;
@@ -163,13 +164,12 @@ convert_agent_data_list_to_agent_control_list (agent_data_list_t list,
dest->heartbeat_interval = src->heartbeat_interval;
dest->connection_status = g_strdup (src->connection_status);
dest->last_update = src->last_update_agent_control;
-
- // Schedule config
- if (src->schedule && strlen (src->schedule) > 0)
- {
- dest->schedule_config = agent_controller_config_schedule_new ();
- dest->schedule_config->schedule = g_strdup (src->schedule);
- }
+ dest->config = src->config;
+ dest->updater_version = g_strdup (src->updater_version);
+ dest->agent_version = g_strdup (src->agent_version);
+ dest->operating_system = g_strdup (src->operating_system);
+ dest->architecture = g_strdup (src->architecture);
+ dest->last_update = src->update_to_latest;
// IP addresses
if (src->ip_addresses && src->ip_addresses->count > 0)
@@ -441,8 +441,20 @@ agent_data_free (agent_data_t data)
if (data->connection_status)
g_free (data->connection_status);
- if (data->schedule)
- g_free (data->schedule);
+ if (data->config)
+ g_free (data->config);
+
+ if (data->updater_version)
+ g_free (data->updater_version);
+
+ if (data->agent_version)
+ g_free (data->agent_version);
+
+ if (data->operating_system)
+ g_free (data->operating_system);
+
+ if (data->architecture)
+ g_free (data->architecture);
if (data->comment)
g_free (data->comment);
@@ -580,10 +592,15 @@ get_agents_by_scanner_and_uuids (scanner_t scanner,
agent->heartbeat_interval = agent_iterator_heartbeat_interval (&iterator);
agent->connection_status = g_strdup (agent_iterator_connection_status (&iterator));
agent->last_update_agent_control = agent_iterator_last_update (&iterator);
- agent->schedule = g_strdup (agent_iterator_schedule (&iterator));
+ agent->config = g_strdup (agent_iterator_config (&iterator));
agent->comment = g_strdup (get_iterator_comment (&iterator));
agent->creation_time = get_iterator_creation_time (&iterator);
agent->modification_time = get_iterator_modification_time (&iterator);
+ agent->updater_version = g_strdup (agent_iterator_updater_version (&iterator));
+ agent->agent_version = g_strdup (agent_iterator_agent_version (&iterator));
+ agent->operating_system = g_strdup (agent_iterator_operating_system (&iterator));
+ agent->architecture = g_strdup (agent_iterator_architecture (&iterator));
+ agent->update_to_latest = agent_iterator_update_to_latest (&iterator);
agent->scanner = scanner;
agent->owner = get_iterator_owner (&iterator);
agent->uuid = g_strdup (get_iterator_uuid (&iterator));
diff --git a/src/manage_agents.h b/src/manage_agents.h
index ad278d484e..34414ad920 100644
--- a/src/manage_agents.h
+++ b/src/manage_agents.h
@@ -79,10 +79,15 @@ struct agent_data
time_t creation_time;
time_t modification_time;
time_t last_update_agent_control;
- gchar *schedule;
+ gchar *config;
gchar *comment;
user_t owner;
scanner_t scanner;
+ gchar *updater_version;
+ gchar *agent_version;
+ gchar *operating_system;
+ gchar *architecture;
+ int update_to_latest;
};
typedef struct agent_data *agent_data_t;
@@ -170,7 +175,7 @@ const gchar *
agent_iterator_connection_status (iterator_t *iterator);
const gchar *
-agent_iterator_schedule (iterator_t *iterator);
+agent_iterator_config (iterator_t *iterator);
int
agent_iterator_authorized (iterator_t *iterator);
@@ -187,6 +192,21 @@ agent_iterator_last_update (iterator_t *iterator);
scanner_t
agent_iterator_scanner (iterator_t *iterator);
+const gchar *
+agent_iterator_updater_version (iterator_t *iterator);
+
+const gchar *
+agent_iterator_agent_version (iterator_t *iterator);
+
+const gchar *
+agent_iterator_operating_system (iterator_t *iterator);
+
+const gchar *
+agent_iterator_architecture (iterator_t *iterator);
+
+int
+agent_iterator_update_to_latest (iterator_t *iterator);
+
int
agent_count (const get_data_t *get);
diff --git a/src/manage_pg.c b/src/manage_pg.c
index 2c22953116..ba429ce11b 100644
--- a/src/manage_pg.c
+++ b/src/manage_pg.c
@@ -2237,11 +2237,16 @@ create_tables ()
" heartbeat_interval INTEGER,"
" connection_status TEXT,"
" last_update INTEGER,"
- " schedule TEXT,"
+ " config TEXT,"
" owner INTEGER REFERENCES users (id) ON DELETE RESTRICT,"
" comment TEXT,"
" creation_time INTEGER,"
- " modification_time INTEGER);");
+ " modification_time INTEGER,"
+ " updater_version TEXT,"
+ " agent_version TEXT,"
+ " operating_system TEXT,"
+ " architecture TEXT,"
+ " update_to_latest INTEGER);");
sql ("CREATE TABLE IF NOT EXISTS agent_ip_addresses"
" (id SERIAL PRIMARY KEY,"
diff --git a/src/manage_sql_agents.c b/src/manage_sql_agents.c
index c0bfe9af71..87ca9b1f8b 100644
--- a/src/manage_sql_agents.c
+++ b/src/manage_sql_agents.c
@@ -80,31 +80,47 @@ agent_column_exists (const gchar *column_name, const gchar *value)
static void
update_existing_agent (agent_data_t agent)
{
- gchar *insert_hostname = sql_insert (agent->hostname);
- gchar *insert_connection_status = sql_insert (agent->connection_status);
- gchar *insert_schedule = sql_insert (agent->schedule);
- gchar *insert_agent_id = sql_insert (agent->agent_id);
-
- sql ("UPDATE agents SET hostname = %s, authorized = %d, min_interval = %d,"
- " heartbeat_interval = %d, connection_status = %s, last_update = %ld,"
- " schedule = %s, owner = %u, modification_time = %ld, scanner = %llu "
- " WHERE agent_id = %s;",
- insert_hostname,
- agent->authorized,
- agent->min_interval,
- agent->heartbeat_interval,
- insert_connection_status,
- agent->last_update_agent_control,
- insert_schedule,
- agent->owner,
- agent->modification_time,
- agent->scanner,
- insert_agent_id);
+ gchar *insert_hostname = sql_insert (agent->hostname);
+ gchar *insert_connection_status = sql_insert (agent->connection_status);
+ gchar *insert_config = sql_insert (agent->config);
+ gchar *insert_agent_id = sql_insert (agent->agent_id);
+ gchar *insert_updater_version = sql_insert (agent->updater_version);
+ gchar *insert_agent_version = sql_insert (agent->agent_version);
+ gchar *insert_operating_system = sql_insert (agent->operating_system);
+ gchar *insert_architecture = sql_insert (agent->architecture);
+
+ sql ("UPDATE agents SET "
+ " hostname = %s,"
+ " authorized = %d,"
+ " min_interval = %d,"
+ " heartbeat_interval = %d,"
+ " connection_status = %s,"
+ " last_update = %ld,"
+ " config = %s,"
+ " owner = %u,"
+ " modification_time = %ld,"
+ " scanner = %llu,"
+ " updater_version = %s,"
+ " agent_version = %s,"
+ " operating_system = %s,"
+ " architecture = %s,"
+ " update_to_latest = %d"
+ " WHERE agent_id = %s;",
+ insert_hostname, agent->authorized, agent->min_interval,
+ agent->heartbeat_interval, insert_connection_status,
+ agent->last_update_agent_control, insert_config, agent->owner,
+ agent->modification_time, agent->scanner, insert_updater_version,
+ insert_agent_version, insert_operating_system, insert_architecture,
+ agent->update_to_latest, insert_agent_id);
g_free (insert_hostname);
g_free (insert_connection_status);
- g_free (insert_schedule);
+ g_free (insert_config);
g_free (insert_agent_id);
+ g_free (insert_updater_version);
+ g_free (insert_agent_version);
+ g_free (insert_operating_system);
+ g_free (insert_architecture);
}
/**
@@ -122,14 +138,21 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
if (agent->uuid == NULL)
return;
}
- gchar *escaped_hostname = sql_copy_escape (agent->hostname);
- gchar *escaped_connection_status = sql_copy_escape (agent->connection_status);
- gchar *escaped_schedule = sql_copy_escape (agent->schedule);
- gchar *escaped_comment = sql_copy_escape ("");
+
+ gchar *escaped_hostname = sql_copy_escape (agent->hostname);
+ gchar *escaped_connection_status = sql_copy_escape (agent->connection_status);
+ gchar *escaped_config = sql_copy_escape (agent->config);
+ gchar *escaped_comment = sql_copy_escape ("");
+
+ gchar *escaped_updater_version = sql_copy_escape (agent->updater_version);
+ gchar *escaped_agent_version = sql_copy_escape (agent->agent_version);
+ gchar *escaped_operating_system = sql_copy_escape (agent->operating_system);
+ gchar *escaped_architecture = sql_copy_escape (agent->architecture);
db_copy_buffer_append_printf (
buffer,
- "%s\t%s\t%s\t%s\t%d\t%d\t%d\t%s\t%ld\t%s\t%u\t%s\t%ld\t%ld\t%llu\n",
+ "%s\t%s\t%s\t%s\t%d\t%d\t%d\t%s\t%ld\t%s\t%u\t%s\t%ld\t%ld\t%llu"
+ "\t%s\t%s\t%s\t%s\t%d\n",
agent->uuid,
agent->name,
agent->agent_id,
@@ -139,18 +162,27 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
agent->heartbeat_interval,
escaped_connection_status,
agent->last_update_agent_control,
- escaped_schedule,
+ escaped_config,
agent->owner,
escaped_comment,
time (NULL), // creation time
agent->modification_time,
- agent->scanner
+ agent->scanner,
+ escaped_updater_version,
+ escaped_agent_version,
+ escaped_operating_system,
+ escaped_architecture,
+ agent->update_to_latest ? 1 : 0
);
g_free (escaped_hostname);
g_free (escaped_connection_status);
- g_free (escaped_schedule);
+ g_free (escaped_config);
g_free (escaped_comment);
+ g_free (escaped_updater_version);
+ g_free (escaped_agent_version);
+ g_free (escaped_operating_system);
+ g_free (escaped_architecture);
}
/**
@@ -258,13 +290,15 @@ sync_agents_from_data_list (agent_data_list_t agent_list)
int status = 0;
db_copy_buffer_init (
- &agent_buffer,
- 64 * 1024,
- "COPY agents (uuid, name, agent_id, hostname, authorized, min_interval, heartbeat_interval,"
- " connection_status, last_update, schedule, owner, comment, creation_time,"
- " modification_time, scanner) FROM STDIN;"
- );
-
+ &agent_buffer, 64 * 1024,
+ "COPY agents ("
+ " uuid, name, agent_id, hostname, authorized, min_interval, "
+ "heartbeat_interval,"
+ " connection_status, last_update, config, owner, comment, creation_time,"
+ " modification_time, scanner, updater_version, agent_version, "
+ "operating_system,"
+ " architecture, update_to_latest"
+ ") FROM STDIN;");
db_copy_buffer_init (
&ip_buffer,
@@ -522,10 +556,10 @@ agent_iterator_last_update (iterator_t *iterator)
}
/**
- * @brief Retrieve schedule string of current agent.
+ * @brief Retrieve config string of current agent.
*/
const char *
-agent_iterator_schedule (iterator_t *iterator)
+agent_iterator_config (iterator_t *iterator)
{
return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 7);
}
@@ -539,6 +573,51 @@ agent_iterator_scanner (iterator_t *iterator)
return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 8);
}
+/**
+ * @brief Retrieve updater version of current agent.
+ */
+const char *
+agent_iterator_updater_version (iterator_t *iterator)
+{
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 9);
+}
+
+/**
+ * @brief Retrieve agent version of current agent.
+ */
+const char *
+agent_iterator_agent_version (iterator_t *iterator)
+{
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 10);
+}
+
+/**
+ * @brief Retrieve operating system of current agent.
+ */
+const char *
+agent_iterator_operating_system (iterator_t *iterator)
+{
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 11);
+}
+
+/**
+ * @brief Retrieve architecture system of current agent.
+ */
+const char *
+agent_iterator_architecture (iterator_t *iterator)
+{
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 12);
+}
+
+/**
+ * @brief Retrieve latest update status of current agent.
+ */
+int
+agent_iterator_update_to_latest (iterator_t *iterator)
+{
+ return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 13);
+}
+
/**
* @brief Count number of agents in the database based on filter.
*
diff --git a/src/manage_sql_agents.h b/src/manage_sql_agents.h
index 01a2eab386..6c95ee22c6 100644
--- a/src/manage_sql_agents.h
+++ b/src/manage_sql_agents.h
@@ -23,20 +23,26 @@
/**
* @brief Agent iterator columns.
*/
-#define AGENT_ITERATOR_COLUMNS \
-{ \
- GET_ITERATOR_COLUMNS (agents), \
- { "agent_id", NULL, KEYWORD_TYPE_STRING }, \
- { "hostname", NULL, KEYWORD_TYPE_STRING }, \
- { "authorized", NULL, KEYWORD_TYPE_INTEGER }, \
- { "min_interval", NULL, KEYWORD_TYPE_INTEGER }, \
- { "heartbeat_interval", NULL, KEYWORD_TYPE_INTEGER }, \
- { "connection_status", NULL, KEYWORD_TYPE_STRING }, \
- { "last_update", NULL, KEYWORD_TYPE_INTEGER }, \
- { "schedule", NULL, KEYWORD_TYPE_STRING }, \
- { "scanner", NULL, KEYWORD_TYPE_INTEGER }, \
- { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \
-}
+#define AGENT_ITERATOR_COLUMNS \
+ { \
+ GET_ITERATOR_COLUMNS (agents), {"agent_id", NULL, KEYWORD_TYPE_STRING}, \
+ {"hostname", NULL, KEYWORD_TYPE_STRING}, \
+ {"authorized", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"min_interval", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"heartbeat_interval", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"connection_status", NULL, KEYWORD_TYPE_STRING}, \
+ {"last_update", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"config", NULL, KEYWORD_TYPE_STRING}, \
+ {"scanner", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"updater_version", NULL, KEYWORD_TYPE_STRING}, \
+ {"agent_version", NULL, KEYWORD_TYPE_STRING}, \
+ {"operating_system", NULL, KEYWORD_TYPE_STRING}, \
+ {"architecture", NULL, KEYWORD_TYPE_STRING}, \
+ {"update_to_latest", NULL, KEYWORD_TYPE_INTEGER}, \
+ { \
+ NULL, NULL, KEYWORD_TYPE_UNKNOWN \
+ } \
+ }
/**
* @brief Filter columns for agent iterator.
@@ -53,12 +59,17 @@
"heartbeat_interval", \
"connection_status", \
"last_update", \
- "schedule", \
+ "config", \
"comment", \
"creation_time", \
"modification_time", \
"owner", \
"id", \
+ "updater_version", \
+ "agent_version", \
+ "operating_system", \
+ "architecture", \
+ "update_to_latest", \
NULL \
}
diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in
index a79f127051..58c96ac4fa 100644
--- a/src/schema_formats/XML/GMP.xml.in
+++ b/src/schema_formats/XML/GMP.xml.in
@@ -9336,7 +9336,7 @@ END:VCALENDAR
The response includes detailed information about each agent, including metadata,
- status, schedule, scanner association, and IP addresses.
+ status, config, scanner association, and IP addresses.
@@ -9421,9 +9421,34 @@ END:VCALENDAR
Last time the agent was updated
- schedule
+ config
+ text
+ Agent scan config
+
+
+ updater_version
text
- Scheduled update interval
+ Updater version string
+
+
+ agent_version
+ text
+ Agent version string
+
+
+ operating_system
+ text
+ Operating system
+
+
+ architecture
+ text
+ CPU architecture (e.g., amd64)
+
+
+ update_to_latest
+ integer
+ Update-to-latest flag (1/0)
comment
@@ -9502,6 +9527,11 @@ END:VCALENDAR
schedule
scanner
ip
+ updater_version
+ agent_version
+ operating_system
+ architecture
+ update_to_latest
owner
@@ -9618,6 +9648,31 @@ END:VCALENDAR
IP addresses of the agent
text
+
+ updater_version
+ Updater version string (may be empty)
+ text
+
+
+ agent_version
+ Agent version string (may be empty)
+ text
+
+
+ operating_system
+ Operating system (may be empty)
+ text
+
+
+ architecture
+ CPU architecture (e.g., amd64)
+ text
+
+
+ update_to_latest
+ Flag to update to latest version (1/0)
+ integer
+
filters
@@ -9747,6 +9802,11 @@ END:VCALENDAR
192.168.79.157
fe80::fe3e:acb9:1b5b:27da
192.168.1.11
+ 1.2.3
+ 0.9.0
+ Linux
+ amd64
+ 0
first=1 rows=10 sort=name
@@ -29189,7 +29249,6 @@ END:VCALENDAR
authorized
min_interval
heartbeat_interval
- schedule
comment
@@ -29227,12 +29286,6 @@ END:VCALENDAR
integer
0
-
- schedule
- Execution schedule string (e.g., "@every 12h")
- text
- 0
-
comment
Optional user-supplied comment
@@ -29263,7 +29316,6 @@ END:VCALENDAR
1
1000
0
- @every 12h
example update
From 3a0ffe3541ee0315c20f89b3688eb6b22e8d6873 Mon Sep 17 00:00:00 2001
From: ozgen
Date: Thu, 21 Aug 2025 13:21:55 +0200
Subject: [PATCH 2/6] Change: extend agent data with scan agent config, Add
modify_agent_control_scan_config
---
src/CMakeLists.txt | 2 +
src/gmp.c | 110 +++-
src/gmp_agent_control_scan_agent_config.c | 342 +++++++++++
src/gmp_agent_control_scan_agent_config.h | 41 ++
src/gmp_agents.c | 693 ++++++++++++++--------
src/gmp_agents.h | 21 +-
src/manage.h | 1 +
src/manage_agent_common.c | 107 +++-
src/manage_agent_common.h | 26 +-
src/manage_agent_control_scan_config.c | 97 +++
src/manage_agent_control_scan_config.h | 28 +
src/manage_agents.c | 318 +++++-----
src/manage_agents.h | 72 +--
src/manage_commands.c | 1 +
src/manage_pg.c | 3 +-
src/manage_sql_agents.c | 332 +++++------
src/manage_sql_agents.h | 45 +-
src/schema_formats/XML/GMP.xml.in | 520 ++++++++++++++--
18 files changed, 2040 insertions(+), 719 deletions(-)
create mode 100644 src/gmp_agent_control_scan_agent_config.c
create mode 100644 src/gmp_agent_control_scan_agent_config.h
create mode 100644 src/manage_agent_control_scan_config.c
create mode 100644 src/manage_agent_control_scan_config.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d8a51cc487..0533e2267d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -159,6 +159,7 @@ set(
manage_agent_groups.c
manage_agents.c
manage_agent_installers.c
+ manage_agent_control_scan_config.c
manage_alerts.c
manage_configs.c
manage_events.c
@@ -212,6 +213,7 @@ set(
set(
ALL_GMP_SRC
gmp.c
+ gmp_agent_control_scan_agent_config.c
gmp_agent_groups.c
gmp_agents.c
gmp_agent_installers.c
diff --git a/src/gmp.c b/src/gmp.c
index 9a0e7fe2bd..17b1d1e2d7 100644
--- a/src/gmp.c
+++ b/src/gmp.c
@@ -84,6 +84,7 @@
*/
#include "gmp.h"
+#include "gmp_agent_control_scan_agent_config.h"
#include "gmp_agent_groups.h"
#include "gmp_agents.h"
#include "gmp_base.h"
@@ -4610,6 +4611,7 @@ typedef enum
CLIENT_MODIFY_TARGET_SSH_LSC_CREDENTIAL_PORT,
CLIENT_MODIFY_TASK,
#if ENABLE_AGENTS
+ CLIENT_MODIFY_AGENT_CONTROL_SCAN_CONFIG,
CLIENT_MODIFY_TASK_AGENT_GROUP,
#endif /* ENABLE_AGENTS */
CLIENT_MODIFY_TASK_ALERT,
@@ -5965,6 +5967,14 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context,
set_client_state (CLIENT_LOGOUT);
}
#if ENABLE_AGENTS
+ else if (strcasecmp ("MODIFY_AGENT_CONTROL_SCAN_CONFIG", element_name)
+ == 0)
+ {
+ modify_agent_control_scan_config_start (gmp_parser,
+ attribute_names,
+ attribute_values);
+ set_client_state (CLIENT_MODIFY_AGENT_CONTROL_SCAN_CONFIG);
+ }
else if (strcasecmp ("MODIFY_AGENT_GROUP", element_name) == 0)
{
modify_agent_group_start (gmp_parser, attribute_names,
@@ -6329,6 +6339,13 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context,
ELSE_READ_OVER;
#if ENABLE_AGENTS
+ case CLIENT_MODIFY_AGENT_CONTROL_SCAN_CONFIG:
+ modify_agent_control_scan_config_element_start (
+ gmp_parser, element_name,
+ attribute_names,
+ attribute_values);
+ break;
+
case CLIENT_MODIFY_AGENT_GROUP:
modify_agent_group_element_start (gmp_parser, element_name,
attribute_names,
@@ -17477,6 +17494,89 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error)
g_free (md5_fingerprint);
g_free (issuer);
}
+#if ENABLE_AGENTS
+ int stype = scanner_iterator_type (&scanners);
+ if (stype == SCANNER_TYPE_AGENT_CONTROLLER
+ || stype == SCANNER_TYPE_AGENT_CONTROLLER_SENSOR)
+ {
+ scanner_t scanner_id = get_iterator_resource (&scanners);
+ agent_controller_scan_agent_config_t cfg =
+ get_agent_control_scan_config (scanner_id);
+
+ if (!cfg)
+ {
+ SEND_TO_CLIENT_OR_FAIL ("");
+ }
+ else
+ {
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* agent_control/retry */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL ("%d",
+ cfg->agent_control.retry.attempts);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_control.retry.delay_in_seconds);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_control.retry.max_jitter_in_seconds);
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* agent_script_executor */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL ("%d",
+ cfg->agent_script_executor.bulk_size)
+ ;
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.bulk_throttle_time_in_ms);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.indexer_dir_depth);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.period_in_seconds);
+
+ GPtrArray *cron = cfg->agent_script_executor.
+ scheduler_cron_time;
+ if (cron && cron->len > 0)
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ "");
+ for (guint i = 0; i < cron->len; ++i)
+ {
+ const char *item = (const char *) cron->pdata[i];
+ gchar *esc = g_markup_escape_text (
+ item ? item : "", -1);
+ SENDF_TO_CLIENT_OR_FAIL ("- %s
", esc);
+ g_free (esc);
+ }
+ SEND_TO_CLIENT_OR_FAIL ("");
+ }
+ else
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ "");
+ }
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* heartbeat */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->heartbeat.interval_in_seconds);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->heartbeat.miss_until_inactive);
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ agent_controller_scan_agent_config_free (cfg);
+ }
+ }
+#endif
}
credential_id = credential_uuid (scanner_iterator_credential (&scanners));
@@ -24334,7 +24434,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
/* Check for the right combination of target and config. */
- if (create_task_data->target_id == NULL
+ if (create_task_data->target_id == NULL
&& create_task_data->agent_group_id == NULL
&& create_task_data->oci_image_target_id == NULL)
{
@@ -24896,6 +24996,10 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
break;
}
#if ENABLE_AGENTS
+ case CLIENT_MODIFY_AGENT_CONTROL_SCAN_CONFIG:
+ if (modify_agent_control_scan_config_element_end (gmp_parser, error, element_name))
+ set_client_state (CLIENT_AUTHENTIC);
+ break;
case CLIENT_MODIFY_AGENT_GROUP:
if (modify_agent_group_element_end (gmp_parser, error, element_name))
set_client_state (CLIENT_AUTHENTIC);
@@ -29120,6 +29224,10 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context,
break;
#if ENABLE_AGENTS
+ case CLIENT_MODIFY_AGENT_CONTROL_SCAN_CONFIG:
+ modify_agent_control_scan_config_element_text (text, text_len);
+ break;
+
case CLIENT_MODIFY_AGENT_GROUP:
modify_agent_group_element_text (text, text_len);
break;
diff --git a/src/gmp_agent_control_scan_agent_config.c b/src/gmp_agent_control_scan_agent_config.c
new file mode 100644
index 0000000000..4dbf889b61
--- /dev/null
+++ b/src/gmp_agent_control_scan_agent_config.c
@@ -0,0 +1,342 @@
+/* Copyright (C) 2025 Greenbone AG
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * @file
+ * @brief GVM GMP layer: Modify Agent-Controller scan-agent configuration.
+ *
+ */
+
+#if ENABLE_AGENTS
+
+#include "gmp_agent_control_scan_agent_config.h"
+#include "manage_agent_control_scan_config.h"
+
+#include "manage_sql.h"
+
+
+#include
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "md gmp"
+
+/* ---------- MODIFY_AGENT_CONTROL_SCAN_CONFIG ---------- */
+/**
+ * @brief The modify_agent_control_scan_config command.
+ */
+typedef struct
+{
+ context_data_t *ctx;
+} modify_scan_cfg_ctx_t;
+
+static modify_scan_cfg_ctx_t modify_scan_cfg_ctx;
+
+/**
+ * @brief Reset command data.
+ */
+static void
+modify_agent_control_scan_config_reset (void)
+{
+ if (modify_scan_cfg_ctx.ctx && modify_scan_cfg_ctx.ctx->first)
+ {
+ free_entity (modify_scan_cfg_ctx.ctx->first->data);
+ g_slist_free_1 (modify_scan_cfg_ctx.ctx->first);
+ }
+ g_free (modify_scan_cfg_ctx.ctx);
+ memset (&modify_scan_cfg_ctx, 0, sizeof (modify_scan_cfg_ctx));
+}
+
+/**
+ * @brief Handle command start.
+ *
+ * @param[in] gmp_parser Active GMP parser (unused).
+ * @param[in] attribute_names Null-terminated array of attribute names.
+ * @param[in] attribute_values Null-terminated array of attribute values.
+ */
+void
+modify_agent_control_scan_config_start (gmp_parser_t *gmp_parser,
+ const gchar **attribute_names,
+ const gchar **attribute_values)
+{
+ (void) gmp_parser;
+ (void) attribute_names;
+ (void) attribute_values;
+ memset (&modify_scan_cfg_ctx, 0, sizeof (modify_scan_cfg_ctx));
+ modify_scan_cfg_ctx.ctx = g_malloc0 (sizeof (context_data_t));
+ xml_handle_start_element (modify_scan_cfg_ctx.ctx,
+ "modify_agent_control_scan_config",
+ attribute_names,
+ attribute_values);
+}
+
+/**
+ * @brief Handle command start element.
+ *
+ * @param[in] gmp_parser Active GMP parser (unused).
+ * @param[in] name Element name.
+ * @param[in] attribute_names Null-terminated array of attribute names.
+ * @param[in] attribute_values Null-terminated array of attribute values.
+ */
+void
+modify_agent_control_scan_config_element_start (gmp_parser_t *gmp_parser,
+ const gchar *name,
+ const gchar **attribute_names,
+ const gchar **attribute_values)
+{
+ xml_handle_start_element (modify_scan_cfg_ctx.ctx, name,
+ attribute_names, attribute_values);
+}
+
+/**
+ * @brief Add text to element in the command
+ *
+ * @param[in] text the text to add.
+ * @param[in] len the length of the text being added.
+ */
+void
+modify_agent_control_scan_config_element_text (const gchar *text, gsize len)
+{
+ xml_handle_text (modify_scan_cfg_ctx.ctx, text, len);
+}
+
+/**
+ * @brief Run modify_agent_control_scan_config command
+ *
+ * @param[in] gmp_parser current instance of GMP parser.
+ * @param[in] error the errors, if any.
+ */
+void
+modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error)
+{
+ const char *scanner_uuid;
+ entity_t root = (entity_t) modify_scan_cfg_ctx.ctx->first->data;
+
+ scanner_uuid = entity_attribute (root, "agent_control_id");
+
+ if (!scanner_uuid || !is_uuid (scanner_uuid))
+ {
+ SENDF_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agent_control_scan_config",
+ "Missing or invalid scanner UUID"));
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ scanner_t scanner = 0;
+ if (find_scanner_with_permission (scanner_uuid, &scanner, "get_scanners"))
+ {
+ if (send_find_error_to_client ("modify_agent_control_scan_config",
+ "scanner", NULL, gmp_parser))
+ error_send_to_client (error);
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+ if (scanner == 0)
+ {
+ if (send_find_error_to_client ("modify_agent_control_scan_config",
+ "scanner", NULL, gmp_parser))
+ error_send_to_client (error);
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ int type = scanner_type (scanner);
+ if (type != SCANNER_TYPE_AGENT_CONTROLLER &&
+ type != SCANNER_TYPE_AGENT_CONTROLLER_SENSOR)
+ {
+ SENDF_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agent_control_scan_config",
+ "Scanner is not an Agent Controller"));
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ /* … */
+ entity_t cfg_e = entity_child (root, "config");
+ if (!cfg_e)
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agent_control_scan_config",
+ "Missing "));
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ agent_controller_scan_agent_config_t cfg =
+ agent_controller_scan_agent_config_new ();
+ if (!cfg)
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_INTERNAL_ERROR ("modify_agent_control_scan_config"));
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ entity_t e = NULL;
+
+ /* … */
+ entity_t ac = entity_child (cfg_e, "agent_control");
+ if (ac)
+ {
+ entity_t retry = entity_child (ac, "retry");
+ if (retry)
+ {
+ e = entity_child (retry, "attempts");
+ if (e)
+ cfg->agent_control.retry.attempts =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (retry, "delay_in_seconds");
+ if (e)
+ cfg->agent_control.retry.delay_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (retry, "max_jitter_in_seconds");
+ if (e)
+ cfg->agent_control.retry.max_jitter_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+ }
+ }
+
+ /* … */
+ entity_t se = entity_child (cfg_e, "agent_script_executor");
+ if (se)
+ {
+ e = entity_child (se, "bulk_size");
+ if (e)
+ cfg->agent_script_executor.bulk_size =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "bulk_throttle_time_in_ms");
+ if (e)
+ cfg->agent_script_executor.bulk_throttle_time_in_ms =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "indexer_dir_depth");
+ if (e)
+ cfg->agent_script_executor.indexer_dir_depth =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "period_in_seconds");
+ if (e)
+ cfg->agent_script_executor.period_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ /* - ...
... */
+ entity_t sct = entity_child (se, "scheduler_cron_time");
+ if (sct)
+ {
+ GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
+ for (GSList *n = sct->entities; n; n = n->next)
+ {
+ entity_t it = n->data;
+ if (it && strcmp (entity_name (it), "item") == 0)
+ {
+ const gchar *txt = entity_text (it);
+ g_ptr_array_add (arr, g_strdup (txt ? txt : ""));
+ }
+ }
+ if (arr->len == 0)
+ g_ptr_array_free (arr, TRUE);
+ else
+ cfg->agent_script_executor.scheduler_cron_time = arr;
+ }
+ }
+
+ /* … */
+ entity_t hb = entity_child (cfg_e, "heartbeat");
+ if (hb)
+ {
+ e = entity_child (hb, "interval_in_seconds");
+ if (e)
+ cfg->heartbeat.interval_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (hb, "miss_until_inactive");
+ if (e)
+ cfg->heartbeat.miss_until_inactive =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+ }
+
+ int rc = modify_agent_control_scan_config (scanner, cfg);
+
+ switch (rc)
+ {
+ case 0:
+ /* Success */
+ SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_agent_control_scan_config"));
+ log_event ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+
+ case -1:
+ /* Invalid arguments (scanner == 0 or cfg == NULL) */
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agent_control_scan_config",
+ "Invalid arguments: missing scanner or "));
+ log_event_fail ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+
+ case -2:
+ /* Connector creation failed */
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_UNAVAILABLE ("modify_agent_control_scan_config",
+ "Could not connect to Agent-Controller"));
+ log_event_fail ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+
+ case -3:
+ /* Controller update rejected/failed (validation/comm error) */
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_UNAVAILABLE ("modify_agent_control_scan_config",
+ "Agent-Controller update failed"));
+ log_event_fail ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+
+ default:
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_INTERNAL_ERROR ("modify_agent_control_scan_config"));
+ log_event_fail ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+ }
+
+ SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_agent_control_scan_config"));
+ modify_agent_control_scan_config_reset ();
+}
+
+/**
+ * @brief End element in the command
+ *
+ *
+ * @param[in] gmp_parser current instance of GMP parser.
+ * @param[in] error the errors, if any.
+ * @param[in] name name of element.
+ *
+ * @return 1 if the command ran successfully, 0 otherwise.
+ */
+int
+modify_agent_control_scan_config_element_end (gmp_parser_t *gmp_parser,
+ GError **error,
+ const gchar *name)
+{
+ xml_handle_end_element (modify_scan_cfg_ctx.ctx, name);
+ if (modify_scan_cfg_ctx.ctx->done)
+ {
+ modify_agent_control_scan_config_run (gmp_parser, error);
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* ENABLE_AGENTS */
\ No newline at end of file
diff --git a/src/gmp_agent_control_scan_agent_config.h b/src/gmp_agent_control_scan_agent_config.h
new file mode 100644
index 0000000000..0915e9c387
--- /dev/null
+++ b/src/gmp_agent_control_scan_agent_config.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2025 Greenbone AG
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * @file
+ * @brief GVM GMP layer: Modify Agent-Controller scan-agent configuration.
+ *
+ */
+
+#ifndef _GVMD_GMP_AGENT_CONTROL_SCAN_AGENT_CONFIG_H
+#define _GVMD_GMP_AGENT_CONTROL_SCAN_AGENT_CONFIG_H
+
+#include "gmp_base.h"
+
+/* -------- MODIFY_AGENT_CONTROL_SCAN_CONFIG -------- */
+
+void
+modify_agent_control_scan_config_start (gmp_parser_t *gmp_parser,
+ const gchar **attribute_names,
+ const gchar **attribute_values);
+
+void
+modify_agent_control_scan_config_element_start (gmp_parser_t *gmp_parser,
+ const gchar *name,
+ const gchar **attribute_names,
+ const gchar **attribute_values);
+
+void
+modify_agent_control_scan_config_element_text (const gchar *text, gsize len);
+
+int
+modify_agent_control_scan_config_element_end (gmp_parser_t *gmp_parser,
+ GError **error,
+ const gchar *name);
+
+void
+modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error);
+
+#endif /* _GVMD_GMP_AGENT_CONTROL_SCAN_AGENT_CONFIG_H */
diff --git a/src/gmp_agents.c b/src/gmp_agents.c
index 78abca5356..5d918aa26b 100644
--- a/src/gmp_agents.c
+++ b/src/gmp_agents.c
@@ -14,6 +14,7 @@
*/
#include "gmp_agents.h"
+
#include "gmp_get.h"
#include "manage.h"
@@ -26,19 +27,23 @@
* @struct get_agents_t
* @brief Structure for storing data related to the GMP command.
*
- * This structure holds generic data needed for handling agent retrieval operations.
+ * This structure holds generic data needed for handling agent retrieval
+ * operations.
*/
typedef struct
{
- get_data_t get; ///< Parameters and context for the get operation (e.g., filters, format).
+ get_data_t get;
} get_agents_t;
+
static get_agents_t get_agents_data;
/**
* @struct modify_agent_data_t
- * @brief Structure for storing context related to the GMP command.
+ * @brief Structure for storing context related to the GMP
+ * command.
*
- * The context is used to accumulate and parse XML input data for modifying agents.
+ * The context is used to accumulate and parse XML input data for modifying
+ * agents.
*/
typedef struct
{
@@ -49,7 +54,8 @@ static modify_agent_data_t modify_agent_data;
/**
* @struct delete_agent_data_t
- * @brief Structure for storing context related to the GMP command.
+ * @brief Structure for storing context related to the GMP
+ * command.
*/
typedef struct
{
@@ -73,7 +79,8 @@ get_agents_reset ()
* @brief Initialize the GMP command by parsing attributes.
*
* @param[in] attribute_names Null-terminated array of attribute names.
- * @param[in] attribute_values Null-terminated array of corresponding attribute values.
+ * @param[in] attribute_values Null-terminated array of corresponding attribute
+ * values.
*/
void
get_agents_start (const gchar **attribute_names, const gchar **attribute_values)
@@ -95,13 +102,11 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
iterator_t agents;
int count = 0, filtered, ret, first;
- ret = init_get ("get_agents",
- &get_agents_data.get,
- "Agents",
- &first);
+ ret = init_get ("get_agents", &get_agents_data.get, "Agents", &first);
if (ret)
{
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("get_agents", "Permission denied"));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("get_agents", "Permission denied"));
get_agents_reset ();
return;
}
@@ -109,7 +114,8 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
ret = init_agent_iterator (&agents, &get_agents_data.get);
if (ret)
{
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("get_agents", "Permission denied"));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("get_agents", "Permission denied"));
get_agents_reset ();
return;
}
@@ -135,60 +141,142 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
scanner = agent_iterator_scanner (&agents);
agent_scanner_uuid = scanner_uuid (scanner);
agent_scanner_name = scanner_name (scanner);
- SEND_GET_COMMON_NO_TRASH (agent,
- &get_agents_data.get,
- &agents);
+ SEND_GET_COMMON_NO_TRASH (agent, &get_agents_data.get, &agents);
// Remaining fields
- SENDF_TO_CLIENT_OR_FAIL ("%s"
- "%s"
- "%i"
- "%i"
- "%i"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%i"
- ""
- "%s"
- "",
- agent_iterator_hostname (&agents),
- agent_iterator_agent_id (&agents),
- agent_iterator_authorized (&agents),
- agent_iterator_min_interval (&agents),
- agent_iterator_heartbeat_interval (&agents),
- agent_iterator_connection_status (&agents),
- iso_if_time (agent_iterator_last_update (&agents)),
- agent_iterator_config (&agents),
- agent_iterator_updater_version (&agents),
- agent_iterator_agent_version (&agents),
- agent_iterator_operating_system (&agents),
- agent_iterator_architecture (&agents),
- agent_iterator_update_to_latest (&agents),
- agent_scanner_uuid ? agent_scanner_uuid : "",
- agent_scanner_name ? agent_scanner_name : "");
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%s"
+ "%s"
+ "%i"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%s"
+ "%i"
+ ""
+ "%s"
+ "",
+ agent_iterator_hostname (&agents), agent_iterator_agent_id (&agents),
+ agent_iterator_authorized (&agents),
+ agent_iterator_connection_status (&agents),
+ iso_if_time (agent_iterator_last_update (&agents)),
+ iso_if_time (agent_iterator_last_updater_heartbeat (&agents)),
+ agent_iterator_updater_version (&agents),
+ agent_iterator_agent_version (&agents),
+ agent_iterator_operating_system (&agents),
+ agent_iterator_architecture (&agents),
+ agent_iterator_update_to_latest (&agents),
+ agent_scanner_uuid ? agent_scanner_uuid : "",
+ agent_scanner_name ? agent_scanner_name : "");
// IPs
- agent_ip_data_list_t ip_list = load_agent_ip_addresses (agent_iterator_agent_id (&agents));
+ agent_ip_data_list_t ip_list =
+ load_agent_ip_addresses (agent_iterator_agent_id (&agents));
if (ip_list)
{
for (int i = 0; i < ip_list->count; ++i)
{
- SENDF_TO_CLIENT_OR_FAIL ("%s", ip_list->items[i]->ip_address);
+ SENDF_TO_CLIENT_OR_FAIL ("%s",
+ ip_list->items[i]->ip_address);
}
agent_ip_data_list_free (ip_list);
}
+ const char *cfg_json = agent_iterator_config (&agents);
+
+ if (!cfg_json || !*cfg_json)
+ {
+ SEND_TO_CLIENT_OR_FAIL ("");
+ }
+ else
+ {
+ agent_controller_scan_agent_config_t cfg =
+ agent_controller_parse_scan_agent_config_string (cfg_json);
+
+ if (!cfg)
+ {
+ SEND_TO_CLIENT_OR_FAIL ("");
+ }
+ else
+ {
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* agent_control/retry */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL ("%d",
+ cfg->agent_control.retry.attempts);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_control.retry.delay_in_seconds);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_control.retry.max_jitter_in_seconds);
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* agent_script_executor */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL ("%d",
+ cfg->agent_script_executor.bulk_size);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.bulk_throttle_time_in_ms);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.indexer_dir_depth);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->agent_script_executor.period_in_seconds);
+
+ /* scheduler_cron_time list */
+ {
+ GPtrArray *cron =
+ cfg->agent_script_executor.scheduler_cron_time;
+ if (cron && cron->len > 0)
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ "");
+ for (guint k = 0; k < cron->len; ++k)
+ {
+ const char *item = (const char *) cron->pdata[k];
+ gchar *esc =
+ g_markup_escape_text (item ? item : "", -1);
+ SENDF_TO_CLIENT_OR_FAIL ("- %s
", esc);
+ g_free (esc);
+ }
+ SEND_TO_CLIENT_OR_FAIL ("");
+ }
+ else
+ {
+ SEND_TO_CLIENT_OR_FAIL (
+ "");
+ }
+ }
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ /* heartbeat */
+ SEND_TO_CLIENT_OR_FAIL ("");
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->heartbeat.interval_in_seconds);
+ SENDF_TO_CLIENT_OR_FAIL (
+ "%d",
+ cfg->heartbeat.miss_until_inactive);
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ SEND_TO_CLIENT_OR_FAIL ("");
+
+ agent_controller_scan_agent_config_free (cfg);
+ }
+ }
// Close agent
SEND_TO_CLIENT_OR_FAIL ("");
count++;
- g_free(agent_scanner_name);
- g_free(agent_scanner_uuid);
+ g_free (agent_scanner_name);
+ g_free (agent_scanner_uuid);
}
cleanup_iterator (&agents);
@@ -197,8 +285,8 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error)
SEND_GET_END ("agent", &get_agents_data.get, count, filtered);
#else
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE ("get_agents",
- "Command unavailable"));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_UNAVAILABLE ("get_agents", "Command unavailable"));
#endif
get_agents_reset ();
@@ -232,14 +320,11 @@ modify_agents_reset ()
* @param[in] attribute_values Null-terminated array of attribute values.
*/
void
-modify_agents_element_start (gmp_parser_t *gmp_parser,
- const gchar *name,
+modify_agents_element_start (gmp_parser_t *gmp_parser, const gchar *name,
const gchar **attribute_names,
const gchar **attribute_values)
{
- xml_handle_start_element (modify_agent_data.context,
- name,
- attribute_names,
+ xml_handle_start_element (modify_agent_data.context, name, attribute_names,
attribute_values);
}
@@ -248,18 +333,18 @@ modify_agents_element_start (gmp_parser_t *gmp_parser,
*
* @param[in] gmp_parser Pointer to the GMP parser instance.
* @param[in] attribute_names Null-terminated array of attribute names.
- * @param[in] attribute_values Null-terminated array of corresponding attribute values.
+ * @param[in] attribute_values Null-terminated array of corresponding attribute
+ * values.
*/
void
-modify_agents_start (gmp_parser_t *gmp_parser,
- const gchar **attribute_names,
+modify_agents_start (gmp_parser_t *gmp_parser, const gchar **attribute_names,
const gchar **attribute_values)
{
memset (&modify_agent_data, 0, sizeof (modify_agent_data_t));
modify_agent_data.context = g_malloc0 (sizeof (context_data_t));
- modify_agents_element_start (gmp_parser, "modify_agents",
- attribute_names, attribute_values);
+ modify_agents_element_start (gmp_parser, "modify_agents", attribute_names,
+ attribute_values);
}
/**
@@ -284,8 +369,7 @@ modify_agents_element_text (const gchar *text, gsize text_len)
* @return 1 if the command has been fully parsed and executed, 0 otherwise.
*/
int
-modify_agents_element_end (gmp_parser_t *gmp_parser,
- GError **error,
+modify_agents_element_end (gmp_parser_t *gmp_parser, GError **error,
const gchar *name)
{
xml_handle_end_element (modify_agent_data.context, name);
@@ -314,7 +398,8 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
entity_t agents_elem = entity_child (root, "agents");
if (!agents_elem)
{
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_agents", "Missing "));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agents", "Missing "));
log_event_fail ("agents", "Agents", NULL, "modified");
modify_agents_reset ();
return;
@@ -362,99 +447,217 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
entity_t e = NULL;
if ((e = entity_child (root, "authorized")))
update->authorized = atoi (entity_text (e));
- if ((e = entity_child (root, "min_interval")))
- update->min_interval = atoi (entity_text (e));
- if ((e = entity_child (root, "heartbeat_interval")))
- update->heartbeat_interval = atoi (entity_text (e));
+ entity_t cfg_e = entity_child (root, "config");
+
+ if (cfg_e)
+ {
+ agent_controller_scan_agent_config_t cfg =
+ agent_controller_scan_agent_config_new ();
+ if (!cfg)
+ {
+ agent_uuid_list_free (agent_uuids);
+ agent_controller_agent_update_free (update);
+ g_free (comment);
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
+ modify_agents_reset ();
+ return;
+ }
+
+ /* ... */
+ entity_t ac = entity_child (cfg_e, "agent_control");
+ if (ac)
+ {
+ entity_t retry = entity_child (ac, "retry");
+ if (retry)
+ {
+ /* attempts */
+ e = entity_child (retry, "attempts");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_control.retry.attempts = atoi (t ? t : "0");
+ }
+ /* delay_in_seconds */
+ e = entity_child (retry, "delay_in_seconds");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_control.retry.delay_in_seconds =
+ atoi (t ? t : "0");
+ }
+ /* max_jitter_in_seconds */
+ e = entity_child (retry, "max_jitter_in_seconds");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_control.retry.max_jitter_in_seconds =
+ atoi (t ? t : "0");
+ }
+ }
+ }
+
+ /* ... */
+ entity_t se = entity_child (cfg_e, "agent_script_executor");
+ if (se)
+ {
+ /* bulk_size */
+ e = entity_child (se, "bulk_size");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_script_executor.bulk_size = atoi (t ? t : "0");
+ }
+ /* bulk_throttle_time_in_ms */
+ e = entity_child (se, "bulk_throttle_time_in_ms");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_script_executor.bulk_throttle_time_in_ms =
+ atoi (t ? t : "0");
+ }
+ /* indexer_dir_depth */
+ e = entity_child (se, "indexer_dir_depth");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_script_executor.indexer_dir_depth = atoi (t ? t : "0");
+ }
+ /* period_in_seconds */
+ e = entity_child (se, "period_in_seconds");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->agent_script_executor.period_in_seconds = atoi (t ? t : "0");
+ }
+
+ /* - ...
... */
+ entity_t sct = entity_child (se, "scheduler_cron_time");
+ if (sct)
+ {
+ GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
+ for (GSList *n = sct->entities; n; n = n->next)
+ {
+ entity_t it = n->data;
+ if (it && strcmp (entity_name (it), "item") == 0)
+ {
+ const gchar *txt = entity_text (it);
+ g_ptr_array_add (arr, g_strdup (txt ? txt : ""));
+ }
+ }
+ if (arr->len == 0)
+ g_ptr_array_free (arr, TRUE);
+ else
+ cfg->agent_script_executor.scheduler_cron_time = arr;
+ }
+ }
+
+ /* ... */
+ entity_t hb = entity_child (cfg_e, "heartbeat");
+ if (hb)
+ {
+ /* interval_in_seconds */
+ e = entity_child (hb, "interval_in_seconds");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->heartbeat.interval_in_seconds = atoi (t ? t : "0");
+ }
+ /* miss_until_inactive */
+ e = entity_child (hb, "miss_until_inactive");
+ if (e)
+ {
+ const char *t = entity_text (e);
+ cfg->heartbeat.miss_until_inactive = atoi (t ? t : "0");
+ }
+ }
+ update->config = cfg;
+ }
+
if ((e = entity_child (root, "comment")))
comment = g_strdup (entity_text (e));
-
- agent_response_t response = modify_and_resync_agents (agent_uuids, update, comment);
+ agent_response_t response =
+ modify_and_resync_agents (agent_uuids, update, comment);
switch (response)
{
- case AGENT_RESPONSE_SUCCESS:
- SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_agents"));
- log_event_plural ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_SUCCESS:
+ SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_agents"));
+ log_event_plural ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_NO_AGENTS_PROVIDED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_agents", "No agents provided"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_NO_AGENTS_PROVIDED:
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("modify_agents", "No agents provided"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_SCANNER_LOOKUP_FAILED:
- if (send_find_error_to_client ("modify_agents",
- "scanner",
- NULL,
- gmp_parser))
- {
- error_send_to_client (error);
- modify_agents_reset ();
- return;
- }
-
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_SCANNER_LOOKUP_FAILED:
+ if (send_find_error_to_client ("modify_agents", "scanner", NULL,
+ gmp_parser))
+ {
+ error_send_to_client (error);
+ modify_agents_reset ();
+ return;
+ }
- case AGENT_RESPONSE_AGENT_NOT_FOUND:
- if (send_find_error_to_client ("modify_agents",
- "agents",
- NULL,
- gmp_parser))
- {
- error_send_to_client (error);
- modify_agents_reset ();
- return;
- }
-
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_INVALID_ARGUMENT:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
- break;
+ case AGENT_RESPONSE_AGENT_NOT_FOUND:
+ if (send_find_error_to_client ("modify_agents", "agents", NULL,
+ gmp_parser))
+ {
+ error_send_to_client (error);
+ modify_agents_reset ();
+ return;
+ }
- case AGENT_RESPONSE_INVALID_AGENT_OWNER:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_AGENT_SCANNER_MISMATCH:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_agents", "Agents belong to different scanners"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_INVALID_ARGUMENT:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
+ break;
- case AGENT_RESPONSE_CONNECTOR_CREATION_FAILED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "modify_agents",
- "Could not connect to Agent-Controller"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_INVALID_AGENT_OWNER:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_CONTROLLER_UPDATE_FAILED:
+ case AGENT_RESPONSE_AGENT_SCANNER_MISMATCH:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX (
+ "modify_agents", "Agents belong to different scanners"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
+
+ case AGENT_RESPONSE_CONNECTOR_CREATION_FAILED:
SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "modify_agents",
- "Updates of Agents in Agent-Controller failed"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ "modify_agents", "Could not connect to Agent-Controller"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_SYNC_FAILED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "modify_agents",
- "Synchronization of Agents in Agent-Controller failed"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_CONTROLLER_UPDATE_FAILED:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
+ "modify_agents", "Updates of Agents in Agent-Controller failed"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
- case AGENT_RESPONSE_INTERNAL_ERROR:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
- case AGENT_RESPONSE_IN_USE_ERROR:
- default:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
- log_event_fail ("agents", "Agents", NULL, "modified");
- break;
+ case AGENT_RESPONSE_SYNC_FAILED:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
+ "modify_agents",
+ "Synchronization of Agents in Agent-Controller failed"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
+
+ case AGENT_RESPONSE_INTERNAL_ERROR:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
+ case AGENT_RESPONSE_IN_USE_ERROR:
+ default:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
}
agent_uuid_list_free (agent_uuids);
@@ -462,8 +665,8 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
g_free (comment);
#else
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE ("modify_agents",
- "Command unavailable"));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_UNAVAILABLE ("modify_agents", "Command unavailable"));
#endif // ENABLE_AGENTS
modify_agents_reset ();
@@ -497,34 +700,32 @@ delete_agent_reset ()
* @param[in] attribute_values Null-terminated array of attribute values.
*/
void
-delete_agents_element_start (gmp_parser_t *gmp_parser,
- const gchar *name,
+delete_agents_element_start (gmp_parser_t *gmp_parser, const gchar *name,
const gchar **attribute_names,
const gchar **attribute_values)
{
- xml_handle_start_element (delete_agent_data.context,
- name,
- attribute_names,
+ xml_handle_start_element (delete_agent_data.context, name, attribute_names,
attribute_values);
}
/**
* @brief Initialize the GMP command.
*
- * @param[in] gmp_parser Pointer to the GMP parser handling the current session.
+ * @param[in] gmp_parser Pointer to the GMP parser handling the current
+ * session.
* @param[in] attribute_names Null-terminated array of attribute names.
- * @param[in] attribute_values Null-terminated array of corresponding attribute values.
+ * @param[in] attribute_values Null-terminated array of corresponding attribute
+ * values.
*/
void
-delete_agents_start (gmp_parser_t *gmp_parser,
- const gchar **attribute_names,
+delete_agents_start (gmp_parser_t *gmp_parser, const gchar **attribute_names,
const gchar **attribute_values)
{
memset (&delete_agent_data, 0, sizeof (delete_agent_data_t));
delete_agent_data.context = g_malloc0 (sizeof (context_data_t));
- delete_agents_element_start (gmp_parser, "delete_agents",
- attribute_names, attribute_values);
+ delete_agents_element_start (gmp_parser, "delete_agents", attribute_names,
+ attribute_values);
}
/**
@@ -542,7 +743,8 @@ delete_agents_element_text (const gchar *text, gsize text_len)
/**
* @brief Handle the end of an XML element within the command.
*
- * @param[in] gmp_parser Pointer to the GMP parser handling the current session.
+ * @param[in] gmp_parser Pointer to the GMP parser handling the current
+ * session.
* @param[in] error Pointer to a GError to store error details, if any.
* @param[in] name Name of the XML element that just ended.
*
@@ -550,8 +752,7 @@ delete_agents_element_text (const gchar *text, gsize text_len)
* 0 otherwise.
*/
int
-delete_agents_element_end (gmp_parser_t *gmp_parser,
- GError **error,
+delete_agents_element_end (gmp_parser_t *gmp_parser, GError **error,
const gchar *name)
{
xml_handle_end_element (delete_agent_data.context, name);
@@ -569,7 +770,8 @@ delete_agents_element_end (gmp_parser_t *gmp_parser,
* @brief Execute the GMP command.
*
* @param[in] gmp_parser Pointer to the GMP parser handling the current session.
- * @param[in] error Pointer to a GError to store error information, if any occurs.
+ * @param[in] error Pointer to a GError to store error information, if any
+ * occurs.
*/
void
delete_agents_run (gmp_parser_t *gmp_parser, GError **error)
@@ -581,7 +783,8 @@ delete_agents_run (gmp_parser_t *gmp_parser, GError **error)
entity_t agents_elem = entity_child (root, "agents");
if (!agents_elem)
{
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("delete_agents", "Missing "));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("delete_agents", "Missing "));
delete_agent_reset ();
return;
}
@@ -626,107 +829,101 @@ delete_agents_run (gmp_parser_t *gmp_parser, GError **error)
switch (response)
{
- case AGENT_RESPONSE_SUCCESS:
- SENDF_TO_CLIENT_OR_FAIL (XML_OK ("delete_agents"));
- log_event_plural ("agents", "Agents", NULL, "deleted");
- break;
-
- case AGENT_RESPONSE_NO_AGENTS_PROVIDED:
- if (send_find_error_to_client ("delete_agents",
- "agents",
- NULL,
- gmp_parser))
- {
- error_send_to_client (error);
- modify_agents_reset ();
- return;
- }
-
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
- case AGENT_RESPONSE_AGENT_NOT_FOUND:
- if (send_find_error_to_client ("modify_agents",
- "agents",
- NULL,
- gmp_parser))
- {
- error_send_to_client (error);
- modify_agents_reset ();
- return;
- }
-
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
- case AGENT_RESPONSE_SCANNER_LOOKUP_FAILED:
- if (send_find_error_to_client ("delete_agents",
- "scanner",
- NULL,
- gmp_parser))
- {
- error_send_to_client (error);
- modify_agents_reset ();
- return;
- }
-
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_SUCCESS:
+ SENDF_TO_CLIENT_OR_FAIL (XML_OK ("delete_agents"));
+ log_event_plural ("agents", "Agents", NULL, "deleted");
+ break;
+
+ case AGENT_RESPONSE_NO_AGENTS_PROVIDED:
+ if (send_find_error_to_client ("delete_agents", "agents", NULL,
+ gmp_parser))
+ {
+ error_send_to_client (error);
+ modify_agents_reset ();
+ return;
+ }
- case AGENT_RESPONSE_INVALID_ARGUMENT:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
+ case AGENT_RESPONSE_AGENT_NOT_FOUND:
+ if (send_find_error_to_client ("modify_agents", "agents", NULL,
+ gmp_parser))
+ {
+ error_send_to_client (error);
+ modify_agents_reset ();
+ return;
+ }
- case AGENT_RESPONSE_INVALID_AGENT_OWNER:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
+ case AGENT_RESPONSE_SCANNER_LOOKUP_FAILED:
+ if (send_find_error_to_client ("delete_agents", "scanner", NULL,
+ gmp_parser))
+ {
+ error_send_to_client (error);
+ modify_agents_reset ();
+ return;
+ }
- case AGENT_RESPONSE_AGENT_SCANNER_MISMATCH:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("delete_agents", "Agents belong to different scanners"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- case AGENT_RESPONSE_CONNECTOR_CREATION_FAILED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "delete_agents",
- "Could not connect to Agent-Controller"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_INVALID_ARGUMENT:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- case AGENT_RESPONSE_CONTROLLER_DELETE_FAILED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "delete_agents",
- "Deletion of Agents in Agent-Controller failed"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_INVALID_AGENT_OWNER:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- case AGENT_RESPONSE_SYNC_FAILED:
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
- "delete_agents",
- "Synchronization of Agents in Agent-Controller failed"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_AGENT_SCANNER_MISMATCH:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX (
+ "delete_agents", "Agents belong to different scanners"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- case AGENT_RESPONSE_INTERNAL_ERROR:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_CONNECTOR_CREATION_FAILED:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
+ "delete_agents", "Could not connect to Agent-Controller"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- case AGENT_RESPONSE_IN_USE_ERROR:
- SENDF_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("delete_agents", "Resource is in use"));
- log_event_fail ("agent", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_CONTROLLER_DELETE_FAILED:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
+ "delete_agents", "Deletion of Agents in Agent-Controller failed"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
- default:
- SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
- log_event_fail ("agents", "Agents", NULL, "deleted");
- break;
+ case AGENT_RESPONSE_SYNC_FAILED:
+ SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE (
+ "delete_agents",
+ "Synchronization of Agents in Agent-Controller failed"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
+
+ case AGENT_RESPONSE_INTERNAL_ERROR:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
+
+ case AGENT_RESPONSE_IN_USE_ERROR:
+ SENDF_TO_CLIENT_OR_FAIL (
+ XML_ERROR_SYNTAX ("delete_agents", "Resource is in use"));
+ log_event_fail ("agent", "Agents", NULL, "deleted");
+ break;
+
+ default:
+ SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("delete_agents"));
+ log_event_fail ("agents", "Agents", NULL, "deleted");
+ break;
}
agent_uuid_list_free (agent_uuids);
#else
- SEND_TO_CLIENT_OR_FAIL (XML_ERROR_UNAVAILABLE ("delete_agents",
- "Command unavailable"));
+ SEND_TO_CLIENT_OR_FAIL (
+ XML_ERROR_UNAVAILABLE ("delete_agents", "Command unavailable"));
#endif
delete_agent_reset ();
}
\ No newline at end of file
diff --git a/src/gmp_agents.h b/src/gmp_agents.h
index 46da71a246..6682c0da6c 100644
--- a/src/gmp_agents.h
+++ b/src/gmp_agents.h
@@ -17,8 +17,7 @@
/* GET_AGENTS. */
void
-get_agents_start (const gchar **,
- const gchar **);
+get_agents_start (const gchar **, const gchar **);
void
get_agents_run (gmp_parser_t *gmp_parser, GError **error);
@@ -26,22 +25,19 @@ get_agents_run (gmp_parser_t *gmp_parser, GError **error);
/* MODIFY_AGENT. */
void
-modify_agents_element_start (gmp_parser_t *gmp_parser,
- const gchar *name,
+modify_agents_element_start (gmp_parser_t *gmp_parser, const gchar *name,
const gchar **attribute_names,
const gchar **attribute_values);
void
-modify_agents_start (gmp_parser_t *gmp_parser,
- const gchar **attribute_names,
+modify_agents_start (gmp_parser_t *gmp_parser, const gchar **attribute_names,
const gchar **attribute_values);
void
modify_agents_element_text (const gchar *text, gsize text_len);
int
-modify_agents_element_end (gmp_parser_t *gmp_parser,
- GError **error,
+modify_agents_element_end (gmp_parser_t *gmp_parser, GError **error,
const gchar *name);
void
@@ -50,22 +46,19 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error);
/* DELETE_AGENTS. */
void
-delete_agents_element_start (gmp_parser_t *gmp_parser,
- const gchar *name,
+delete_agents_element_start (gmp_parser_t *gmp_parser, const gchar *name,
const gchar **attribute_names,
const gchar **attribute_values);
void
-delete_agents_start (gmp_parser_t *gmp_parser,
- const gchar **attribute_names,
+delete_agents_start (gmp_parser_t *gmp_parser, const gchar **attribute_names,
const gchar **attribute_values);
void
delete_agents_element_text (const gchar *text, gsize text_len);
int
-delete_agents_element_end (gmp_parser_t *gmp_parser,
- GError **error,
+delete_agents_element_end (gmp_parser_t *gmp_parser, GError **error,
const gchar *name);
void
diff --git a/src/manage.h b/src/manage.h
index 6a8190977f..3d83e9ed0b 100644
--- a/src/manage.h
+++ b/src/manage.h
@@ -56,6 +56,7 @@
#if ENABLE_AGENTS
#include
+#include "manage_agent_control_scan_config.h"
#include "manage_agent_groups.h"
#include "manage_agents.h"
#endif
diff --git a/src/manage_agent_common.c b/src/manage_agent_common.c
index 588fc7e2d1..def2a95738 100644
--- a/src/manage_agent_common.c
+++ b/src/manage_agent_common.c
@@ -10,6 +10,9 @@
#if ENABLE_AGENTS
#include "manage_agent_common.h"
+#include "manage_sql.h"
+
+#include
#undef G_LOG_DOMAIN
/**
@@ -27,15 +30,15 @@
agent_uuid_list_t
agent_uuid_list_new (int count)
{
- if (count <= 0)
- return NULL;
+ if (count <= 0)
+ return NULL;
- agent_uuid_list_t list = g_malloc0 (sizeof (struct agent_uuid_list));
+ agent_uuid_list_t list = g_malloc0 (sizeof (struct agent_uuid_list));
- list->count = count;
- list->agent_uuids = g_malloc0 (sizeof (gchar *) * (count + 1));
+ list->count = count;
+ list->agent_uuids = g_malloc0 (sizeof (gchar *) * (count + 1));
- return list;
+ return list;
}
/**
@@ -46,14 +49,94 @@ agent_uuid_list_new (int count)
void
agent_uuid_list_free (agent_uuid_list_t uuid_list)
{
- if (!uuid_list)
- return;
+ if (!uuid_list)
+ return;
+
+ for (int i = 0; i < uuid_list->count; ++i)
+ g_free (uuid_list->agent_uuids[i]);
+
+ g_free (uuid_list->agent_uuids);
+ g_free (uuid_list);
+}
+
+/**
+ * @brief Initialize a new GVMD agent connector from a scanner.
+ *
+ * Builds and configures a connection to the agent controller using
+ * scanner information.
+ *
+ * @param[in] scanner Scanner ID used to resolve connection info.
+ * @return Allocated gvmd_agent_connector_t or NULL on failure.
+ */
+gvmd_agent_connector_t
+gvmd_agent_connector_new_from_scanner (scanner_t scanner)
+{
+ assert (scanner);
+
+ gboolean has_relay = scanner_has_relay (scanner);
+ char *host = scanner_host (scanner, has_relay);
+ int port = scanner_port (scanner, has_relay);
+ char *ca_cert = scanner_ca_pub (scanner);
+ char *cert = scanner_key_pub (scanner);
+ char *key = scanner_key_priv (scanner);
+
+ if (!host || port <= 0)
+ {
+ g_warning ("%s: Invalid scanner host or port", __func__);
+ g_free (host);
+ g_free (ca_cert);
+ g_free (cert);
+ g_free (key);
+ return NULL;
+ }
- for (int i = 0; i < uuid_list->count; ++i)
- g_free (uuid_list->agent_uuids[i]);
+ const char *protocol = "https";
+ if (!ca_cert || !cert)
+ {
+ g_debug ("%s: Falling back to HTTP due to missing CA or cert", __func__);
+ protocol = "http";
+ }
- g_free (uuid_list->agent_uuids);
- g_free (uuid_list);
+ gvmd_agent_connector_t conn =
+ g_malloc0 (sizeof (struct gvmd_agent_connector));
+ conn->base = agent_controller_connector_new ();
+
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_HOST, host);
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_PORT, &port);
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_PROTOCOL,
+ protocol);
+
+ if (ca_cert)
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_CA_CERT,
+ ca_cert);
+ if (cert)
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_CERT,
+ cert);
+ if (key)
+ agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_KEY, key);
+
+ conn->scanner_id = scanner;
+
+ g_free (host);
+ g_free (ca_cert);
+ g_free (cert);
+ g_free (key);
+
+ return conn;
+}
+
+/**
+ * @brief Free a GVMD agent connector.
+ *
+ * @param[in] conn GVMD agent connector to free.
+ */
+void
+gvmd_agent_connector_free (gvmd_agent_connector_t conn)
+{
+ if (!conn)
+ return;
+ agent_controller_connector_free (conn->base);
+ g_free (conn);
}
#endif // ENABLE_AGENTS
\ No newline at end of file
diff --git a/src/manage_agent_common.h b/src/manage_agent_common.h
index 83983d6ad5..b83cc8f88a 100644
--- a/src/manage_agent_common.h
+++ b/src/manage_agent_common.h
@@ -15,19 +15,41 @@
#ifndef _GVMD_MANAGE_AGENT_COMMON_H
#define _GVMD_MANAGE_AGENT_COMMON_H
+#include "iterator.h"
+#include "manage_get.h"
+#include "manage_resources.h"
+
+#include
#include
+/**
+ * @struct gvmd_agent_connector
+ * @brief Holds scanner context and base agent controller connection.
+ */
+struct gvmd_agent_connector
+{
+ agent_controller_connector_t base; ///< Original gvm-libs connector
+ scanner_t scanner_id; ///< GVMD-specific scanner id
+};
+typedef struct gvmd_agent_connector *gvmd_agent_connector_t;
+
/**
* @struct agent_uuid_list
* @brief A structure to store a list of agent UUIDs.
*/
struct agent_uuid_list
{
- int count; ///< Number of UUIDs in the list
- gchar **agent_uuids; ///< Array of UUID strings
+ int count; ///< Number of UUIDs in the list
+ gchar **agent_uuids; ///< Array of UUID strings
};
typedef struct agent_uuid_list *agent_uuid_list_t;
+gvmd_agent_connector_t
+gvmd_agent_connector_new_from_scanner (scanner_t scanner);
+
+void
+gvmd_agent_connector_free (gvmd_agent_connector_t conn);
+
agent_uuid_list_t
agent_uuid_list_new (int count);
diff --git a/src/manage_agent_control_scan_config.c b/src/manage_agent_control_scan_config.c
new file mode 100644
index 0000000000..907e45825a
--- /dev/null
+++ b/src/manage_agent_control_scan_config.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2025 Greenbone AG
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * @file
+ * @brief Manage layer: Agent Controller scan-agent configuration.
+ *
+ * Functions for retrieving and updating the scan-agent configuration
+ * stored by an Agent Controller scanner.
+ */
+
+#if ENABLE_AGENTS
+#include "manage_agent_control_scan_config.h"
+
+#undef G_LOG_DOMAIN
+/**
+ * @brief GLib log domain.
+ */
+#define G_LOG_DOMAIN "md manage"
+
+/**
+ * @brief Retrieve the scan agent configuration for a given scanner.
+ *
+ * @param[in] scanner Scanner row id whose agent config is requested.
+ *
+ * @return A newly allocated #agent_controller_scan_agent_config_t on success;
+ * NULL if @p scanner is invalid, no configuration is available, or an
+ * allocation/parse error occurs.
+ */
+agent_controller_scan_agent_config_t
+get_agent_control_scan_config (scanner_t scanner)
+{
+ gvmd_agent_connector_t connector = NULL;
+ agent_controller_scan_agent_config_t agent_config = NULL;
+
+ if (scanner == 0)
+ return NULL;
+
+ connector = gvmd_agent_connector_new_from_scanner (scanner);
+
+ if (!connector)
+ return NULL;
+ agent_config = agent_controller_get_scan_agent_config (connector->base);
+ if (!agent_config)
+ {
+ gvmd_agent_connector_free (connector);
+ return NULL;
+ }
+
+ gvmd_agent_connector_free (connector);
+
+ return agent_config;
+}
+
+/**
+ * @brief Modify (persist/propagate) the scan agent configuration for a scanner.
+ *
+ * @param[in] scanner Scanner row identifier (must be non-zero).
+ * @param[in] cfg New configuration to apply (must be non-NULL).
+ *
+ * @return
+ * 0 on success (configuration accepted by the Agent Controller).
+ * -1 invalid arguments (either @p scanner == 0 or @p cfg == NULL).
+ * -2 failed to create a connector for @p scanner
+ * (e.g., scanner not found/misconfigured).
+ * -3 Agent Controller update failed (error propagated from
+ * agent_controller_update_scan_agent_config(), e.g., validation or
+ * communication failure).
+ */
+int
+modify_agent_control_scan_config (scanner_t scanner,
+ agent_controller_scan_agent_config_t cfg)
+{
+ gvmd_agent_connector_t connector = NULL;
+ int res = 0;
+ if (!cfg || !scanner)
+ return -1;
+
+ connector = gvmd_agent_connector_new_from_scanner (scanner);
+ if (!connector)
+ return -2;
+
+ res = agent_controller_update_scan_agent_config (connector->base, cfg);
+ if (res == -1)
+ {
+ g_warning ("%s: Failed to update scan agent config", __func__);
+ res = -3;
+ }
+
+ gvmd_agent_connector_free (connector);
+ agent_controller_scan_agent_config_free (cfg);
+ return res;
+}
+
+#endif // ENABLE_AGENTS
diff --git a/src/manage_agent_control_scan_config.h b/src/manage_agent_control_scan_config.h
new file mode 100644
index 0000000000..4c0944d9ba
--- /dev/null
+++ b/src/manage_agent_control_scan_config.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2025 Greenbone AG
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * @file
+ * @brief Manage layer: Agent Controller scan-agent configuration.
+ *
+ * Functions for retrieving and updating the scan-agent configuration
+ * stored by an Agent Controller scanner.
+ */
+
+#if ENABLE_AGENTS
+#ifndef _GVMD_MANAGE_AGENT_SCAN_CONFIG_H
+#define _GVMD_MANAGE_AGENT_SCAN_CONFIG_H
+
+#include "manage_agent_common.h"
+
+agent_controller_scan_agent_config_t
+get_agent_control_scan_config (scanner_t scanner);
+
+int
+modify_agent_control_scan_config (scanner_t scanner,
+ agent_controller_scan_agent_config_t);
+
+#endif //_GVMD_MANAGE_AGENT_SCAN_CONFIG_H
+#endif // ENABLE_AGENTS
diff --git a/src/manage_agents.c b/src/manage_agents.c
index 016123be91..f8cbcbade4 100644
--- a/src/manage_agents.c
+++ b/src/manage_agents.c
@@ -30,9 +30,9 @@
*
* @param[in] count Number of agent entries to allocate space for.
*
- * @return A newly allocated agent_data_list_t on success, or NULL on memory allocation failure.
+ * @return A newly allocated agent_data_list_t on success, or NULL on memory
+ * allocation failure.
*/
-
static agent_data_list_t
agent_data_list_new (int count)
{
@@ -44,6 +44,95 @@ agent_data_list_new (int count)
return list;
}
+/**
+ * @brief Deep-copy a GPtrArray of char*.
+ *
+ * @param[in] src Source pointer array to duplicate (may be NULL).
+ *
+ * @return A newly allocated #GPtrArray on success; NULL if @p src is NULL
+ * or if an allocation fails.
+ */
+static GPtrArray *
+dup_str_ptr_array (const GPtrArray *src)
+{
+ if (!src)
+ return NULL;
+
+ GPtrArray *dst = g_ptr_array_sized_new (src->len);
+ if (!dst)
+ return NULL;
+
+ g_ptr_array_set_free_func (dst, g_free);
+
+ for (guint i = 0; i < src->len; ++i)
+ {
+ const char *s = g_ptr_array_index ((GPtrArray *) src, i);
+ char *copy = s ? g_strdup (s) : NULL;
+
+ if (s && !copy)
+ {
+ g_ptr_array_free (dst, TRUE);
+ return NULL;
+ }
+
+ g_ptr_array_add (dst, copy);
+ }
+
+ return dst;
+}
+
+/**
+ * @brief Deep-copy a scan agent configuration structure.
+ *
+ * @param[in] src Source configuration to copy. May be NULL.
+ *
+ * @return A newly allocated #agent_controller_scan_agent_config_t on success;
+ * NULL if @p src is NULL or if any allocation fails. On failure, any
+ * partially allocated memory is released.
+ */
+static agent_controller_scan_agent_config_t
+copy_agent_controller_scan_agent_config (
+ agent_controller_scan_agent_config_t src)
+{
+ if (!src)
+ return NULL;
+
+ agent_controller_scan_agent_config_t dst =
+ agent_controller_scan_agent_config_new ();
+
+ /* Plain struct copies */
+ dst->agent_control.retry.attempts = src->agent_control.retry.attempts;
+ dst->agent_control.retry.delay_in_seconds =
+ src->agent_control.retry.delay_in_seconds;
+ dst->agent_control.retry.max_jitter_in_seconds =
+ src->agent_control.retry.max_jitter_in_seconds;
+
+ dst->agent_script_executor.bulk_size = src->agent_script_executor.bulk_size;
+ dst->agent_script_executor.bulk_throttle_time_in_ms =
+ src->agent_script_executor.bulk_throttle_time_in_ms;
+ dst->agent_script_executor.indexer_dir_depth =
+ src->agent_script_executor.indexer_dir_depth;
+ dst->agent_script_executor.period_in_seconds =
+ src->agent_script_executor.period_in_seconds;
+
+ dst->heartbeat.interval_in_seconds = src->heartbeat.interval_in_seconds;
+ dst->heartbeat.miss_until_inactive = src->heartbeat.miss_until_inactive;
+
+ /* Deep copy of GPtrArray */
+ dst->agent_script_executor.scheduler_cron_time =
+ dup_str_ptr_array (src->agent_script_executor.scheduler_cron_time);
+
+ if (src->agent_script_executor.scheduler_cron_time
+ && !dst->agent_script_executor.scheduler_cron_time)
+ {
+ /* allocation failed – clean up partial dst */
+ agent_controller_scan_agent_config_free (dst);
+ return NULL;
+ }
+
+ return dst;
+}
+
/**
* @brief Populate GVMD agent data list from agent controller list.
*
@@ -52,14 +141,16 @@ agent_data_list_new (int count)
*
* @param[in] list List of agents from the agent controller.
* @param[in] scanner Scanner ID associated with these agents.
- * @param[out] out_list Pre-allocated agent_data_list_t with `count` matching `list->count`.
+ * @param[out] out_list Pre-allocated agent_data_list_t with `count` matching
+ * `list->count`.
*
- * @return AGENT_RESPONSE_SUCCESS on success, or an appropriate AGENT_RESPONSE_* error code.
+ * @return AGENT_RESPONSE_SUCCESS on success, or an appropriate AGENT_RESPONSE_*
+ * error code.
*/
static agent_response_t
-convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t list,
- scanner_t scanner,
- agent_data_list_t out_list)
+convert_agent_control_list_to_agent_data_list (
+ agent_controller_agent_list_t list, scanner_t scanner,
+ agent_data_list_t out_list)
{
if (!list || list->count == 0 || !out_list)
return AGENT_RESPONSE_INVALID_ARGUMENT;
@@ -87,11 +178,9 @@ convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t lis
dest->agent_id = g_strdup (src->agent_id);
dest->hostname = g_strdup (src->hostname);
dest->authorized = src->authorized;
- dest->min_interval = src->min_interval;
- dest->heartbeat_interval = src->heartbeat_interval;
dest->connection_status = g_strdup (src->connection_status);
dest->last_update_agent_control = src->last_update;
- dest->config = g_strdup (src->config);
+ dest->config = copy_agent_controller_scan_agent_config (src->config);
dest->updater_version = g_strdup (src->updater_version);
dest->agent_version = g_strdup (src->agent_version);
dest->operating_system = g_strdup (src->operating_system);
@@ -105,15 +194,18 @@ convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t lis
{
dest->ip_addresses = agent_ip_data_list_new (src->ip_address_count);
dest->ip_addresses->count = src->ip_address_count;
- dest->ip_addresses->items = g_malloc0 (sizeof (agent_ip_data_t) * src->ip_address_count);
+ dest->ip_addresses->items =
+ g_malloc0 (sizeof (agent_ip_data_t) * src->ip_address_count);
for (int j = 0; j < src->ip_address_count; ++j)
{
if (!src->ip_addresses[j])
continue;
- dest->ip_addresses->items[j] = g_malloc0 (sizeof (struct agent_ip_data));
- dest->ip_addresses->items[j]->ip_address = g_strdup (src->ip_addresses[j]);
+ dest->ip_addresses->items[j] =
+ g_malloc0 (sizeof (struct agent_ip_data));
+ dest->ip_addresses->items[j]->ip_address =
+ g_strdup (src->ip_addresses[j]);
}
}
else
@@ -137,8 +229,8 @@ convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t lis
* Transforms internal GVMD agent records into a format understood
* by the agent controller for update or deletion operations.
*
- * The caller is responsible for freeing the populated `agent_controller_agent_list_t`
- * using the appropriate cleanup function.
+ * The caller is responsible for freeing the populated
+ * `agent_controller_agent_list_t` using the appropriate cleanup function.
*
* @param[in] list Source list of GVMD agent_data_t entries.
* @param[out] out_list Target agent controller list to populate.
@@ -146,8 +238,8 @@ convert_agent_control_list_to_agent_data_list (agent_controller_agent_list_t lis
* @return AGENT_RESPONSE_SUCCESS on success, otherwise an error code on failure
*/
static agent_response_t
-convert_agent_data_list_to_agent_control_list (agent_data_list_t list,
- agent_controller_agent_list_t out_list)
+convert_agent_data_list_to_agent_control_list (
+ agent_data_list_t list, agent_controller_agent_list_t out_list)
{
if (!list || list->count == 0)
return AGENT_RESPONSE_INVALID_ARGUMENT;
@@ -160,11 +252,10 @@ convert_agent_data_list_to_agent_control_list (agent_data_list_t list,
dest->agent_id = g_strdup (src->agent_id);
dest->hostname = g_strdup (src->hostname);
dest->authorized = src->authorized;
- dest->min_interval = src->min_interval;
- dest->heartbeat_interval = src->heartbeat_interval;
dest->connection_status = g_strdup (src->connection_status);
dest->last_update = src->last_update_agent_control;
- dest->config = src->config;
+ dest->last_updater_heartbeat = src->last_updater_heartbeat;
+ dest->config = copy_agent_controller_scan_agent_config (src->config);
dest->updater_version = g_strdup (src->updater_version);
dest->agent_version = g_strdup (src->agent_version);
dest->operating_system = g_strdup (src->operating_system);
@@ -175,11 +266,13 @@ convert_agent_data_list_to_agent_control_list (agent_data_list_t list,
if (src->ip_addresses && src->ip_addresses->count > 0)
{
dest->ip_address_count = src->ip_addresses->count;
- dest->ip_addresses = g_malloc0 (sizeof (char *) * dest->ip_address_count);
+ dest->ip_addresses =
+ g_malloc0 (sizeof (char *) * dest->ip_address_count);
for (int j = 0; j < dest->ip_address_count; ++j)
{
- dest->ip_addresses[j] = g_strdup (src->ip_addresses->items[j]->ip_address);
+ dest->ip_addresses[j] =
+ g_strdup (src->ip_addresses->items[j]->ip_address);
}
}
@@ -198,12 +291,13 @@ convert_agent_data_list_to_agent_control_list (agent_data_list_t list,
* @param[in] agent_uuids List of agent UUIDs to retrieve.
* @param[out] out_list Output list for agent controller formatted agents.
*
- * @return AGENT_RESPONSE_SUCCESS on success, or an appropriate error code on failure.
+ * @return AGENT_RESPONSE_SUCCESS on success, or an appropriate error code on
+ * failure.
*/
static agent_response_t
get_agent_controller_agents_from_uuids (scanner_t scanner,
- agent_uuid_list_t agent_uuids,
- agent_controller_agent_list_t out_list)
+ agent_uuid_list_t agent_uuids,
+ agent_controller_agent_list_t out_list)
{
if (!scanner)
{
@@ -224,9 +318,8 @@ get_agent_controller_agents_from_uuids (scanner_t scanner,
}
agent_data_list_t agent_data_list = agent_data_list_new (agent_uuids->count);
- agent_response_t get_agent_result = get_agents_by_scanner_and_uuids (scanner,
- agent_uuids,
- agent_data_list);
+ agent_response_t get_agent_result =
+ get_agents_by_scanner_and_uuids (scanner, agent_uuids, agent_data_list);
if (get_agent_result != 0)
{
agent_data_list_free (agent_data_list);
@@ -235,7 +328,8 @@ get_agent_controller_agents_from_uuids (scanner_t scanner,
return get_agent_result;
}
- int convert_result = convert_agent_data_list_to_agent_control_list (agent_data_list, out_list);
+ int convert_result =
+ convert_agent_data_list_to_agent_control_list (agent_data_list, out_list);
if (convert_result != AGENT_RESPONSE_SUCCESS)
{
@@ -249,7 +343,8 @@ get_agent_controller_agents_from_uuids (scanner_t scanner,
}
/**
- * @brief Maps the return value of get_scanner_from_agent_uuid() to agent_response_t.
+ * @brief Maps the return value of get_scanner_from_agent_uuid() to
+ * agent_response_t.
*
* @param[in] result Return code from get_scanner_from_agent_uuid().
*
@@ -275,81 +370,6 @@ map_get_scanner_result_to_agent_response (int result)
}
}
-/**
- * @brief Initialize a new GVMD agent connector from a scanner.
- *
- * Builds and configures a connection to the agent controller using
- * scanner information.
- *
- * @param[in] scanner Scanner ID used to resolve connection info.
- * @return Allocated gvmd_agent_connector_t or NULL on failure.
- */
-gvmd_agent_connector_t
-gvmd_agent_connector_new_from_scanner (scanner_t scanner)
-{
- assert (scanner);
-
- gboolean has_relay = scanner_has_relay (scanner);
- char *host = scanner_host (scanner, has_relay);
- int port = scanner_port (scanner, has_relay);
- char *ca_cert = scanner_ca_pub (scanner);
- char *cert = scanner_key_pub (scanner);
- char *key = scanner_key_priv (scanner);
-
- if (!host || port <= 0)
- {
- g_warning ("%s: Invalid scanner host or port", __func__);
- g_free (host);
- g_free (ca_cert);
- g_free (cert);
- g_free (key);
- return NULL;
- }
-
- const char *protocol = "https";
- if (!ca_cert || !cert)
- {
- g_debug ("%s: Falling back to HTTP due to missing CA or cert", __func__);
- protocol = "http";
- }
-
- gvmd_agent_connector_t conn = g_malloc0 (sizeof (struct gvmd_agent_connector));
- conn->base = agent_controller_connector_new ();
-
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_HOST, host);
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_PORT, &port);
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_PROTOCOL, protocol);
-
- if (ca_cert)
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_CA_CERT, ca_cert);
- if (cert)
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_CERT, cert);
- if (key)
- agent_controller_connector_builder (conn->base, AGENT_CONTROLLER_KEY, key);
-
- conn->scanner_id = scanner;
-
- g_free (host);
- g_free (ca_cert);
- g_free (cert);
- g_free (key);
-
- return conn;
-}
-
-/**
- * @brief Free a GVMD agent connector.
- *
- * @param[in] conn GVMD agent connector to free.
- */
-void
-gvmd_agent_connector_free (gvmd_agent_connector_t conn)
-{
- if (!conn) return;
- agent_controller_connector_free (conn->base);
- g_free (conn);
-}
-
/**
* @brief Free an agent_ip_data_list_t and its contents.
*
@@ -368,24 +388,25 @@ agent_ip_data_list_free (agent_ip_data_list_t ip_list)
if (ip_list->items[i])
{
if (ip_list->items[i]->ip_address)
- g_free(ip_list->items[i]->ip_address);
+ g_free (ip_list->items[i]->ip_address);
- g_free(ip_list->items[i]);
+ g_free (ip_list->items[i]);
ip_list->items[i] = NULL;
}
}
- g_free(ip_list->items);
+ g_free (ip_list->items);
ip_list->items = NULL;
}
- g_free(ip_list);
+ g_free (ip_list);
}
/**
* @brief Allocate and initialize an agent_ip_data_list_t structure.
*
* @param[in] count Number of IP address items to allocate.
- * @return A newly allocated agent_ip_data_list_t, or NULL on allocation failure.
+ * @return A newly allocated agent_ip_data_list_t, or NULL on allocation
+ * failure.
*/
agent_ip_data_list_t
agent_ip_data_list_new (int count)
@@ -442,7 +463,7 @@ agent_data_free (agent_data_t data)
g_free (data->connection_status);
if (data->config)
- g_free (data->config);
+ agent_controller_scan_agent_config_free (data->config);
if (data->updater_version)
g_free (data->updater_version);
@@ -493,7 +514,8 @@ agent_data_list_free (agent_data_list_t agents)
* Gets all agent information from the agent controller
* and saves it into GVMD's internal database.
*
- * @param[in] connector An initialized agent controller connector with scanner ID.
+ * @param[in] connector An initialized agent controller connector with scanner
+ * ID.
*
* @return AGENT_RESPONSE_SUCCESS on success,
* or a specific AGENT_RESPONSE_* error code on failure.
@@ -516,13 +538,13 @@ sync_agents_from_agent_controller (gvmd_agent_connector_t connector)
return AGENT_RESPONSE_SUCCESS;
}
- agent_data_list_t agent_data_list = agent_data_list_new (agent_controller_agents->count);
- agent_response_t convert_result = convert_agent_control_list_to_agent_data_list (
- agent_controller_agents,
- connector->scanner_id,
- agent_data_list);
+ agent_data_list_t agent_data_list =
+ agent_data_list_new (agent_controller_agents->count);
+ agent_response_t convert_result =
+ convert_agent_control_list_to_agent_data_list (
+ agent_controller_agents, connector->scanner_id, agent_data_list);
- if (convert_result!= AGENT_RESPONSE_SUCCESS)
+ if (convert_result != AGENT_RESPONSE_SUCCESS)
{
agent_data_list_free (agent_data_list);
agent_controller_agent_list_free (agent_controller_agents);
@@ -554,15 +576,13 @@ sync_agents_from_agent_controller (gvmd_agent_connector_t connector)
* @param[in] uuid_list List of agent UUIDs to look up.
* @param[out] out_list Output list to populate with matching agents.
*
-* @return AGENT_RESPONSE_SUCCESS on success,
+ * @return AGENT_RESPONSE_SUCCESS on success,
* or a specific AGENT_RESPONSE_* error code on failure.
*/
agent_response_t
-get_agents_by_scanner_and_uuids (scanner_t scanner,
- agent_uuid_list_t uuid_list,
+get_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t uuid_list,
agent_data_list_t out_list)
{
-
if (!out_list || !uuid_list || out_list->count == 0 || uuid_list->count == 0)
return AGENT_RESPONSE_INVALID_ARGUMENT;
@@ -577,28 +597,35 @@ get_agents_by_scanner_and_uuids (scanner_t scanner,
if (agent_iterator_scanner (&iterator) != scanner)
{
cleanup_iterator (&iterator);
- return AGENT_RESPONSE_AGENT_SCANNER_MISMATCH; // Mismatch found, early exit
+ return AGENT_RESPONSE_AGENT_SCANNER_MISMATCH;
}
agent_data_t agent = g_malloc0 (sizeof (struct agent_data));
if (!agent)
continue;
+ /* config conversion */
+ const gchar *cfg_str = g_strdup (agent_iterator_config (&iterator));
+ agent_controller_scan_agent_config_t config =
+ agent_controller_parse_scan_agent_config_string (cfg_str);
+
agent->row_id = iterator_int64 (&iterator, 0);
agent->agent_id = g_strdup (agent_iterator_agent_id (&iterator));
agent->hostname = g_strdup (agent_iterator_hostname (&iterator));
agent->authorized = agent_iterator_authorized (&iterator);
- agent->min_interval = agent_iterator_min_interval (&iterator);
- agent->heartbeat_interval = agent_iterator_heartbeat_interval (&iterator);
- agent->connection_status = g_strdup (agent_iterator_connection_status (&iterator));
+ agent->connection_status =
+ g_strdup (agent_iterator_connection_status (&iterator));
agent->last_update_agent_control = agent_iterator_last_update (&iterator);
- agent->config = g_strdup (agent_iterator_config (&iterator));
+ agent->config = config;
agent->comment = g_strdup (get_iterator_comment (&iterator));
agent->creation_time = get_iterator_creation_time (&iterator);
agent->modification_time = get_iterator_modification_time (&iterator);
- agent->updater_version = g_strdup (agent_iterator_updater_version (&iterator));
- agent->agent_version = g_strdup (agent_iterator_agent_version (&iterator));
- agent->operating_system = g_strdup (agent_iterator_operating_system (&iterator));
+ agent->updater_version =
+ g_strdup (agent_iterator_updater_version (&iterator));
+ agent->agent_version =
+ g_strdup (agent_iterator_agent_version (&iterator));
+ agent->operating_system =
+ g_strdup (agent_iterator_operating_system (&iterator));
agent->architecture = g_strdup (agent_iterator_architecture (&iterator));
agent->update_to_latest = agent_iterator_update_to_latest (&iterator);
agent->scanner = scanner;
@@ -625,8 +652,8 @@ get_agents_by_scanner_and_uuids (scanner_t scanner,
* Sends update instructions for the selected agents and re-synchronizes
* their state from the agent controller.
*
-* @param[in] agent_uuids List of agent UUIDs to be modified.
- * @param[in] agent_update Update parameters to apply (e.g., authorize/revoke).
+ * @param[in] agent_uuids List of agent UUIDs to be modified.
+ * @param[in] agent_update Update parameters to apply (e.g. authorize/revoke).
* @param[in] comment Optional comment string to apply to agents in GVMD.
*
* @return AGENT_RESPONSE_SUCCESS on success,
@@ -647,15 +674,14 @@ modify_and_resync_agents (agent_uuid_list_t agent_uuids,
}
int ret = get_scanner_from_agent_uuid (agent_uuids->agent_uuids[0], &scanner);
- agent_response_t map_response = map_get_scanner_result_to_agent_response (ret);
+ agent_response_t map_response =
+ map_get_scanner_result_to_agent_response (ret);
if (map_response != AGENT_RESPONSE_SUCCESS)
return map_response;
agent_control_list = agent_controller_agent_list_new (agent_uuids->count);
agent_response_t get_response = get_agent_controller_agents_from_uuids (
- scanner,
- agent_uuids,
- agent_control_list);
+ scanner, agent_uuids, agent_control_list);
if (get_response != AGENT_RESPONSE_SUCCESS)
{
agent_controller_agent_list_free (agent_control_list);
@@ -672,9 +698,7 @@ modify_and_resync_agents (agent_uuid_list_t agent_uuids,
}
int update_result = agent_controller_update_agents (
- connector->base,
- agent_control_list,
- agent_update);
+ connector->base, agent_control_list, agent_update);
if (update_result < 0)
{
@@ -685,8 +709,8 @@ modify_and_resync_agents (agent_uuid_list_t agent_uuids,
return AGENT_RESPONSE_CONTROLLER_UPDATE_FAILED;
}
- if (comment)
- update_agents_comment (agent_uuids, comment);
+ if (comment)
+ update_agents_comment (agent_uuids, comment);
agent_response_t result = sync_agents_from_agent_controller (connector);
if (result != AGENT_RESPONSE_SUCCESS)
@@ -730,15 +754,14 @@ delete_and_resync_agents (agent_uuid_list_t agent_uuids)
}
int ret = get_scanner_from_agent_uuid (agent_uuids->agent_uuids[0], &scanner);
- agent_response_t map_response = map_get_scanner_result_to_agent_response (ret);
+ agent_response_t map_response =
+ map_get_scanner_result_to_agent_response (ret);
if (map_response != AGENT_RESPONSE_SUCCESS)
return map_response;
agent_control_list = agent_controller_agent_list_new (agent_uuids->count);
agent_response_t get_result = get_agent_controller_agents_from_uuids (
- scanner,
- agent_uuids,
- agent_control_list);
+ scanner, agent_uuids, agent_control_list);
if (get_result != AGENT_RESPONSE_SUCCESS)
{
agent_controller_agent_list_free (agent_control_list);
@@ -761,9 +784,8 @@ delete_and_resync_agents (agent_uuid_list_t agent_uuids)
return AGENT_RESPONSE_CONNECTOR_CREATION_FAILED;
}
- int update_result = agent_controller_delete_agents (
- connector->base,
- agent_control_list);
+ int update_result =
+ agent_controller_delete_agents (connector->base, agent_control_list);
if (update_result < 0)
{
diff --git a/src/manage_agents.h b/src/manage_agents.h
index 34414ad920..66f4adb716 100644
--- a/src/manage_agents.h
+++ b/src/manage_agents.h
@@ -20,24 +20,11 @@
#include "iterator.h"
#include "manage_agent_common.h"
-#include "manage_get.h"
-#include "manage_resources.h"
#include
typedef resource_t agent_t;
-/**
- * @struct gvmd_agent_connector
- * @brief Holds scanner context and base agent controller connection.
- */
-struct gvmd_agent_connector
-{
- agent_controller_connector_t base; ///< Original gvm-libs connector
- scanner_t scanner_id; ///< GVMD-specific scanner id
-};
-typedef struct gvmd_agent_connector *gvmd_agent_connector_t;
-
/**
* @struct agent_ip_data
* @brief Represents a single IP address associated with an agent.
@@ -66,20 +53,19 @@ typedef struct agent_ip_data_list *agent_ip_data_list_t;
struct agent_data
{
agent_t row_id;
- gchar * uuid;
- gchar * name;
+ gchar *uuid;
+ gchar *name;
gchar *agent_id;
gchar *hostname;
int authorized;
- int min_interval;
- int heartbeat_interval;
gchar *connection_status;
agent_ip_data_list_t ip_addresses;
int ip_address_count;
time_t creation_time;
time_t modification_time;
time_t last_update_agent_control;
- gchar *config;
+ time_t last_updater_heartbeat;
+ agent_controller_scan_agent_config_t config;
gchar *comment;
user_t owner;
scanner_t scanner;
@@ -102,28 +88,23 @@ struct agent_data_list
};
typedef struct agent_data_list *agent_data_list_t;
-typedef enum {
- AGENT_RESPONSE_SUCCESS = 0, ///< Success
- AGENT_RESPONSE_NO_AGENTS_PROVIDED = -1, ///< No agent UUIDs provided
- AGENT_RESPONSE_SCANNER_LOOKUP_FAILED = -2, ///< Scanner lookup failed
- AGENT_RESPONSE_AGENT_SCANNER_MISMATCH = -3, ///< Agent list count mismatch (not same scanner)
- AGENT_RESPONSE_CONNECTOR_CREATION_FAILED = -4, ///< Failed to create connector
- AGENT_RESPONSE_CONTROLLER_UPDATE_FAILED = -5, ///< Failed to update agents
- AGENT_RESPONSE_CONTROLLER_DELETE_FAILED = -6, ///< Failed to delete agents
- AGENT_RESPONSE_SYNC_FAILED = -7, ///< Failed during sync
- AGENT_RESPONSE_INVALID_ARGUMENT = -8, ///< Failed invalid argument
- AGENT_RESPONSE_INVALID_AGENT_OWNER = -9, ///< Failed getting owner UUID
- AGENT_RESPONSE_AGENT_NOT_FOUND = -10, ///< Failed getting owner UUID
- AGENT_RESPONSE_INTERNAL_ERROR = -11, ///< Internal error
- AGENT_RESPONSE_IN_USE_ERROR = -12 ///< Agent is used by an Agent Group
+typedef enum
+{
+ AGENT_RESPONSE_SUCCESS = 0, ///< Success
+ AGENT_RESPONSE_NO_AGENTS_PROVIDED = -1, ///< No agent UUIDs provided
+ AGENT_RESPONSE_SCANNER_LOOKUP_FAILED = -2, ///< Scanner lookup failed
+ AGENT_RESPONSE_AGENT_SCANNER_MISMATCH = -3, ///< Agent list count mismatch (not same scanner)
+ AGENT_RESPONSE_CONNECTOR_CREATION_FAILED = -4, ///< Failed to create connector
+ AGENT_RESPONSE_CONTROLLER_UPDATE_FAILED = -5, ///< Failed to update agents
+ AGENT_RESPONSE_CONTROLLER_DELETE_FAILED = -6, ///< Failed to delete agents
+ AGENT_RESPONSE_SYNC_FAILED = -7, ///< Failed during sync
+ AGENT_RESPONSE_INVALID_ARGUMENT = -8, ///< Failed invalid argument
+ AGENT_RESPONSE_INVALID_AGENT_OWNER = -9, ///< Failed getting owner UUID
+ AGENT_RESPONSE_AGENT_NOT_FOUND = -10, ///< Failed getting owner UUID
+ AGENT_RESPONSE_INTERNAL_ERROR = -11, ///< Internal error
+ AGENT_RESPONSE_IN_USE_ERROR = -12 ///< Agent is used by an Agent Group
} agent_response_t;
-gvmd_agent_connector_t
-gvmd_agent_connector_new_from_scanner (scanner_t scanner);
-
-void
-gvmd_agent_connector_free (gvmd_agent_connector_t conn);
-
void
agent_ip_data_list_free (agent_ip_data_list_t ip_list);
@@ -143,8 +124,7 @@ agent_response_t
sync_agents_from_agent_controller (gvmd_agent_connector_t connector);
agent_response_t
-get_agents_by_scanner_and_uuids (scanner_t scanner,
- agent_uuid_list_t uuid_list,
+get_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t uuid_list,
agent_data_list_t out_list);
agent_response_t
@@ -180,15 +160,12 @@ agent_iterator_config (iterator_t *iterator);
int
agent_iterator_authorized (iterator_t *iterator);
-int
-agent_iterator_min_interval (iterator_t *iterator);
-
-int
-agent_iterator_heartbeat_interval (iterator_t *iterator);
-
time_t
agent_iterator_last_update (iterator_t *iterator);
+time_t
+agent_iterator_last_updater_heartbeat (iterator_t *iterator);
+
scanner_t
agent_iterator_scanner (iterator_t *iterator);
@@ -217,7 +194,8 @@ int
agent_in_use (agent_t agent);
void
-delete_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t agent_uuids);
+delete_agents_by_scanner_and_uuids (scanner_t scanner,
+ agent_uuid_list_t agent_uuids);
gboolean
agents_in_use (agent_uuid_list_t agent_uuids);
diff --git a/src/manage_commands.c b/src/manage_commands.c
index ccab368724..483a4bbce5 100644
--- a/src/manage_commands.c
+++ b/src/manage_commands.c
@@ -127,6 +127,7 @@ command_t gmp_commands[]
{"GET_VULNS", "Get all vulnerabilities."},
{"HELP", "Get this help text."},
#if ENABLE_AGENTS
+ {"MODIFY_AGENT_CONTROL_SCAN_CONFIG", "Modify an agent control scan agent configuration."},
{"MODIFY_AGENT_GROUP", "Modify an agent group."},
{"MODIFY_AGENTS", "Modify one or more existing agents."},
#endif /* ENABLE_AGENTS */
diff --git a/src/manage_pg.c b/src/manage_pg.c
index cec1b82aac..c83d6b0f52 100644
--- a/src/manage_pg.c
+++ b/src/manage_pg.c
@@ -2233,10 +2233,9 @@ create_tables ()
" scanner INTEGER NOT NULL REFERENCES scanners (id) ON DELETE RESTRICT,"
" hostname TEXT,"
" authorized INTEGER NOT NULL,"
- " min_interval INTEGER,"
- " heartbeat_interval INTEGER,"
" connection_status TEXT,"
" last_update INTEGER,"
+ " last_updater_heartbeat INTEGER,"
" config TEXT,"
" owner INTEGER REFERENCES users (id) ON DELETE RESTRICT,"
" comment TEXT,"
diff --git a/src/manage_sql_agents.c b/src/manage_sql_agents.c
index 87ca9b1f8b..dc6031d072 100644
--- a/src/manage_sql_agents.c
+++ b/src/manage_sql_agents.c
@@ -17,6 +17,7 @@
#if ENABLE_AGENTS
#include "manage_sql_agents.h"
+
#include "manage_sql_copy.h"
#include
@@ -36,8 +37,7 @@ static void
delete_existing_agent_ips (const gchar *agent_id)
{
gchar *insert_agent_id = sql_insert (agent_id);
- sql ("DELETE FROM agent_ip_addresses WHERE agent_id = %s;",
- insert_agent_id);
+ sql ("DELETE FROM agent_ip_addresses WHERE agent_id = %s;", insert_agent_id);
g_free (insert_agent_id);
}
@@ -58,8 +58,8 @@ agent_column_exists (const gchar *column_name, const gchar *value)
}
gchar *insert_value = sql_insert (value);
- gchar *query = g_strdup_printf (
- "SELECT COUNT(*) FROM agents WHERE %s = %s;", column_name, insert_value);
+ gchar *query = g_strdup_printf ("SELECT COUNT(*) FROM agents WHERE %s = %s;",
+ column_name, insert_value);
int result = sql_int (query);
@@ -80,9 +80,14 @@ agent_column_exists (const gchar *column_name, const gchar *value)
static void
update_existing_agent (agent_data_t agent)
{
+ gchar *config_string =
+ agent_controller_convert_scan_agent_config_string (agent->config);
+ if (!config_string)
+ config_string = g_strdup ("");
+
gchar *insert_hostname = sql_insert (agent->hostname);
gchar *insert_connection_status = sql_insert (agent->connection_status);
- gchar *insert_config = sql_insert (agent->config);
+ gchar *insert_config = sql_insert (config_string);
gchar *insert_agent_id = sql_insert (agent->agent_id);
gchar *insert_updater_version = sql_insert (agent->updater_version);
gchar *insert_agent_version = sql_insert (agent->agent_version);
@@ -92,10 +97,9 @@ update_existing_agent (agent_data_t agent)
sql ("UPDATE agents SET "
" hostname = %s,"
" authorized = %d,"
- " min_interval = %d,"
- " heartbeat_interval = %d,"
" connection_status = %s,"
" last_update = %ld,"
+ " last_updater_heartbeat = %ld,"
" config = %s,"
" owner = %u,"
" modification_time = %ld,"
@@ -106,12 +110,11 @@ update_existing_agent (agent_data_t agent)
" architecture = %s,"
" update_to_latest = %d"
" WHERE agent_id = %s;",
- insert_hostname, agent->authorized, agent->min_interval,
- agent->heartbeat_interval, insert_connection_status,
- agent->last_update_agent_control, insert_config, agent->owner,
- agent->modification_time, agent->scanner, insert_updater_version,
- insert_agent_version, insert_operating_system, insert_architecture,
- agent->update_to_latest, insert_agent_id);
+ insert_hostname, agent->authorized, insert_connection_status,
+ agent->last_update_agent_control, agent->last_updater_heartbeat,
+ insert_config, agent->owner, agent->modification_time, agent->scanner,
+ insert_updater_version, insert_agent_version, insert_operating_system,
+ insert_architecture, agent->update_to_latest ? 1 : 0, insert_agent_id);
g_free (insert_hostname);
g_free (insert_connection_status);
@@ -121,6 +124,7 @@ update_existing_agent (agent_data_t agent)
g_free (insert_agent_version);
g_free (insert_operating_system);
g_free (insert_architecture);
+ g_free (config_string);
}
/**
@@ -139,9 +143,14 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
return;
}
+ gchar *config_string =
+ agent_controller_convert_scan_agent_config_string (agent->config);
+ if (!config_string)
+ config_string = g_strdup ("");
+
gchar *escaped_hostname = sql_copy_escape (agent->hostname);
gchar *escaped_connection_status = sql_copy_escape (agent->connection_status);
- gchar *escaped_config = sql_copy_escape (agent->config);
+ gchar *escaped_config = sql_copy_escape (config_string);
gchar *escaped_comment = sql_copy_escape ("");
gchar *escaped_updater_version = sql_copy_escape (agent->updater_version);
@@ -151,29 +160,16 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
db_copy_buffer_append_printf (
buffer,
- "%s\t%s\t%s\t%s\t%d\t%d\t%d\t%s\t%ld\t%s\t%u\t%s\t%ld\t%ld\t%llu"
- "\t%s\t%s\t%s\t%s\t%d\n",
- agent->uuid,
- agent->name,
- agent->agent_id,
- escaped_hostname,
- agent->authorized,
- agent->min_interval,
- agent->heartbeat_interval,
- escaped_connection_status,
- agent->last_update_agent_control,
- escaped_config,
- agent->owner,
- escaped_comment,
- time (NULL), // creation time
- agent->modification_time,
- agent->scanner,
- escaped_updater_version,
- escaped_agent_version,
- escaped_operating_system,
- escaped_architecture,
- agent->update_to_latest ? 1 : 0
- );
+ "%s\t%s\t%s\t%llu\t%s\t%d\t%s\t%ld\t%ld\t%s\t%u\t%s\t%ld\t%ld\t%s\t%s\t%"
+ "s\t%s\t%d\n",
+ agent->uuid, agent->name, agent->agent_id, agent->scanner, escaped_hostname,
+ agent->authorized, escaped_connection_status,
+ agent->last_update_agent_control, agent->last_updater_heartbeat,
+ escaped_config, agent->owner, escaped_comment,
+ time (NULL), // creation_time
+ agent->modification_time, escaped_updater_version, escaped_agent_version,
+ escaped_operating_system, escaped_architecture,
+ agent->update_to_latest ? 1 : 0);
g_free (escaped_hostname);
g_free (escaped_connection_status);
@@ -183,6 +179,7 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
g_free (escaped_agent_version);
g_free (escaped_operating_system);
g_free (escaped_architecture);
+ g_free (config_string);
}
/**
@@ -193,24 +190,21 @@ append_agent_row_to_buffer (db_copy_buffer_t *buffer, agent_data_t agent)
* @param[in] ip_list List of IP addresses to append.
*/
static void
-append_ip_rows_to_buffer (db_copy_buffer_t *buffer,
- const gchar *agent_id,
+append_ip_rows_to_buffer (db_copy_buffer_t *buffer, const gchar *agent_id,
agent_ip_data_list_t ip_list)
{
- if (!ip_list) return;
+ if (!ip_list)
+ return;
- gchar *escaped_agent_id = sql_copy_escape (agent_id);
+ gchar *escaped_agent_id = sql_copy_escape (agent_id);
for (int j = 0; j < ip_list->count; ++j)
{
agent_ip_data_t ip = ip_list->items[j];
- gchar *escaped_ip_address = sql_copy_escape (ip->ip_address);
+ gchar *escaped_ip_address = sql_copy_escape (ip->ip_address);
- db_copy_buffer_append_printf (
- buffer,
- "%s\t%s\n",
- escaped_agent_id,
- escaped_ip_address);
+ db_copy_buffer_append_printf (buffer, "%s\t%s\n", escaped_agent_id,
+ escaped_ip_address);
g_free (escaped_ip_address);
}
@@ -234,7 +228,6 @@ append_ip_rows_to_buffer (db_copy_buffer_t *buffer,
int
get_scanner_from_agent_uuid (const gchar *agent_uuid, scanner_t *scanner)
{
-
if (!agent_uuid)
{
g_warning ("%s: Agent UUID is required but missing", __func__);
@@ -245,7 +238,8 @@ get_scanner_from_agent_uuid (const gchar *agent_uuid, scanner_t *scanner)
int exists = agent_column_exists ("uuid", agent_uuid);
if (exists == -1)
{
- g_warning ("%s: Failed to check if agent UUID '%s' exists (DB error)", __func__, agent_uuid);
+ g_warning ("%s: Failed to check if agent UUID '%s' exists (DB error)",
+ __func__, agent_uuid);
manage_option_cleanup ();
return -2;
}
@@ -257,12 +251,14 @@ get_scanner_from_agent_uuid (const gchar *agent_uuid, scanner_t *scanner)
}
gchar *insert_agent_uuid = sql_insert (agent_uuid);
- *scanner = sql_int ("SELECT scanner FROM agents WHERE uuid = %s;", insert_agent_uuid);
+ *scanner =
+ sql_int ("SELECT scanner FROM agents WHERE uuid = %s;", insert_agent_uuid);
g_free (insert_agent_uuid);
if (*scanner <= 0)
{
- g_warning ("%s: Failed to find scanner for agent UUID %s", __func__, agent_uuid);
+ g_warning ("%s: Failed to find scanner for agent UUID %s", __func__,
+ agent_uuid);
manage_option_cleanup ();
return -4;
}
@@ -285,26 +281,36 @@ sync_agents_from_data_list (agent_data_list_t agent_list)
if (!agent_list || agent_list->count == 0)
return 0;
- db_copy_buffer_t agent_buffer = { 0 };
- db_copy_buffer_t ip_buffer = { 0 };
+ db_copy_buffer_t agent_buffer = {0};
+ db_copy_buffer_t ip_buffer = {0};
int status = 0;
- db_copy_buffer_init (
- &agent_buffer, 64 * 1024,
- "COPY agents ("
- " uuid, name, agent_id, hostname, authorized, min_interval, "
- "heartbeat_interval,"
- " connection_status, last_update, config, owner, comment, creation_time,"
- " modification_time, scanner, updater_version, agent_version, "
- "operating_system,"
- " architecture, update_to_latest"
- ") FROM STDIN;");
+ db_copy_buffer_init (&agent_buffer, 64 * 1024,
+ "COPY agents ("
+ " uuid,"
+ " name,"
+ " agent_id,"
+ " scanner,"
+ " hostname,"
+ " authorized,"
+ " connection_status,"
+ " last_update,"
+ " last_updater_heartbeat,"
+ " config,"
+ " owner,"
+ " comment,"
+ " creation_time,"
+ " modification_time,"
+ " updater_version,"
+ " agent_version,"
+ " operating_system,"
+ " architecture,"
+ " update_to_latest"
+ ") FROM STDIN;");
db_copy_buffer_init (
- &ip_buffer,
- 32 * 1024,
- "COPY agent_ip_addresses (agent_id, ip_address) FROM STDIN;"
- );
+ &ip_buffer, 32 * 1024,
+ "COPY agent_ip_addresses (agent_id, ip_address) FROM STDIN;");
sql_begin_immediate ();
@@ -316,15 +322,16 @@ sync_agents_from_data_list (agent_data_list_t agent_list)
if (exists)
{
- update_existing_agent(agent);
- delete_existing_agent_ips(agent->agent_id);
+ update_existing_agent (agent);
+ delete_existing_agent_ips (agent->agent_id);
}
else
{
append_agent_row_to_buffer (&agent_buffer, agent);
}
- append_ip_rows_to_buffer (&ip_buffer, agent->agent_id, agent->ip_addresses);
+ append_ip_rows_to_buffer (&ip_buffer, agent->agent_id,
+ agent->ip_addresses);
}
if (db_copy_buffer_commit (&agent_buffer, TRUE))
@@ -357,7 +364,8 @@ sync_agents_from_data_list (agent_data_list_t agent_list)
* @brief Initialize SQL-based agent iterator with filtering support.
*
* @param[out] iterator Pointer to the iterator to initialize.
- * @param[in] get Get parameters containing filtering criteria (e.g., agent ID).
+ * @param[in] get Get parameters containing filtering criteria (e.g.,
+ * agent ID).
*
* @return 0 on success, -1 on failure.
*/
@@ -379,16 +387,12 @@ init_agent_iterator (iterator_t *iterator, get_data_t *get)
where_clause = g_strdup_printf ("agent_id = '%s'", quoted);
}
- int ret = init_get_iterator (iterator,
- "agent",
- get,
- columns,
- NULL, // no trash columns
+ int ret = init_get_iterator (iterator, "agent", get, columns,
+ NULL, // no trash columns
filter_columns,
- 0, // no trashcan
- NULL, // no joins
- where_clause,
- 0);
+ 0, // no trashcan
+ NULL, // no joins
+ where_clause, 0);
g_free (where_clause);
g_free (quoted);
@@ -397,7 +401,8 @@ init_agent_iterator (iterator_t *iterator, get_data_t *get)
}
/**
- * @brief Initialize an agent iterator for a specific scanner and list of agent UUIDs.
+ * @brief Initialize an agent iterator for a specific scanner and list of agent
+ * UUIDs.
*
* @param[out] iterator Pointer to the iterator to initialize.
* @param[in] uuid_list List of agent UUIDs to include in the iteration.
@@ -407,7 +412,7 @@ init_agent_uuid_list_iterator (iterator_t *iterator,
agent_uuid_list_t uuid_list)
{
get_data_t get;
- memset(&get, 0, sizeof(get));
+ memset (&get, 0, sizeof (get));
get.type = "agent";
get.ignore_pagination = 1;
get.ignore_max_rows_per_page = 1;
@@ -421,8 +426,7 @@ init_agent_uuid_list_iterator (iterator_t *iterator,
for (int i = 0; i < uuid_list->count; ++i)
{
gchar *quoted_uuid = sql_quote (uuid_list->agent_uuids[i]);
- g_string_append_printf (where_clause, "'%s'%s",
- quoted_uuid,
+ g_string_append_printf (where_clause, "'%s'%s", quoted_uuid,
(i < uuid_list->count - 1) ? ", " : "");
g_free (quoted_uuid);
}
@@ -430,16 +434,12 @@ init_agent_uuid_list_iterator (iterator_t *iterator,
}
static column_t columns[] = AGENT_ITERATOR_COLUMNS;
static const char *filter_columns[] = AGENT_ITERATOR_FILTER_COLUMNS;
- init_get_iterator (iterator,
- "agent",
- &get,
- columns,
- NULL, // no trash columns
+ init_get_iterator (iterator, "agent", &get, columns,
+ NULL, // no trash columns
filter_columns,
- 0, // no trashcan
- NULL, // no joins
- where_clause->str,
- 0);
+ 0, // no trashcan
+ NULL, // no joins
+ where_clause->str, 0);
g_string_free (where_clause, TRUE);
}
@@ -459,7 +459,7 @@ load_agent_ip_addresses (const char *agent_id)
gchar *inserted_agent_id = sql_insert (agent_id);
gchar *count_query = g_strdup_printf (
"SELECT COUNT(*) FROM agent_ip_addresses WHERE agent_id = %s;",
- inserted_agent_id);
+ inserted_agent_id);
int count = sql_int (count_query);
g_free (count_query);
@@ -472,9 +472,10 @@ load_agent_ip_addresses (const char *agent_id)
iterator_t ip_iterator;
- init_iterator (&ip_iterator,
- "SELECT ip_address FROM agent_ip_addresses WHERE agent_id = %s;",
- inserted_agent_id);
+ init_iterator (
+ &ip_iterator,
+ "SELECT ip_address FROM agent_ip_addresses WHERE agent_id = %s;",
+ inserted_agent_id);
int index = 0;
while (next (&ip_iterator) && index < count)
@@ -520,39 +521,30 @@ agent_iterator_authorized (iterator_t *iterator)
}
/**
- * @brief Retrieve min_interval of current agent.
+ * @brief Retrieve connection status string of current agent.
*/
-int
-agent_iterator_min_interval (iterator_t *iterator)
+const char *
+agent_iterator_connection_status (iterator_t *iterator)
{
- return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 3);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 3);
}
/**
- * @brief Retrieve heartbeat_interval of current agent.
+ * @brief Retrieve last update timestamp of current agent.
*/
-int
-agent_iterator_heartbeat_interval (iterator_t *iterator)
+time_t
+agent_iterator_last_update (iterator_t *iterator)
{
return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 4);
}
-/**
- * @brief Retrieve connection status string of current agent.
- */
-const char *
-agent_iterator_connection_status (iterator_t *iterator)
-{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 5);
-}
-
/**
* @brief Retrieve last update timestamp of current agent.
*/
time_t
-agent_iterator_last_update (iterator_t *iterator)
+agent_iterator_last_updater_heartbeat (iterator_t *iterator)
{
- return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 6);
+ return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 5);
}
/**
@@ -561,7 +553,7 @@ agent_iterator_last_update (iterator_t *iterator)
const char *
agent_iterator_config (iterator_t *iterator)
{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 7);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 6);
}
/**
@@ -570,7 +562,7 @@ agent_iterator_config (iterator_t *iterator)
scanner_t
agent_iterator_scanner (iterator_t *iterator)
{
- return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 8);
+ return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 7);
}
/**
@@ -579,7 +571,7 @@ agent_iterator_scanner (iterator_t *iterator)
const char *
agent_iterator_updater_version (iterator_t *iterator)
{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 9);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 8);
}
/**
@@ -588,7 +580,7 @@ agent_iterator_updater_version (iterator_t *iterator)
const char *
agent_iterator_agent_version (iterator_t *iterator)
{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 10);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 9);
}
/**
@@ -597,7 +589,7 @@ agent_iterator_agent_version (iterator_t *iterator)
const char *
agent_iterator_operating_system (iterator_t *iterator)
{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 11);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 10);
}
/**
@@ -606,7 +598,7 @@ agent_iterator_operating_system (iterator_t *iterator)
const char *
agent_iterator_architecture (iterator_t *iterator)
{
- return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 12);
+ return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 11);
}
/**
@@ -615,7 +607,7 @@ agent_iterator_architecture (iterator_t *iterator)
int
agent_iterator_update_to_latest (iterator_t *iterator)
{
- return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 13);
+ return iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 12);
}
/**
@@ -630,8 +622,7 @@ agent_count (const get_data_t *get)
static const char *extra_columns[] = AGENT_ITERATOR_FILTER_COLUMNS;
static column_t columns[] = AGENT_ITERATOR_COLUMNS;
- return count ("agent", get, columns, NULL, extra_columns,
- 0, 0, 0, TRUE);
+ return count ("agent", get, columns, NULL, extra_columns, 0, 0, 0, TRUE);
}
/**
@@ -643,7 +634,7 @@ agent_count (const get_data_t *get)
int
agent_writable (agent_t agent)
{
- (void)agent;
+ (void) agent;
return 1;
}
@@ -660,7 +651,8 @@ agent_in_use (agent_t agent)
"WITH usage_counts AS ("
" SELECT COUNT(*) AS count FROM agent_group_agents WHERE agent_id = %llu"
" UNION ALL "
- " SELECT COUNT(*) AS count FROM agent_group_agents_trash WHERE agent = %llu"
+ " SELECT COUNT(*) AS count FROM agent_group_agents_trash WHERE agent = "
+ "%llu"
") "
"SELECT SUM(count) FROM usage_counts;",
agent, agent);
@@ -670,15 +662,16 @@ agent_in_use (agent_t agent)
* @brief Delete agents and associated IPs using a filtered UUID list.
*
* Deletes agents from the database and their associated IPs.
- * If @p agent_uuids is provided and non-empty, only those agents will be deleted.
- * If @p agent_uuids is NULL or empty, and @p scanner is non-zero,
+ * If @p agent_uuids is provided and non-empty, only those agents will be
+ * deleted. If @p agent_uuids is NULL or empty, and @p scanner is non-zero,
* deletes all agents associated with that scanner.
*
* @param[in] scanner Optional scanner filter (0 to ignore).
* @param[in] agent_uuids List of agent UUIDs to delete.
*/
void
-delete_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t agent_uuids)
+delete_agents_by_scanner_and_uuids (scanner_t scanner,
+ agent_uuid_list_t agent_uuids)
{
GString *where_clause = g_string_new ("WHERE 1=1");
@@ -690,7 +683,8 @@ delete_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t agent_u
{
if (i > 0)
g_string_append (where_clause, ", ");
- g_string_append_printf (where_clause, "'%s'", agent_uuids->agent_uuids[i]);
+ g_string_append_printf (where_clause, "'%s'",
+ agent_uuids->agent_uuids[i]);
}
g_string_append (where_clause, ")");
@@ -704,15 +698,12 @@ delete_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t agent_u
sql_begin_immediate ();
// Delete associated IPs
- sql (
- "DELETE FROM agent_ip_addresses "
- "WHERE agent_id IN (SELECT agent_id FROM agents %s);",
- where_clause->str);
+ sql ("DELETE FROM agent_ip_addresses "
+ "WHERE agent_id IN (SELECT agent_id FROM agents %s);",
+ where_clause->str);
// Delete agents
- sql (
- "DELETE FROM agents %s;",
- where_clause->str);
+ sql ("DELETE FROM agents %s;", where_clause->str);
sql_commit ();
@@ -742,10 +733,8 @@ update_agents_comment (agent_uuid_list_t agent_uuids, const gchar *new_comment)
sql_begin_immediate ();
- sql (
- "UPDATE agents SET comment = '%s' WHERE uuid IN (%s);",
- new_comment,
- uuid_list->str);
+ sql ("UPDATE agents SET comment = '%s' WHERE uuid IN (%s);", new_comment,
+ uuid_list->str);
sql_commit ();
@@ -764,33 +753,31 @@ update_agents_comment (agent_uuid_list_t agent_uuids, const gchar *new_comment)
* 2 if scanner mismatch.
*/
int
-agent_id_by_uuid_and_scanner (const gchar *agent_uuid,
- scanner_t scanner_id,
+agent_id_by_uuid_and_scanner (const gchar *agent_uuid, scanner_t scanner_id,
agent_t *agent_id_out)
{
g_return_val_if_fail (agent_uuid != NULL, 1);
g_return_val_if_fail (agent_id_out != NULL, 1);
// Get the agent ID with matching scanner
- agent_t agent_id = sql_int64_0 (
- "SELECT id FROM agents WHERE uuid = '%s' AND scanner = %llu;",
- agent_uuid, scanner_id);
+ agent_t agent_id =
+ sql_int64_0 ("SELECT id FROM agents WHERE uuid = '%s' AND scanner = %llu;",
+ agent_uuid, scanner_id);
if (agent_id != 0)
- {
- *agent_id_out = agent_id;
- return 0; // success
- }
+ {
+ *agent_id_out = agent_id;
+ return 0; // success
+ }
// Check if agent exists but scanner doesn't match
- agent_id = sql_int64_0 (
- "SELECT id FROM agents WHERE uuid = '%s';",
- agent_uuid);
+ agent_id =
+ sql_int64_0 ("SELECT id FROM agents WHERE uuid = '%s';", agent_uuid);
if (agent_id != 0)
- return 2; // scanner mismatch
+ return 2; // scanner mismatch
- return 1; // agent not found
+ return 1; // agent not found
}
/**
@@ -809,24 +796,23 @@ agents_in_use (agent_uuid_list_t agent_uuids)
GString *uuid_filter = g_string_new ("");
for (int i = 0; i < agent_uuids->count; ++i)
- {
- if (i > 0)
- g_string_append (uuid_filter, ", ");
- g_string_append_printf (uuid_filter, "'%s'", agent_uuids->agent_uuids[i]);
- }
-
- int count = sql_int (
- "WITH matching_agents AS ("
- " SELECT id FROM agents WHERE uuid IN (%s)"
- ") "
- "SELECT COUNT(*) FROM ("
- " SELECT agent_id AS id FROM agent_group_agents"
- " WHERE agent_id IN (SELECT id FROM matching_agents)"
- " UNION ALL "
- " SELECT agent AS id FROM agent_group_agents_trash"
- " WHERE agent IN (SELECT id FROM matching_agents)"
- ") AS used_agents;",
- uuid_filter->str);
+ {
+ if (i > 0)
+ g_string_append (uuid_filter, ", ");
+ g_string_append_printf (uuid_filter, "'%s'", agent_uuids->agent_uuids[i]);
+ }
+
+ int count = sql_int ("WITH matching_agents AS ("
+ " SELECT id FROM agents WHERE uuid IN (%s)"
+ ") "
+ "SELECT COUNT(*) FROM ("
+ " SELECT agent_id AS id FROM agent_group_agents"
+ " WHERE agent_id IN (SELECT id FROM matching_agents)"
+ " UNION ALL "
+ " SELECT agent AS id FROM agent_group_agents_trash"
+ " WHERE agent IN (SELECT id FROM matching_agents)"
+ ") AS used_agents;",
+ uuid_filter->str);
g_string_free (uuid_filter, TRUE);
diff --git a/src/manage_sql_agents.h b/src/manage_sql_agents.h
index 6c95ee22c6..2fdb318861 100644
--- a/src/manage_sql_agents.h
+++ b/src/manage_sql_agents.h
@@ -17,8 +17,8 @@
#ifndef _GVMD_MANAGE_SQL_AGENTS_H
#define _GVMD_MANAGE_SQL_AGENTS_H
-#include "manage_sql.h"
#include "manage_agents.h"
+#include "manage_sql.h"
/**
* @brief Agent iterator columns.
@@ -28,10 +28,9 @@
GET_ITERATOR_COLUMNS (agents), {"agent_id", NULL, KEYWORD_TYPE_STRING}, \
{"hostname", NULL, KEYWORD_TYPE_STRING}, \
{"authorized", NULL, KEYWORD_TYPE_INTEGER}, \
- {"min_interval", NULL, KEYWORD_TYPE_INTEGER}, \
- {"heartbeat_interval", NULL, KEYWORD_TYPE_INTEGER}, \
{"connection_status", NULL, KEYWORD_TYPE_STRING}, \
{"last_update", NULL, KEYWORD_TYPE_INTEGER}, \
+ {"last_updater_heartbeat", NULL, KEYWORD_TYPE_INTEGER}, \
{"config", NULL, KEYWORD_TYPE_STRING}, \
{"scanner", NULL, KEYWORD_TYPE_INTEGER}, \
{"updater_version", NULL, KEYWORD_TYPE_STRING}, \
@@ -47,31 +46,14 @@
/**
* @brief Filter columns for agent iterator.
*/
-#define AGENT_ITERATOR_FILTER_COLUMNS \
-{ \
- "uuid", \
- "agent_id", \
- "name", \
- "hostname", \
- "scanner", \
- "authorized", \
- "min_interval", \
- "heartbeat_interval", \
- "connection_status", \
- "last_update", \
- "config", \
- "comment", \
- "creation_time", \
- "modification_time", \
- "owner", \
- "id", \
- "updater_version", \
- "agent_version", \
- "operating_system", \
- "architecture", \
- "update_to_latest", \
- NULL \
-}
+#define AGENT_ITERATOR_FILTER_COLUMNS \
+ { \
+ "uuid", "agent_id", "name", "hostname", "scanner", "authorized", \
+ "min_interval", "last_update", "last_updater_heartbeat", "comment", \
+ "creation_time", "modification_time", "owner", "id", "updater_version", \
+ "agent_version", "operating_system", "architecture", "update_to_latest", \
+ NULL \
+ }
int
sync_agents_from_data_list (agent_data_list_t agent_list);
@@ -80,10 +62,11 @@ void
update_agents_comment (agent_uuid_list_t agent_uuids, const gchar *new_comment);
int
-get_scanner_from_agent_uuid(const gchar *agent_uuid, scanner_t *scanner);
+get_scanner_from_agent_uuid (const gchar *agent_uuid, scanner_t *scanner);
int
-agent_id_by_uuid_and_scanner (const gchar *agent_uuid, scanner_t scanner_id, agent_t *agent_id);
+agent_id_by_uuid_and_scanner (const gchar *agent_uuid, scanner_t scanner_id,
+ agent_t *agent_id);
#endif //_GVMD_MANAGE_SQL_AGENTS_H
-#endif // ENABLE_AGENTS
\ No newline at end of file
+#endif // ENABLE_AGENTS
diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in
index 419b24c98d..5f92fa4eeb 100644
--- a/src/schema_formats/XML/GMP.xml.in
+++ b/src/schema_formats/XML/GMP.xml.in
@@ -9383,16 +9383,6 @@ END:VCALENDAR
integer
Whether the agent is authorized (1) or not (0)
-
- min_interval
- integer
- Minimum interval between scans (in seconds)
-
-
- heartbeat_interval
- integer
- Interval for agent heartbeat (in seconds)
-
connection_status
text
@@ -9404,9 +9394,9 @@ END:VCALENDAR
Last time the agent was updated
- config
- text
- Agent scan config
+ last_updater_heartbeat
+ iso_time
+ Last heartbeat timestamp received from updater
updater_version
@@ -9503,10 +9493,9 @@ END:VCALENDAR
hostname
agent_id
authorized
- min_interval
- heartbeat_interval
connection_status
last_update
+ last_updater_heartbeat
schedule
scanner
ip
@@ -9515,6 +9504,7 @@ END:VCALENDAR
operating_system
architecture
update_to_latest
+ config
owner
@@ -9585,16 +9575,6 @@ END:VCALENDAR
Authorization flag
integer
-
- min_interval
- Minimum interval in seconds
- integer
-
-
- heartbeat_interval
- Heartbeat interval in seconds
- integer
-
connection_status
Connection status of the agent
@@ -9605,6 +9585,11 @@ END:VCALENDAR
Timestamp of last update
iso_time
+
+ last_updater_heartbeat
+ Timestamp of last heartbeat received from updater
+ iso_time
+
schedule
Agent schedule
@@ -9656,6 +9641,91 @@ END:VCALENDAR
Flag to update to latest version (1/0)
integer
+
+ config
+ Structured agent-controller scan configuration
+
+ agent_control
+ agent_script_executor
+ heartbeat
+
+
+ agent_control
+ retry
+
+ retry
+
+ attempts
+ delay_in_seconds
+ max_jitter_in_seconds
+
+
+ attempts
+ integer
+
+
+ delay_in_seconds
+ integer
+
+
+ max_jitter_in_seconds
+ integer
+
+
+
+
+ agent_script_executor
+
+ bulk_size
+ bulk_throttle_time_in_ms
+ indexer_dir_depth
+ period_in_seconds
+ scheduler_cron_time
+
+
+ bulk_size
+ integer
+
+
+ bulk_throttle_time_in_ms
+ integer
+
+
+ indexer_dir_depth
+ integer
+
+
+ period_in_seconds
+ integer
+
+
+ scheduler_cron_time
+ cron
+
+ cron
+ A cron expression defining execution schedule
+ text
+
+
+
+
+ heartbeat
+
+ interval_in_seconds
+ miss_until_inactive
+
+
+ interval_in_seconds
+ Expected heartbeat interval from the updater/agent
+ integer
+
+
+ miss_until_inactive
+ Consecutive missed heartbeats before marking agent inactive
+ integer
+
+
+
filters
@@ -9772,10 +9842,9 @@ END:VCALENDAR
GAT-29
GAT-29-p0MPX0FT
1
- 2000
- 0
inactive
2025-05-23T08:25:17Z
+ 2025-05-23T08:24:59Z
@every 8h
Agent Controller
@@ -9790,6 +9859,29 @@ END:VCALENDAR
Linux
amd64
0
+
+
+
+ 3
+ 10
+ 5
+
+
+
+ 50
+ 250
+ 3
+ 3600
+
+ @every 8h
+ 0 0 * * *
+
+
+
+ 600
+ 1
+
+
first=1 rows=10 sort=name
@@ -22723,6 +22815,9 @@ END:VCALENDAR
configs
tasks
info
+ @IF_ENABLE_AGENTS@
+ agent_control_config
+ @ENDIF_ENABLE_AGENTS@
owner
@@ -23046,6 +23141,93 @@ END:VCALENDAR
+ @IF_ENABLE_AGENTS@
+
+ agent_control_config
+ Structured agent-controller scan configuration
+
+ agent_control
+ agent_script_executor
+ heartbeat
+
+
+ agent_control
+ retry
+
+ retry
+
+ attempts
+ delay_in_seconds
+ max_jitter_in_seconds
+
+
+ attempts
+ integer
+
+
+ delay_in_seconds
+ integer
+
+
+ max_jitter_in_seconds
+ integer
+
+
+
+
+ agent_script_executor
+
+ bulk_size
+ bulk_throttle_time_in_ms
+ indexer_dir_depth
+ period_in_seconds
+ scheduler_cron_time
+
+
+ bulk_size
+ integer
+
+
+ bulk_throttle_time_in_ms
+ integer
+
+
+ indexer_dir_depth
+ integer
+
+
+ period_in_seconds
+ integer
+
+
+ scheduler_cron_time
+ cron
+
+ cron
+ A cron expression defining execution schedule
+ text
+
+
+
+
+ heartbeat
+
+ interval_in_seconds
+ miss_until_inactive
+
+
+ interval_in_seconds
+ Expected heartbeat interval from the updater/agent
+ integer
+
+
+ miss_until_inactive
+ Consecutive missed heartbeats before marking agent inactive
+ integer
+
+
+
+ @ENDIF_ENABLE_AGENTS@
filters
@@ -23194,6 +23376,60 @@ END:VCALENDAR
+ @IF_ENABLE_AGENTS@
+
+ Get full details of a single Agent Control scanner
+
+
+
+
+
+
+ Default Scanner
+
+ 2014-01-01T13:57:25+01:00
+ 2014-01-18T12:07:36+01:00
+ 0
+ 1
+ localhost
+ 9391
+ 2
+ ...
+ ...
+
+
+ Debian desktops
+
+ ...
+
+
+ ...
+
+
+
+ 5
+ 60
+ 10
+
+
+
+ 2
+ 100
+ 10
+ 60
+
+ - 0 23 * * *
+
+
+
+ 600
+ 1
+
+
+
+
+
+ @ENDIF_ENABLE_AGENTS@
get_schedules
@@ -29170,6 +29406,136 @@ END:VCALENDAR
@IF_ENABLE_AGENTS@
+
+ modify_agent_control_scan_config
+ Modify agents
+
+
+ The client uses the modify_agent_control_scan_config command to update the
+ existing agent control scan agent config.
+
+
+
+
+ agent_control_id
+ uuid
+ 1
+
+ config
+
+
+ config
+ Structured agent-controller configuration
+
+ agent_control
+ agent_script_executor
+ heartbeat
+
+
+ agent_control
+ retry
+
+ retry
+
+ attempts
+ delay_in_seconds
+ max_jitter_in_seconds
+
+ attemptsinteger
+ delay_in_secondsinteger
+ max_jitter_in_secondsinteger
+
+
+
+ agent_script_executor
+
+ bulk_size
+ bulk_throttle_time_in_ms
+ indexer_dir_depth
+ period_in_seconds
+ scheduler_cron_time
+
+ bulk_sizeinteger
+ bulk_throttle_time_in_msinteger
+ indexer_dir_depthinteger
+ period_in_secondsinteger
+
+ scheduler_cron_time
+ item
+
+ item
+ Cron expression
+ text
+
+
+
+
+ heartbeat
+ Heartbeat cadence and inactivity threshold
+
+ interval_in_seconds
+ miss_until_inactive
+
+
+ interval_in_seconds
+ Expected updater/agent heartbeat interval
+ integer
+
+
+ miss_until_inactive
+ Consecutive missed heartbeats before marking agent inactive
+ integer
+
+
+
+
+
+
+ status
+ status
+ 1
+
+
+ status_text
+ text
+ 1
+
+
+
+
+ Modify agents
+
+
+
+
+
+ 6
+ 60
+ 10
+
+
+
+ 2
+ 300
+ 100
+ 1000
+
+ - 0 */12 * * *
+
+
+
+ 300
+ 1
+
+
+ example update
+
+
+
+
+
+
+
modify_agent_group
Modify an agent group
@@ -29265,8 +29631,7 @@ END:VCALENDAR
agents
authorized
- min_interval
- heartbeat_interval
+ config
comment
@@ -29293,16 +29658,69 @@ END:VCALENDAR
0
- min_interval
- Minimum interval between two scans
- integer
- 0
-
-
- heartbeat_interval
- Expected heartbeat interval
- integer
- 0
+ config
+ Structured agent-controller configuration
+
+ agent_control
+ agent_script_executor
+ heartbeat
+
+
+ agent_control
+ retry
+
+ retry
+
+ attempts
+ delay_in_seconds
+ max_jitter_in_seconds
+
+ attemptsinteger
+ delay_in_secondsinteger
+ max_jitter_in_secondsinteger
+
+
+
+ agent_script_executor
+
+ bulk_size
+ bulk_throttle_time_in_ms
+ indexer_dir_depth
+ period_in_seconds
+ scheduler_cron_time
+
+ bulk_sizeinteger
+ bulk_throttle_time_in_msinteger
+ indexer_dir_depthinteger
+ period_in_secondsinteger
+
+ scheduler_cron_time
+ item
+
+ item
+ Cron expression
+ text
+
+
+
+
+ heartbeat
+ Heartbeat cadence and inactivity threshold
+
+ interval_in_seconds
+ miss_until_inactive
+
+
+ interval_in_seconds
+ Expected updater/agent heartbeat interval
+ integer
+
+
+ miss_until_inactive
+ Consecutive missed heartbeats before marking agent inactive
+ integer
+
+
comment
@@ -29332,8 +29750,28 @@ END:VCALENDAR
1
- 1000
- 0
+
+
+
+ 6
+ 60
+ 10
+
+
+
+ 2
+ 300
+ 100
+ 1000
+
+ - 0 */12 * * *
+
+
+
+ 300
+ 1
+
+
example update
From 3c6d8d23ff291004fa3183a72b3f185ef9649d2c Mon Sep 17 00:00:00 2001
From: ozgen
Date: Thu, 21 Aug 2025 16:44:26 +0200
Subject: [PATCH 3/6] Change: improve scan-agent-config validation error
reporting
---
src/gmp_agent_control_scan_agent_config.c | 28 +++++++++++-
src/gmp_agents.c | 25 ++++++++++-
src/manage_agent_common.c | 39 ++++++++++++++++
src/manage_agent_common.h | 3 ++
src/manage_agent_control_scan_config.c | 54 +++++++++++++++++------
src/manage_agent_control_scan_config.h | 7 +--
src/manage_agents.c | 14 +++++-
src/manage_agents.h | 6 ++-
8 files changed, 152 insertions(+), 24 deletions(-)
diff --git a/src/gmp_agent_control_scan_agent_config.c b/src/gmp_agent_control_scan_agent_config.c
index 4dbf889b61..59aa709cc7 100644
--- a/src/gmp_agent_control_scan_agent_config.c
+++ b/src/gmp_agent_control_scan_agent_config.c
@@ -260,7 +260,8 @@ modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error)
atoi (entity_text (e) ? entity_text (e) : "0");
}
- int rc = modify_agent_control_scan_config (scanner, cfg);
+ GPtrArray *errs = NULL;
+ int rc = modify_agent_control_scan_config (scanner, cfg, &errs);
switch (rc)
{
@@ -293,7 +294,30 @@ modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error)
return;
case -3:
- /* Controller update rejected/failed (validation/comm error) */
+ gchar *status_text = concat_error_messages (errs, "; ");
+ if (!status_text)
+ status_text = g_markup_escape_text ("Validation failed for .", -1);
+
+ gchar *xml = g_markup_printf_escaped(
+ "",
+ status_text ? status_text : "Validation failed for ."
+ );
+
+ if (send_to_client(xml, gmp_parser->client_writer, gmp_parser->client_writer_data))
+ error_send_to_client(error);
+
+ g_free(xml);
+ g_free(status_text);
+ if (errs)
+ g_ptr_array_free(errs, TRUE);
+ log_event_fail("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
+ modify_agent_control_scan_config_reset ();
+ return;
+
+ case -4:
SEND_TO_CLIENT_OR_FAIL (
XML_ERROR_UNAVAILABLE ("modify_agent_control_scan_config",
"Agent-Controller update failed"));
diff --git a/src/gmp_agents.c b/src/gmp_agents.c
index 5d918aa26b..b3eb3e86ec 100644
--- a/src/gmp_agents.c
+++ b/src/gmp_agents.c
@@ -575,8 +575,10 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
if ((e = entity_child (root, "comment")))
comment = g_strdup (entity_text (e));
+
+ GPtrArray *errs = NULL;
agent_response_t response =
- modify_and_resync_agents (agent_uuids, update, comment);
+ modify_and_resync_agents (agent_uuids, update, comment, &errs);
switch (response)
{
@@ -648,11 +650,32 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
"Synchronization of Agents in Agent-Controller failed"));
log_event_fail ("agents", "Agents", NULL, "modified");
break;
+ case AGENT_RESPONSE_CONTROLLER_UPDATE_REJECTED:
+ gchar *status_text = concat_error_messages (errs, "; ");
+ if (!status_text)
+ status_text = g_markup_escape_text ("Validation failed for .", -1);
+
+ gchar *xml = g_markup_printf_escaped(
+ "",
+ status_text ? status_text : "Validation failed for ."
+ );
+
+ if (send_to_client(xml, gmp_parser->client_writer, gmp_parser->client_writer_data))
+ error_send_to_client(error);
+
+ g_free(xml);
+ g_free(status_text);
+ if (errs) g_ptr_array_free(errs, TRUE);
+ log_event_fail ("agents", "Agents", NULL, "modified");
+ break;
case AGENT_RESPONSE_INTERNAL_ERROR:
SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
log_event_fail ("agents", "Agents", NULL, "modified");
break;
+
case AGENT_RESPONSE_IN_USE_ERROR:
default:
SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("modify_agents"));
diff --git a/src/manage_agent_common.c b/src/manage_agent_common.c
index def2a95738..0a82544883 100644
--- a/src/manage_agent_common.c
+++ b/src/manage_agent_common.c
@@ -139,4 +139,43 @@ gvmd_agent_connector_free (gvmd_agent_connector_t conn)
g_free (conn);
}
+/**
+ * @brief Join an array of gchar* with a separator, skipping NULL/empty entries.
+ *
+ * @param[in] arr GPtrArray of gchar* (may be NULL).
+ * @param[in] sep Separator string, default to "; " if NULL.
+ *
+ * @return Newly allocated joined string, or NULL if no non-empty entries.
+ * Caller must g_free().
+ */
+gchar *
+concat_error_messages (const GPtrArray *errors, const gchar *sep)
+{
+ if (!errors || errors->len == 0)
+ return NULL;
+
+ const gchar *use_sep = sep ? sep : "; ";
+ GString *gs = NULL;
+
+ for (guint i = 0; i < errors->len; ++i)
+ {
+ const gchar *m = g_ptr_array_index ((GPtrArray *)errors, i);
+ if (!m || !*m)
+ continue;
+
+ if (!gs)
+ gs = g_string_new (m);
+ else
+ {
+ g_string_append (gs, use_sep);
+ g_string_append (gs, m);
+ }
+ }
+
+ if (!gs)
+ return NULL;
+
+ return g_string_free (gs, FALSE);
+}
+
#endif // ENABLE_AGENTS
\ No newline at end of file
diff --git a/src/manage_agent_common.h b/src/manage_agent_common.h
index b83cc8f88a..4821868210 100644
--- a/src/manage_agent_common.h
+++ b/src/manage_agent_common.h
@@ -56,5 +56,8 @@ agent_uuid_list_new (int count);
void
agent_uuid_list_free (agent_uuid_list_t uuid_list);
+gchar *
+concat_error_messages (const GPtrArray *errors, const gchar *sep);
+
#endif // _GVMD_MANAGE_AGENT_COMMON_H
#endif // ENABLE_AGENTS
diff --git a/src/manage_agent_control_scan_config.c b/src/manage_agent_control_scan_config.c
index 907e45825a..794a6bb4ea 100644
--- a/src/manage_agent_control_scan_config.c
+++ b/src/manage_agent_control_scan_config.c
@@ -65,33 +65,59 @@ get_agent_control_scan_config (scanner_t scanner)
* -1 invalid arguments (either @p scanner == 0 or @p cfg == NULL).
* -2 failed to create a connector for @p scanner
* (e.g., scanner not found/misconfigured).
- * -3 Agent Controller update failed (error propagated from
- * agent_controller_update_scan_agent_config(), e.g., validation or
+ * -3 Agent Controller update rejected with validation (error propagated from
+ * agent_controller_update_scan_agent_config(), e.g., validation).
+ * -4 Agent Controller update failed (error propagated from
+ * agent_controller_update_scan_agent_config(),
* communication failure).
*/
int
modify_agent_control_scan_config (scanner_t scanner,
- agent_controller_scan_agent_config_t cfg)
+ agent_controller_scan_agent_config_t cfg,
+ GPtrArray **errors)
{
+ int ret = 0;
gvmd_agent_connector_t connector = NULL;
- int res = 0;
- if (!cfg || !scanner)
+
+ /* Avoid returning stale error arrays from previous calls */
+ if (errors)
+ *errors = NULL;
+
+ if (!scanner || !cfg)
return -1;
connector = gvmd_agent_connector_new_from_scanner (scanner);
if (!connector)
- return -2;
+ {
+ ret = -2;
+ goto cleanup;
+ }
- res = agent_controller_update_scan_agent_config (connector->base, cfg);
- if (res == -1)
+ int rc = agent_controller_update_scan_agent_config (
+ connector->base, cfg, errors);
+
+ if (rc == AGENT_RESP_OK)
+ {
+ ret = 0;
+ }
+ else if (errors && *errors && (*errors)->len > 0)
{
- g_warning ("%s: Failed to update scan agent config", __func__);
- res = -3;
+ g_warning ("%s: Agent Controller rejected scan-agent-config update",
+ __func__);
+ ret = -3;
+ }
+ else
+ {
+ g_warning ("%s: Agent Controller update failed (no details)", __func__);
+ ret = -4;
}
- gvmd_agent_connector_free (connector);
+cleanup:
+ if (connector)
+ gvmd_agent_connector_free (connector);
+
agent_controller_scan_agent_config_free (cfg);
- return res;
-}
-#endif // ENABLE_AGENTS
+ return ret;
+}
+#endif // ENABLE_AGENTS
\ No newline at end of file
diff --git a/src/manage_agent_control_scan_config.h b/src/manage_agent_control_scan_config.h
index 4c0944d9ba..4731155408 100644
--- a/src/manage_agent_control_scan_config.h
+++ b/src/manage_agent_control_scan_config.h
@@ -18,11 +18,12 @@
#include "manage_agent_common.h"
agent_controller_scan_agent_config_t
-get_agent_control_scan_config (scanner_t scanner);
+get_agent_control_scan_config(scanner_t scanner);
int
-modify_agent_control_scan_config (scanner_t scanner,
- agent_controller_scan_agent_config_t);
+modify_agent_control_scan_config(scanner_t scanner,
+ agent_controller_scan_agent_config_t cfg,
+ GPtrArray** errors);
#endif //_GVMD_MANAGE_AGENT_SCAN_CONFIG_H
#endif // ENABLE_AGENTS
diff --git a/src/manage_agents.c b/src/manage_agents.c
index f8cbcbade4..1c628f99c3 100644
--- a/src/manage_agents.c
+++ b/src/manage_agents.c
@@ -662,7 +662,8 @@ get_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t uuid_list,
agent_response_t
modify_and_resync_agents (agent_uuid_list_t agent_uuids,
agent_controller_agent_update_t agent_update,
- const gchar *comment)
+ const gchar *comment,
+ GPtrArray **errors)
{
scanner_t scanner = 0;
agent_controller_agent_list_t agent_control_list = NULL;
@@ -698,7 +699,16 @@ modify_and_resync_agents (agent_uuid_list_t agent_uuids,
}
int update_result = agent_controller_update_agents (
- connector->base, agent_control_list, agent_update);
+ connector->base, agent_control_list, agent_update, errors);
+
+ if (update_result < 0 && errors && *errors && (*errors)->len > 0)
+ {
+ g_warning ("%s: agent_controller_update_agents rejected", __func__);
+ agent_controller_agent_list_free (agent_control_list);
+ gvmd_agent_connector_free (connector);
+ manage_option_cleanup ();
+ return AGENT_RESPONSE_CONTROLLER_UPDATE_REJECTED;
+ }
if (update_result < 0)
{
diff --git a/src/manage_agents.h b/src/manage_agents.h
index 66f4adb716..a1ca2206b4 100644
--- a/src/manage_agents.h
+++ b/src/manage_agents.h
@@ -102,7 +102,8 @@ typedef enum
AGENT_RESPONSE_INVALID_AGENT_OWNER = -9, ///< Failed getting owner UUID
AGENT_RESPONSE_AGENT_NOT_FOUND = -10, ///< Failed getting owner UUID
AGENT_RESPONSE_INTERNAL_ERROR = -11, ///< Internal error
- AGENT_RESPONSE_IN_USE_ERROR = -12 ///< Agent is used by an Agent Group
+ AGENT_RESPONSE_IN_USE_ERROR = -12, ///< Agent is used by an Agent Group
+ AGENT_RESPONSE_CONTROLLER_UPDATE_REJECTED = -13 ///< Agent update validation error
} agent_response_t;
void
@@ -130,7 +131,8 @@ get_agents_by_scanner_and_uuids (scanner_t scanner, agent_uuid_list_t uuid_list,
agent_response_t
modify_and_resync_agents (agent_uuid_list_t agent_uuids,
agent_controller_agent_update_t agent_update,
- const gchar *comment);
+ const gchar *comment,
+ GPtrArray **errors);
agent_response_t
delete_and_resync_agents (agent_uuid_list_t agent_uuids);
From b06cfe5a03975d0238449349fe770d46bd82fc86 Mon Sep 17 00:00:00 2001
From: ozgen
Date: Fri, 22 Aug 2025 10:26:06 +0200
Subject: [PATCH 4/6] Update libgvm_agent_controller with 22.26
---
src/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0533e2267d..6ebb8de838 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -44,7 +44,7 @@ if(ENABLE_AGENTS)
pkg_check_modules(
LIBGVM_AGENT_CONTROLLER
REQUIRED
- libgvm_agent_controller>=22.24
+ libgvm_agent_controller>=22.26
)
else(ENABLE_AGENTS)
message(STATUS "ENABLE_AGENTS flag is not enabled")
From e657f8958bf9d59f19ce6a5b6c0df8b5c8c11173 Mon Sep 17 00:00:00 2001
From: ozgen
Date: Fri, 22 Aug 2025 14:16:53 +0200
Subject: [PATCH 5/6] Applying review comments
---
src/gmp_agent_control_scan_agent_config.c | 228 ++++++++++++----------
src/gmp_agent_control_scan_agent_config.h | 8 +
src/gmp_agents.c | 114 +----------
src/manage_agent_common.c | 39 ----
src/manage_agent_common.h | 4 +-
src/manage_utils.c | 48 +++++
src/manage_utils.h | 3 +
src/manage_utils_tests.c | 124 ++++++++++++
8 files changed, 312 insertions(+), 256 deletions(-)
diff --git a/src/gmp_agent_control_scan_agent_config.c b/src/gmp_agent_control_scan_agent_config.c
index 59aa709cc7..ddce3820b8 100644
--- a/src/gmp_agent_control_scan_agent_config.c
+++ b/src/gmp_agent_control_scan_agent_config.c
@@ -13,7 +13,6 @@
#include "gmp_agent_control_scan_agent_config.h"
#include "manage_agent_control_scan_config.h"
-
#include "manage_sql.h"
@@ -166,99 +165,7 @@ modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error)
agent_controller_scan_agent_config_t cfg =
agent_controller_scan_agent_config_new ();
- if (!cfg)
- {
- SEND_TO_CLIENT_OR_FAIL (
- XML_INTERNAL_ERROR ("modify_agent_control_scan_config"));
- modify_agent_control_scan_config_reset ();
- return;
- }
-
- entity_t e = NULL;
-
- /* … */
- entity_t ac = entity_child (cfg_e, "agent_control");
- if (ac)
- {
- entity_t retry = entity_child (ac, "retry");
- if (retry)
- {
- e = entity_child (retry, "attempts");
- if (e)
- cfg->agent_control.retry.attempts =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (retry, "delay_in_seconds");
- if (e)
- cfg->agent_control.retry.delay_in_seconds =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (retry, "max_jitter_in_seconds");
- if (e)
- cfg->agent_control.retry.max_jitter_in_seconds =
- atoi (entity_text (e) ? entity_text (e) : "0");
- }
- }
-
- /* … */
- entity_t se = entity_child (cfg_e, "agent_script_executor");
- if (se)
- {
- e = entity_child (se, "bulk_size");
- if (e)
- cfg->agent_script_executor.bulk_size =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (se, "bulk_throttle_time_in_ms");
- if (e)
- cfg->agent_script_executor.bulk_throttle_time_in_ms =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (se, "indexer_dir_depth");
- if (e)
- cfg->agent_script_executor.indexer_dir_depth =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (se, "period_in_seconds");
- if (e)
- cfg->agent_script_executor.period_in_seconds =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- /* - ...
... */
- entity_t sct = entity_child (se, "scheduler_cron_time");
- if (sct)
- {
- GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
- for (GSList *n = sct->entities; n; n = n->next)
- {
- entity_t it = n->data;
- if (it && strcmp (entity_name (it), "item") == 0)
- {
- const gchar *txt = entity_text (it);
- g_ptr_array_add (arr, g_strdup (txt ? txt : ""));
- }
- }
- if (arr->len == 0)
- g_ptr_array_free (arr, TRUE);
- else
- cfg->agent_script_executor.scheduler_cron_time = arr;
- }
- }
-
- /* … */
- entity_t hb = entity_child (cfg_e, "heartbeat");
- if (hb)
- {
- e = entity_child (hb, "interval_in_seconds");
- if (e)
- cfg->heartbeat.interval_in_seconds =
- atoi (entity_text (e) ? entity_text (e) : "0");
-
- e = entity_child (hb, "miss_until_inactive");
- if (e)
- cfg->heartbeat.miss_until_inactive =
- atoi (entity_text (e) ? entity_text (e) : "0");
- }
+ build_scan_agent_config_from_entity (cfg_e, cfg);
GPtrArray *errs = NULL;
int rc = modify_agent_control_scan_config (scanner, cfg, &errs);
@@ -294,26 +201,29 @@ modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error)
return;
case -3:
- gchar *status_text = concat_error_messages (errs, "; ");
+ gchar *status_text = concat_error_messages (
+ errs, "; ", "Validation failed for config: ");
if (!status_text)
- status_text = g_markup_escape_text ("Validation failed for .", -1);
+ status_text = g_markup_escape_text ("Validation failed for config.",
+ -1);
- gchar *xml = g_markup_printf_escaped(
+ gchar *xml = g_markup_printf_escaped (
"",
status_text ? status_text : "Validation failed for ."
- );
+ );
- if (send_to_client(xml, gmp_parser->client_writer, gmp_parser->client_writer_data))
- error_send_to_client(error);
+ if (send_to_client (xml, gmp_parser->client_writer,
+ gmp_parser->client_writer_data))
+ error_send_to_client (error);
- g_free(xml);
- g_free(status_text);
+ g_free (xml);
+ g_free (status_text);
if (errs)
- g_ptr_array_free(errs, TRUE);
- log_event_fail("agent_control_scan_config", "Agent Control Scan Config",
- scanner_uuid, "modified");
+ g_ptr_array_free (errs, TRUE);
+ log_event_fail ("agent_control_scan_config", "Agent Control Scan Config",
+ scanner_uuid, "modified");
modify_agent_control_scan_config_reset ();
return;
@@ -363,4 +273,112 @@ modify_agent_control_scan_config_element_end (gmp_parser_t *gmp_parser,
return 0;
}
+/**
+ * @brief Populate an Agent-Controller scan config from a subtree.
+ *
+ * @param[in] root Entity node representing the subtree
+ * (i.e., the parent of , ,
+ * and elements).
+ * @param[in,out] out_cfg Pre-allocated config object to populate. Must not be NULL.
+ *
+ * @return 0 on success; -1 if @p out_cfg is NULL.
+ */
+int
+build_scan_agent_config_from_entity (
+ entity_t root,
+ agent_controller_scan_agent_config_t out_cfg)
+{
+ if (!out_cfg)
+ return -1;
+
+ entity_t e = NULL;
+
+ /* … */
+ entity_t ac = entity_child (root, "agent_control");
+ if (ac)
+ {
+ entity_t retry = entity_child (ac, "retry");
+ if (retry)
+ {
+ e = entity_child (retry, "attempts");
+ if (e)
+ out_cfg->agent_control.retry.attempts =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (retry, "delay_in_seconds");
+ if (e)
+ out_cfg->agent_control.retry.delay_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (retry, "max_jitter_in_seconds");
+ if (e)
+ out_cfg->agent_control.retry.max_jitter_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+ }
+ }
+
+ /* … */
+ entity_t se = entity_child (root, "agent_script_executor");
+ if (se)
+ {
+ e = entity_child (se, "bulk_size");
+ if (e)
+ out_cfg->agent_script_executor.bulk_size =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "bulk_throttle_time_in_ms");
+ if (e)
+ out_cfg->agent_script_executor.bulk_throttle_time_in_ms =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "indexer_dir_depth");
+ if (e)
+ out_cfg->agent_script_executor.indexer_dir_depth =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (se, "period_in_seconds");
+ if (e)
+ out_cfg->agent_script_executor.period_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ /* - ...
... */
+ entity_t sct = entity_child (se, "scheduler_cron_time");
+ if (sct)
+ {
+ GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
+ for (GSList *n = sct->entities; n; n = n->next)
+ {
+ entity_t it = n->data;
+ if (it && strcmp (entity_name (it), "item") == 0)
+ {
+ const gchar *txt = entity_text (it);
+ g_ptr_array_add (arr, g_strdup (txt ? txt : ""));
+ }
+ }
+ if (arr->len == 0)
+ g_ptr_array_free (arr, TRUE);
+ else
+ out_cfg->agent_script_executor.scheduler_cron_time = arr;
+ }
+ }
+
+ /* … */
+ entity_t hb = entity_child (root, "heartbeat");
+ if (hb)
+ {
+ e = entity_child (hb, "interval_in_seconds");
+ if (e)
+ out_cfg->heartbeat.interval_in_seconds =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+
+ e = entity_child (hb, "miss_until_inactive");
+ if (e)
+ out_cfg->heartbeat.miss_until_inactive =
+ atoi (entity_text (e) ? entity_text (e) : "0");
+ }
+
+ return 0;
+}
+
+
#endif /* ENABLE_AGENTS */
\ No newline at end of file
diff --git a/src/gmp_agent_control_scan_agent_config.h b/src/gmp_agent_control_scan_agent_config.h
index 0915e9c387..73c4849a69 100644
--- a/src/gmp_agent_control_scan_agent_config.h
+++ b/src/gmp_agent_control_scan_agent_config.h
@@ -14,6 +14,9 @@
#include "gmp_base.h"
+#include
+#include
+
/* -------- MODIFY_AGENT_CONTROL_SCAN_CONFIG -------- */
void
@@ -38,4 +41,9 @@ modify_agent_control_scan_config_element_end (gmp_parser_t *gmp_parser,
void
modify_agent_control_scan_config_run (gmp_parser_t *gmp_parser, GError **error);
+int
+build_scan_agent_config_from_entity (
+ entity_t root,
+ agent_controller_scan_agent_config_t out_cfg);
+
#endif /* _GVMD_GMP_AGENT_CONTROL_SCAN_AGENT_CONFIG_H */
diff --git a/src/gmp_agents.c b/src/gmp_agents.c
index 857f7bd573..215672ff63 100644
--- a/src/gmp_agents.c
+++ b/src/gmp_agents.c
@@ -15,6 +15,7 @@
#include "gmp_agents.h"
+#include "gmp_agent_control_scan_agent_config.h"
#include "gmp_get.h"
#include "manage.h"
@@ -463,113 +464,7 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
return;
}
- /* ... */
- entity_t ac = entity_child (cfg_e, "agent_control");
- if (ac)
- {
- entity_t retry = entity_child (ac, "retry");
- if (retry)
- {
- /* attempts */
- e = entity_child (retry, "attempts");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_control.retry.attempts = atoi (t ? t : "0");
- }
- /* delay_in_seconds */
- e = entity_child (retry, "delay_in_seconds");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_control.retry.delay_in_seconds =
- atoi (t ? t : "0");
- }
- /* max_jitter_in_seconds */
- e = entity_child (retry, "max_jitter_in_seconds");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_control.retry.max_jitter_in_seconds =
- atoi (t ? t : "0");
- }
- }
- }
-
- /* ... */
- entity_t se = entity_child (cfg_e, "agent_script_executor");
- if (se)
- {
- /* bulk_size */
- e = entity_child (se, "bulk_size");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_script_executor.bulk_size = atoi (t ? t : "0");
- }
- /* bulk_throttle_time_in_ms */
- e = entity_child (se, "bulk_throttle_time_in_ms");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_script_executor.bulk_throttle_time_in_ms =
- atoi (t ? t : "0");
- }
- /* indexer_dir_depth */
- e = entity_child (se, "indexer_dir_depth");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_script_executor.indexer_dir_depth = atoi (t ? t : "0");
- }
- /* period_in_seconds */
- e = entity_child (se, "period_in_seconds");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->agent_script_executor.period_in_seconds = atoi (t ? t : "0");
- }
-
- /* - ...
... */
- entity_t sct = entity_child (se, "scheduler_cron_time");
- if (sct)
- {
- GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
- for (GSList *n = sct->entities; n; n = n->next)
- {
- entity_t it = n->data;
- if (it && strcmp (entity_name (it), "item") == 0)
- {
- const gchar *txt = entity_text (it);
- g_ptr_array_add (arr, g_strdup (txt ? txt : ""));
- }
- }
- if (arr->len == 0)
- g_ptr_array_free (arr, TRUE);
- else
- cfg->agent_script_executor.scheduler_cron_time = arr;
- }
- }
-
- /* ... */
- entity_t hb = entity_child (cfg_e, "heartbeat");
- if (hb)
- {
- /* interval_in_seconds */
- e = entity_child (hb, "interval_in_seconds");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->heartbeat.interval_in_seconds = atoi (t ? t : "0");
- }
- /* miss_until_inactive */
- e = entity_child (hb, "miss_until_inactive");
- if (e)
- {
- const char *t = entity_text (e);
- cfg->heartbeat.miss_until_inactive = atoi (t ? t : "0");
- }
- }
+ build_scan_agent_config_from_entity (cfg_e, cfg);
update->config = cfg;
}
@@ -651,9 +546,10 @@ modify_agents_run (gmp_parser_t *gmp_parser, GError **error)
log_event_fail ("agents", "Agents", NULL, "modified");
break;
case AGENT_RESPONSE_CONTROLLER_UPDATE_REJECTED:
- gchar *status_text = concat_error_messages (errs, "; ");
+ gchar *status_text = concat_error_messages (
+ errs, "; ", "Validation failed for config: ");
if (!status_text)
- status_text = g_markup_escape_text ("Validation failed for .", -1);
+ status_text = g_markup_escape_text ("Validation failed for config.", -1);
gchar *xml = g_markup_printf_escaped(
"len == 0)
- return NULL;
-
- const gchar *use_sep = sep ? sep : "; ";
- GString *gs = NULL;
-
- for (guint i = 0; i < errors->len; ++i)
- {
- const gchar *m = g_ptr_array_index ((GPtrArray *)errors, i);
- if (!m || !*m)
- continue;
-
- if (!gs)
- gs = g_string_new (m);
- else
- {
- g_string_append (gs, use_sep);
- g_string_append (gs, m);
- }
- }
-
- if (!gs)
- return NULL;
-
- return g_string_free (gs, FALSE);
-}
-
#endif // ENABLE_AGENTS
\ No newline at end of file
diff --git a/src/manage_agent_common.h b/src/manage_agent_common.h
index 4821868210..3f001fa3ce 100644
--- a/src/manage_agent_common.h
+++ b/src/manage_agent_common.h
@@ -18,6 +18,7 @@
#include "iterator.h"
#include "manage_get.h"
#include "manage_resources.h"
+#include "manage_utils.h"
#include
#include
@@ -56,8 +57,5 @@ agent_uuid_list_new (int count);
void
agent_uuid_list_free (agent_uuid_list_t uuid_list);
-gchar *
-concat_error_messages (const GPtrArray *errors, const gchar *sep);
-
#endif // _GVMD_MANAGE_AGENT_COMMON_H
#endif // ENABLE_AGENTS
diff --git a/src/manage_utils.c b/src/manage_utils.c
index f01eb6a09d..26d8236bbe 100644
--- a/src/manage_utils.c
+++ b/src/manage_utils.c
@@ -1491,3 +1491,51 @@ clean_hosts_string (const char *hosts)
return g_string_free (new_hosts, FALSE);
}
+
+/**
+ * @brief Join an array of gchar* with a separator, skipping NULL/empty entries.
+ *
+ * @param[in] errors GPtrArray of gchar* (may be NULL).
+ * @param[in] sep Separator string, default to "; " if NULL.
+ * @param[in] prefix Prefix string, default to "" if NULL.
+ *
+ * @return Newly allocated joined string, or NULL if no non-empty entries.
+ * Caller must g_free().
+ */
+gchar *
+concat_error_messages (const GPtrArray *errors, const gchar *sep, const gchar *prefix)
+{
+ if (!errors || errors->len == 0)
+ return NULL;
+
+ if (prefix == NULL)
+ prefix = "";
+
+ const gchar *use_sep = sep ? sep : "; ";
+
+ GString *gs = NULL;
+
+ for (guint i = 0; i < errors->len; ++i)
+ {
+ const gchar *m = g_ptr_array_index ((GPtrArray *)errors, i);
+ if (!m || !*m)
+ continue;
+
+ if (!gs)
+ {
+ /* first non-empty: start with prefix */
+ gs = g_string_new (prefix);
+ g_string_append (gs, m);
+ }
+ else
+ {
+ g_string_append (gs, use_sep);
+ g_string_append (gs, m);
+ }
+ }
+
+ if (!gs)
+ return NULL;
+
+ return g_string_free (gs, FALSE);
+}
diff --git a/src/manage_utils.h b/src/manage_utils.h
index 2a05c1a4c7..cf59bf5cf5 100644
--- a/src/manage_utils.h
+++ b/src/manage_utils.h
@@ -101,4 +101,7 @@ icalendar_first_time_from_vcalendar (icalcomponent *, icaltimezone *);
gchar *
clean_hosts_string (const char *);
+gchar *
+concat_error_messages (const GPtrArray *errors, const gchar *sep, const gchar *prefix);
+
#endif /* not _GVMD_MANAGE_UTILS_H */
diff --git a/src/manage_utils_tests.c b/src/manage_utils_tests.c
index 0ab7f6a97b..1e48fe91b7 100644
--- a/src/manage_utils_tests.c
+++ b/src/manage_utils_tests.c
@@ -73,6 +73,20 @@ verify_next (time_t next, time_t first, time_t now, int period)
|| next == get_next_time (first, now, 2 * 60, 2);
}
+static GPtrArray *
+make_str_array (const char **vals, size_t n)
+{
+ GPtrArray *a = g_ptr_array_new_with_free_func (g_free);
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (vals[i] == NULL)
+ g_ptr_array_add (a, NULL);
+ else
+ g_ptr_array_add (a, g_strdup (vals[i]));
+ }
+ return a;
+}
+
Ensure (manage_utils, icalendar_next_time_from_string_utc)
{
time_t next, now;
@@ -191,6 +205,106 @@ Ensure (manage_utils, clean_hosts_string_zeroes)
g_free (clean_str);
}
+/* concat_error_messages tests */
+
+Ensure (manage_utils, concat_error_messages_null_array_returns_null)
+{
+ gchar *s = concat_error_messages (NULL, NULL, "Validation failed for : ");
+ assert_that (s, is_null);
+}
+
+Ensure (manage_utils, concat_error_messages_empty_array_returns_null)
+{
+ GPtrArray *arr = g_ptr_array_new_with_free_func (g_free);
+ gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
+ assert_that (s, is_null);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_single_item_with_prefix)
+{
+ const char *vals[] = {"attempts must be >= 0"};
+ GPtrArray *arr = make_str_array (vals, 1);
+
+ gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
+ assert_that (s, is_equal_to_string ("Validation failed for : attempts must be >= 0"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_multiple_default_sep_and_prefix)
+{
+ const char *vals[] = {"period_in_seconds required", "bulk_size must be positive", "cron invalid"};
+ GPtrArray *arr = make_str_array (vals, 3);
+
+ gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
+ assert_that (s, is_equal_to_string (
+ "Validation failed for : period_in_seconds required; bulk_size must be positive; cron invalid"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_custom_separator)
+{
+ const char *vals[] = {"a", "b", "c"};
+ GPtrArray *arr = make_str_array (vals, 3);
+
+ gchar *s = concat_error_messages (arr, " | ", "Validation failed for : ");
+ assert_that (s, is_equal_to_string ("Validation failed for : a | b | c"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_skips_null_and_empty)
+{
+ const char *vals[] = {NULL, "", "first", "", "second", NULL};
+ GPtrArray *arr = make_str_array (vals, sizeof (vals) / sizeof (vals[0]));
+
+ gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
+ assert_that (s, is_equal_to_string ("Validation failed for : first; second"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_all_null_or_empty_returns_null)
+{
+ const char *vals[] = {NULL, "", NULL, ""};
+ GPtrArray *arr = make_str_array (vals, sizeof (vals) / sizeof (vals[0]));
+
+ gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
+ assert_that (s, is_null);
+
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_null_prefix_means_no_prefix)
+{
+ const char *vals[] = {"x", "y"};
+ GPtrArray *arr = make_str_array (vals, 2);
+
+ gchar *s = concat_error_messages (arr, NULL, NULL);
+ assert_that (s, is_equal_to_string ("x; y"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
+Ensure (manage_utils, concat_error_messages_empty_separator)
+{
+ const char *vals[] = {"aa", "bb", "cc"};
+ GPtrArray *arr = make_str_array (vals, 3);
+
+ gchar *s = concat_error_messages (arr, "", "P: ");
+ assert_that (s, is_equal_to_string ("P: aabbcc"));
+
+ g_free (s);
+ g_ptr_array_free (arr, TRUE);
+}
+
/* Test suite. */
int
@@ -209,6 +323,16 @@ main (int argc, char **argv)
add_test_with_context (suite, manage_utils, clean_hosts_string_zeroes);
+ add_test_with_context (suite, manage_utils, concat_error_messages_null_array_returns_null);
+ add_test_with_context (suite, manage_utils, concat_error_messages_empty_array_returns_null);
+ add_test_with_context (suite, manage_utils, concat_error_messages_single_item_with_prefix);
+ add_test_with_context (suite, manage_utils, concat_error_messages_multiple_default_sep_and_prefix);
+ add_test_with_context (suite, manage_utils, concat_error_messages_custom_separator);
+ add_test_with_context (suite, manage_utils, concat_error_messages_skips_null_and_empty);
+ add_test_with_context (suite, manage_utils, concat_error_messages_all_null_or_empty_returns_null);
+ add_test_with_context (suite, manage_utils, concat_error_messages_null_prefix_means_no_prefix);
+ add_test_with_context (suite, manage_utils, concat_error_messages_empty_separator);
+
if (argc > 1)
return run_single_test (suite, argv[1], create_text_reporter ());
From 53894ddae75d6210599e4f5cf2cd88a6081f20c0 Mon Sep 17 00:00:00 2001
From: ozgen
Date: Fri, 22 Aug 2025 14:21:23 +0200
Subject: [PATCH 6/6] Fix formatting issues
---
src/manage_utils.c | 429 ++++++++++++++++++---------------------
src/manage_utils.h | 3 +-
src/manage_utils_tests.c | 164 ++++++++-------
3 files changed, 286 insertions(+), 310 deletions(-)
diff --git a/src/manage_utils.c b/src/manage_utils.c
index 26d8236bbe..8189737630 100644
--- a/src/manage_utils.c
+++ b/src/manage_utils.c
@@ -27,12 +27,11 @@
#include /* for assert */
#include
-#include /* for getenv */
-#include /* for sscanf */
-#include /* for strcmp */
-
#include
#include
+#include /* for sscanf */
+#include /* for getenv */
+#include /* for strcmp */
#undef G_LOG_DOMAIN
/**
@@ -95,7 +94,7 @@ current_offset (const char *zone)
return 0;
}
tzset ();
- offset = - (now - mktime (&now_broken));
+ offset = -(now - mktime (&now_broken));
/* Revert to stored TZ. */
if (tz)
@@ -167,9 +166,7 @@ manage_count_hosts_max (const char *given_hosts, const char *exclude_hosts,
gchar *clean_exclude_hosts;
clean_exclude_hosts = clean_hosts_string (exclude_hosts);
- if (gvm_hosts_exclude_with_max (hosts,
- clean_exclude_hosts,
- max_hosts)
+ if (gvm_hosts_exclude_with_max (hosts, clean_exclude_hosts, max_hosts)
< 0)
{
g_free (clean_hosts);
@@ -268,7 +265,7 @@ level_max_severity (const char *level)
* @return 1 if host has equal in hosts_str, 0 otherwise.
*/
int
-hosts_str_contains (const char* hosts_str, const char* find_host_str,
+hosts_str_contains (const char *hosts_str, const char *find_host_str,
int max_hosts)
{
gvm_hosts_t *hosts, *find_hosts;
@@ -297,12 +294,12 @@ hosts_str_contains (const char* hosts_str, const char* find_host_str,
* @return 1 yes, 0 no.
*/
int
-valid_db_resource_type (const char* type)
+valid_db_resource_type (const char *type)
{
if (type == NULL)
return 0;
#if ENABLE_AGENTS
- if(strcasecmp (type, "agent_group") == 0)
+ if (strcasecmp (type, "agent_group") == 0)
return 1;
#endif
@@ -312,8 +309,7 @@ valid_db_resource_type (const char* type)
return 1;
#endif /* ENABLE_AGENTS */
- return (strcasecmp (type, "alert") == 0)
- || (strcasecmp (type, "config") == 0)
+ return (strcasecmp (type, "alert") == 0) || (strcasecmp (type, "config") == 0)
|| (strcasecmp (type, "cpe") == 0)
|| (strcasecmp (type, "credential") == 0)
|| (strcasecmp (type, "cve") == 0)
@@ -321,10 +317,8 @@ valid_db_resource_type (const char* type)
|| (strcasecmp (type, "dfn_cert_adv") == 0)
|| (strcasecmp (type, "filter") == 0)
|| (strcasecmp (type, "group") == 0)
- || (strcasecmp (type, "host") == 0)
- || (strcasecmp (type, "os") == 0)
- || (strcasecmp (type, "note") == 0)
- || (strcasecmp (type, "nvt") == 0)
+ || (strcasecmp (type, "host") == 0) || (strcasecmp (type, "os") == 0)
+ || (strcasecmp (type, "note") == 0) || (strcasecmp (type, "nvt") == 0)
#if ENABLE_CONTAINER_SCANNING
|| (strcasecmp (type, "oci_image_target") == 0)
#endif /* ENABLE_CONTAINER_SCANNING */
@@ -354,14 +348,15 @@ void
blank_control_chars (char *string)
{
for (; *string; string++)
- if (iscntrl (*string) && *string != '\n') *string = ' ';
+ if (iscntrl (*string) && *string != '\n')
+ *string = ' ';
}
/**
* @brief GVM product ID.
*/
-#define GVM_PRODID "-//Greenbone.net//NONSGML Greenbone Security Manager " \
- GVMD_VERSION "//EN"
+#define GVM_PRODID \
+ "-//Greenbone.net//NONSGML Greenbone Security Manager " GVMD_VERSION "//EN"
/**
* @brief Try to get a built-in libical timezone from a tzid or city name.
@@ -370,7 +365,7 @@ blank_control_chars (char *string)
*
* @return The built-in timezone if found, else NULL.
*/
-icaltimezone*
+icaltimezone *
icalendar_timezone_from_string (const char *tzid)
{
if (tzid)
@@ -398,9 +393,8 @@ icalendar_timezone_from_string (const char *tzid)
* @return The generated iCalendar component.
*/
icalcomponent *
-icalendar_from_old_schedule_data (time_t first_time,
- time_t period, time_t period_months,
- time_t duration,
+icalendar_from_old_schedule_data (time_t first_time, time_t period,
+ time_t period_months, time_t duration,
int byday_mask)
{
gchar *uid;
@@ -413,8 +407,7 @@ icalendar_from_old_schedule_data (time_t first_time,
// Setup base calendar component
ical_new = icalcomponent_new_vcalendar ();
icalcomponent_add_property (ical_new, icalproperty_new_version ("2.0"));
- icalcomponent_add_property (ical_new,
- icalproperty_new_prodid (GVM_PRODID));
+ icalcomponent_add_property (ical_new, icalproperty_new_prodid (GVM_PRODID));
// Create event component
vevent = icalcomponent_new_vevent ();
@@ -502,13 +495,12 @@ icalendar_from_old_schedule_data (time_t first_time,
if (byday_mask & (1 << mask_bit))
{
recurrence.by_day[array_pos] = ical_day;
- array_pos ++;
+ array_pos++;
}
}
}
- icalcomponent_add_property (vevent,
- icalproperty_new_rrule (recurrence));
+ icalcomponent_add_property (vevent, icalproperty_new_rrule (recurrence));
}
// Add duration
@@ -547,8 +539,8 @@ icalendar_simplify_vevent (icalcomponent *vevent, icaltimezone *zone,
// Check for errors
icalrestriction_check (vevent);
- error_prop = icalcomponent_get_first_property (vevent,
- ICAL_XLICERROR_PROPERTY);
+ error_prop =
+ icalcomponent_get_first_property (vevent, ICAL_XLICERROR_PROPERTY);
if (error_prop)
{
if (error)
@@ -594,12 +586,10 @@ icalendar_simplify_vevent (icalcomponent *vevent, icaltimezone *zone,
* Technically there can be multiple ones but behavior is undefined in
* the iCalendar specification.
*/
- rrule_prop = icalcomponent_get_first_property (vevent,
- ICAL_RRULE_PROPERTY);
+ rrule_prop = icalcomponent_get_first_property (vevent, ICAL_RRULE_PROPERTY);
// Warn about EXRULE being deprecated
- exrule_prop = icalcomponent_get_first_property (vevent,
- ICAL_EXRULE_PROPERTY);
+ exrule_prop = icalcomponent_get_first_property (vevent, ICAL_EXRULE_PROPERTY);
if (exrule_prop)
{
g_string_append_printf (warnings_buffer,
@@ -620,8 +610,7 @@ icalendar_simplify_vevent (icalcomponent *vevent, icaltimezone *zone,
}
// Simplify and copy RDATE properties
- rdate_prop = icalcomponent_get_first_property (vevent,
- ICAL_RDATE_PROPERTY);
+ rdate_prop = icalcomponent_get_first_property (vevent, ICAL_RDATE_PROPERTY);
while (rdate_prop)
{
struct icaldatetimeperiodtype old_datetimeperiod, new_datetimeperiod;
@@ -633,38 +622,36 @@ icalendar_simplify_vevent (icalcomponent *vevent, icaltimezone *zone,
new_datetimeperiod.period = icalperiodtype_null_period ();
if (icalperiodtype_is_null_period (old_datetimeperiod.period))
{
- new_datetimeperiod.time
- = icaltime_convert_to_zone (old_datetimeperiod.time, zone);
+ new_datetimeperiod.time =
+ icaltime_convert_to_zone (old_datetimeperiod.time, zone);
}
else
{
- new_datetimeperiod.time
- = icaltime_convert_to_zone (old_datetimeperiod.period.start, zone);
+ new_datetimeperiod.time =
+ icaltime_convert_to_zone (old_datetimeperiod.period.start, zone);
}
new_rdate = icalproperty_new_rdate (new_datetimeperiod);
icalcomponent_add_property (vevent_simplified, new_rdate);
- rdate_prop
- = icalcomponent_get_next_property (vevent, ICAL_RDATE_PROPERTY);
+ rdate_prop =
+ icalcomponent_get_next_property (vevent, ICAL_RDATE_PROPERTY);
}
// Copy EXDATE properties
- exdate_prop = icalcomponent_get_first_property (vevent,
- ICAL_EXDATE_PROPERTY);
+ exdate_prop = icalcomponent_get_first_property (vevent, ICAL_EXDATE_PROPERTY);
while (exdate_prop)
{
icaltimetype original_exdate_time, exdate_time;
icalproperty *prop_clone;
original_exdate_time = icalproperty_get_exdate (exdate_prop);
- exdate_time
- = icaltime_convert_to_zone (original_exdate_time, zone);
+ exdate_time = icaltime_convert_to_zone (original_exdate_time, zone);
prop_clone = icalproperty_new_exdate (exdate_time);
icalcomponent_add_property (vevent_simplified, prop_clone);
- exdate_prop
- = icalcomponent_get_next_property (vevent, ICAL_EXDATE_PROPERTY);
+ exdate_prop =
+ icalcomponent_get_next_property (vevent, ICAL_EXDATE_PROPERTY);
}
// Generate UID for event
@@ -683,16 +670,16 @@ icalendar_simplify_vevent (icalcomponent *vevent, icaltimezone *zone,
/**
* @brief Error return for icalendar_from_string.
*/
-#define ICAL_RETURN_ERROR(message) \
- do \
- { \
- if (error) \
- *error = message; \
- icalcomponent_free (ical_parsed); \
- icalcomponent_free (ical_new); \
- g_string_free (warnings_buffer, TRUE); \
- return NULL; \
- } \
+#define ICAL_RETURN_ERROR(message) \
+ do \
+ { \
+ if (error) \
+ *error = message; \
+ icalcomponent_free (ical_parsed); \
+ icalcomponent_free (ical_new); \
+ g_string_free (warnings_buffer, TRUE); \
+ return NULL; \
+ } \
while (0)
/**
@@ -726,8 +713,8 @@ icalendar_from_string (const char *ical_string, icaltimezone *zone,
// Check for errors
icalrestriction_check (ical_parsed);
- error_prop = icalcomponent_get_first_property (ical_parsed,
- ICAL_XLICERROR_PROPERTY);
+ error_prop =
+ icalcomponent_get_first_property (ical_parsed, ICAL_XLICERROR_PROPERTY);
if (error_prop)
{
if (error)
@@ -742,109 +729,102 @@ icalendar_from_string (const char *ical_string, icaltimezone *zone,
ical_new = icalcomponent_new_vcalendar ();
icalcomponent_add_property (ical_new, icalproperty_new_version ("2.0"));
- icalcomponent_add_property (ical_new,
- icalproperty_new_prodid (GVM_PRODID));
+ icalcomponent_add_property (ical_new, icalproperty_new_prodid (GVM_PRODID));
- timezone_component
- = icalcomponent_new_clone (icaltimezone_get_component (zone));
+ timezone_component =
+ icalcomponent_new_clone (icaltimezone_get_component (zone));
icalcomponent_add_component (ical_new, timezone_component);
switch (icalcomponent_isa (ical_parsed))
{
- case ICAL_NO_COMPONENT:
- // The text must contain valid iCalendar component
- ICAL_RETURN_ERROR
- (g_strdup_printf ("String contains no iCalendar component"));
- break;
- case ICAL_XROOT_COMPONENT:
- case ICAL_VCALENDAR_COMPONENT:
- // Check multiple components
- ical_iter = icalcomponent_begin_component (ical_parsed,
- ICAL_ANY_COMPONENT);
- icalcomponent *subcomp;
- while ((subcomp = icalcompiter_deref (&ical_iter)))
- {
- icalcomponent *new_vevent;
- switch (icalcomponent_isa (subcomp))
- {
- case ICAL_VEVENT_COMPONENT:
- // Copy and simplify only the first VEVENT, ignoring all
- // following ones.
- if (vevent_count == 0)
- {
- new_vevent = icalendar_simplify_vevent
- (subcomp,
- zone,
- error,
- warnings_buffer);
- if (new_vevent == NULL)
- ICAL_RETURN_ERROR (*error);
- icalcomponent_add_component (ical_new, new_vevent);
- }
- vevent_count ++;
- break;
- case ICAL_VTIMEZONE_COMPONENT:
- // Timezones are collected separately
- break;
- case ICAL_VJOURNAL_COMPONENT:
- case ICAL_VTODO_COMPONENT:
- // VJOURNAL and VTODO components are ignored
- other_component_count ++;
- break;
- default:
- // Unexpected components
- ICAL_RETURN_ERROR
- (g_strdup_printf ("Unexpected component type: %s",
- icalcomponent_kind_to_string
- (icalcomponent_isa (subcomp))));
- }
- icalcompiter_next (&ical_iter);
- }
-
- if (vevent_count == 0)
- {
- ICAL_RETURN_ERROR
- (g_strdup_printf ("iCalendar string must contain a VEVENT"));
- }
- else if (vevent_count > 1)
- {
- g_string_append_printf (warnings_buffer,
- ""
- "iCalendar contains %d VEVENT components"
- " but only the first one will be used"
- "",
- vevent_count);
- }
-
- if (other_component_count)
- {
- g_string_append_printf (warnings_buffer,
- ""
- "iCalendar contains %d VTODO and/or"
- " VJOURNAL component(s) which will be"
- " ignored"
- "",
- other_component_count);
- }
- break;
- case ICAL_VEVENT_COMPONENT:
+ case ICAL_NO_COMPONENT:
+ // The text must contain valid iCalendar component
+ ICAL_RETURN_ERROR (
+ g_strdup_printf ("String contains no iCalendar component"));
+ break;
+ case ICAL_XROOT_COMPONENT:
+ case ICAL_VCALENDAR_COMPONENT:
+ // Check multiple components
+ ical_iter =
+ icalcomponent_begin_component (ical_parsed, ICAL_ANY_COMPONENT);
+ icalcomponent *subcomp;
+ while ((subcomp = icalcompiter_deref (&ical_iter)))
{
icalcomponent *new_vevent;
+ switch (icalcomponent_isa (subcomp))
+ {
+ case ICAL_VEVENT_COMPONENT:
+ // Copy and simplify only the first VEVENT, ignoring all
+ // following ones.
+ if (vevent_count == 0)
+ {
+ new_vevent = icalendar_simplify_vevent (subcomp, zone, error,
+ warnings_buffer);
+ if (new_vevent == NULL)
+ ICAL_RETURN_ERROR (*error);
+ icalcomponent_add_component (ical_new, new_vevent);
+ }
+ vevent_count++;
+ break;
+ case ICAL_VTIMEZONE_COMPONENT:
+ // Timezones are collected separately
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ case ICAL_VTODO_COMPONENT:
+ // VJOURNAL and VTODO components are ignored
+ other_component_count++;
+ break;
+ default:
+ // Unexpected components
+ ICAL_RETURN_ERROR (g_strdup_printf (
+ "Unexpected component type: %s",
+ icalcomponent_kind_to_string (icalcomponent_isa (subcomp))));
+ }
+ icalcompiter_next (&ical_iter);
+ }
- new_vevent = icalendar_simplify_vevent (ical_parsed,
- zone,
- error,
- warnings_buffer);
- if (new_vevent == NULL)
- ICAL_RETURN_ERROR (*error);
- icalcomponent_add_component (ical_new, new_vevent);
+ if (vevent_count == 0)
+ {
+ ICAL_RETURN_ERROR (
+ g_strdup_printf ("iCalendar string must contain a VEVENT"));
}
- break;
- default:
- ICAL_RETURN_ERROR
- (g_strdup_printf ("iCalendar string must be a VCALENDAR or VEVENT"
- " component or consist of multiple elements."));
- break;
+ else if (vevent_count > 1)
+ {
+ g_string_append_printf (warnings_buffer,
+ ""
+ "iCalendar contains %d VEVENT components"
+ " but only the first one will be used"
+ "",
+ vevent_count);
+ }
+
+ if (other_component_count)
+ {
+ g_string_append_printf (warnings_buffer,
+ ""
+ "iCalendar contains %d VTODO and/or"
+ " VJOURNAL component(s) which will be"
+ " ignored"
+ "",
+ other_component_count);
+ }
+ break;
+ case ICAL_VEVENT_COMPONENT:
+ {
+ icalcomponent *new_vevent;
+
+ new_vevent =
+ icalendar_simplify_vevent (ical_parsed, zone, error, warnings_buffer);
+ if (new_vevent == NULL)
+ ICAL_RETURN_ERROR (*error);
+ icalcomponent_add_component (ical_new, new_vevent);
+ }
+ break;
+ default:
+ ICAL_RETURN_ERROR (
+ g_strdup_printf ("iCalendar string must be a VCALENDAR or VEVENT"
+ " component or consist of multiple elements."));
+ break;
}
icalcomponent_free (ical_parsed);
@@ -878,7 +858,6 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
icalcomponent *vevent;
icalproperty *rrule_prop;
-
assert (period);
assert (period_months);
assert (byday_mask);
@@ -894,14 +873,12 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
// Process only the first VEVENT
// Others should be removed by icalendar_from_string
- vevent = icalcomponent_get_first_component (vcalendar,
- ICAL_VEVENT_COMPONENT);
+ vevent = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
if (vevent == NULL)
return -1;
// Process only first RRULE.
- rrule_prop = icalcomponent_get_first_property (vevent,
- ICAL_RRULE_PROPERTY);
+ rrule_prop = icalcomponent_get_first_property (vevent, ICAL_RRULE_PROPERTY);
if (rrule_prop)
{
struct icalrecurrencetype recurrence;
@@ -911,30 +888,30 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
// Get period or period_months
switch (recurrence.freq)
{
- case ICAL_YEARLY_RECURRENCE:
- *period_months = recurrence.interval * 12;
- break;
- case ICAL_MONTHLY_RECURRENCE:
- *period_months = recurrence.interval;
- break;
- case ICAL_WEEKLY_RECURRENCE:
- *period = recurrence.interval * 604800;
- break;
- case ICAL_DAILY_RECURRENCE:
- *period = recurrence.interval * 86400;
- break;
- case ICAL_HOURLY_RECURRENCE:
- *period = recurrence.interval * 3600;
- break;
- case ICAL_MINUTELY_RECURRENCE:
- *period = recurrence.interval * 60;
- break;
- case ICAL_SECONDLY_RECURRENCE:
- *period = recurrence.interval;
- case ICAL_NO_RECURRENCE:
- break;
- default:
- return -1;
+ case ICAL_YEARLY_RECURRENCE:
+ *period_months = recurrence.interval * 12;
+ break;
+ case ICAL_MONTHLY_RECURRENCE:
+ *period_months = recurrence.interval;
+ break;
+ case ICAL_WEEKLY_RECURRENCE:
+ *period = recurrence.interval * 604800;
+ break;
+ case ICAL_DAILY_RECURRENCE:
+ *period = recurrence.interval * 86400;
+ break;
+ case ICAL_HOURLY_RECURRENCE:
+ *period = recurrence.interval * 3600;
+ break;
+ case ICAL_MINUTELY_RECURRENCE:
+ *period = recurrence.interval * 60;
+ break;
+ case ICAL_SECONDLY_RECURRENCE:
+ *period = recurrence.interval;
+ case ICAL_NO_RECURRENCE:
+ break;
+ default:
+ return -1;
}
/*
@@ -945,8 +922,8 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
array_pos = 0;
while (recurrence.by_day[array_pos] != ICAL_RECURRENCE_ARRAY_MAX)
{
- int ical_day = icalrecurrencetype_day_day_of_week
- (recurrence.by_day[array_pos]);
+ int ical_day =
+ icalrecurrencetype_day_day_of_week (recurrence.by_day[array_pos]);
int mask_bit = -1;
if (ical_day == 1)
@@ -958,7 +935,7 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
{
*byday_mask |= (1 << mask_bit);
}
- array_pos ++;
+ array_pos++;
}
}
@@ -975,10 +952,10 @@ icalendar_approximate_rrule_from_vcalendar (icalcomponent *vcalendar,
*
* @return GPtrArray with pointers to collected times or NULL on error.
*/
-static GPtrArray*
+static GPtrArray *
icalendar_times_from_vevent (icalcomponent *vevent, icalproperty_kind type)
{
- GPtrArray* times;
+ GPtrArray *times;
icalproperty *date_prop;
if (icalcomponent_isa (vevent) != ICAL_VEVENT_COMPONENT
@@ -1029,9 +1006,7 @@ icalendar_time_matches_array (icaltimetype time, GPtrArray *times_array)
if (times_array == NULL)
return FALSE;
- for (index = 0;
- found == FALSE && index < times_array->len;
- index++)
+ for (index = 0; found == FALSE && index < times_array->len; index++)
{
int compare_result;
icaltimetype *array_time = g_ptr_array_index (times_array, index);
@@ -1058,10 +1033,8 @@ icalendar_time_matches_array (icaltimetype time, GPtrArray *times_array)
* @return The next or previous time as time_t.
*/
static time_t
-icalendar_next_time_from_rdates (GPtrArray *rdates,
- icaltimetype ref_time_ical,
- icaltimezone *tz,
- int periods_offset)
+icalendar_next_time_from_rdates (GPtrArray *rdates, icaltimetype ref_time_ical,
+ icaltimezone *tz, int periods_offset)
{
int index;
time_t ref_time, closest_time;
@@ -1114,10 +1087,8 @@ static time_t
icalendar_next_time_from_recurrence (struct icalrecurrencetype recurrence,
icaltimetype dtstart,
icaltimetype reference_time,
- icaltimezone *tz,
- GPtrArray *exdates,
- GPtrArray *rdates,
- int periods_offset)
+ icaltimezone *tz, GPtrArray *exdates,
+ GPtrArray *rdates, int periods_offset)
{
icalrecur_iterator *recur_iter;
icaltimetype recur_time, prev_time, next_time;
@@ -1251,8 +1222,7 @@ icalendar_next_time_from_vcalendar (icalcomponent *vcalendar,
// Process only the first VEVENT
// Others should be removed by icalendar_from_string
- vevent = icalcomponent_get_first_component (vcalendar,
- ICAL_VEVENT_COMPONENT);
+ vevent = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
if (vevent == NULL)
return 0;
@@ -1261,7 +1231,7 @@ icalendar_next_time_from_vcalendar (icalcomponent *vcalendar,
if (icaltime_is_null_time (dtstart))
return 0;
- tz = (icaltimezone*) icaltime_get_timezone (dtstart);
+ tz = (icaltimezone *) icaltime_get_timezone (dtstart);
if (tz == NULL)
{
tz = icalendar_timezone_from_string (default_tzid);
@@ -1294,11 +1264,9 @@ icalendar_next_time_from_vcalendar (icalcomponent *vcalendar,
icalrecurrencetype_clear (&recurrence);
// Calculate next time.
- next_time = icalendar_next_time_from_recurrence (recurrence,
- dtstart_with_tz,
- ical_reference_time, tz,
- exdates, rdates,
- periods_offset);
+ next_time = icalendar_next_time_from_recurrence (
+ recurrence, dtstart_with_tz, ical_reference_time, tz, exdates, rdates,
+ periods_offset);
// Cleanup
g_ptr_array_free (exdates, TRUE);
@@ -1321,19 +1289,15 @@ icalendar_next_time_from_vcalendar (icalcomponent *vcalendar,
* @return The next or previous time as a time_t.
*/
time_t
-icalendar_next_time_from_string (const char *ical_string,
- time_t reference_time,
- const char *default_tzid,
- int periods_offset)
+icalendar_next_time_from_string (const char *ical_string, time_t reference_time,
+ const char *default_tzid, int periods_offset)
{
time_t next_time;
icalcomponent *ical_parsed;
ical_parsed = icalcomponent_new_from_string (ical_string);
- next_time = icalendar_next_time_from_vcalendar (ical_parsed,
- reference_time,
- default_tzid,
- periods_offset);
+ next_time = icalendar_next_time_from_vcalendar (ical_parsed, reference_time,
+ default_tzid, periods_offset);
icalcomponent_free (ical_parsed);
return next_time;
}
@@ -1360,8 +1324,7 @@ icalendar_duration_from_vcalendar (icalcomponent *vcalendar)
// Process only the first VEVENT
// Others should be removed by icalendar_from_string
- vevent = icalcomponent_get_first_component (vcalendar,
- ICAL_VEVENT_COMPONENT);
+ vevent = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
if (vevent == NULL)
return 0;
@@ -1397,8 +1360,7 @@ icalendar_first_time_from_vcalendar (icalcomponent *vcalendar,
// Process only the first VEVENT
// Others should be removed by icalendar_from_string
- vevent = icalcomponent_get_first_component (vcalendar,
- ICAL_VEVENT_COMPONENT);
+ vevent = icalcomponent_get_first_component (vcalendar, ICAL_VEVENT_COMPONENT);
if (vevent == NULL)
return 0;
@@ -1407,7 +1369,7 @@ icalendar_first_time_from_vcalendar (icalcomponent *vcalendar,
if (icaltime_is_null_time (dtstart))
return 0;
- tz = (icaltimezone*) icaltime_get_timezone (dtstart);
+ tz = (icaltimezone *) icaltime_get_timezone (dtstart);
if (tz == NULL)
tz = default_tz;
@@ -1443,20 +1405,20 @@ clean_hosts_string (const char *hosts)
* - A final group of digits, separated with a slash "-"
* (CIDR notation, e.g. "192.168.123.001/027)
*/
- ipv4_match_regex
- = g_regex_new ("^[0-9]+(?:\\.[0-9]+){3}"
- "(?:\\/[0-9]+|-[0-9]+(?:(?:\\.[0-9]+){3})?)?$",
- 0, 0, NULL);
+ ipv4_match_regex =
+ g_regex_new ("^[0-9]+(?:\\.[0-9]+){3}"
+ "(?:\\/[0-9]+|-[0-9]+(?:(?:\\.[0-9]+){3})?)?$",
+ 0, 0, NULL);
/*
* Regular expression matching leading zeroes in groups of digits
* separated by dots or other characters.
* First line matches zeroes before non-zero numbers, e.g. "000" in "000120"
* Second line matches groups of all zeroes except one, e.g. "00" in "000"
*/
- ipv4_replace_regex
- = g_regex_new ("(?<=\\D|^)(0+)(?=(?:(?:[1-9]\\d*)(?:\\D|$)))"
- "|(?<=\\D|^)(0+)(?=0(?:\\D|$))",
- 0, 0, NULL);
+ ipv4_replace_regex =
+ g_regex_new ("(?<=\\D|^)(0+)(?=(?:(?:[1-9]\\d*)(?:\\D|$)))"
+ "|(?<=\\D|^)(0+)(?=0(?:\\D|$))",
+ 0, 0, NULL);
new_hosts = g_string_new ("");
hosts_split = g_strsplit (hosts, ",", -1);
@@ -1472,8 +1434,8 @@ clean_hosts_string (const char *hosts)
* with empty strings,
* e.g. "000.001.002.003-004" becomes "0.1.2.3-4"
*/
- new_item = g_regex_replace (ipv4_replace_regex,
- *item, -1, 0, "", 0, NULL);
+ new_item =
+ g_regex_replace (ipv4_replace_regex, *item, -1, 0, "", 0, NULL);
g_string_append (new_hosts, new_item);
g_free (new_item);
}
@@ -1503,7 +1465,8 @@ clean_hosts_string (const char *hosts)
* Caller must g_free().
*/
gchar *
-concat_error_messages (const GPtrArray *errors, const gchar *sep, const gchar *prefix)
+concat_error_messages (const GPtrArray *errors, const gchar *sep,
+ const gchar *prefix)
{
if (!errors || errors->len == 0)
return NULL;
@@ -1517,7 +1480,7 @@ concat_error_messages (const GPtrArray *errors, const gchar *sep, const gchar *p
for (guint i = 0; i < errors->len; ++i)
{
- const gchar *m = g_ptr_array_index ((GPtrArray *)errors, i);
+ const gchar *m = g_ptr_array_index ((GPtrArray *) errors, i);
if (!m || !*m)
continue;
diff --git a/src/manage_utils.h b/src/manage_utils.h
index cf59bf5cf5..dcf78a12b7 100644
--- a/src/manage_utils.h
+++ b/src/manage_utils.h
@@ -102,6 +102,7 @@ gchar *
clean_hosts_string (const char *);
gchar *
-concat_error_messages (const GPtrArray *errors, const gchar *sep, const gchar *prefix);
+concat_error_messages (const GPtrArray *errors, const gchar *sep,
+ const gchar *prefix);
#endif /* not _GVMD_MANAGE_UTILS_H */
diff --git a/src/manage_utils_tests.c b/src/manage_utils_tests.c
index 1e48fe91b7..2c00ec195c 100644
--- a/src/manage_utils_tests.c
+++ b/src/manage_utils_tests.c
@@ -22,8 +22,12 @@
#include
Describe (manage_utils);
-BeforeEach (manage_utils) {}
-AfterEach (manage_utils) {}
+BeforeEach (manage_utils)
+{
+}
+AfterEach (manage_utils)
+{
+}
/* add_months */
@@ -93,38 +97,34 @@ Ensure (manage_utils, icalendar_next_time_from_string_utc)
/* Start in past. */
now = time (NULL);
- next = icalendar_next_time_from_string
- ("BEGIN:VCALENDAR\n"
- "VERSION:2.0\n"
- "BEGIN:VEVENT\n"
- "DTSTART:20200101T000000Z\n"
- "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
- "DURATION:PT0S\n"
- "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
- "DTSTAMP:19700101T000000Z\n"
- "END:VEVENT\n"
- "END:VCALENDAR\n",
- now,
- "UTC",
- 0);
+ next = icalendar_next_time_from_string (
+ "BEGIN:VCALENDAR\n"
+ "VERSION:2.0\n"
+ "BEGIN:VEVENT\n"
+ "DTSTART:20200101T000000Z\n"
+ "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
+ "DURATION:PT0S\n"
+ "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
+ "DTSTAMP:19700101T000000Z\n"
+ "END:VEVENT\n"
+ "END:VCALENDAR\n",
+ now, "UTC", 0);
assert_that (verify_next (next, EPOCH_2020JAN1_UTC, now, 2 * 60),
is_equal_to (1));
/* Start in future. */
- next = icalendar_next_time_from_string
- ("BEGIN:VCALENDAR\n"
- "VERSION:2.0\n"
- "BEGIN:VEVENT\n"
- "DTSTART:20300101T000000Z\n"
- "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
- "DURATION:PT0S\n"
- "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
- "DTSTAMP:19700101T000000Z\n"
- "END:VEVENT\n"
- "END:VCALENDAR\n",
- now,
- "UTC",
- 0);
+ next = icalendar_next_time_from_string (
+ "BEGIN:VCALENDAR\n"
+ "VERSION:2.0\n"
+ "BEGIN:VEVENT\n"
+ "DTSTART:20300101T000000Z\n"
+ "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
+ "DURATION:PT0S\n"
+ "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
+ "DTSTAMP:19700101T000000Z\n"
+ "END:VEVENT\n"
+ "END:VCALENDAR\n",
+ now, "UTC", 0);
assert_that (next, is_equal_to (EPOCH_2030JAN1_UTC));
}
@@ -134,35 +134,34 @@ Ensure (manage_utils, icalendar_next_time_from_string_tz)
now = time (NULL);
- next = icalendar_next_time_from_string
- ("BEGIN:VCALENDAR\n"
- "VERSION:2.0\n"
- /* Timezone definition. */
- "BEGIN:VTIMEZONE\n"
- "TZID:/freeassociation.sourceforge.net/Africa/Harare\n"
- "X-LIC-LOCATION:Africa/Harare\n"
- "BEGIN:STANDARD\n"
- "TZNAME:CAT\n"
- "DTSTART:19030301T000000\n"
- "TZOFFSETFROM:+021020\n"
- "TZOFFSETTO:+0200\n"
- "END:STANDARD\n"
- "END:VTIMEZONE\n"
- /* Event. */
- "BEGIN:VEVENT\n"
- "DTSTART;TZID=/freeassociation.sourceforge.net/Africa/Harare:\n"
- " 20200101T000000\n"
- "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
- "DURATION:PT0S\n"
- "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
- "DTSTAMP:19700101T000000Z\n"
- "END:VEVENT\n"
- "END:VCALENDAR\n",
- now,
- "Africa/Harare",
- 0);
-
- assert_that (verify_next (next, EPOCH_2020JAN1_HAR, now, 2 * 60), is_equal_to (1));
+ next = icalendar_next_time_from_string (
+ "BEGIN:VCALENDAR\n"
+ "VERSION:2.0\n"
+ /* Timezone definition. */
+ "BEGIN:VTIMEZONE\n"
+ "TZID:/freeassociation.sourceforge.net/Africa/Harare\n"
+ "X-LIC-LOCATION:Africa/Harare\n"
+ "BEGIN:STANDARD\n"
+ "TZNAME:CAT\n"
+ "DTSTART:19030301T000000\n"
+ "TZOFFSETFROM:+021020\n"
+ "TZOFFSETTO:+0200\n"
+ "END:STANDARD\n"
+ "END:VTIMEZONE\n"
+ /* Event. */
+ "BEGIN:VEVENT\n"
+ "DTSTART;TZID=/freeassociation.sourceforge.net/Africa/Harare:\n"
+ " 20200101T000000\n"
+ "RRULE:FREQ=MINUTELY;INTERVAL=2\n"
+ "DURATION:PT0S\n"
+ "UID:a486116b-8058-4b1e-9fc5-0eeec5948792\n"
+ "DTSTAMP:19700101T000000Z\n"
+ "END:VEVENT\n"
+ "END:VCALENDAR\n",
+ now, "Africa/Harare", 0);
+
+ assert_that (verify_next (next, EPOCH_2020JAN1_HAR, now, 2 * 60),
+ is_equal_to (1));
}
/* Hosts test */
@@ -199,9 +198,8 @@ Ensure (manage_utils, clean_hosts_string_zeroes)
// List of addresses and ranges
clean_str = clean_hosts_string ("000.001.002.003, 040.050.060.070-80,"
" 123.012.001.001-123.012.001.010");
- assert_that (clean_str,
- is_equal_to_string ("0.1.2.3, 40.50.60.70-80,"
- " 123.12.1.1-123.12.1.10"));
+ assert_that (clean_str, is_equal_to_string ("0.1.2.3, 40.50.60.70-80,"
+ " 123.12.1.1-123.12.1.10"));
g_free (clean_str);
}
@@ -227,7 +225,8 @@ Ensure (manage_utils, concat_error_messages_single_item_with_prefix)
GPtrArray *arr = make_str_array (vals, 1);
gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
- assert_that (s, is_equal_to_string ("Validation failed for : attempts must be >= 0"));
+ assert_that (
+ s, is_equal_to_string ("Validation failed for : attempts must be >= 0"));
g_free (s);
g_ptr_array_free (arr, TRUE);
@@ -235,12 +234,14 @@ Ensure (manage_utils, concat_error_messages_single_item_with_prefix)
Ensure (manage_utils, concat_error_messages_multiple_default_sep_and_prefix)
{
- const char *vals[] = {"period_in_seconds required", "bulk_size must be positive", "cron invalid"};
+ const char *vals[] = {"period_in_seconds required",
+ "bulk_size must be positive", "cron invalid"};
GPtrArray *arr = make_str_array (vals, 3);
gchar *s = concat_error_messages (arr, NULL, "Validation failed for : ");
assert_that (s, is_equal_to_string (
- "Validation failed for : period_in_seconds required; bulk_size must be positive; cron invalid"));
+ "Validation failed for : period_in_seconds required; "
+ "bulk_size must be positive; cron invalid"));
g_free (s);
g_ptr_array_free (arr, TRUE);
@@ -318,20 +319,31 @@ main (int argc, char **argv)
add_test_with_context (suite, manage_utils, add_months_negative_months);
add_test_with_context (suite, manage_utils, add_months_positive_months);
- add_test_with_context (suite, manage_utils, icalendar_next_time_from_string_utc);
- add_test_with_context (suite, manage_utils, icalendar_next_time_from_string_tz);
+ add_test_with_context (suite, manage_utils,
+ icalendar_next_time_from_string_utc);
+ add_test_with_context (suite, manage_utils,
+ icalendar_next_time_from_string_tz);
add_test_with_context (suite, manage_utils, clean_hosts_string_zeroes);
- add_test_with_context (suite, manage_utils, concat_error_messages_null_array_returns_null);
- add_test_with_context (suite, manage_utils, concat_error_messages_empty_array_returns_null);
- add_test_with_context (suite, manage_utils, concat_error_messages_single_item_with_prefix);
- add_test_with_context (suite, manage_utils, concat_error_messages_multiple_default_sep_and_prefix);
- add_test_with_context (suite, manage_utils, concat_error_messages_custom_separator);
- add_test_with_context (suite, manage_utils, concat_error_messages_skips_null_and_empty);
- add_test_with_context (suite, manage_utils, concat_error_messages_all_null_or_empty_returns_null);
- add_test_with_context (suite, manage_utils, concat_error_messages_null_prefix_means_no_prefix);
- add_test_with_context (suite, manage_utils, concat_error_messages_empty_separator);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_null_array_returns_null);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_empty_array_returns_null);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_single_item_with_prefix);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_multiple_default_sep_and_prefix);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_custom_separator);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_skips_null_and_empty);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_all_null_or_empty_returns_null);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_null_prefix_means_no_prefix);
+ add_test_with_context (suite, manage_utils,
+ concat_error_messages_empty_separator);
if (argc > 1)
return run_single_test (suite, argv[1], create_text_reporter ());