Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions agent_controller/agent_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,37 @@ agent_controller_parse_scan_agent_config (cJSON *root)
return d;
}

/**
* @brief Extract the filename from a Content-Disposition header value.
*
* @param[in] content_disposition The Content-Disposition header value to parse.
*
* @return A newly allocated string containing the filename, or NULL if not
* found. The caller is responsible for freeing the returned string
* with g_free().
*/
static gchar *
content_disposition_filename (const gchar *content_disposition)
{
const gchar *start;
const gchar *end;

if (!content_disposition)
return NULL;

start = strstr (content_disposition, "filename=\"");
if (!start)
return NULL;

start += strlen ("filename=\"");
end = strchr (start, '"');

if (!end || end == start)
return NULL;

return g_strndup (start, end - start);
}

/**
* @brief Creates a new Agent Controller connector.
*/
Expand Down Expand Up @@ -1221,6 +1252,33 @@ agent_controller_installer_instruction_free (
g_free (instr);
}

/**
* @brief Allocate/zero a new support bundle struct.
*
* @return Newly allocated support bundle struct
*/
agent_controller_support_bundle_t
agent_controller_support_bundle_new (void)
{
return g_malloc0 (sizeof (struct agent_controller_support_bundle));
}

/**
* @brief Free a support bundle struct.
*
* @param[in] bundle to be freed
*/
void
agent_controller_support_bundle_free (agent_controller_support_bundle_t bundle)
{
if (!bundle)
return;

g_free (bundle->data);
g_free (bundle->filename);
g_free (bundle);
}

/**
* @brief Allocates and initializes a new scan agent config structure.
*
Expand Down Expand Up @@ -1979,3 +2037,103 @@ agent_controller_get_installer_instruction (agent_controller_connector_t conn,
gvm_http_response_free (response);
return instr;
}

/**
* @brief Downloads a support bundle for a specific agent.
*
* @param[in] conn Active connector to the Agent Controller.
* @param[in] agent_id ID of the agent.
* @param[in] days Number of days of logs to include. A value of 0 uses the
* Agent Controller's configured default.
*
* @return Newly allocated support bundle on success, NULL on failure.
* Free with agent_controller_support_bundle_free().
*/
agent_controller_support_bundle_t
agent_controller_download_support_bundle (agent_controller_connector_t conn,
const gchar *agent_id, int days)
{
gvm_http_headers_t *headers;
gvm_http_response_t *response;
agent_controller_support_bundle_t bundle;
gchar *escaped_agent_id;
gchar *path;

if (!conn || !agent_id || *agent_id == '\0' || days < 0)
return NULL;

escaped_agent_id = g_uri_escape_string (agent_id, NULL, TRUE);
if (!escaped_agent_id)
return NULL;

if (days > 0)
path =
g_strdup_printf ("/agent-control/v2/api/agents/%s/support-bundle?days=%d",
escaped_agent_id, days);
else
path = g_strdup_printf ("/agent-control/v2/api/agents/%s/support-bundle",
escaped_agent_id);

g_free (escaped_agent_id);

headers = init_custom_header (conn->apikey, FALSE);
if (!headers)
{
g_free (path);
return NULL;
}

if (!add_custom_header (headers, "Accept", "application/octet-stream"))
{
gvm_http_headers_free (headers);
g_free (path);
return NULL;
}

response =
agent_controller_send_request_with_headers (conn, GET, path, NULL, headers);

gvm_http_headers_free (headers);
g_free (path);

if (!response)
return NULL;

if (response->http_status != 200)
{
g_warning ("%s: Received HTTP status %ld", __func__,
response->http_status);
gvm_http_response_free (response);
return NULL;
}

if (!response->data || response->size == 0)
{
g_warning ("%s: Received an empty support bundle", __func__);
gvm_http_response_free (response);
return NULL;
}

bundle = agent_controller_support_bundle_new ();
if (!bundle)
{
gvm_http_response_free (response);
return NULL;
}

/*
* Transfer ownership of the binary buffer from the generic HTTP response
* to the Agent Controller support-bundle object.
*/
bundle->data = (guint8 *) response->data;
bundle->size = response->size;
bundle->filename =
content_disposition_filename (response->content_disposition);

response->data = NULL;
response->size = 0;

gvm_http_response_free (response);

return bundle;
}
24 changes: 24 additions & 0 deletions agent_controller/agent_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,20 @@ struct agent_controller_installer_instruction
typedef struct agent_controller_installer_instruction
*agent_controller_installer_instruction_t;

/**
* @brief Struct representing a support bundle for agents.
*/
struct agent_controller_support_bundle
{
guint8 *data; ///> The data of the support bundle file (e.g., ZIP archive)
gsize size; ///< Size of the data in bytes
gchar *filename; ///< Suggested filename for the support bundle (e.g.,
///< "support_bundle.zip")
};

typedef struct agent_controller_support_bundle
*agent_controller_support_bundle_t;

agent_controller_connector_t
agent_controller_connector_new (void);

Expand Down Expand Up @@ -286,6 +300,12 @@ void
agent_controller_installer_instruction_free (
agent_controller_installer_instruction_t instr);

agent_controller_support_bundle_t
agent_controller_support_bundle_new (void);

void
agent_controller_support_bundle_free (agent_controller_support_bundle_t bundle);

agent_controller_agent_list_t
agent_controller_get_agents (agent_controller_connector_t conn);

Expand Down Expand Up @@ -341,4 +361,8 @@ agent_controller_installer_instruction_t
agent_controller_get_installer_instruction (agent_controller_connector_t conn,
instructions_lang_type_t lang_type);

agent_controller_support_bundle_t
agent_controller_download_support_bundle (agent_controller_connector_t conn,
const gchar *agent_id, int days);

#endif /* not _GVM_AGENT_CONTROLLER_AGENT_CONTROLLER_H */
Loading
Loading