From d2d4ee5994f2475b90fa27d49b208fa8b8c7dc58 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Tue, 5 Dec 2023 09:52:54 +0100 Subject: [PATCH] Add: New compliance filter keywords for results The filters of the get_reports and get_results commands now support two new keywords for filtering results by their compliance status: The option "compliance_levels" that allows a selection applying to the whole filter similar to "levels" for severity and a "compliant" column that can be used with boolean operator keywords. --- src/manage_sql.c | 84 ++++++++++++++++++++++++++++--- src/manage_sql.h | 2 +- src/schema_formats/XML/GMP.xml.in | 44 ++++++++++++++++ 3 files changed, 123 insertions(+), 7 deletions(-) diff --git a/src/manage_sql.c b/src/manage_sql.c index 4933a31e1..b9754e402 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -22031,6 +22031,63 @@ where_levels_auto (const char *levels, const char *new_severity_sql) return levels_sql; } +/** + * @brief Return SQL WHERE for restricting a SELECT to compliance levels. + * + * @param[in] levels String describing compliance levels to include in + * report (for example, "yniu" for "yes, "no", "incomplete" + * and "undefined"). All levels if NULL. + * + * @return WHERE clause for compliance levels if one is required, else NULL. + */ +static gchar* +where_compliance_levels (const char *levels) +{ + int count; + GString *levels_sql; + + if (levels == NULL) + return NULL; + + levels_sql = g_string_new (""); + count = 0; + + g_string_append_printf (levels_sql, + " AND coalesce(" + " lower(substring(description, '^Compliant:[\\s]*([A-Z_]*)'))," + " 'undefined') IN ("); + + if (strchr (levels, 'y')) + { + g_string_append (levels_sql, "'yes'"); + count++; + } + if (strchr (levels, 'n')) + { + g_string_append (levels_sql, count ? ", 'no'" : "'no'"); + count++; + } + if (strchr (levels, 'i')) + { + g_string_append (levels_sql, count ? ", 'incomplete'" : "'incomplete'"); + count++; + } + if (strchr (levels, 'u')) + { + g_string_append (levels_sql, count ? ", 'undefined'" : "'undefined'"); + count++; + } + g_string_append (levels_sql, ")"); + + if (count == 4) + { + /* All compliance levels selected, so no restriction is necessary. */ + g_string_free (levels_sql, TRUE); + return NULL; + } + return g_string_free (levels_sql, FALSE); +} + /** * @brief Return SQL WHERE for restricting a SELECT to a minimum QoD. * @@ -22061,7 +22118,7 @@ where_qod (int min_qod) "description", "task", "report", "cvss_base", "nvt_version", \ "severity", "original_severity", "vulnerability", "date", "report_id", \ "solution_type", "qod", "qod_type", "task_id", "cve", "hostname", \ - "path", NULL } + "path", "compliant", NULL } // TODO Combine with RESULT_ITERATOR_COLUMNS. /** @@ -22173,6 +22230,10 @@ where_qod (int min_qod) KEYWORD_TYPE_INTEGER }, \ { "(SELECT name FROM tasks WHERE tasks.id = task)", \ "task", \ + KEYWORD_TYPE_STRING }, \ + { "coalesce(lower(substring(description, '^Compliant:[\\s]*([A-Z_]*)'))," \ + " 'undefined')", \ + "compliant", \ KEYWORD_TYPE_STRING }, /** @@ -22349,6 +22410,10 @@ where_qod (int min_qod) { "nvts.tag", \ NULL, \ KEYWORD_TYPE_STRING }, \ + { "coalesce(lower(substring(description, '^Compliant:[\\s]*([A-Z_]*)'))," \ + " 'undefined')", \ + "compliant", \ + KEYWORD_TYPE_STRING }, \ /** * @brief Result iterator columns. @@ -22599,8 +22664,9 @@ results_extra_where (int trash, report_t report, const gchar* host, { gchar *extra_where; int min_qod; - gchar *levels; + gchar *levels, *compliance_levels; gchar *report_clause, *host_clause, *min_qod_clause; + gchar *compliance_levels_clause; GString *levels_clause; gchar *new_severity_sql; @@ -22609,6 +22675,7 @@ results_extra_where (int trash, report_t report, const gchar* host, levels = filter_term_value (filter, "levels"); if (levels == NULL) levels = g_strdup ("hmlgdf"); + compliance_levels = filter_term_value (filter, "compliance_levels"); // Build clause fragments @@ -22637,19 +22704,24 @@ results_extra_where (int trash, report_t report, const gchar* host, given_new_severity_sql ? given_new_severity_sql : new_severity_sql); + + compliance_levels_clause = where_compliance_levels (compliance_levels); + g_free (levels); g_free (new_severity_sql); - extra_where = g_strdup_printf("%s%s%s%s", + extra_where = g_strdup_printf("%s%s%s%s%s", report_clause ? report_clause : "", host_clause ? host_clause : "", levels_clause->str, - min_qod_clause ? min_qod_clause : ""); + min_qod_clause ? min_qod_clause : "", + compliance_levels_clause ?: ""); g_free (min_qod_clause); g_string_free (levels_clause, TRUE); g_free (report_clause); g_free (host_clause); + g_free (compliance_levels_clause); return extra_where; } @@ -23606,7 +23678,7 @@ gchar ** result_iterator_cert_bunds (iterator_t* iterator) { if (iterator->done) return 0; - return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 35); + return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 36); } /** @@ -23620,7 +23692,7 @@ gchar ** result_iterator_dfn_certs (iterator_t* iterator) { if (iterator->done) return 0; - return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 36); + return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 37); } /** diff --git a/src/manage_sql.h b/src/manage_sql.h index 6ea3ac24c..7d98f1994 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -291,7 +291,7 @@ typedef struct /** * @brief Delta results columns offset for result iterator. */ -#define RESULT_ITERATOR_DELTA_COLUMN_OFFSET GET_ITERATOR_COLUMN_COUNT + 37 +#define RESULT_ITERATOR_DELTA_COLUMN_OFFSET GET_ITERATOR_COLUMN_COUNT + 38 /* Variables */ diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index fa40654bd..ff552e157 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -58,6 +58,16 @@ along with this program. If not, see . text + + compliance_levels + A string selecting compliance levels that may include the characters y, n, i and u + + The meanings of the letters for each level are: "y" for "yes" (compliant), + "n" for "no" (not compliant), "i" for "incomplete" and "u" for "undefined" + (without compliance information). + + xsd:token { pattern = "y?n?i?u?" } + ctime A date and time, in the C `ctime' format @@ -15535,6 +15545,11 @@ END:VCALENDAR boolean Whether to apply Overrides + +