From f7e50860d24afa7cae4817494d65f20c35158112 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Mon, 23 Sep 2024 11:08:55 +0200 Subject: [PATCH 1/7] Add: Added the new CVE scan method with the new CPE matching. --- src/manage.c | 398 ++++++++++++++++++++++++++++++++------- src/manage.h | 47 ++++- src/manage_pg.c | 13 +- src/manage_sql.c | 206 +++++++++++++++++++- src/manage_sql_secinfo.c | 105 ++++++++--- 5 files changed, 667 insertions(+), 102 deletions(-) diff --git a/src/manage.c b/src/manage.c index c924ca36e..97688b391 100644 --- a/src/manage.c +++ b/src/manage.c @@ -60,6 +60,7 @@ #include "manage_sql_nvts.h" #include "manage_sql_tickets.h" #include "manage_sql_tls_certificates.h" +#include "sql.h" #include "utils.h" #include @@ -86,9 +87,11 @@ #include #include #include +#include #include #include #include +#include #include #undef G_LOG_DOMAIN @@ -3106,6 +3109,138 @@ set_scanner_connection_retry (int new_retry) /* CVE tasks. */ +static int +check_version (const gchar *target, const gchar *start_incl, const gchar *start_excl, const gchar *end_incl, const gchar *end_excl) +{ + int result; + + if (start_incl != NULL) + { + result = cmp_versions (start_incl, target); + if (result == -5) + return -1; + if (result > 0) + { + return 0; + } + } + if (start_excl != NULL) + { + result = cmp_versions (start_excl, target); + if (result == -5) + return -1; + if (result >= 0) + { + return 0; + } + } + + if (end_incl != NULL) + { + result = cmp_versions (end_incl, target); + if (result == -5) + return -1; + if (result < 0) + { + return 0; + } + } + + if (end_excl != NULL) + { + result = cmp_versions (end_excl, target); + if (result == -5) + return -1; + if (result <= 0) + { + return 0; + } + } + + return (1); +} + +static void +check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, report_host_t report_host, const char *host_cpe) +{ + iterator_t cpe_match_node_childs; + gchar *operator; + operator = sql_string ("SELECT operator FROM scap.cpe_match_nodes WHERE id = %llu", node); + init_cpe_match_node_childs_iterator (&cpe_match_node_childs, node); + while (next (&cpe_match_node_childs)) + { + long long int child_node; + child_node = cpe_match_node_childs_iterator_id (&cpe_match_node_childs); + check_cpe_match_rule (child_node, match, vulnerable, report_host, host_cpe); + if (strcmp (operator, "AND") == 0 && !(*match)) + return; + if (strcmp (operator, "OR") == 0 && (*match) && (*vulnerable)) + return; + } + iterator_t cpe_match_ranges; + init_cpe_match_range_iterator (&cpe_match_ranges, node); + while (next (&cpe_match_ranges)) + { + iterator_t cpe_host_details_products; + gchar *range_fs_cpe; + gchar *range_uri_product; + gchar *vsi, *vse, *vei, *vee; + range_fs_cpe = vsi = vse = vei = vee = NULL; + range_fs_cpe = g_strdup (cpe_match_range_iterator_cpe (&cpe_match_ranges)); + vsi = (gchar*) cpe_match_range_iterator_version_start_incl(&cpe_match_ranges); + if (vsi != NULL) + vsi = g_strdup (cpe_match_range_iterator_version_start_incl(&cpe_match_ranges)); + vse = g_strdup (cpe_match_range_iterator_version_start_excl(&cpe_match_ranges)); + vei = g_strdup (cpe_match_range_iterator_version_end_incl(&cpe_match_ranges)); + vee = g_strdup (cpe_match_range_iterator_version_end_excl(&cpe_match_ranges)); + range_uri_product = fs_cpe_to_uri_product (range_fs_cpe); + init_host_details_cpe_product_iterator (&cpe_host_details_products, range_uri_product, report_host); + while (next (&cpe_host_details_products)) + { + cpe_struct_t source, target; + const char *host_details_cpe; + gboolean matches; + host_details_cpe = host_details_cpe_product_iterator_value(&cpe_host_details_products); + cpe_struct_init (&source); + cpe_struct_init (&target); + fs_cpe_to_cpe_struct (range_fs_cpe, &source); + uri_cpe_to_cpe_struct (host_details_cpe, &target); + matches = cpe_struct_match (source, target); + if (matches) + { + int result; + result = check_version (target.version, vsi, vse, vei, vee); + if (result == 1) + *match = TRUE; + } + cpe_struct_free (&source); + cpe_struct_free (&target); + } + if (*match && cpe_match_range_iterator_vulnerable(&cpe_match_ranges) == 1) + { + cpe_struct_t source, target; + cpe_struct_init (&source); + cpe_struct_init (&target); + fs_cpe_to_cpe_struct (range_fs_cpe, &source); + uri_cpe_to_cpe_struct (host_cpe, &target); + if (cpe_struct_match (source, target)) + *vulnerable = TRUE; + cpe_struct_free (&source); + cpe_struct_free (&target); + } + g_free (range_uri_product); + g_free (range_fs_cpe); + g_free (vsi); + g_free (vse); + g_free (vei); + g_free (vee); + if (strcmp (operator, "AND") == 0 && !(*match)) + return; + if (strcmp (operator, "OR") == 0 && (*match) && (*vulnerable)) + return; + } +} + /** * @brief Perform a CVE "scan" on a host. * @@ -3161,89 +3296,218 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) results = g_array_new (TRUE, TRUE, sizeof (result_t)); start_time = time (NULL); prognosis_report_host = 0; - init_host_prognosis_iterator (&prognosis, report_host); - while (next (&prognosis)) + + gboolean use_json = FALSE; + if (sql_int64_0 ("SELECT count(*) FROM scap.cpe_match_nodes") > 0) + use_json = TRUE; + + if (use_json) { - const char *app, *cve; - double severity; - gchar *desc; - iterator_t locations_iter; - GString *locations; - result_t result; + iterator_t host_details_cpe; + init_host_details_cpe_iterator (&host_details_cpe, report_host); + while (next (&host_details_cpe)) + { + iterator_t cpe_match_root_node; + iterator_t locations_iter; + result_t result; + char *cpe_product; + const char *host_cpe; + double severity; + + host_cpe = host_details_cpe_iterator_cpe (&host_details_cpe); + cpe_product = uri_cpe_to_fs_product (host_cpe); + init_cpe_match_nodes_iterator (&cpe_match_root_node, cpe_product); + while (next (&cpe_match_root_node)) + { + result_t root_node; + gboolean match, vulnerable; + const char *app, *cve; + + vulnerable = FALSE; + match = FALSE; + root_node = cpe_match_nodes_iterator_root_id (&cpe_match_root_node); + check_cpe_match_rule (root_node, &match, &vulnerable, report_host, host_cpe); + if (match && vulnerable) + { + GString *locations; + gchar *desc; + + if (prognosis_report_host == 0) + prognosis_report_host = manage_report_host_add (report, + ip, + start_time, + 0); + + severity = sql_double ("SELECT severity FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); + + app = host_cpe; + cve = sql_string ("SELECT name FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); + locations = g_string_new(""); + + insert_report_host_detail (global_current_report, ip, "cve", cve, + "CVE Scanner", "App", app, NULL); + + init_app_locations_iterator (&locations_iter, report_host, app); + + while (next (&locations_iter)) + { + const char *location; + location = app_locations_iterator_location (&locations_iter); + + if (location == NULL) + { + g_warning ("%s: Location is null for ip %s, app %s", + __func__, ip, app); + continue; + } + + if (locations->len) + { + g_string_append (locations, ", "); + } + g_string_append (locations, location); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", app, location, NULL); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_at", + location, NULL); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_by", + /* Detected by itself. */ + cve, NULL); + } + + const char *description; + description = sql_string ("SELECT description FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); - if (prognosis_report_host == 0) - prognosis_report_host = manage_report_host_add (report, - ip, - start_time, - 0); + desc = g_strdup_printf ("The host carries the product: %s\n" + "It is vulnerable according to: %s.\n" + "%s%s%s" + "\n" + "%s", + app, + cve, + locations->len + ? "The product was found at: " + : "", + locations->len ? locations->str : "", + locations->len ? ".\n" : "", + description); - severity = prognosis_iterator_cvss_double (&prognosis); + g_debug ("%s: making result with severity %1.1f desc [%s]", + __func__, severity, desc); - app = prognosis_iterator_cpe (&prognosis); - cve = prognosis_iterator_cve (&prognosis); - locations = g_string_new(""); + result = make_cve_result (task, ip, cve, severity, desc); + g_free (desc); - insert_report_host_detail (global_current_report, ip, "cve", cve, - "CVE Scanner", "App", app, NULL); + g_array_append_val (results, result); - init_app_locations_iterator (&locations_iter, report_host, app); + g_string_free (locations, TRUE); - while (next (&locations_iter)) + } + } + g_free (cpe_product); + } + cleanup_iterator (&host_details_cpe); + } + + if (!use_json) + { + init_host_prognosis_iterator (&prognosis, report_host); + while (next (&prognosis)) { - const char *location; - location = app_locations_iterator_location (&locations_iter); + const char *app, *cve; + double severity; + gchar *desc; + iterator_t locations_iter; + GString *locations; + result_t result; + + if (prognosis_report_host == 0) + prognosis_report_host = manage_report_host_add (report, + ip, + start_time, + 0); + + severity = prognosis_iterator_cvss_double (&prognosis); + + app = prognosis_iterator_cpe (&prognosis); + cve = prognosis_iterator_cve (&prognosis); + locations = g_string_new(""); + + insert_report_host_detail (global_current_report, ip, "cve", cve, + "CVE Scanner", "App", app, NULL); - if (location == NULL) + init_app_locations_iterator (&locations_iter, report_host, app); + + while (next (&locations_iter)) { - g_warning ("%s: Location is null for ip %s, app %s", - __func__, ip, app); - continue; - } + const char *location; + location = app_locations_iterator_location (&locations_iter); + + if (location == NULL) + { + g_warning ("%s: Location is null for ip %s, app %s", + __func__, ip, app); + continue; + } - if (locations->len) - g_string_append (locations, ", "); - g_string_append (locations, location); + if (locations->len) + g_string_append (locations, ", "); + g_string_append (locations, location); - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", app, location, NULL); + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", app, location, NULL); - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", "detected_at", - location, NULL); + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_at", + location, NULL); - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", "detected_by", - /* Detected by itself. */ - cve, NULL); - } + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_by", + /* Detected by itself. */ + cve, NULL); + } - desc = g_strdup_printf ("The host carries the product: %s\n" - "It is vulnerable according to: %s.\n" - "%s%s%s" - "\n" - "%s", - app, - cve, - locations->len - ? "The product was found at: " - : "", - locations->len ? locations->str : "", - locations->len ? ".\n" : "", - prognosis_iterator_description - (&prognosis)); - - g_debug ("%s: making result with severity %1.1f desc [%s]", - __func__, severity, desc); - - result = make_cve_result (task, ip, cve, severity, desc); - g_free (desc); - - g_array_append_val (results, result); - - g_string_free (locations, TRUE); + desc = g_strdup_printf ("The host carries the product: %s\n" + "It is vulnerable according to: %s.\n" + "%s%s%s" + "\n" + "%s", + app, + cve, + locations->len + ? "The product was found at: " + : "", + locations->len ? locations->str : "", + locations->len ? ".\n" : "", + prognosis_iterator_description + (&prognosis)); + + g_debug ("%s: making result with severity %1.1f desc [%s]", + __func__, severity, desc); + + result = make_cve_result (task, ip, cve, severity, desc); + g_free (desc); + + g_array_append_val (results, result); + + g_string_free (locations, TRUE); + } + cleanup_iterator (&prognosis); } - cleanup_iterator (&prognosis); - report_add_results_array (report, results); g_array_free (results, TRUE); diff --git a/src/manage.h b/src/manage.h index 0ee2e9c23..226f56753 100644 --- a/src/manage.h +++ b/src/manage.h @@ -1688,7 +1688,52 @@ void init_app_locations_iterator (iterator_t*, report_host_t, const gchar *); const char * -app_locations_iterator_location (iterator_t *); +app_locations_iterator_location (iterator_t*); + +void +init_cpe_match_nodes_iterator (iterator_t*, const char *); + +long long int +cpe_match_nodes_iterator_root_id (iterator_t*); + +void +init_host_details_cpe_iterator (iterator_t*, report_host_t); + +const char* +host_details_cpe_iterator_cpe (iterator_t*); + +void +init_cpe_match_node_childs_iterator (iterator_t*, long long int); + +long long int +cpe_match_node_childs_iterator_id (iterator_t*); + +void +init_cpe_match_range_iterator (iterator_t*, long long int); + +const char* +cpe_match_range_iterator_cpe (iterator_t*); + +const char* +cpe_match_range_iterator_version_start_incl (iterator_t*); + +const char* +cpe_match_range_iterator_version_start_excl (iterator_t*); + +const char* +cpe_match_range_iterator_version_end_incl (iterator_t*); + +const char* +cpe_match_range_iterator_version_end_excl (iterator_t*); + +int +cpe_match_range_iterator_vulnerable (iterator_t*); + +void +init_host_details_cpe_product_iterator (iterator_t*, const char *, report_host_t); + +const char* +host_details_cpe_product_iterator_value (iterator_t*); void init_host_prognosis_iterator (iterator_t*, report_host_t); diff --git a/src/manage_pg.c b/src/manage_pg.c index dba91d68f..e4e8ca4b8 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -1589,6 +1589,8 @@ manage_create_sql_functions () " THEN $1 = 0" " WHEN 'false'" " THEN $1 = -1" + " WHEN 'error'" + " THEN $1 = -3" " ELSE 0::boolean" " END);" "$$ LANGUAGE SQL" @@ -3533,6 +3535,7 @@ manage_db_init (const gchar *name) sql ("CREATE TABLE scap2.cpe_match_nodes" " (id SERIAL PRIMARY KEY," " parent_id INTEGER DEFAULT 0," + " root_id INTEGER DEFAULT 0," " cve_id INTEGER DEFAULT 0," " operator text);"); @@ -3540,11 +3543,11 @@ manage_db_init (const gchar *name) " (id SERIAL PRIMARY KEY," " node_id INTEGER DEFAULT 0," " vulnerable INTEGER DEFAULT 0," - " cpe text," - " version_start_incl text," - " version_start_excl text," - " version_end_incl text," - " version_end_excl text);"); + " cpe text DEFAULT NULL," + " version_start_incl text DEFAULT NULL," + " version_start_excl text DEFAULT NULL," + " version_end_incl text DEFAULT NULL," + " version_end_excl text DEFAULT NULL);"); sql ("CREATE TABLE scap2.cpe_details" " (id SERIAL PRIMARY KEY," diff --git a/src/manage_sql.c b/src/manage_sql.c index c90a3a882..a3b67eb7b 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -20446,6 +20446,198 @@ app_locations_iterator_location (iterator_t *iterator) return iterator_string (iterator, 0); } +/** + * @brief Initialize an iterator of CPEs for a report's host. + * + * @param[in] iterator Iterator. + * @param[in] report_host Report host. + */ +void +init_host_details_cpe_iterator (iterator_t* iterator, report_host_t report_host) +{ + init_iterator (iterator, + "SELECT LOWER (value) FROM report_host_details" + " WHERE name = 'App' and report_host = %llu;", + report_host); +} + +/** + * @brief Get a CPE from an CPE iterator. + * + * @param[in] iterator Iterator. + * + * @return The CPE. + */ +DEF_ACCESS (host_details_cpe_iterator_cpe, 0); + +/** + * @brief Initialize an iterator of CPEs for a product of a report's host. + * + * @param[in] iterator Iterator. + * @param[in] product The product for which to get the CPEs. + * @param[in] report_host Report host. + */ +void +init_host_details_cpe_product_iterator (iterator_t* iterator, const char *product, report_host_t report_host) +{ + gchar *quoted_product; + quoted_product = sql_quote (product); + init_iterator (iterator, + "SELECT DISTINCT LOWER (value) FROM report_host_details" + " WHERE name = 'App' AND report_host = %llu" + " AND value like '%s%s';", + report_host, quoted_product, "%"); + g_free (quoted_product); +} + +/** + * @brief Get a CPE from an CPE product iterator. + * + * @param[in] iterator Iterator. + * + * @return The CPE. + */ +DEF_ACCESS (host_details_cpe_product_iterator_value, 0); + +/** + * @brief Initialize an iterator of root_ids of CPE match nodes. + * + * @param[in] iterator Iterator. + * @param[in] cpe The cpe contained in the match nodes. + */ +void +init_cpe_match_nodes_iterator (iterator_t* iterator, const char *cpe) +{ + gchar *quoted_cpe; + quoted_cpe = sql_quote (cpe); + init_iterator (iterator, + "SELECT DISTINCT root_id" + " FROM scap.cpe_match_nodes, scap.cpe_match_range" + " WHERE cpe like '%s%s' AND scap.cpe_match_nodes.id = node_id;", + quoted_cpe, "%"); + g_free (quoted_cpe); +} + +/** + * @brief Get a root id from an CPE match node iterator. + * + * @param[in] iterator Iterator. + * + * @return The root id. + */ +long long int +cpe_match_nodes_iterator_root_id (iterator_t* iterator) +{ + return iterator_int64 (iterator, 0); +} + +/** + * @brief Initialize an iterator of childs of an CPE match node. + * + * @param[in] iterator Iterator. + * @param[in] node The match node with the childs. + */ +void +init_cpe_match_node_childs_iterator (iterator_t* iterator, long long int node) +{ + init_iterator (iterator, + "SELECT id FROM scap.cpe_match_nodes" + " WHERE parent_id = %llu;", + node); +} + +/** + * @brief Get a child from an CPE match node childs iterator. + * + * @param[in] iterator Iterator. + * + * @return The id of the child node. + */ +long long int +cpe_match_node_childs_iterator_id (iterator_t* iterator) +{ + return iterator_int64 (iterator, 0); +} + +/** + * @brief Initialize an iterator of match ranges of an CPE match node. + * + * @param[in] iterator Iterator. + * @param[in] node The match node with match ranges. + */ +void +init_cpe_match_range_iterator (iterator_t* iterator, long long int node) +{ + init_iterator (iterator, + "SELECT vulnerable, cpe, version_start_incl," + " version_start_excl, version_end_incl, version_end_excl" + " FROM scap.cpe_match_range" + " WHERE node_id = %llu;", + node); +} + +/** + * @brief Return if the CPE of the actual match node is vulnerable. + * + * @param[in] iterator Iterator. + * + * @return 1 if the match node is vulnerable, 0 otherwise. + */ +int +cpe_match_range_iterator_vulnerable (iterator_t* iterator) +{ + return iterator_int64 (iterator, 0); +} + +/** + * @brief Return the CPE of the actual match node. + * + * @param[in] iterator Iterator. + * + * @return The CPE of the actual match node. + */ +DEF_ACCESS (cpe_match_range_iterator_cpe, 1); + +/** + * @brief Return the start included version of the actual match node. + * + * @param[in] iterator Iterator. + * + * @return The start included version of the actual match node, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_range_iterator_version_start_incl, 2); + +/** + * @brief Return the start excluded version of the actual match node. + * + * @param[in] iterator Iterator. + * + * @return The start excluded version of the actual match node, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_range_iterator_version_start_excl, 3); + +/** + * @brief Return the end included version of the actual match node. + * + * @param[in] iterator Iterator. + * + * @return The end included version of the actual match node, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_range_iterator_version_end_incl, 4); + +/** + * @brief Return the end excluded version of the actual match node. + * + * @param[in] iterator Iterator. + * + * @return The end excluded version of the actual match node, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_range_iterator_version_end_excl, 5); + /** * @brief Initialise a report host prognosis iterator. * @@ -22357,6 +22549,16 @@ where_levels_auto (const char *levels, const char *new_severity_sql) g_string_append (levels_sql, ", 'false'"); count++; } + if (strchr (levels, 'e')) + { + g_string_append (levels_sql, ", 'error'"); + count++; + } + if (strchr (levels, 'd')) + { + g_string_append (levels_sql, ", 'error'"); + count++; + } if (count == 0) { @@ -23086,6 +23288,8 @@ results_extra_where (int trash, report_t report, const gchar* host, min_qod_clause = where_qod (min_qod); + g_message ("PROTO1: %s", levels); + fflush (NULL); levels_clause = where_levels_auto (levels ? levels : "hmlgdf", given_new_severity_sql ? given_new_severity_sql @@ -23099,7 +23303,7 @@ results_extra_where (int trash, report_t report, const gchar* host, extra_where = g_strdup_printf("%s%s%s%s%s", report_clause ? report_clause : "", host_clause ? host_clause : "", - levels_clause->str, + (levels_clause && levels_clause->str) ? levels_clause->str : "", min_qod_clause ? min_qod_clause : "", compliance_levels_clause ?: ""); diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index d189d83bb..e592f4606 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -2703,7 +2703,9 @@ json_object_item_double (cJSON *object, char *key, double fallback) * @brief Save the node of a cve match rule tree. * * @param[in] parent_id The parent_id of the node. If this value is 0, - * this node is the root of the tree. + * the node is the root of the tree. + * @param[in] root_id The id of the root of the tree. If this value + * is 0, the node is the root of the tree. * @param[in] cve_id The id of the CVE to which the tree belongs. * @param[in] operator The operator for the match rules. * @@ -2737,7 +2739,6 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) cJSON *cpe_js; gboolean vulnerable = FALSE; - char * cpe = NULL; char * version_start_incl = NULL; char * version_start_excl = NULL; char * version_end_incl = NULL; @@ -2745,9 +2746,9 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) cJSON_ArrayForEach(match_rule, match_rules) { - char *quoted_cpe; + char *quoted_cpe = NULL; + char *sql_cpe = NULL; vulnerable = FALSE; - cpe = NULL; version_start_incl = NULL; version_start_excl = NULL; version_end_incl = NULL; @@ -2757,22 +2758,40 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) vulnerable = TRUE; else vulnerable = FALSE; + cpe_js = cJSON_GetObjectItemCaseSensitive(match_rule, "cpe23Uri"); - if (cpe_js != NULL) - cpe = cpe_js->valuestring; - quoted_cpe = sql_quote (cpe); + if (cpe_js != NULL && strcmp (cpe_js->valuestring, "(null)")) + { + quoted_cpe = sql_quote (cpe_js->valuestring); + sql_cpe = g_strdup_printf ("'%s'", quoted_cpe); + g_free (quoted_cpe); + } + else + sql_cpe = g_strdup ("NULL"); + ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionStartIncluding"); - if (ver_se != NULL) - version_start_incl = ver_se->valuestring; + if (ver_se != NULL && strcmp (ver_se->valuestring, "(null)")) + version_start_incl = g_strdup_printf ("'%s'", ver_se->valuestring); + else + version_start_incl = g_strdup ("NULL"); + ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionStartExcluding"); - if (ver_se != NULL) - version_start_excl = ver_se->valuestring; + if (ver_se != NULL && strcmp (ver_se->valuestring, "(null)")) + version_start_excl = g_strdup_printf ("'%s'", ver_se->valuestring); + else + version_start_excl = g_strdup ("NULL"); + ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionEndIncluding"); - if (ver_se != NULL) - version_end_incl = ver_se->valuestring; + if (ver_se != NULL && strcmp (ver_se->valuestring, "(null)")) + version_end_incl = g_strdup_printf ("'%s'", ver_se->valuestring); + else + version_end_incl = g_strdup ("NULL"); + ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionEndExcluding"); - if (ver_se != NULL) - version_end_excl = ver_se->valuestring; + if (ver_se != NULL && strcmp (ver_se->valuestring, "(null)")) + version_end_excl = g_strdup_printf ("'%s'", ver_se->valuestring); + else + version_end_excl = g_strdup ("NULL"); sql ("INSERT INTO scap2.cpe_match_range" @@ -2780,30 +2799,51 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) " version_start_incl, version_start_excl," " version_end_incl, version_end_excl)" " VALUES" - " (%llu, %d, '%s', '%s', '%s', '%s', '%s')", + " (%llu, %d, %s, %s, %s, %s, %s)", id, vulnerable ? 1 : 0, - quoted_cpe, - version_start_incl, - version_start_excl, - version_end_incl, - version_end_excl); - g_free (quoted_cpe); + sql_cpe ? sql_cpe : "", + version_start_incl ? version_start_incl : "", + version_start_excl ? version_start_excl : "", + version_end_incl ? version_end_incl : "", + version_end_excl ? version_end_excl : ""); + + g_free (sql_cpe); + g_free (version_start_incl); + g_free (version_start_excl); + g_free (version_end_incl); + g_free (version_end_excl); } } +/** + * @brief Set the root id for a node of a cve match rule tree. + * + * @param[in] id The id of the node for which the root id is to be set. + * @param[in] root_id The id of the root of the tree this node belongs to. + */ +static void +set_root_id (long int id, long int root_id) +{ + sql ("UPDATE scap2.cpe_match_nodes set root_id = %i" + " WHERE id = %i;", + root_id, + id); +} + /** * @brief Load and add recursively all nodes of a match rule tree for a * specific CVE. Build a match rule tree. * - * @param[in] parent_id The parent_id of the nodes to insert + * @param[in] parent_id The parent id of the nodes to insert * (0 for the root node). + * @param[in] root_id The root id of the nodes to insert * @param[in] cveid The id of the CVE the tree belongs to. * @param[in] nodes The JSON object that contains the rules for a * specific tree level. */ static void -load_nodes (resource_t parent_id, resource_t cveid, cJSON *nodes) +load_nodes (resource_t parent_id, resource_t cveid, resource_t root_id, cJSON *nodes) { cJSON *node; resource_t id; @@ -2823,13 +2863,22 @@ load_nodes (resource_t parent_id, resource_t cveid, cJSON *nodes) cJSON_ArrayForEach(node, nodes) { operator = cJSON_GetObjectItemCaseSensitive(node, "operator"); - if (operator) - id = save_node (parent_id, cveid, operator->valuestring); + if (operator && operator->valuestring) + { + id = save_node (parent_id, cveid, operator->valuestring); + } + else + return; + + if (parent_id == 0) + root_id = id; + set_root_id (id, root_id); + cpe_match_rules = cJSON_GetObjectItemCaseSensitive(node, "cpe_match"); if (cpe_match_rules) add_cpe_match_rules (id, cpe_match_rules); child_nodes = cJSON_GetObjectItemCaseSensitive(node, "children"); - load_nodes (id, cveid, child_nodes); + load_nodes (id, cveid, root_id, child_nodes); } } @@ -3007,7 +3056,7 @@ handle_json_cve_item (cJSON *item) g_warning("%s: nodes missing for %s.", __func__, cve_id); return -1; } - load_nodes (0, cve_db_id, nodes_json); + load_nodes (0, cve_db_id, 0, nodes_json); return 0; } From d0c6ffd8c925476de5a50bc89bcd171896f0f85f Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Tue, 24 Sep 2024 10:14:33 +0200 Subject: [PATCH 2/7] Small amendment. --- src/manage.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/manage.c b/src/manage.c index 97688b391..54b549754 100644 --- a/src/manage.c +++ b/src/manage.c @@ -3298,7 +3298,9 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) prognosis_report_host = 0; gboolean use_json = FALSE; - if (sql_int64_0 ("SELECT count(*) FROM scap.cpe_match_nodes") > 0) + if (sql_int64_0 ("SELECT count(1) FROM information_schema.tables" + " WHERE table_schema = 'scap'" + " AND table_name = 'cpe_match_nodes';") > 0) use_json = TRUE; if (use_json) From 271bd1e7ad20292afb2c5c4aaee0d1eba3775343 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Wed, 25 Sep 2024 13:24:27 +0200 Subject: [PATCH 3/7] Small amendment. --- src/manage_sql.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/manage_sql.c b/src/manage_sql.c index 5b19f2237..c468b3b5e 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -20453,10 +20453,10 @@ app_locations_iterator_location (iterator_t *iterator) * @param[in] report_host Report host. */ void -init_host_details_cpe_iterator (iterator_t* iterator, report_host_t report_host) +init_host_details_cpe_iterator (iterator_t *iterator, report_host_t report_host) { init_iterator (iterator, - "SELECT LOWER (value) FROM report_host_details" + "SELECT DISTINCT LOWER (value) FROM report_host_details" " WHERE name = 'App' and report_host = %llu;", report_host); } From ed5123e29077dd2a5e73fc81326f3e2cab33ad31 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Fri, 18 Oct 2024 16:06:09 +0200 Subject: [PATCH 4/7] Some amendments. --- src/manage.c | 316 +++++++++++++++++++++------------------ src/manage_sql.c | 11 +- src/manage_sql_secinfo.c | 10 +- 3 files changed, 176 insertions(+), 161 deletions(-) diff --git a/src/manage.c b/src/manage.c index 54b549754..159d5fa60 100644 --- a/src/manage.c +++ b/src/manage.c @@ -3165,6 +3165,8 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, { iterator_t cpe_match_node_childs; gchar *operator; + iterator_t cpe_match_ranges; + operator = sql_string ("SELECT operator FROM scap.cpe_match_nodes WHERE id = %llu", node); init_cpe_match_node_childs_iterator (&cpe_match_node_childs, node); while (next (&cpe_match_node_childs)) @@ -3177,7 +3179,7 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, if (strcmp (operator, "OR") == 0 && (*match) && (*vulnerable)) return; } - iterator_t cpe_match_ranges; + init_cpe_match_range_iterator (&cpe_match_ranges, node); while (next (&cpe_match_ranges)) { @@ -3187,12 +3189,10 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, gchar *vsi, *vse, *vei, *vee; range_fs_cpe = vsi = vse = vei = vee = NULL; range_fs_cpe = g_strdup (cpe_match_range_iterator_cpe (&cpe_match_ranges)); - vsi = (gchar*) cpe_match_range_iterator_version_start_incl(&cpe_match_ranges); - if (vsi != NULL) - vsi = g_strdup (cpe_match_range_iterator_version_start_incl(&cpe_match_ranges)); - vse = g_strdup (cpe_match_range_iterator_version_start_excl(&cpe_match_ranges)); - vei = g_strdup (cpe_match_range_iterator_version_end_incl(&cpe_match_ranges)); - vee = g_strdup (cpe_match_range_iterator_version_end_excl(&cpe_match_ranges)); + vsi = g_strdup (cpe_match_range_iterator_version_start_incl (&cpe_match_ranges)); + vse = g_strdup (cpe_match_range_iterator_version_start_excl (&cpe_match_ranges)); + vei = g_strdup (cpe_match_range_iterator_version_end_incl (&cpe_match_ranges)); + vee = g_strdup (cpe_match_range_iterator_version_end_excl (&cpe_match_ranges)); range_uri_product = fs_cpe_to_uri_product (range_fs_cpe); init_host_details_cpe_product_iterator (&cpe_host_details_products, range_uri_product, report_host); while (next (&cpe_host_details_products)) @@ -3200,12 +3200,12 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, cpe_struct_t source, target; const char *host_details_cpe; gboolean matches; - host_details_cpe = host_details_cpe_product_iterator_value(&cpe_host_details_products); + host_details_cpe = host_details_cpe_product_iterator_value (&cpe_host_details_products); cpe_struct_init (&source); cpe_struct_init (&target); fs_cpe_to_cpe_struct (range_fs_cpe, &source); uri_cpe_to_cpe_struct (host_details_cpe, &target); - matches = cpe_struct_match (source, target); + matches = cpe_struct_match (&source, &target); if (matches) { int result; @@ -3216,18 +3216,18 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, cpe_struct_free (&source); cpe_struct_free (&target); } - if (*match && cpe_match_range_iterator_vulnerable(&cpe_match_ranges) == 1) - { - cpe_struct_t source, target; - cpe_struct_init (&source); - cpe_struct_init (&target); - fs_cpe_to_cpe_struct (range_fs_cpe, &source); - uri_cpe_to_cpe_struct (host_cpe, &target); - if (cpe_struct_match (source, target)) - *vulnerable = TRUE; - cpe_struct_free (&source); - cpe_struct_free (&target); - } + if (*match && cpe_match_range_iterator_vulnerable (&cpe_match_ranges) == 1) + { + cpe_struct_t source, target; + cpe_struct_init (&source); + cpe_struct_init (&target); + fs_cpe_to_cpe_struct (range_fs_cpe, &source); + uri_cpe_to_cpe_struct (host_cpe, &target); + if (cpe_struct_match (&source, &target)) + *vulnerable = TRUE; + cpe_struct_free (&source); + cpe_struct_free (&target); + } g_free (range_uri_product); g_free (range_fs_cpe); g_free (vsi); @@ -3241,6 +3241,150 @@ check_cpe_match_rule (long long int node, gboolean *match, gboolean *vulnerable, } } +/** + * @brief Perform the json CVE "scan" for the found report host. + * + * @param[in] task Task. + * @param[in] report The report to add the host, results and details to. + * @param[in] report_host The report host. + * @param[in] ip The ip of the report host. + * @param[in] start_time The start time of the scan. + * + * @param[out] prognosis_report_host The report_host with prognosis results + * and host details. + * @param[out] results The results of the scan. + */ +static void +cve_scan_report_host_json (task_t task, + report_t report, + report_host_t report_host, + gchar *ip, + int start_time, + int *prognosis_report_host, + GArray *results) +{ + iterator_t host_details_cpe; + init_host_details_cpe_iterator (&host_details_cpe, report_host); + while (next (&host_details_cpe)) + { + iterator_t cpe_match_root_node; + iterator_t locations_iter; + result_t result; + char *cpe_product; + const char *host_cpe; + double severity; + + g_message ("PROTO1: WHILE1"); + + host_cpe = host_details_cpe_iterator_cpe (&host_details_cpe); + cpe_product = uri_cpe_to_fs_product (host_cpe); + init_cpe_match_nodes_iterator (&cpe_match_root_node, cpe_product); + while (next (&cpe_match_root_node)) + { + result_t root_node; + gboolean match, vulnerable; + const char *app, *cve; + + vulnerable = FALSE; + match = FALSE; + root_node = cpe_match_nodes_iterator_root_id (&cpe_match_root_node); + check_cpe_match_rule (root_node, &match, &vulnerable, report_host, host_cpe); + if (match && vulnerable) + { + GString *locations; + gchar *desc; + + if (*prognosis_report_host == 0) + *prognosis_report_host = manage_report_host_add (report, + ip, + start_time, + 0); + + severity = sql_double ("SELECT severity FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); + + app = host_cpe; + cve = sql_string ("SELECT name FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); + locations = g_string_new (""); + + insert_report_host_detail (global_current_report, ip, "cve", cve, + "CVE Scanner", "App", app, NULL); + + init_app_locations_iterator (&locations_iter, report_host, app); + + while (next (&locations_iter)) + { + const char *location; + location = app_locations_iterator_location (&locations_iter); + + if (location == NULL) + { + g_warning ("%s: Location is null for ip %s, app %s", + __func__, ip, app); + continue; + } + + if (locations->len) + { + g_string_append (locations, ", "); + } + g_string_append (locations, location); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", app, location, NULL); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_at", + location, NULL); + + insert_report_host_detail (report, ip, "cve", cve, + "CVE Scanner", "detected_by", + /* Detected by itself. */ + cve, NULL); + } + + const char *description; + description = sql_string ("SELECT description FROM scap.cves, scap.cpe_match_nodes" + " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" + " AND scap.cpe_match_nodes.id = %llu;", + root_node); + + desc = g_strdup_printf ("The host carries the product: %s\n" + "It is vulnerable according to: %s.\n" + "%s%s%s" + "\n" + "%s", + app, + cve, + locations->len + ? "The product was found at: " + : "", + locations->len ? locations->str : "", + locations->len ? ".\n" : "", + description); + + g_debug ("%s: making result with severity %1.1f desc [%s]", + __func__, severity, desc); + + result = make_cve_result (task, ip, cve, severity, desc); + g_free (desc); + + g_array_append_val (results, result); + + g_string_free (locations, TRUE); + + } + } + g_free (cpe_product); + } + cleanup_iterator (&host_details_cpe); +} + /** * @brief Perform a CVE "scan" on a host. * @@ -3297,136 +3441,18 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) start_time = time (NULL); prognosis_report_host = 0; - gboolean use_json = FALSE; if (sql_int64_0 ("SELECT count(1) FROM information_schema.tables" " WHERE table_schema = 'scap'" " AND table_name = 'cpe_match_nodes';") > 0) - use_json = TRUE; - - if (use_json) { - iterator_t host_details_cpe; - init_host_details_cpe_iterator (&host_details_cpe, report_host); - while (next (&host_details_cpe)) - { - iterator_t cpe_match_root_node; - iterator_t locations_iter; - result_t result; - char *cpe_product; - const char *host_cpe; - double severity; - - host_cpe = host_details_cpe_iterator_cpe (&host_details_cpe); - cpe_product = uri_cpe_to_fs_product (host_cpe); - init_cpe_match_nodes_iterator (&cpe_match_root_node, cpe_product); - while (next (&cpe_match_root_node)) - { - result_t root_node; - gboolean match, vulnerable; - const char *app, *cve; - - vulnerable = FALSE; - match = FALSE; - root_node = cpe_match_nodes_iterator_root_id (&cpe_match_root_node); - check_cpe_match_rule (root_node, &match, &vulnerable, report_host, host_cpe); - if (match && vulnerable) - { - GString *locations; - gchar *desc; - - if (prognosis_report_host == 0) - prognosis_report_host = manage_report_host_add (report, - ip, - start_time, - 0); - - severity = sql_double ("SELECT severity FROM scap.cves, scap.cpe_match_nodes" - " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" - " AND scap.cpe_match_nodes.id = %llu;", - root_node); - - app = host_cpe; - cve = sql_string ("SELECT name FROM scap.cves, scap.cpe_match_nodes" - " WHERE scap.cves.id = cpe_match_nodes.cve_id" - " AND scap.cpe_match_nodes.id = %llu;", - root_node); - locations = g_string_new(""); - - insert_report_host_detail (global_current_report, ip, "cve", cve, - "CVE Scanner", "App", app, NULL); - - init_app_locations_iterator (&locations_iter, report_host, app); - - while (next (&locations_iter)) - { - const char *location; - location = app_locations_iterator_location (&locations_iter); - - if (location == NULL) - { - g_warning ("%s: Location is null for ip %s, app %s", - __func__, ip, app); - continue; - } - - if (locations->len) - { - g_string_append (locations, ", "); - } - g_string_append (locations, location); - - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", app, location, NULL); - - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", "detected_at", - location, NULL); - - insert_report_host_detail (report, ip, "cve", cve, - "CVE Scanner", "detected_by", - /* Detected by itself. */ - cve, NULL); - } - - const char *description; - description = sql_string ("SELECT description FROM scap.cves, scap.cpe_match_nodes" - " WHERE scap.cves.id = scap.cpe_match_nodes.cve_id" - " AND scap.cpe_match_nodes.id = %llu;", - root_node); - - desc = g_strdup_printf ("The host carries the product: %s\n" - "It is vulnerable according to: %s.\n" - "%s%s%s" - "\n" - "%s", - app, - cve, - locations->len - ? "The product was found at: " - : "", - locations->len ? locations->str : "", - locations->len ? ".\n" : "", - description); - - g_debug ("%s: making result with severity %1.1f desc [%s]", - __func__, severity, desc); - - result = make_cve_result (task, ip, cve, severity, desc); - g_free (desc); - - g_array_append_val (results, result); - - g_string_free (locations, TRUE); - - } - } - g_free (cpe_product); - } - cleanup_iterator (&host_details_cpe); + // Use new JSON CVE scan + cve_scan_report_host_json (task, report, report_host, ip, + start_time, &prognosis_report_host, + results); } - - if (!use_json) + else { + // Use XML CVE scan init_host_prognosis_iterator (&prognosis, report_host); while (next (&prognosis)) { diff --git a/src/manage_sql.c b/src/manage_sql.c index c468b3b5e..d0746a186 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -20513,8 +20513,8 @@ init_cpe_match_nodes_iterator (iterator_t* iterator, const char *cpe) init_iterator (iterator, "SELECT DISTINCT root_id" " FROM scap.cpe_match_nodes, scap.cpe_match_range" - " WHERE cpe like '%s%s' AND scap.cpe_match_nodes.id = node_id;", - quoted_cpe, "%"); + " WHERE cpe like '%s%%' AND scap.cpe_match_nodes.id = node_id;", + quoted_cpe); g_free (quoted_cpe); } @@ -22554,11 +22554,6 @@ where_levels_auto (const char *levels, const char *new_severity_sql) g_string_append (levels_sql, ", 'error'"); count++; } - if (strchr (levels, 'd')) - { - g_string_append (levels_sql, ", 'error'"); - count++; - } if (count == 0) { @@ -23288,8 +23283,6 @@ results_extra_where (int trash, report_t report, const gchar* host, min_qod_clause = where_qod (min_qod); - g_message ("PROTO1: %s", levels); - fflush (NULL); levels_clause = where_levels_auto (levels ? levels : "hmlgdf", given_new_severity_sql ? given_new_severity_sql diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 6b552f035..2ecf26ec3 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -2704,8 +2704,6 @@ json_object_item_double (cJSON *object, char *key, double fallback) * * @param[in] parent_id The parent_id of the node. If this value is 0, * the node is the root of the tree. - * @param[in] root_id The id of the root of the tree. If this value - * is 0, the node is the root of the tree. * @param[in] cve_id The id of the CVE to which the tree belongs. * @param[in] operator The operator for the match rules. * @@ -2837,8 +2835,8 @@ set_root_id (long int id, long int root_id) * * @param[in] parent_id The parent id of the nodes to insert * (0 for the root node). - * @param[in] root_id The root id of the nodes to insert * @param[in] cveid The id of the CVE the tree belongs to. + * @param[in] root_id The root id of the nodes to insert. * @param[in] nodes The JSON object that contains the rules for a * specific tree level. */ @@ -2864,14 +2862,12 @@ load_nodes (resource_t parent_id, resource_t cveid, resource_t root_id, cJSON *n { operator = cJSON_GetObjectItemCaseSensitive(node, "operator"); if (operator && operator->valuestring) - { - id = save_node (parent_id, cveid, operator->valuestring); - } + id = save_node (parent_id, cveid, operator->valuestring); else return; if (parent_id == 0) - root_id = id; + root_id = id; set_root_id (id, root_id); cpe_match_rules = cJSON_GetObjectItemCaseSensitive(node, "cpe_match"); From 94377da9dc8e81e49906b38ae0b6246698b022e8 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Fri, 18 Oct 2024 17:18:12 +0200 Subject: [PATCH 5/7] Removed stray (debug) message. --- src/manage.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/manage.c b/src/manage.c index 159d5fa60..fca82209f 100644 --- a/src/manage.c +++ b/src/manage.c @@ -3274,8 +3274,6 @@ cve_scan_report_host_json (task_t task, const char *host_cpe; double severity; - g_message ("PROTO1: WHILE1"); - host_cpe = host_details_cpe_iterator_cpe (&host_details_cpe); cpe_product = uri_cpe_to_fs_product (host_cpe); init_cpe_match_nodes_iterator (&cpe_match_root_node, cpe_product); From cfc885af072e6a6e0804116d7022f4141c8320a8 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Tue, 22 Oct 2024 10:13:56 +0200 Subject: [PATCH 6/7] Changed location of initialization of "*quoted_cpe". --- src/manage_sql_secinfo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 2ecf26ec3..6230408de 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -2744,7 +2744,6 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) cJSON_ArrayForEach(match_rule, match_rules) { - char *quoted_cpe = NULL; char *sql_cpe = NULL; vulnerable = FALSE; version_start_incl = NULL; @@ -2760,7 +2759,7 @@ add_cpe_match_rules (result_t id, cJSON *match_rules) cpe_js = cJSON_GetObjectItemCaseSensitive(match_rule, "cpe23Uri"); if (cpe_js != NULL && strcmp (cpe_js->valuestring, "(null)")) { - quoted_cpe = sql_quote (cpe_js->valuestring); + char *quoted_cpe = sql_quote (cpe_js->valuestring); sql_cpe = g_strdup_printf ("'%s'", quoted_cpe); g_free (quoted_cpe); } From 2168aa40aca3266fe64e538ee6bed4756b7e1535 Mon Sep 17 00:00:00 2001 From: Johannes Helmold Date: Tue, 22 Oct 2024 10:22:26 +0200 Subject: [PATCH 7/7] Removed the option "e" for the display of errors. --- src/manage_sql.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/manage_sql.c b/src/manage_sql.c index d0746a186..fc1bf3905 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -22549,11 +22549,6 @@ where_levels_auto (const char *levels, const char *new_severity_sql) g_string_append (levels_sql, ", 'false'"); count++; } - if (strchr (levels, 'e')) - { - g_string_append (levels_sql, ", 'error'"); - count++; - } if (count == 0) {