From b7c0a6e4d3c7129b149064dded721004046468be Mon Sep 17 00:00:00 2001 From: ozgen Date: Thu, 18 Jun 2026 11:42:31 +0200 Subject: [PATCH 1/3] add: support origin URL in agent installer instructions Add an optional origin_url parameter when requesting agent installer instructions from the Agent Controller. URL-encode the origin URL before adding it to the request query and update the unit tests to cover URLs with reserved characters, empty values, and failed requests. --- agent_controller/agent_controller.c | 57 +++++++++++++---- agent_controller/agent_controller.h | 3 +- agent_controller/agent_controller_tests.c | 78 ++++++++++++++++++++++- 3 files changed, 122 insertions(+), 16 deletions(-) diff --git a/agent_controller/agent_controller.c b/agent_controller/agent_controller.c index 3fc58989..89f48aab 100644 --- a/agent_controller/agent_controller.c +++ b/agent_controller/agent_controller.c @@ -1971,24 +1971,33 @@ agent_controller_get_scan_id (const gchar *body) /** * @brief Retrieves installer instructions for agents. * - * @param[in] conn Active connector to the Agent Controller - * @param[in] lang_type Language type for the instructions + * @param[in] conn Active connector to the Agent Controller. + * @param[in] lang_type Language type for the instructions. + * @param[in] origin_url Origin URL included in the installer instructions. + * May be NULL or empty. * * @return Newly allocated installer instruction struct on success, NULL on * failure. Caller must free with - * agent_controller_installer_instruction_free(). + * agent_controller_installer_instruction_free(). */ agent_controller_installer_instruction_t agent_controller_get_installer_instruction (agent_controller_connector_t conn, - instructions_lang_type_t lang_type) + instructions_lang_type_t lang_type, + const gchar *origin_url) { + gvm_http_headers_t *headers; + gvm_http_response_t *response; + agent_controller_installer_instruction_t instr; + gchar *escaped_origin_url = NULL; + gchar *path; + if (!conn) { g_warning ("%s: Connector is NULL", __func__); return NULL; } - gvm_http_headers_t *headers = init_custom_header (conn->apikey, FALSE); + headers = init_custom_header (conn->apikey, FALSE); if (!headers) return NULL; @@ -1998,11 +2007,36 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn, return NULL; } - gchar *path = g_strdup_printf ( - "/agent-control/public/v2/api/installers/instructions?lang=%s", - instructions_lang_type_to_str (lang_type)); + if (origin_url && *origin_url) + { + escaped_origin_url = g_uri_escape_string (origin_url, NULL, FALSE); + if (!escaped_origin_url) + { + gvm_http_headers_free (headers); + return NULL; + } - gvm_http_response_t *response = + path = g_strdup_printf ( + "/agent-control/public/v2/api/installers/instructions" + "?lang=%s&origin_url=%s", + instructions_lang_type_to_str (lang_type), escaped_origin_url); + + g_free (escaped_origin_url); + } + else + { + path = g_strdup_printf ( + "/agent-control/public/v2/api/installers/instructions?lang=%s", + instructions_lang_type_to_str (lang_type)); + } + + if (!path) + { + gvm_http_headers_free (headers); + return NULL; + } + + response = agent_controller_send_request_with_headers (conn, GET, path, NULL, headers); gvm_http_headers_free (headers); @@ -2022,9 +2056,7 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn, return NULL; } - agent_controller_installer_instruction_t instr = - agent_controller_installer_instruction_new (); - + instr = agent_controller_installer_instruction_new (); if (!instr) { gvm_http_response_free (response); @@ -2035,6 +2067,7 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn, instr->instruction = response->data ? g_strdup (response->data) : NULL; gvm_http_response_free (response); + return instr; } diff --git a/agent_controller/agent_controller.h b/agent_controller/agent_controller.h index c3b9b4c5..26bb00bf 100644 --- a/agent_controller/agent_controller.h +++ b/agent_controller/agent_controller.h @@ -359,7 +359,8 @@ agent_controller_parse_scan_agent_config_string (const gchar *); agent_controller_installer_instruction_t agent_controller_get_installer_instruction (agent_controller_connector_t conn, - instructions_lang_type_t lang_type); + instructions_lang_type_t lang_type, + const gchar *origin_url); agent_controller_support_bundle_t agent_controller_download_support_bundle (agent_controller_connector_t conn, diff --git a/agent_controller/agent_controller_tests.c b/agent_controller/agent_controller_tests.c index 07d01ede..f67bb57f 100644 --- a/agent_controller/agent_controller_tests.c +++ b/agent_controller/agent_controller_tests.c @@ -3466,7 +3466,7 @@ Ensure (agent_controller, mock_response_data = g_strdup ("{\"instruction\":\"install agent\"}"); agent_controller_installer_instruction_t instr = - agent_controller_get_installer_instruction (conn, EN); + agent_controller_get_installer_instruction (conn, EN, NULL); assert_that (instr, is_not_null); assert_that (instr->lang_type, is_equal_to (EN)); @@ -3498,7 +3498,7 @@ Ensure (agent_controller, mock_response_data = g_strdup ("{\"instruction\":\"agent installieren\"}"); agent_controller_installer_instruction_t instr = - agent_controller_get_installer_instruction (conn, DE); + agent_controller_get_installer_instruction (conn, DE, NULL); assert_that (instr, is_not_null); assert_that (instr->lang_type, is_equal_to (DE)); @@ -3513,6 +3513,53 @@ Ensure (agent_controller, agent_controller_connector_free (conn); } +Ensure (agent_controller, get_installer_instruction_includes_encoded_origin_url) +{ + agent_controller_connector_t conn = make_conn (); + + mock_http_status = 200; + mock_response_data = g_strdup ("{\"instruction\":\"install agent\"}"); + + agent_controller_installer_instruction_t instr = + agent_controller_get_installer_instruction ( + conn, EN, "https://example.com:8443/gsa/path?foo=bar&value=one two"); + + assert_that (instr, is_not_null); + assert_that (instr->lang_type, is_equal_to (EN)); + assert_that (instr->instruction, + is_equal_to_string ("{\"instruction\":\"install agent\"}")); + + assert_that (last_sent_url, + is_equal_to_string ( + "http://localhost:8081/agent-control/public/" + "v2/api/installers/instructions?lang=en" + "&origin_url=https%3A%2F%2Fexample.com%3A8443%2Fgsa%2Fpath" + "%3Ffoo%3Dbar%26value%3Done%20two")); + + agent_controller_installer_instruction_free (instr); + agent_controller_connector_free (conn); +} + +Ensure (agent_controller, get_installer_instruction_omits_empty_origin_url) +{ + agent_controller_connector_t conn = make_conn (); + + mock_http_status = 200; + mock_response_data = g_strdup ("{\"instruction\":\"install agent\"}"); + + agent_controller_installer_instruction_t instr = + agent_controller_get_installer_instruction (conn, EN, ""); + + assert_that (instr, is_not_null); + + assert_that (last_sent_url, + is_equal_to_string ("http://localhost:8081/agent-control/public/" + "v2/api/installers/instructions?lang=en")); + + agent_controller_installer_instruction_free (instr); + agent_controller_connector_free (conn); +} + Ensure (agent_controller, get_installer_instruction_returns_null_when_request_fails) { @@ -3522,7 +3569,7 @@ Ensure (agent_controller, g_clear_pointer (&mock_response_data, g_free); agent_controller_installer_instruction_t instr = - agent_controller_get_installer_instruction (conn, EN); + agent_controller_get_installer_instruction (conn, EN, NULL); assert_that (instr, is_null); assert_that (last_sent_url, @@ -3532,6 +3579,28 @@ Ensure (agent_controller, agent_controller_connector_free (conn); } +Ensure (agent_controller, + get_installer_instruction_returns_null_when_request_with_origin_fails) +{ + agent_controller_connector_t conn = make_conn (); + + mock_http_status = 500; + g_clear_pointer (&mock_response_data, g_free); + + agent_controller_installer_instruction_t instr = + agent_controller_get_installer_instruction (conn, DE, + "https://example.com"); + + assert_that (instr, is_null); + + assert_that (last_sent_url, + is_equal_to_string ("http://localhost:8081/agent-control/public/" + "v2/api/installers/instructions?lang=de" + "&origin_url=https%3A%2F%2Fexample.com")); + + agent_controller_connector_free (conn); +} + Ensure (agent_controller, content_disposition_filename_extracts_filename) { const gchar *header = @@ -4212,6 +4281,9 @@ main (int argc, char **argv) add_test_with_context ( suite, agent_controller, get_installer_instruction_returns_null_when_request_fails); + add_test_with_context ( + suite, agent_controller, + get_installer_instruction_returns_null_when_request_with_origin_fails); add_test_with_context (suite, agent_controller, content_disposition_filename_extracts_filename); From d63ed07c611ccdeea756d05e887f69ffd40fb606 Mon Sep 17 00:00:00 2001 From: ozgen Date: Thu, 18 Jun 2026 11:51:41 +0200 Subject: [PATCH 2/3] refactor: reduce origin URL variable scope --- agent_controller/agent_controller.c | 7 ++++++- agent_controller/agent_controller_tests.c | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/agent_controller/agent_controller.c b/agent_controller/agent_controller.c index 89f48aab..b1d44cf9 100644 --- a/agent_controller/agent_controller.c +++ b/agent_controller/agent_controller.c @@ -1988,7 +1988,6 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn, gvm_http_headers_t *headers; gvm_http_response_t *response; agent_controller_installer_instruction_t instr; - gchar *escaped_origin_url = NULL; gchar *path; if (!conn) @@ -2009,6 +2008,12 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn, if (origin_url && *origin_url) { + gchar *escaped_origin_url; + + /* + * Pass origin_url so the Agent Controller can include the correct server + * address in the generated executable installation command. + */ escaped_origin_url = g_uri_escape_string (origin_url, NULL, FALSE); if (!escaped_origin_url) { diff --git a/agent_controller/agent_controller_tests.c b/agent_controller/agent_controller_tests.c index f67bb57f..e1e5c22b 100644 --- a/agent_controller/agent_controller_tests.c +++ b/agent_controller/agent_controller_tests.c @@ -4281,6 +4281,12 @@ main (int argc, char **argv) add_test_with_context ( suite, agent_controller, get_installer_instruction_returns_null_when_request_fails); + add_test_with_context ( + suite, agent_controller, + get_installer_instruction_includes_encoded_origin_url); + add_test_with_context ( + suite, agent_controller, + get_installer_instruction_omits_empty_origin_url); add_test_with_context ( suite, agent_controller, get_installer_instruction_returns_null_when_request_with_origin_fails); From 7c85e7fdc64f3f90c985f32454e0911338288ccc Mon Sep 17 00:00:00 2001 From: ozgen Date: Thu, 18 Jun 2026 12:04:55 +0200 Subject: [PATCH 3/3] ix formatting issues --- agent_controller/agent_controller_tests.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/agent_controller/agent_controller_tests.c b/agent_controller/agent_controller_tests.c index e1e5c22b..05df1819 100644 --- a/agent_controller/agent_controller_tests.c +++ b/agent_controller/agent_controller_tests.c @@ -4281,12 +4281,10 @@ main (int argc, char **argv) add_test_with_context ( suite, agent_controller, get_installer_instruction_returns_null_when_request_fails); - add_test_with_context ( - suite, agent_controller, - get_installer_instruction_includes_encoded_origin_url); - add_test_with_context ( - suite, agent_controller, - get_installer_instruction_omits_empty_origin_url); + add_test_with_context (suite, agent_controller, + get_installer_instruction_includes_encoded_origin_url); + add_test_with_context (suite, agent_controller, + get_installer_instruction_omits_empty_origin_url); add_test_with_context ( suite, agent_controller, get_installer_instruction_returns_null_when_request_with_origin_fails);