From 12b44f31fad64013ec1f9f9100cc13dce2b1f53b Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 2 Oct 2024 11:51:30 +0200 Subject: [PATCH] Change deprecated_by of CPEs to a list. --- src/gmp.c | 14 +++-- src/manage.h | 6 ++ src/manage_pg.c | 5 ++ src/manage_sql_secinfo.c | 93 +++++++++++++++++++++++-------- src/schema_formats/XML/GMP.xml.in | 13 +++++ 5 files changed, 103 insertions(+), 28 deletions(-) diff --git a/src/gmp.c b/src/gmp.c index c2627b2ae..233bc3fd6 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -13438,16 +13438,18 @@ handle_get_info (gmp_parser_t *gmp_parser, GError **error) if (get_info_data->details == 1) { - const char *deprecated_by_id - = cpe_info_iterator_deprecated_by_id (&info); - if (deprecated_by_id && strcmp (deprecated_by_id, "")) + iterator_t deprecated_by, cves, refs; + + init_cpe_deprecated_by_iterator (&deprecated_by, + get_iterator_name (&info)); + while (next (&deprecated_by)) { xml_string_append (result, - "%s", - deprecated_by_id); + "", + cpe_deprecated_by_iterator_deprecated_by + (&deprecated_by)); } - iterator_t cves, refs; g_string_append (result, ""); init_cpe_cve_iterator (&cves, get_iterator_name (&info), 0, NULL); while (next (&cves)) diff --git a/src/manage.h b/src/manage.h index 6d34f02f9..9d2434292 100644 --- a/src/manage.h +++ b/src/manage.h @@ -3339,6 +3339,12 @@ manage_scap_update_time (); /* CPE. */ +void +init_cpe_deprecated_by_iterator (iterator_t *, const char *); + +const char * +cpe_deprecated_by_iterator_deprecated_by (iterator_t *); + void init_cpe_cve_iterator (iterator_t *, const char *, int, const char *); diff --git a/src/manage_pg.c b/src/manage_pg.c index 7088a4e9c..0cad6c0af 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -3538,6 +3538,11 @@ manage_db_init (const gchar *name) " ref TEXT," " type TEXT);"); + sql ("CREATE TABLE scap2.cpes_deprecated_by" + " (id SERIAL PRIMARY KEY," + " cpe TEXT," + " deprecated_by TEXT);"); + sql ("CREATE TABLE scap2.cpe_match_nodes" " (id SERIAL PRIMARY KEY," " parent_id INTEGER DEFAULT 0," diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index b03413453..680602322 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -696,6 +696,28 @@ cve_info_filter_columns () return filter_columns; } +/** + * @brief Initialise an iterator listing CPEs another CPE is deprecated_by. + * + * @param[in] iterator Iterator. + * @param[in] cpe CPE to get which other CPEs it's deprecated by. + */ +void +init_cpe_deprecated_by_iterator (iterator_t *iterator, const char *cpe) +{ + gchar *quoted_cpe; + assert (cpe); + quoted_cpe = sql_quote (cpe); + init_iterator (iterator, + "SELECT deprecated_by FROM cpes_deprecated_by" + " WHERE cpe = '%s'" + " ORDER BY deprecated_by;", + quoted_cpe); + g_free (quoted_cpe); +} + +DEF_ACCESS (cpe_deprecated_by_iterator_deprecated_by, 0); + /** * @brief Initialise an CVE iterator, for CVEs reported for a certain CPE. * @@ -2272,19 +2294,19 @@ scap_cpes_json_skip_to_products (gvm_json_pull_parser_t *parser, /** * @brief Insert a SCAP CPE from JSON. * - * @param[in] inserts Pointer to SQL buffer. + * @param[in] inserts Pointer to SQL buffer for main CPE entries. + * @param[in] deprecated_by_inserts Pointer to SQL buffer for deprecated_by. * @param[in] product_item JSON object from the products list. * * @return 0 success, -1 error. */ static int -handle_json_cpe_item (inserts_t *inserts, cJSON *product_item) +handle_json_cpe_item (inserts_t *inserts, inserts_t *deprecated_by_inserts, + cJSON *product_item) { cJSON *cpe_item; char *name, *cpe_name_id, *last_modified, *title_text; - char *deprecated_by; gchar *quoted_name, *quoted_title, *quoted_cpe_name_id; - gchar *quoted_deprecated_by; cJSON *titles, *title; time_t modification_time; int deprecated; @@ -2347,48 +2369,70 @@ handle_json_cpe_item (inserts_t *inserts, cJSON *product_item) return -1; } - deprecated_by = NULL; + quoted_name = fs_to_uri_convert_and_quote_cpe_name (name); if (deprecated) { /* CPEs can have multiple deprecatedBy entries, * but for the GMP field only the first one is used */ - cJSON *deprecated_by_array, *first_deprecated_by; + cJSON *deprecated_by_array, *deprecated_by_item; + char *deprecated_by_id; + gchar *quoted_deprecated_by_id; deprecated_by_array = cJSON_GetObjectItemCaseSensitive (cpe_item, "deprecatedBy"); if (! cJSON_IsArray (deprecated_by_array)) { g_warning ("%s: 'deprecatedBy' field missing or not an array", __func__); + g_free (quoted_name); return -1; } else if (cJSON_GetArraySize (deprecated_by_array) == 0) { g_warning ("%s: 'deprecatedBy' array is empty", __func__); + g_free (quoted_name); return -1; } - first_deprecated_by = cJSON_GetArrayItem (deprecated_by_array, 0); - deprecated_by = json_object_item_string (first_deprecated_by, "cpeName"); - if (deprecated_by == NULL) + cJSON_ArrayForEach (deprecated_by_item, deprecated_by_array) { - g_warning ("%s: Could not get 'cpeName' string from 'deprecatedBy'", - __func__); - return -1; + deprecated_by_id = json_object_item_string (deprecated_by_item, + "cpeName"); + if (deprecated_by_id == NULL) + { + g_warning ("%s: 'cpeName' field in 'deprecatedBy' missing or not" + " a string", + __func__); + g_free (quoted_name); + return -1; + } + + quoted_deprecated_by_id + = fs_to_uri_convert_and_quote_cpe_name (deprecated_by_id); + + g_message ("%s deprecated by %s", quoted_name, quoted_deprecated_by_id); + + first = inserts_check_size (deprecated_by_inserts); + + g_string_append_printf (deprecated_by_inserts->statement, + "%s ('%s', '%s')", + first ? "" : ",", + quoted_name, + quoted_deprecated_by_id); + + deprecated_by_inserts->current_chunk_size++; + + g_free (quoted_deprecated_by_id); } } - quoted_name = fs_to_uri_convert_and_quote_cpe_name (name); quoted_cpe_name_id = sql_quote (cpe_name_id); quoted_title = sql_quote (title_text ? title_text : ""); - quoted_deprecated_by - = deprecated_by ? fs_to_uri_convert_and_quote_cpe_name (deprecated_by) - : NULL; first = inserts_check_size (inserts); g_string_append_printf (inserts->statement, - "%s ('%s', '%s', '%s', %li, %li, %d, '%s', '%s')", + "%s ('%s', '%s', '%s', %li, %li, %d, '%s')", first ? "" : ",", quoted_name, quoted_name, @@ -2396,7 +2440,6 @@ handle_json_cpe_item (inserts_t *inserts, cJSON *product_item) modification_time, modification_time, deprecated, - quoted_deprecated_by ? quoted_deprecated_by : "", quoted_cpe_name_id); inserts->current_chunk_size++; @@ -2404,7 +2447,6 @@ handle_json_cpe_item (inserts_t *inserts, cJSON *product_item) g_free (quoted_title); g_free (quoted_name); g_free (quoted_cpe_name_id); - g_free (quoted_deprecated_by); return 0; } @@ -2490,7 +2532,7 @@ handle_json_cpe_refs (inserts_t *inserts, cJSON *product_item) static int update_scap_cpes_from_json_file (const gchar *path) { - inserts_t inserts; + inserts_t inserts, deprecated_by_inserts; gvm_json_pull_parser_t parser; gvm_json_pull_event_t event; FILE *json_stream = fopen (path, "r"); @@ -2517,7 +2559,7 @@ update_scap_cpes_from_json_file (const gchar *path) setting_secinfo_sql_buffer_threshold_bytes (), "INSERT INTO scap2.cpes" " (uuid, name, title, creation_time," - " modification_time, deprecated, deprecated_by_id," + " modification_time, deprecated," " cpe_name_id)" " VALUES", " ON CONFLICT (uuid) DO UPDATE" @@ -2529,6 +2571,12 @@ update_scap_cpes_from_json_file (const gchar *path) " deprecated_by_id = EXCLUDED.deprecated_by_id," " cpe_name_id = EXCLUDED.cpe_name_id"); + inserts_init (&deprecated_by_inserts, 10, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpes_deprecated_by (cpe, deprecated_by)" + " VALUES ", + ""); + while (event.type == GVM_JSON_PULL_EVENT_OBJECT_START) { gchar *error_message; @@ -2543,7 +2591,7 @@ update_scap_cpes_from_json_file (const gchar *path) sql_commit (); return -1; } - if (handle_json_cpe_item (&inserts, entry)) + if (handle_json_cpe_item (&inserts, &deprecated_by_inserts, entry)) { gvm_json_pull_event_cleanup (&event); gvm_json_pull_parser_cleanup (&parser); @@ -2556,6 +2604,7 @@ update_scap_cpes_from_json_file (const gchar *path) gvm_json_pull_parser_next (&parser, &event); } inserts_run (&inserts, TRUE); + inserts_run (&deprecated_by_inserts, TRUE); sql_commit (); gvm_json_pull_parser_cleanup (&parser); diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 473cf3b2e..0d36df7e2 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -12996,6 +12996,7 @@ END:VCALENDAR severity cve_refs deprecated + deprecated_by cves references raw_data @@ -13036,6 +13037,18 @@ END:VCALENDAR boolean + + deprecated_by + Another CPE the current one is deprecated by + + + cpe_id + uuid + CPE id the current CPE is deprecated by + 1 + + + cves CVEs referring to this CPE. Only when details were requested