From 31b62c26071606dc756e643924b2e5c4a6c5b323 Mon Sep 17 00:00:00 2001 From: Ahmed Abdelsalam Date: Thu, 30 Jan 2025 11:38:44 +0100 Subject: [PATCH 1/4] Fix: Reject creating tags of the wrong subtype --- src/manage_sql.c | 61 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/manage_sql.c b/src/manage_sql.c index e055b0544..f78d596c2 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -57003,14 +57003,18 @@ tag_add_resource (tag_t tag, const char *type, const char *uuid, * @brief Find a resource by UUID and add it as a tag resource. * * @param[in] tag Tag to attach to the resource. - * @param[in] type The resource Type. + * @param[in] type The resource type. + * @param[in] tag_type The tag type. Could be a sub-type. * @param[in] uuid The resource UUID. * @param[in] permission The permission required to get the resource. * * @return 0 success, -1 error, 1 resource not found. */ static int -tag_add_resource_uuid (tag_t tag, const char *type, const char *uuid, +tag_add_resource_uuid (tag_t tag, + const char *type, + const char *tag_type, + const char *uuid, const char *permission) { int resource_location = LOCATION_TABLE; @@ -57041,6 +57045,43 @@ tag_add_resource_uuid (tag_t tag, const char *type, const char *uuid, if (resource == 0) return 1; + if ((strcmp (type, "task") == 0) + || (strcmp (type, "config") == 0) + || (strcmp (type, "report") == 0)) + { + gchar *usage_type; + if (strcmp (type, "report")) + usage_type = sql_string("SELECT usage_type FROM %ss WHERE id = %llu", + type, resource); + else + { + task_t task; + if (report_task (resource, &task)) + return -1; + + usage_type = sql_string("SELECT usage_type FROM tasks WHERE id = %llu", + task); + } + + if (usage_type == NULL) + return -1; + + int same_type = (strcmp (tag_type, type) == 0); + + if (same_type && ((strcmp (usage_type, "audit") == 0) + || (strcmp (usage_type, "policy") == 0))) + { + g_free (usage_type); + return 1; + } + if (!same_type && (strcmp (usage_type, "scan") == 0)) + { + g_free (usage_type); + return 1; + } + g_free (usage_type); + } + return tag_add_resource (tag, type, uuid, resource, resource_location); } @@ -57061,6 +57102,8 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, gchar *resource_permission, *current_uuid; int index; + gchar *resource_type = g_strdup (type); + if (type_is_info_subtype (type)) resource_permission = g_strdup ("get_info"); else if (type_is_asset_subtype (type)) @@ -57068,17 +57111,20 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, else if (type_is_report_subtype (type)) { resource_permission = g_strdup ("get_reports"); - type = g_strdup("report"); + g_free (resource_type); + resource_type = g_strdup("report"); } else if (type_is_task_subtype (type)) { resource_permission = g_strdup ("get_tasks"); - type = g_strdup("task"); + g_free (resource_type); + resource_type = g_strdup("task"); } else if (type_is_config_subtype (type)) { resource_permission = g_strdup ("get_configs"); - type = g_strdup("config"); + g_free (resource_type); + resource_type = g_strdup("config"); } else resource_permission = g_strdup_printf ("get_%ss", type); @@ -57088,16 +57134,19 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, { int ret; - ret = tag_add_resource_uuid (tag, type, current_uuid, + ret = tag_add_resource_uuid (tag, resource_type, type, current_uuid, resource_permission); if (ret) { g_free (resource_permission); + g_free (resource_type); if (error_extra) *error_extra = g_strdup (current_uuid); return ret; } } + g_free (resource_permission); + g_free (resource_type); return 0; } From e5323e729404a85f0f92638ce95e40a7a74f4a9e Mon Sep 17 00:00:00 2001 From: Ahmed Abdelsalam Date: Mon, 3 Feb 2025 20:13:33 +0100 Subject: [PATCH 2/4] Adjust tag iterator and resources count to return correct subtypes --- src/manage_pg.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/manage_sql.c | 20 +++++++++++++----- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/manage_pg.c b/src/manage_pg.c index f98ef0b23..ccad8c7c2 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -970,6 +970,61 @@ manage_create_sql_functions () " $$ LANGUAGE plpgsql" " IMMUTABLE;"); + sql ("CREATE OR REPLACE FUNCTION tag_resources_count (" + " tag_id integer," + " tag_type text)" + " RETURNS integer AS $$" + " DECLARE table_name text;" + " DECLARE count integer;" + " DECLARE usage_types text[];" + " BEGIN" + " IF $2 = 'audit' OR $2 = 'audit_report' OR $2 = 'policy'" + " THEN" + " usage_types := ARRAY['audit', 'policy'];" + " ELSIF $2 = 'task' OR $2 = 'report' OR $2 = 'config' " + " THEN" + " usage_types := ARRAY['scan'];" + " END IF;" + " CASE" + " WHEN $2 = 'audit' OR $2 = 'policy' OR $2 = 'task' OR $2 = 'config'" + " THEN" + " SELECT resource_type INTO table_name FROM tag_resources WHERE tag = $1;" + " table_name := table_name || 's';" + " EXECUTE" + " 'SELECT count(*)" + " FROM tag_resources" + " JOIN ' || table_name || '" + " ON ' || table_name || '.id = resource" + " WHERE tag= $1 AND ' || table_name || '.usage_type = ANY($2)" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" + " INTO count" + " USING $1, usage_types;" + " WHEN $2 = 'audit_report' OR $2 = 'report'" + " THEN" + " EXECUTE" + " 'SELECT count(*)" + " FROM tag_resources" + " JOIN tasks" + " ON tasks.id = (SELECT task FROM reports" + " WHERE reports.id = resource)" + " WHERE tag= $1 AND tasks.usage_type = ANY($2)" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" + " INTO count" + " USING $1, usage_types; " + " ELSE" + " EXECUTE" + " 'SELECT count(*)" + " FROM tag_resources" + " WHERE tag = $1" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" + " INTO count" + " USING $1;" + " END CASE;" + " RETURN count;" + " END;" + " $$ LANGUAGE plpgsql" + " IMMUTABLE;"); + /* Functions in SQL. */ if (sql_int ("SELECT (EXISTS (SELECT * FROM information_schema.tables" diff --git a/src/manage_sql.c b/src/manage_sql.c index f78d596c2..24563b4b6 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -29703,7 +29703,7 @@ print_report_xml_start (report_t report, report_t delta, task_t task, { iterator_t tags; - init_resource_tag_iterator (&tags, "report", report, 1, NULL, 1); + init_resource_tag_iterator (&tags, report_type, report, 1, NULL, 1); while (next (&tags)) { @@ -57956,9 +57956,7 @@ modify_tag (const char *tag_id, const char *name, const char *comment, { "resource_type", NULL, KEYWORD_TYPE_STRING }, \ { "active", NULL, KEYWORD_TYPE_INTEGER }, \ { "value", NULL, KEYWORD_TYPE_STRING }, \ - { "(SELECT count(*) FROM tag_resources" \ - " WHERE tag = tags.id" \ - " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ")", \ + { "tag_resources_count (id, resource_type)", \ "resources", KEYWORD_TYPE_INTEGER }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -58144,6 +58142,7 @@ init_resource_tag_iterator (iterator_t* iterator, const char* type, { get_data_t get; gchar *owned_clause, *with_clause; + const char *parent_type; assert (type); assert (resource); @@ -58153,11 +58152,21 @@ init_resource_tag_iterator (iterator_t* iterator, const char* type, owned_clause = acl_where_owned ("tag", &get, 1, "any", 0, NULL, 0, &with_clause); + if (type_is_report_subtype (type)) + parent_type = "report"; + else if (type_is_task_subtype (type)) + parent_type = "task"; + else if (type_is_config_subtype (type)) + parent_type = "config"; + else + parent_type = type; + init_iterator (iterator, "%s" " SELECT id, uuid, name, value, comment" " FROM tags" - " WHERE EXISTS" + " WHERE resource_type = '%s'" + " AND EXISTS" " (SELECT * FROM tag_resources" " WHERE resource_type = '%s'" " AND resource = %llu" @@ -58168,6 +58177,7 @@ init_resource_tag_iterator (iterator_t* iterator, const char* type, " ORDER BY %s %s;", with_clause ? with_clause : "", type, + parent_type, resource, LOCATION_TABLE, active_only ? " AND active=1" : "", From 9d9f988e70019056c44ec796c33a9829e1f9d8dd Mon Sep 17 00:00:00 2001 From: Ahmed Abdelsalam Date: Wed, 5 Feb 2025 15:54:20 +0100 Subject: [PATCH 3/4] Address review remark --- src/manage_sql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manage_sql.c b/src/manage_sql.c index 24563b4b6..5e4ef0994 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -57112,7 +57112,7 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, { resource_permission = g_strdup ("get_reports"); g_free (resource_type); - resource_type = g_strdup("report"); + resource_type = g_strdup ("report"); } else if (type_is_task_subtype (type)) { From e9ac8bc92bacf2bb6f8a676e6cc79503a35f4570 Mon Sep 17 00:00:00 2001 From: Ahmed Abdelsalam Date: Thu, 6 Feb 2025 14:57:58 +0100 Subject: [PATCH 4/4] Fix the counts for tags in trash and refactor count function --- src/manage_pg.c | 113 ++++++++++++++++++++++++++++++++--------------- src/manage_sql.c | 13 +++--- 2 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/manage_pg.c b/src/manage_pg.c index ccad8c7c2..3657ebd5f 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -974,53 +974,96 @@ manage_create_sql_functions () " tag_id integer," " tag_type text)" " RETURNS integer AS $$" - " DECLARE table_name text;" - " DECLARE count integer;" " DECLARE usage_types text[];" " BEGIN" - " IF $2 = 'audit' OR $2 = 'audit_report' OR $2 = 'policy'" + " IF tag_type = 'audit' OR tag_type = 'audit_report'" + " OR tag_type = 'policy'" " THEN" " usage_types := ARRAY['audit', 'policy'];" - " ELSIF $2 = 'task' OR $2 = 'report' OR $2 = 'config' " + " ELSIF tag_type = 'task' OR tag_type = 'report'" + " OR tag_type = 'config'" " THEN" " usage_types := ARRAY['scan'];" " END IF;" " CASE" - " WHEN $2 = 'audit' OR $2 = 'policy' OR $2 = 'task' OR $2 = 'config'" + " WHEN tag_type = 'audit' OR tag_type = 'task'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources" + " JOIN tasks" + " ON tasks.id = resource" + " WHERE tag_resources.tag = tag_id" + " AND tasks.usage_type = ANY(usage_types)" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ");" + " WHEN tag_type = 'policy' OR tag_type = 'config'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources" + " JOIN configs" + " ON configs.id = resource" + " WHERE tag_resources.tag = tag_id" + " AND configs.usage_type = ANY(usage_types)" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ");" + " WHEN tag_type = 'audit_report' OR tag_type = 'report'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources" + " JOIN tasks" + " ON tasks.id = (SELECT task FROM reports" + " WHERE reports.id = resource)" + " WHERE tag_resources.tag = tag_id" + " AND tasks.usage_type = ANY(usage_types)" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ");" + " ELSE" + " RETURN (SELECT count(*)" + " FROM tag_resources" + " WHERE tag_resources.tag = tag_id" + " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ");" + " END CASE;" + " END;" + " $$ LANGUAGE plpgsql" + " IMMUTABLE;"); + + sql ("CREATE OR REPLACE FUNCTION tag_resources_trash_count (" + " tag_id integer," + " tag_type text)" + " RETURNS integer AS $$" + " DECLARE usage_types text[];" + " BEGIN" + " IF tag_type = 'audit' OR tag_type = 'audit_report'" + " OR tag_type = 'policy'" " THEN" - " SELECT resource_type INTO table_name FROM tag_resources WHERE tag = $1;" - " table_name := table_name || 's';" - " EXECUTE" - " 'SELECT count(*)" - " FROM tag_resources" - " JOIN ' || table_name || '" - " ON ' || table_name || '.id = resource" - " WHERE tag= $1 AND ' || table_name || '.usage_type = ANY($2)" - " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" - " INTO count" - " USING $1, usage_types;" - " WHEN $2 = 'audit_report' OR $2 = 'report'" + " usage_types := ARRAY['audit', 'policy'];" + " ELSIF tag_type = 'task' OR tag_type = 'report'" + " OR tag_type = 'config'" " THEN" - " EXECUTE" - " 'SELECT count(*)" - " FROM tag_resources" - " JOIN tasks" - " ON tasks.id = (SELECT task FROM reports" - " WHERE reports.id = resource)" - " WHERE tag= $1 AND tasks.usage_type = ANY($2)" - " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" - " INTO count" - " USING $1, usage_types; " + " usage_types := ARRAY['scan'];" + " END IF;" + " CASE" + " WHEN tag_type = 'audit' OR tag_type = 'task'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources_trash" + " JOIN tasks" + " ON tasks.id = resource" + " WHERE tag_resources_trash.tag = tag_id" + " AND tasks.usage_type = ANY(usage_types));" + " WHEN tag_type = 'policy' OR tag_type = 'config'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources_trash" + " JOIN configs" + " ON configs.id = resource" + " WHERE tag_resources_trash.tag = tag_id" + " AND configs.usage_type = ANY(usage_types));" + " WHEN tag_type = 'audit_report' OR tag_type = 'report'" + " THEN RETURN (SELECT count(*)" + " FROM tag_resources_trash" + " JOIN tasks" + " ON tasks.id = (SELECT task FROM reports" + " WHERE reports.id = resource)" + " WHERE tag_resources_trash.tag = tag_id" + " AND tasks.usage_type = ANY(usage_types));" " ELSE" - " EXECUTE" - " 'SELECT count(*)" - " FROM tag_resources" - " WHERE tag = $1" - " AND resource_location = " G_STRINGIFY (LOCATION_TABLE) ";'" - " INTO count" - " USING $1;" + " RETURN (SELECT count(*)" + " FROM tag_resources_trash" + " WHERE tag_resources_trash.tag = tag_id);" " END CASE;" - " RETURN count;" " END;" " $$ LANGUAGE plpgsql" " IMMUTABLE;"); diff --git a/src/manage_sql.c b/src/manage_sql.c index 5e4ef0994..3f52490de 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -57051,7 +57051,7 @@ tag_add_resource_uuid (tag_t tag, { gchar *usage_type; if (strcmp (type, "report")) - usage_type = sql_string("SELECT usage_type FROM %ss WHERE id = %llu", + usage_type = sql_string ("SELECT usage_type FROM %ss WHERE id = %llu", type, resource); else { @@ -57059,7 +57059,7 @@ tag_add_resource_uuid (tag_t tag, if (report_task (resource, &task)) return -1; - usage_type = sql_string("SELECT usage_type FROM tasks WHERE id = %llu", + usage_type = sql_string ("SELECT usage_type FROM tasks WHERE id = %llu", task); } @@ -57118,13 +57118,13 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, { resource_permission = g_strdup ("get_tasks"); g_free (resource_type); - resource_type = g_strdup("task"); + resource_type = g_strdup ("task"); } else if (type_is_config_subtype (type)) { resource_permission = g_strdup ("get_configs"); g_free (resource_type); - resource_type = g_strdup("config"); + resource_type = g_strdup ("config"); } else resource_permission = g_strdup_printf ("get_%ss", type); @@ -57956,7 +57956,7 @@ modify_tag (const char *tag_id, const char *name, const char *comment, { "resource_type", NULL, KEYWORD_TYPE_STRING }, \ { "active", NULL, KEYWORD_TYPE_INTEGER }, \ { "value", NULL, KEYWORD_TYPE_STRING }, \ - { "tag_resources_count (id, resource_type)", \ + { "tag_resources_count (tags.id, tags.resource_type)", \ "resources", KEYWORD_TYPE_INTEGER }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -57970,8 +57970,7 @@ modify_tag (const char *tag_id, const char *name, const char *comment, { "resource_type", NULL, KEYWORD_TYPE_STRING }, \ { "active", NULL, KEYWORD_TYPE_INTEGER }, \ { "value", NULL, KEYWORD_TYPE_STRING }, \ - { "(SELECT count(*) FROM tag_resources_trash" \ - " WHERE tag = tags_trash.id)", \ + { "tag_resources_trash_count (tags_trash.id, tags_trash.resource_type)", \ "resources", KEYWORD_TYPE_INTEGER }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ }