diff --git a/.docker/prod.Dockerfile b/.docker/prod.Dockerfile index 1872962b8..6141b6ce3 100644 --- a/.docker/prod.Dockerfile +++ b/.docker/prod.Dockerfile @@ -72,9 +72,6 @@ ARG DEBIAN_FRONTEND=noninteractive # s/mime email encryption # gpgsm -# Loading scap and cert data -# xml-twig-tools - # Required for set up certificates for GVM # gnutls-bin diff --git a/.docker/setup-mta.sh b/.docker/setup-mta.sh index 51aaa00ea..e27d763f1 100644 --- a/.docker/setup-mta.sh +++ b/.docker/setup-mta.sh @@ -1,19 +1,19 @@ #!/bin/bash # Make any changes only when MTA_HOST has been set -if [ -n MTA_HOST ]; then +if [ -n "$MTA_HOST" ]; then echo "setting up configuration file for mail agent" CONFIG="/etc/msmtprc" echo "host $MTA_HOST" > $CONFIG - [ -n MTA_PORT ] && echo "port $MTA_PORT" >> $CONFIG - [ -n MTA_TLS ] && echo "tls $MTA_TLS" >> $CONFIG - [ -n MTA_STARTTLS ] && echo "tls_starttls $MTA_STARTTLS" >> $CONFIG - [ -n MTA_TLS_CERTCHECK ] && echo "tls_certcheck $MTA_TLS_CERTCHECK" >> $CONFIG - [ -n MTA_AUTH ] && echo "auth $MTA_AUTH" >> $CONFIG - [ -n MTA_USER ] && echo "user $MTA_USER" >> $CONFIG - [ -n MTA_FROM ] && echo "from $MTA_FROM" >> $CONFIG - [ -n MTA_PASSWORD ] && echo "password $MTA_PASSWORD" >> $CONFIG - [ -n MTA_LOGFILE ] && echo "logfile $MTA_LOGFILE" >> $CONFIG + [ -n "$MTA_PORT" ] && echo "port $MTA_PORT" >> $CONFIG + [ -n "$MTA_TLS" ] && echo "tls $MTA_TLS" >> $CONFIG + [ -n "$MTA_STARTTLS" ] && echo "tls_starttls $MTA_STARTTLS" >> $CONFIG + [ -n "$MTA_TLS_CERTCHECK" ] && echo "tls_certcheck $MTA_TLS_CERTCHECK" >> $CONFIG + [ -n "$MTA_AUTH" ] && echo "auth $MTA_AUTH" >> $CONFIG + [ -n "$MTA_USER" ] && echo "user $MTA_USER" >> $CONFIG + [ -n "$MTA_FROM" ] && echo "from $MTA_FROM" >> $CONFIG + [ -n "$MTA_PASSWORD" ] && echo "password $MTA_PASSWORD" >> $CONFIG + [ -n "$MTA_LOGFILE" ] && echo "logfile $MTA_LOGFILE" >> $CONFIG chown gvmd:mail $CONFIG chmod 750 $CONFIG fi diff --git a/.docker/start-gvmd.sh b/.docker/start-gvmd.sh index 7083b8f81..a05ca0824 100644 --- a/.docker/start-gvmd.sh +++ b/.docker/start-gvmd.sh @@ -18,7 +18,7 @@ [ -z "$USER" ] && USER="admin" [ -z "$PASSWORD" ] && PASSWORD="admin" -[ -z "$GVMD_ARGS" ] && GVMD_ARGS="--listen-mode=666" +[ -z "$GVMD_ARGS" ] && GVMD_ARGS="-f --listen-mode=666" [ -z "$GVMD_USER" ] && GVMD_USER="gvmd" [ -z "$PGRES_DATA" ] && PGRES_DATA="/var/lib/postgresql" @@ -49,6 +49,4 @@ gvmd --modify-setting 78eceaec-3385-11ea-b237-28d24461215b --value "$uid" echo "starting gvmd" gvmd $GVMD_ARGS || - (cat /var/log/gvm/gvmd.log && exit 1) - -tail -f /var/log/gvm/gvmd.log + (echo "Starting gvmd failed" && exit 1) \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 470a23bb2..c74217b0c 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -64,7 +64,7 @@ jobs: - name: Configure and run tests run: CTEST_OUTPUT_ON_FAILURE=1 cmake --build build -- tests test - name: Upload test coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: file: build/coverage/coverage.xml token: ${{ secrets.CODECOV_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index bc7b71249..e6c9eb3a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required (VERSION 3.0) message ("-- Configuring Greenbone Vulnerability Manager...") project (gvm - VERSION 23.10.1 + VERSION 24.1.3 LANGUAGES C) if (POLICY CMP0005) @@ -103,7 +103,7 @@ include (CPack) set (GVMD_DATABASE_VERSION 256) -set (GVMD_SCAP_DATABASE_VERSION 21) +set (GVMD_SCAP_DATABASE_VERSION 22) set (GVMD_CERT_DATABASE_VERSION 8) @@ -163,11 +163,13 @@ if (NOT GVMD_STATE_DIR) set (GVMD_STATE_DIR "${GVM_STATE_DIR}/gvmd") endif (NOT GVMD_STATE_DIR) -if (NOT GVM_LOG_DIR) - set (GVM_LOG_DIR "${LOCALSTATEDIR}/log/gvm") -else (NOT GVM_LOG_DIR) - set (GVM_LOG_DIR "${GVM_LOG_DIR}") -endif (NOT GVM_LOG_DIR) +if (NOT GVMD_LOG_FILE) + if (GVM_LOG_DIR) + set (GVMD_LOG_FILE "${GVM_LOG_DIR}/gvmd.log") + else (GVM_LOG_DIR) + set (GVMD_LOG_FILE "-") + endif (GVM_LOG_DIR) +endif (NOT GVMD_LOG_FILE) set (GVM_SCAP_RES_DIR "${GVM_DATA_DIR}/scap") set (GVM_CERT_RES_DIR "${GVM_DATA_DIR}/cert") @@ -247,25 +249,25 @@ if (NOT CVSS3_RATINGS) endif (NOT CVSS3_RATINGS) add_definitions (-DCVSS3_RATINGS=${CVSS3_RATINGS}) -if (NOT COMPLIANCE_REPORTS) - set (COMPLIANCE_REPORTS 1) -endif (NOT COMPLIANCE_REPORTS) -add_definitions (-DCOMPLIANCE_REPORTS=${COMPLIANCE_REPORTS}) +if (CVSS3_RATINGS EQUAL 1) + set(IF_CVSS3_RATINGS "") + set(ENDIF_CVSS3_RATINGS "") + set(IF_NOT_CVSS3_RATINGS "") +elseif (CVSS3_RATINGS EQUAL 0) + set(IF_CVSS3_RATINGS "") + set(IF_NOT_CVSS3_RATINGS "") + set(ENDIF_NOT_CVSS3_RATINGS "") +endif() message ("-- Install prefix: ${CMAKE_INSTALL_PREFIX}") +message ("-- Log file: ${GVMD_LOG_FILE}") ## Version set (GVMD_VERSION "${PROJECT_VERSION_STRING}") -if (COMPLIANCE_REPORTS EQUAL 1) - set(IF_COMPLIANCE_REPORTS "") - set(ENDIF_COMPLIANCE_REPORTS "") -elseif (COMPLIANCE_REPORTS EQUAL 0) - set(IF_COMPLIANCE_REPORTS "") -endif() - # Configure Doxyfile with version number configure_file (doc/Doxyfile.in doc/Doxyfile) configure_file (doc/Doxyfile_full.in doc/Doxyfile_full) diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index a9c1ce686..5756751d5 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -15,9 +15,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - if (NOT SYSTEMD_SERVICE_DIR) - set (SYSTEMD_SERVICE_DIR "/lib/systemd/system") + set (SYSTEMD_SERVICE_DIR "${LIBDIR}/systemd/system") endif (NOT SYSTEMD_SERVICE_DIR) if (NOT LOGROTATE_DIR) diff --git a/src/gmp.c b/src/gmp.c index 8ede8d6a9..533026a4f 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -101,6 +101,7 @@ #include "manage_report_configs.h" #include "manage_report_formats.h" #include "manage_tls_certificates.h" +#include "sql.h" #include "utils.h" #include @@ -128,6 +129,7 @@ #include #include #include +#include #undef G_LOG_DOMAIN /** @@ -447,6 +449,7 @@ typedef struct char *certificate; ///< Certificate for client certificate auth. char *comment; ///< Comment. char *copy; ///< UUID of resource to copy. + char *kdc; ///< Kerberos KDC (key distribution centers). int key; ///< Whether the command included a key element. char *key_phrase; ///< Passphrase for key. char *key_private; ///< Private key from key. @@ -458,6 +461,7 @@ typedef struct char *auth_algorithm; ///< SNMP Authentication algorithm. char *privacy_password; ///< SNMP Privacy password. char *privacy_algorithm; ///< SNMP Privacy algorithm. + char *realm; ///< Kerberos realm. char *type; ///< Type of credential. } create_credential_data_t; @@ -473,6 +477,7 @@ create_credential_data_reset (create_credential_data_t *data) free (data->certificate); free (data->comment); free (data->copy); + free (data->kdc); free (data->key_phrase); free (data->key_private); free (data->key_public); @@ -483,6 +488,7 @@ create_credential_data_reset (create_credential_data_t *data) free (data->auth_algorithm); free (data->privacy_password); free (data->privacy_algorithm); + free (data->realm); free (data->type); memset (data, 0, sizeof (create_credential_data_t)); @@ -944,6 +950,7 @@ typedef struct char *esxi_credential_id; ///< ESXi credential for new target. char *esxi_lsc_credential_id; ///< ESXi credential (deprecated). char *snmp_credential_id; ///< SNMP credential for new target. + char *krb5_credential_id; ///< Kerberos 5 credential for new target. char *name; ///< Name of new target. } create_target_data_t; @@ -976,6 +983,7 @@ create_target_data_reset (create_target_data_t *data) free (data->esxi_credential_id); free (data->esxi_lsc_credential_id); free (data->snmp_credential_id); + free (data->krb5_credential_id); free (data->name); memset (data, 0, sizeof (create_target_data_t)); @@ -1899,7 +1907,6 @@ get_overrides_data_reset (get_overrides_data_t *data) typedef struct { get_data_t get; ///< Get args. - char *resource_id; ///< Resource whose permissions to get. } get_permissions_data_t; /** @@ -1910,8 +1917,6 @@ typedef struct static void get_permissions_data_reset (get_permissions_data_t *data) { - free (data->resource_id); - get_data_reset (&data->get); memset (data, 0, sizeof (get_permissions_data_t)); } @@ -2513,6 +2518,7 @@ typedef struct char *comment; ///< Comment. char *community; ///< SNMP Community string. char *credential_id; ///< ID of credential to modify. + char *kdc; ///< Kerberos KDC (key distribution centers). int key; ///< Whether the command included a key element. char *key_phrase; ///< Passphrase for key. char *key_private; ///< Private key from key. @@ -2522,6 +2528,7 @@ typedef struct char *password; ///< Password associated with login name. char *privacy_algorithm; ///< SNMP Privacy algorithm. char *privacy_password; ///< SNMP Privacy password. + char *realm; ///< Kerberos realm. } modify_credential_data_t; /** @@ -2538,6 +2545,7 @@ modify_credential_data_reset (modify_credential_data_t *data) free (data->comment); free (data->community); free (data->credential_id); + free (data->kdc); free (data->key_phrase); free (data->key_private); free (data->key_public); @@ -2546,6 +2554,7 @@ modify_credential_data_reset (modify_credential_data_t *data) free (data->password); free (data->privacy_algorithm); free (data->privacy_password); + free (data->realm); memset (data, 0, sizeof (modify_credential_data_t)); } @@ -2873,6 +2882,7 @@ typedef struct char *esxi_credential_id; ///< ESXi credential for target. char *esxi_lsc_credential_id; ///< ESXi credential for target (deprecated). char *snmp_credential_id; ///< SNMP credential for target. + char *krb5_credential_id; ///< Kerberos 5 credential for target. char *target_id; ///< Target UUID. } modify_target_data_t; @@ -2903,6 +2913,7 @@ modify_target_data_reset (modify_target_data_t *data) free (data->esxi_credential_id); free (data->esxi_lsc_credential_id); free (data->snmp_credential_id); + free (data->krb5_credential_id); free (data->target_id); memset (data, 0, sizeof (modify_target_data_t)); @@ -4086,6 +4097,7 @@ typedef enum CLIENT_CREATE_CREDENTIAL_COMMENT, CLIENT_CREATE_CREDENTIAL_COMMUNITY, CLIENT_CREATE_CREDENTIAL_COPY, + CLIENT_CREATE_CREDENTIAL_KDC, CLIENT_CREATE_CREDENTIAL_KEY, CLIENT_CREATE_CREDENTIAL_KEY_PHRASE, CLIENT_CREATE_CREDENTIAL_KEY_PRIVATE, @@ -4096,6 +4108,7 @@ typedef enum CLIENT_CREATE_CREDENTIAL_PRIVACY, CLIENT_CREATE_CREDENTIAL_PRIVACY_ALGORITHM, CLIENT_CREATE_CREDENTIAL_PRIVACY_PASSWORD, + CLIENT_CREATE_CREDENTIAL_REALM, CLIENT_CREATE_CREDENTIAL_TYPE, CLIENT_CREATE_FILTER, CLIENT_CREATE_FILTER_COMMENT, @@ -4283,6 +4296,7 @@ typedef enum CLIENT_CREATE_TARGET_NAME, CLIENT_CREATE_TARGET_PORT_LIST, CLIENT_CREATE_TARGET_PORT_RANGE, + CLIENT_CREATE_TARGET_KRB5_CREDENTIAL, CLIENT_CREATE_TARGET_SMB_CREDENTIAL, CLIENT_CREATE_TARGET_SNMP_CREDENTIAL, CLIENT_CREATE_TARGET_SSH_CREDENTIAL, @@ -4418,6 +4432,7 @@ typedef enum CLIENT_MODIFY_CREDENTIAL_CERTIFICATE, CLIENT_MODIFY_CREDENTIAL_COMMENT, CLIENT_MODIFY_CREDENTIAL_COMMUNITY, + CLIENT_MODIFY_CREDENTIAL_KDC, CLIENT_MODIFY_CREDENTIAL_KEY, CLIENT_MODIFY_CREDENTIAL_KEY_PHRASE, CLIENT_MODIFY_CREDENTIAL_KEY_PRIVATE, @@ -4428,6 +4443,7 @@ typedef enum CLIENT_MODIFY_CREDENTIAL_PRIVACY, CLIENT_MODIFY_CREDENTIAL_PRIVACY_ALGORITHM, CLIENT_MODIFY_CREDENTIAL_PRIVACY_PASSWORD, + CLIENT_MODIFY_CREDENTIAL_REALM, CLIENT_MODIFY_FILTER, CLIENT_MODIFY_FILTER_COMMENT, CLIENT_MODIFY_FILTER_NAME, @@ -4518,6 +4534,7 @@ typedef enum CLIENT_MODIFY_TARGET_REVERSE_LOOKUP_UNIFY, CLIENT_MODIFY_TARGET_NAME, CLIENT_MODIFY_TARGET_PORT_LIST, + CLIENT_MODIFY_TARGET_KRB5_CREDENTIAL, CLIENT_MODIFY_TARGET_SMB_CREDENTIAL, CLIENT_MODIFY_TARGET_SNMP_CREDENTIAL, CLIENT_MODIFY_TARGET_SSH_CREDENTIAL, @@ -5461,8 +5478,6 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, get_data_parse_attributes (&get_permissions_data->get, "permission", attribute_names, attribute_values); - append_attribute (attribute_names, attribute_values, "resource_id", - &get_permissions_data->resource_id); set_client_state (CLIENT_GET_PERMISSIONS); } else if (strcasecmp ("GET_PREFERENCES", element_name) == 0) @@ -5511,7 +5526,7 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, append_attribute (attribute_names, attribute_values, "config_id", &get_reports_data->config_id); - + append_attribute (attribute_names, attribute_values, "format_id", &get_reports_data->format_id); @@ -5602,7 +5617,7 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, "type", &typebuf)) get_resource_names_data->type = g_ascii_strdown (typebuf, -1); set_client_state (CLIENT_GET_RESOURCE_NAMES); - } + } else if (strcasecmp ("GET_RESULTS", element_name) == 0) { const gchar* attribute; @@ -6281,6 +6296,10 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, gvm_append_string (&modify_credential_data->community, ""); set_client_state (CLIENT_MODIFY_CREDENTIAL_COMMUNITY); } + else if (strcasecmp ("KDC", element_name) == 0) + { + set_client_state (CLIENT_MODIFY_CREDENTIAL_KDC); + } else if (strcasecmp ("KEY", element_name) == 0) { modify_credential_data->key = 1; @@ -6300,6 +6319,10 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, gvm_append_string (&modify_credential_data->privacy_algorithm, ""); } + else if (strcasecmp ("REALM", element_name) == 0) + { + set_client_state (CLIENT_MODIFY_CREDENTIAL_REALM); + } ELSE_READ_OVER; case CLIENT_MODIFY_CREDENTIAL_KEY: @@ -6614,6 +6637,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, &modify_target_data->port_list_id); set_client_state (CLIENT_MODIFY_TARGET_PORT_LIST); } + else if (strcasecmp ("KRB5_CREDENTIAL", element_name) == 0) + { + append_attribute (attribute_names, attribute_values, "id", + &modify_target_data->krb5_credential_id); + set_client_state (CLIENT_MODIFY_TARGET_KRB5_CREDENTIAL); + } else if (strcasecmp ("SSH_CREDENTIAL", element_name) == 0) { append_attribute (attribute_names, attribute_values, "id", @@ -6960,6 +6989,8 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, set_client_state (CLIENT_CREATE_CREDENTIAL_COMMENT); else if (strcasecmp ("COMMUNITY", element_name) == 0) set_client_state (CLIENT_CREATE_CREDENTIAL_COMMUNITY); + else if (strcasecmp ("KDC", element_name) == 0) + set_client_state (CLIENT_CREATE_CREDENTIAL_KDC); else if (strcasecmp ("KEY", element_name) == 0) { create_credential_data->key = 1; @@ -6978,6 +7009,8 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, } else if (strcasecmp ("PRIVACY", element_name) == 0) set_client_state (CLIENT_CREATE_CREDENTIAL_PRIVACY); + else if (strcasecmp ("REALM", element_name) == 0) + set_client_state (CLIENT_CREATE_CREDENTIAL_REALM); else if (strcasecmp ("TYPE", element_name) == 0) set_client_state (CLIENT_CREATE_CREDENTIAL_TYPE); ELSE_READ_OVER; @@ -7621,6 +7654,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context, gvm_append_string (&create_target_data->port_range, ""); set_client_state (CLIENT_CREATE_TARGET_PORT_RANGE); } + else if (strcasecmp ("KRB5_CREDENTIAL", element_name) == 0) + { + append_attribute (attribute_names, attribute_values, "id", + &create_target_data->krb5_credential_id); + set_client_state (CLIENT_CREATE_TARGET_KRB5_CREDENTIAL); + } else if (strcasecmp ("SSH_CREDENTIAL", element_name) == 0) { append_attribute (attribute_names, attribute_values, "id", @@ -8449,7 +8488,7 @@ buffer_override_xml (GString *buffer, iterator_t *overrides, buffer_xml_append_printf (buffer, "%s", iso_if_time (get_iterator_creation_time (overrides))); - + buffer_xml_append_printf (buffer, "%s", iso_if_time (get_iterator_modification_time (overrides))); @@ -8467,7 +8506,8 @@ buffer_override_xml (GString *buffer, iterator_t *overrides, override_iterator_active (overrides), strlen (excerpt) < strlen (text), excerpt, - override_iterator_threat (overrides) + (override_iterator_severity (overrides) + && override_iterator_threat (overrides)) ? override_iterator_threat (overrides) : "", override_iterator_severity (overrides) @@ -8561,7 +8601,8 @@ buffer_override_xml (GString *buffer, iterator_t *overrides, ? override_iterator_hosts (overrides) : "", override_iterator_port (overrides) ? override_iterator_port (overrides) : "", - override_iterator_threat (overrides) + (override_iterator_severity (overrides) + && override_iterator_threat (overrides)) ? override_iterator_threat (overrides) : "", override_iterator_severity (overrides) ? override_iterator_severity (overrides) : "", @@ -9351,9 +9392,9 @@ results_xml_append_nvt (iterator_t *results, GString *buffer, int cert_loaded) * */ void -buffer_diff(GString *buffer, const char *descr, const char *delta_descr) +buffer_diff(GString *buffer, const char *descr, const char *delta_descr) { - + gchar *diff = strdiff (descr ? descr : "", delta_descr ? delta_descr : ""); if (diff) @@ -9426,7 +9467,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, report_t report; task_t selected_task; time_t creation_time; - + comment = get_iterator_comment (results); name = get_iterator_name (results); host = result_iterator_host (results); @@ -9501,7 +9542,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, { const char *owner_name; time_t modification_time; - + if (use_delta_fields) { owner_name = result_iterator_delta_owner_name (results); @@ -9543,7 +9584,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, { if (task == 0) selected_task = result_iterator_delta_task (results); - + result_task_name = task_name(result_iterator_delta_task (results)); result_report_id = report_uuid(result_iterator_delta_report (results)); } @@ -9551,7 +9592,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, { if (task == 0) selected_task = result_iterator_task (results); - + result_task_name = task_name (result_iterator_task (results)); result_report_id = report_uuid (result_iterator_report (results)); } @@ -9672,14 +9713,14 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, const char *nvt_version, *level; if (use_delta_fields) { - nvt_version = result_iterator_delta_nvt_version (results); + nvt_version = result_iterator_delta_nvt_version (results); level = result_iterator_delta_level (results); - } + } else { nvt_version = result_iterator_scan_nvt_version (results); level = result_iterator_level (results); - } + } buffer_xml_append_printf (buffer, "%s" @@ -9710,7 +9751,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, { /* Only send the original severity if it has changed. */ if (strncmp (original_severity, - severity, + severity, /* Avoid rounding differences. */ 3)) buffer_xml_append_printf (buffer, @@ -9747,7 +9788,7 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, if (delta_state) g_string_append_printf (buffer, "%s", delta_state); - if(delta_results) { + if(delta_results) { /* delta reports version 1 */ if (changed) { @@ -9766,8 +9807,8 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, g_free (delta_nl_descr); } } else { - /* delta reports version 2 */ - if (changed) + /* delta reports version 2 */ + if (changed) { gchar *delta_nl_descr; const char *delta_descr; @@ -9810,8 +9851,8 @@ buffer_results_xml (GString *buffer, iterator_t *results, task_t task, g_free (nl_descr_escaped); } - if (use_delta_fields - ? result_iterator_delta_may_have_tickets (results) + if (use_delta_fields + ? result_iterator_delta_may_have_tickets (results) : result_iterator_may_have_tickets (results)) buffer_result_tickets_xml (buffer, result); @@ -12336,6 +12377,19 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) SEND_TO_CLIENT_OR_FAIL (formats_xml); g_free (formats_xml); + if (type && (strcmp (type, "krb5") == 0)) + { + const char *kdc, *realm; + kdc = credential_iterator_kdc (&credentials); + realm = credential_iterator_realm (&credentials); + + SENDF_TO_CLIENT_OR_FAIL + ("%s" + "%s", + kdc ? kdc : "", + realm ? realm : ""); + } + if (type && (strcmp (type, "snmp") == 0)) { const char *auth_algorithm, *privacy_algorithm; @@ -12956,11 +13010,6 @@ handle_get_features (gmp_parser_t *gmp_parser, GError **error) " status=\"" STATUS_OK "\"" " status_text=\"" STATUS_OK_TEXT "\">"); - SENDF_TO_CLIENT_OR_FAIL ("" - "COMPLIANCE_REPORTS" - "", - COMPLIANCE_REPORTS ? 1 : 0); - SENDF_TO_CLIENT_OR_FAIL ("" "CVSS3_RATINGS" "", @@ -13252,6 +13301,211 @@ handle_get_groups (gmp_parser_t *gmp_parser, GError **error) set_client_state (CLIENT_AUTHENTIC); } +/** + * @brief Print CPE match node with its matched CPEs. + * + * @param[in] node CPE match node to print. + * @param[in] buffer Buffer into which to print match node. + */ +static void +print_cpe_match_nodes_xml (resource_t node, GString *buffer) +{ + iterator_t cpe_match_nodes, cpe_match_ranges; + + init_iterator (&cpe_match_nodes, + "SELECT operator, negate" + " FROM scap.cpe_match_nodes WHERE id = %llu;", + node); + + const char *operator = NULL; + int negate = 0; + while (next (&cpe_match_nodes)) + { + operator = iterator_string (&cpe_match_nodes, 0); + negate = iterator_int (&cpe_match_nodes, 1); + } + cleanup_iterator (&cpe_match_nodes); + + xml_string_append (buffer, "%s", operator?: ""); + xml_string_append (buffer, "%s", negate? "1" : "0"); + + init_cpe_match_string_iterator (&cpe_match_ranges, node); + while (next (&cpe_match_ranges)) + { + const gchar *vsi, *vse, *vei, *vee, *match_criteria_id, *criteria, *status; + + xml_string_append (buffer, ""); + match_criteria_id + = cpe_match_string_iterator_match_criteria_id (&cpe_match_ranges); + criteria = cpe_match_string_iterator_criteria (&cpe_match_ranges); + status = cpe_match_string_iterator_status (&cpe_match_ranges); + + xml_string_append (buffer, + "%s" + "%s" + "%s", + criteria?: "", + cpe_match_string_iterator_vulnerable (&cpe_match_ranges) != 0 + ? "1" + : "0", + status?: ""); + + vsi = cpe_match_string_iterator_version_start_incl (&cpe_match_ranges); + vse = cpe_match_string_iterator_version_start_excl (&cpe_match_ranges); + vei = cpe_match_string_iterator_version_end_incl (&cpe_match_ranges); + vee = cpe_match_string_iterator_version_end_excl (&cpe_match_ranges); + + xml_string_append (buffer, + "%s", + vsi ?: ""); + xml_string_append (buffer, + "%s", + vse ?: ""); + xml_string_append (buffer, + "%s", + vei ?: ""); + xml_string_append (buffer, + "%s", + vee ?: ""); + + iterator_t cpe_matches; + init_cpe_match_string_matches_iterator ( + &cpe_matches, match_criteria_id, NULL + ); + xml_string_append (buffer, ""); + + while (next (&cpe_matches)) + { + iterator_t cpes; + + init_iterator (&cpes, + "SELECT deprecated FROM scap.cpes" + " WHERE cpe_name_id = '%s';", + cpe_matches_cpe_name_id(&cpe_matches)); + + const char* cpe = cpe_matches_cpe_name (&cpe_matches); + + int deprecated = 0; + while (next (&cpes)) + { + deprecated = iterator_int (&cpes, 0); + } + cleanup_iterator (&cpes); + + xml_string_append (buffer, "", cpe?: ""); + xml_string_append (buffer, + "%s", + deprecated ? "1" : "0"); + if (deprecated) + { + iterator_t deprecated_by; + init_cpe_deprecated_by_iterator (&deprecated_by, cpe); + while (next (&deprecated_by)) + { + xml_string_append (buffer, + "", + cpe_deprecated_by_iterator_deprecated_by + (&deprecated_by)); + } + cleanup_iterator (&deprecated_by); + } + xml_string_append (buffer, ""); + } + xml_string_append (buffer, ""); + xml_string_append (buffer, ""); + cleanup_iterator (&cpe_matches); + } + cleanup_iterator (&cpe_match_ranges); +} +/** + * @brief Print CVE affected software configurations + * + * @param[in] cve_uuid uuid of the CVE. + * @param[out] result Buffer into which to print. + * + */ +static void +print_cve_configurations_xml (const gchar *cve_uuid, GString *result) +{ + iterator_t cpe_match_root_nodes; + xml_string_append (result, ""); + init_cve_cpe_match_nodes_iterator (&cpe_match_root_nodes, cve_uuid); + while (next (&cpe_match_root_nodes)) + { + result_t root_node; + iterator_t cpe_match_node_childs; + root_node = cpe_match_nodes_iterator_root_id (&cpe_match_root_nodes); + xml_string_append (result, ""); + print_cpe_match_nodes_xml (root_node, result); + init_cpe_match_node_childs_iterator (&cpe_match_node_childs, root_node); + while (next (&cpe_match_node_childs)) + { + resource_t child_node; + child_node = + cpe_match_node_childs_iterator_id (&cpe_match_node_childs); + xml_string_append (result, ""); + print_cpe_match_nodes_xml (child_node, result); + xml_string_append (result, ""); + } + xml_string_append (result, ""); + cleanup_iterator (&cpe_match_node_childs); + } + xml_string_append (result, ""); + cleanup_iterator (&cpe_match_root_nodes); +} + +/** + * @brief Print CVE references + * + * @param[in] cve_uuid uuid of the CVE. + * @param[out] result Buffer into which to print. + * + */ +static void +print_cve_references_xml (const gchar *cve_uuid, GString *result) +{ + iterator_t references; + init_cve_reference_iterator (&references, cve_uuid); + xml_string_append (result, ""); + while (next (&references)) + { + xml_string_append (result, ""); + xml_string_append (result, + "%s", + cve_reference_iterator_url (&references)); + xml_string_append (result, ""); + const char * tags_array = cve_reference_iterator_tags (&references); + if(tags_array && strlen (tags_array) > 2) + { + char *trimmed_array + = g_strndup (tags_array + 1, strlen (tags_array) - 2); + gchar **tags, **current_tag; + tags = g_strsplit (trimmed_array, ",", -1); + current_tag = tags; + while (*current_tag) + { + if (strlen (*current_tag) > 2 + && (*current_tag)[0] == '"' + && (*current_tag)[strlen (*current_tag) - 1] == '"') + { + char *trimmed_tag = g_strndup (*current_tag + 1, + strlen (*current_tag) - 2); + xml_string_append (result, "%s", trimmed_tag); + g_free (trimmed_tag); + } + else + xml_string_append (result, "%s", *current_tag); + current_tag++; + } + g_strfreev (tags); + g_free (trimmed_array); + } + xml_string_append (result, ""); + xml_string_append (result, ""); + } + xml_string_append (result, ""); + cleanup_iterator (&references); +} /** * @brief Handle end of GET_INFO element. * @@ -13473,24 +13727,36 @@ handle_get_info (gmp_parser_t *gmp_parser, GError **error) "%s", cpe_info_iterator_title (&info)); xml_string_append (result, - "%s" + "%s" "%s" "%s" - "%s", - cpe_info_iterator_nvd_id (&info) - ? cpe_info_iterator_nvd_id (&info) + "%s", + cpe_info_iterator_cpe_name_id (&info) + ? cpe_info_iterator_cpe_name_id (&info) : "", cpe_info_iterator_severity (&info) ? cpe_info_iterator_severity (&info) : "", cpe_info_iterator_cve_refs (&info), - cpe_info_iterator_status (&info) - ? cpe_info_iterator_status (&info) - : ""); + cpe_info_iterator_deprecated (&info) + ? cpe_info_iterator_deprecated (&info) + : "0"); if (get_info_data->details == 1) { - iterator_t cves; + 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, + "", + cpe_deprecated_by_iterator_deprecated_by + (&deprecated_by)); + } + cleanup_iterator (&deprecated_by); + g_string_append (result, ""); init_cpe_cve_iterator (&cves, get_iterator_name (&info), 0, NULL); while (next (&cves)) @@ -13518,6 +13784,16 @@ handle_get_info (gmp_parser_t *gmp_parser, GError **error) : ""); cleanup_iterator (&cves); g_string_append (result, ""); + + g_string_append (result, ""); + init_cpe_reference_iterator (&refs, get_iterator_name (&info)); + while (next (&refs)) + xml_string_append (result, + "%s", + cpe_reference_iterator_href (&refs), + cpe_reference_iterator_type (&refs)); + cleanup_iterator (&refs); + g_string_append (result, ""); } } else if (g_strcmp0 ("cve", get_info_data->type) == 0) @@ -13605,6 +13881,10 @@ handle_get_info (gmp_parser_t *gmp_parser, GError **error) ""); } g_string_append (result, ""); + + const gchar *cve_uuid = get_iterator_uuid (&info); + print_cve_configurations_xml (cve_uuid, result); + print_cve_references_xml (cve_uuid, result); } } else if (g_strcmp0 ("cert_bund_adv", get_info_data->type) == 0) @@ -14903,31 +15183,27 @@ handle_get_reports (gmp_parser_t *gmp_parser, GError **error) overrides = filter_term_apply_overrides (filter ? filter : get->filter); min_qod = filter_term_min_qod (filter ? filter : get->filter); levels = filter_term_value (filter ? filter : get->filter, "levels"); - #if COMPLIANCE_REPORTS == 1 - gchar *compliance_levels; - compliance_levels = filter_term_value (filter - ? filter - : get->filter, - "compliance_levels"); - - /* Setup result filter from overrides. */ - get_reports_data->get.filter - = g_strdup_printf - ("apply_overrides=%i min_qod=%i levels=%s compliance_levels=%s", - overrides, - min_qod, - levels ? levels : "hmlgdf", - compliance_levels ? compliance_levels : "yniu"); - g_free (compliance_levels); - #else - /* Setup result filter from overrides. */ - get_reports_data->get.filter - = g_strdup_printf - ("apply_overrides=%i min_qod=%i levels=%s", - overrides, - min_qod, - levels ? levels : "hmlgdf"); - #endif + + gchar *compliance_levels; + compliance_levels = filter_term_value (filter + ? filter + : get->filter, + "compliance_levels"); + + /* Setup result filter from overrides. */ + get_reports_data->get.filter + = g_strdup_printf + ("apply_overrides=%i min_qod=%i levels=%s compliance_levels=%s", + overrides, + min_qod, +#if CVSS3_RATINGS == 1 + levels ? levels : "chmlgdf", +#else + levels ? levels : "hmlgdf", +#endif + compliance_levels ? compliance_levels : "yniu"); + g_free (compliance_levels); + g_free (filter); g_free (levels); } @@ -15318,7 +15594,7 @@ print_report_config_params (gmp_parser_t *gmp_parser, GError **error, SENDF_TO_CLIENT_OR_FAIL ("%s", - report_config_param_iterator_using_default (¶ms), + report_config_param_iterator_using_default (¶ms), value ? value : ""); if (value) { @@ -15493,27 +15769,27 @@ handle_get_report_configs (gmp_parser_t *gmp_parser, GError **error) { SEND_TO_CLIENT_OR_FAIL ("1"); } - - SENDF_TO_CLIENT_OR_FAIL + + SENDF_TO_CLIENT_OR_FAIL ("", report_config_iterator_report_format_id (&report_configs) ); - + if (!orphan) { - SENDF_TO_CLIENT_OR_FAIL + SENDF_TO_CLIENT_OR_FAIL ("%s", report_config_iterator_report_format_name (&report_configs) ); - + if (report_config_iterator_report_format_readable (&report_configs) == 0) { SENDF_TO_CLIENT_OR_FAIL (""); } } - + SENDF_TO_CLIENT_OR_FAIL (""); - + print_report_config_params (gmp_parser, error, report_config_param_iterator_rowid ( &report_configs @@ -15896,16 +16172,16 @@ handle_get_report_formats (gmp_parser_t *gmp_parser, GError **error) } /** - * @brief Assign resource iterator with an init iterator based on the type + * @brief Assign resource iterator with an init iterator based on the type * in the get command data. * * @param[in] resource_names_data data for get_resource_names command. * @param[out] iterator address of iterator function pointer. - * + * * @return 1 if type is invalid, else 0. */ int -select_resource_iterator (get_resource_names_data_t *resource_names_data, +select_resource_iterator (get_resource_names_data_t *resource_names_data, int (**iterator) (iterator_t*, get_data_t *)) { if (g_strcmp0 ("cpe", resource_names_data->type) == 0) @@ -15955,7 +16231,7 @@ select_resource_iterator (get_resource_names_data_t *resource_names_data, else if (g_strcmp0 ("group", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_group_iterator; - } + } else if (g_strcmp0 ("note", resource_names_data->type) == 0) { *iterator = init_note_iterator_all; @@ -15963,43 +16239,41 @@ select_resource_iterator (get_resource_names_data_t *resource_names_data, else if (g_strcmp0 ("override", resource_names_data->type) == 0) { *iterator = init_override_iterator_all; - } + } else if (g_strcmp0 ("permission", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_permission_iterator; - } + } else if (g_strcmp0 ("port_list", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_port_list_iterator; - } + } else if (g_strcmp0 ("report", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_report_iterator; -#if COMPLIANCE_REPORTS == 1 - get_data_set_extra (&resource_names_data->get, + get_data_set_extra (&resource_names_data->get, "usage_type", g_strdup ("scan")); - } + } else if (g_strcmp0 ("audit_report", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_report_iterator; - get_data_set_extra (&resource_names_data->get, + get_data_set_extra (&resource_names_data->get, "usage_type", g_strdup ("audit")); -#endif } else if (g_strcmp0 ("report_config", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_report_config_iterator; - } + } else if (g_strcmp0 ("report_format", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_report_format_iterator; - } + } else if (g_strcmp0 ("role", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_role_iterator; - } + } else if (g_strcmp0 ("config", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_config_iterator; @@ -16017,15 +16291,15 @@ select_resource_iterator (get_resource_names_data_t *resource_names_data, else if (g_strcmp0 ("scanner", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_scanner_iterator; - } + } else if (g_strcmp0 ("schedule", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_schedule_iterator; - } + } else if (g_strcmp0 ("target", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_target_iterator; - } + } else if (g_strcmp0 ("task", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_task_iterator; @@ -16043,11 +16317,11 @@ select_resource_iterator (get_resource_names_data_t *resource_names_data, else if (g_strcmp0 ("tls_certificate", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_tls_certificate_iterator; - } + } else if (g_strcmp0 ("user", resource_names_data->type) == 0) { *iterator = (int (*) (iterator_t*, get_data_t *))init_user_iterator; - } + } else { return 1; @@ -16078,10 +16352,10 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) return; } - if ((((g_strcmp0 ("host", get_resource_names_data->type) == 0) + if ((((g_strcmp0 ("host", get_resource_names_data->type) == 0) ||(g_strcmp0 ("os", get_resource_names_data->type) == 0)) && (acl_user_may ("get_assets") == 0)) - || ((g_strcmp0 ("result", get_resource_names_data->type) == 0) + || ((g_strcmp0 ("result", get_resource_names_data->type) == 0) && (acl_user_may ("get_results") == 0)) || (((g_strcmp0 ("report", get_resource_names_data->type) == 0) || (g_strcmp0 ("audit_report", get_resource_names_data->type) == 0)) @@ -16129,9 +16403,9 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) get_resource_names_data_reset (get_resource_names_data); set_client_state (CLIENT_AUTHENTIC); return; - } + } - if (select_resource_iterator(get_resource_names_data, &init_resource_iterator)) + if (select_resource_iterator(get_resource_names_data, &init_resource_iterator)) { if (send_find_error_to_client ("get_resource_names", "type", get_resource_names_data->type, gmp_parser)) @@ -16156,7 +16430,7 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) error_send_to_client (error); return; } - break; + break; case 2: if (send_find_error_to_client ("get_resource_names", "filter", get_resource_names_data->get.filt_id, @@ -16175,7 +16449,7 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) set_client_state (CLIENT_AUTHENTIC); return; } - + SEND_GET_START ("resource_name"); SENDF_TO_CLIENT_OR_FAIL ("%s", get_resource_names_data->type); @@ -16183,8 +16457,8 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) { GString *result; result = g_string_new (""); - - if(g_strcmp0 ("tls_certificate", get_resource_names_data->type) == 0) + + if(g_strcmp0 ("tls_certificate", get_resource_names_data->type) == 0) { buffer_xml_append_printf (result, "" @@ -16194,8 +16468,8 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) : "", tls_certificate_iterator_subject_dn (&resource) ? tls_certificate_iterator_subject_dn (&resource) - : ""); - } + : ""); + } else if (g_strcmp0 ("override", get_resource_names_data->type) == 0) { buffer_xml_append_printf (result, @@ -16206,9 +16480,9 @@ handle_get_resource_names (gmp_parser_t *gmp_parser, GError **error) : "", override_iterator_nvt_name (&resource) ? override_iterator_nvt_name (&resource) - : ""); + : ""); } - else + else { buffer_xml_append_printf (result, "" @@ -17609,18 +17883,20 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error) char *ssh_name, *ssh_uuid, *smb_name, *smb_uuid; char *esxi_name, *esxi_uuid, *snmp_name, *snmp_uuid; char *ssh_elevate_name, *ssh_elevate_uuid; + char *krb5_name, *krb5_uuid; const char *port_list_uuid, *port_list_name, *ssh_port; const char *hosts, *exclude_hosts, *reverse_lookup_only; const char *reverse_lookup_unify, *allow_simultaneous_ips; credential_t ssh_credential, smb_credential; credential_t esxi_credential, snmp_credential; - credential_t ssh_elevate_credential; + credential_t ssh_elevate_credential, krb5_credential; int port_list_trash, max_hosts, port_list_available; int ssh_credential_available; int smb_credential_available; int esxi_credential_available; int snmp_credential_available; int ssh_elevate_credential_available; + int krb5_credential_available; ret = get_next (&targets, &get_targets_data->get, &first, &count, init_target_iterator); @@ -17638,6 +17914,7 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error) snmp_credential = target_iterator_snmp_credential (&targets); ssh_elevate_credential = target_iterator_ssh_elevate_credential (&targets); + krb5_credential = target_iterator_krb5_credential (&targets); ssh_credential_available = 1; if (ssh_credential) @@ -17795,6 +18072,38 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error) ssh_elevate_uuid = NULL; } + krb5_credential_available = 1; + if (krb5_credential) + { + if (get_targets_data->get.trash + && target_iterator_krb5_trash (&targets)) + { + krb5_name + = trash_credential_name (krb5_credential); + krb5_uuid + = trash_credential_uuid (krb5_credential); + krb5_credential_available + = trash_credential_readable (krb5_credential); + } + else + { + credential_t found; + + krb5_name = credential_name (krb5_credential); + krb5_uuid = credential_uuid (krb5_credential); + if (find_credential_with_permission (krb5_uuid, + &found, + "get_credentials")) + abort (); + krb5_credential_available = (found > 0); + } + } + else + { + krb5_name = NULL; + krb5_uuid = NULL; + } + port_list_uuid = target_iterator_port_list_uuid (&targets); port_list_name = target_iterator_port_list_name (&targets); port_list_trash = target_iterator_port_list_trash (&targets); @@ -17905,6 +18214,18 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error) SEND_TO_CLIENT_OR_FAIL (""); SENDF_TO_CLIENT_OR_FAIL ("" + "" + "%s" + "%i", + krb5_uuid ? krb5_uuid : "", + krb5_name ? krb5_name : "", + (get_targets_data->get.trash + && target_iterator_krb5_trash (&targets))); + + if (krb5_credential_available == 0) + SEND_TO_CLIENT_OR_FAIL (""); + + SENDF_TO_CLIENT_OR_FAIL ("" "" "%s" "" @@ -17962,6 +18283,8 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error) free (esxi_uuid); free (ssh_elevate_name); free (ssh_elevate_uuid); + free (krb5_name); + free (krb5_uuid); } cleanup_iterator (&targets); filtered = get_targets_data->get.id @@ -18175,6 +18498,9 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) int target_in_trash, scanner_in_trash; int holes = 0, infos = 0, logs = 0, warnings = 0; int holes_2 = 0, infos_2 = 0, warnings_2 = 0; +#if CVSS3_RATINGS == 1 + int criticals = 0, criticals_2 = 0; +#endif int false_positives = 0, task_scanner_type; int target_available, config_available; int scanner_available; @@ -18280,13 +18606,20 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) if (first_report_id && (get_tasks_data->get.trash == 0)) { // TODO Could skip this count for tasks page. +#if CVSS3_RATINGS == 1 + if (report_counts (first_report_id, + &criticals_2, &holes_2, &infos_2, &logs, + &warnings_2, &false_positives, + &severity_2, apply_overrides, min_qod)) +#else if (report_counts (first_report_id, &holes_2, &infos_2, &logs, &warnings_2, &false_positives, &severity_2, apply_overrides, min_qod)) - g_error ("%s: GET_TASKS: error getting counts for" - " first report, aborting", - __func__); +#endif + g_error ("%s: GET_TASKS: error getting counts for" + " first report, aborting", + __func__); } second_last_report_id = task_second_last_report_id (index); @@ -18296,11 +18629,20 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) * doing the count again. */ if (((first_report_id == NULL) || (strcmp (second_last_report_id, first_report_id))) +#if CVSS3_RATINGS == 1 + && report_counts (second_last_report_id, + &criticals_2, &holes_2, &infos_2, + &logs, &warnings_2, + &false_positives, &severity_2, + apply_overrides, min_qod) +#else && report_counts (second_last_report_id, &holes_2, &infos_2, &logs, &warnings_2, &false_positives, &severity_2, - apply_overrides, min_qod)) + apply_overrides, min_qod) +#endif + ) g_error ("%s: GET_TASKS: error getting counts for" " second report, aborting", __func__); @@ -18349,6 +18691,16 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) && strcmp (last_report_id, second_last_report_id))) { +#if CVSS3_RATINGS == 1 + if (report_counts + (last_report_id, + &criticals, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + apply_overrides, min_qod)) + g_error ("%s: GET_TASKS: error getting counts for" + " last report, aborting", + __func__); +#else if (report_counts (last_report_id, &holes, &infos, &logs, @@ -18357,9 +18709,13 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) g_error ("%s: GET_TASKS: error getting counts for" " last report, aborting", __func__); +#endif } else { +#if CVSS3_RATINGS == 1 + criticals = criticals_2; +#endif holes = holes_2; infos = infos_2; warnings = warnings_2; @@ -18413,10 +18769,16 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) "%s" "%s" "" - "%i" - "%i" +#if CVSS3_RATINGS == 1 + "%i" +#endif + "%i" + "%i" + "%i" + "%i" "%i" - "%i" + "%i" + "%i" "" "%i" "" @@ -18430,10 +18792,16 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) timestamp, scan_start, scan_end, +#if CVSS3_RATINGS == 1 + criticals, +#endif + holes, holes, infos, + infos, logs, warnings, + warnings, false_positives, severity); free (scan_start); @@ -18585,11 +18953,19 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) progress_xml, task_iterator_total_reports (&tasks), task_iterator_finished_reports (&tasks), +#if CVSS3_RATINGS == 1 + get_tasks_data->get.trash + ? "" + : task_iterator_trend_counts + (&tasks, criticals, holes, warnings, infos, severity, + criticals_2, holes_2, warnings_2, infos_2, severity_2), +#else get_tasks_data->get.trash ? "" : task_iterator_trend_counts - (&tasks, holes, warnings, infos, severity, - holes_2, warnings_2, infos_2, severity_2), + (&tasks, 0, holes, warnings, infos, severity, + 0, holes_2, warnings_2, infos_2, severity_2), +#endif task_schedule_xml, current_report, last_report); @@ -19383,10 +19759,21 @@ gmp_xml_handle_result () { create_report_data->result_severity = strdup (""); } +#if CVSS3_RATINGS == 1 + else if (strcasecmp (create_report_data->result_threat, "Critical") == 0) + { + create_report_data->result_severity = strdup ("10.0"); + } + else if (strcasecmp (create_report_data->result_threat, "High") == 0) + { + create_report_data->result_severity = strdup ("8.9"); + } +#else else if (strcasecmp (create_report_data->result_threat, "High") == 0) { create_report_data->result_severity = strdup ("10.0"); } +#endif else if (strcasecmp (create_report_data->result_threat, "Medium") == 0) { create_report_data->result_severity = strdup ("5.0"); @@ -20227,7 +20614,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, case CLIENT_GET_RESOURCE_NAMES: handle_get_resource_names (gmp_parser, error); - break; + break; case CLIENT_GET_RESULTS: handle_get_results (gmp_parser, error); @@ -21117,6 +21504,8 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, create_credential_data->auth_algorithm, create_credential_data->privacy_password, create_credential_data->privacy_algorithm, + create_credential_data->kdc, + create_credential_data->realm, create_credential_data->type, create_credential_data->allow_insecure, &new_credential)) @@ -21224,6 +21613,16 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, (XML_ERROR_SYNTAX ("create_credential", "Cannot determine type for new credential")); break; + case 19: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_credential", + "Selected type requires a kdc")); + break; + case 20: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_credential", + "Selected type requires a realm")); + break; case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("create_credential", @@ -21246,6 +21645,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_CREATE_CREDENTIAL, COMMENT); CLOSE (CLIENT_CREATE_CREDENTIAL, COMMUNITY); CLOSE (CLIENT_CREATE_CREDENTIAL, COPY); + CLOSE (CLIENT_CREATE_CREDENTIAL, KDC); CLOSE (CLIENT_CREATE_CREDENTIAL, KEY); CLOSE (CLIENT_CREATE_CREDENTIAL_KEY, PHRASE); CLOSE (CLIENT_CREATE_CREDENTIAL_KEY, PRIVATE); @@ -21256,6 +21656,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_CREATE_CREDENTIAL, PRIVACY); CLOSE (CLIENT_CREATE_CREDENTIAL_PRIVACY, ALGORITHM); CLOSE (CLIENT_CREATE_CREDENTIAL_PRIVACY, PASSWORD); + CLOSE (CLIENT_CREATE_CREDENTIAL, REALM); CLOSE (CLIENT_CREATE_CREDENTIAL, TYPE); case CLIENT_CREATE_FILTER: @@ -22696,6 +23097,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, credential_t ssh_credential = 0, ssh_elevate_credential = 0; credential_t smb_credential = 0; credential_t esxi_credential = 0, snmp_credential = 0; + credential_t krb5_credential = 0; target_t new_target; if (create_target_data->copy) @@ -22764,6 +23166,12 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, (XML_ERROR_SYNTAX ("create_target", "Hosts must be at least one" " character long")); + else if (create_target_data->smb_credential_id + && create_target_data->krb5_credential_id) + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_target", + "Targets cannot have both an SMB and" + " Kerberos 5 credential")); else if (create_target_data->ssh_credential_id && find_credential_with_permission (create_target_data->ssh_credential_id, @@ -22872,6 +23280,25 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, return; } } + else if (create_target_data->krb5_credential_id + && find_credential_with_permission + (create_target_data->krb5_credential_id, + &krb5_credential, + "get_credentials")) + SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("create_target")); + else if (create_target_data->krb5_credential_id + && krb5_credential == 0) + { + if (send_find_error_to_client + ("create_target", "Credential", + create_target_data->krb5_credential_id, + gmp_parser)) + { + error_send_to_client (error); + return; + } + } + /* Create target from host string. */ else switch (create_target (create_target_data->name, @@ -22889,6 +23316,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, smb_credential, esxi_credential, snmp_credential, + krb5_credential, create_target_data->reverse_lookup_only, create_target_data->reverse_lookup_unify, create_target_data->alive_tests, @@ -22998,6 +23426,13 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, " different from the SSH credential")); log_event_fail ("target", "Target", NULL, "created"); break; + case 16: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("create_target", + "Kerberos 5 credential must be of type" + " 'krb5'")); + log_event_fail ("target", "Target", NULL, "created"); + break; case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("create_target", @@ -23037,6 +23472,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_CREATE_TARGET, NAME); CLOSE (CLIENT_CREATE_TARGET, PORT_LIST); CLOSE (CLIENT_CREATE_TARGET, PORT_RANGE); + CLOSE (CLIENT_CREATE_TARGET, KRB5_CREDENTIAL); CLOSE (CLIENT_CREATE_TARGET, SSH_CREDENTIAL); CLOSE (CLIENT_CREATE_TARGET, SSH_LSC_CREDENTIAL); CLOSE (CLIENT_CREATE_TARGET, SSH_ELEVATE_CREDENTIAL); @@ -24311,6 +24747,8 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, modify_credential_data->auth_algorithm, modify_credential_data->privacy_password, modify_credential_data->privacy_algorithm, + modify_credential_data->kdc, + modify_credential_data->realm, modify_credential_data->allow_insecure)) { case 0: @@ -24433,6 +24871,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_MODIFY_CREDENTIAL, CERTIFICATE); CLOSE (CLIENT_MODIFY_CREDENTIAL, COMMENT); CLOSE (CLIENT_MODIFY_CREDENTIAL, COMMUNITY); + CLOSE (CLIENT_MODIFY_CREDENTIAL, KDC); CLOSE (CLIENT_MODIFY_CREDENTIAL, KEY); CLOSE (CLIENT_MODIFY_CREDENTIAL_KEY, PHRASE); CLOSE (CLIENT_MODIFY_CREDENTIAL_KEY, PRIVATE); @@ -24443,6 +24882,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_MODIFY_CREDENTIAL, PRIVACY); CLOSE (CLIENT_MODIFY_CREDENTIAL_PRIVACY, ALGORITHM); CLOSE (CLIENT_MODIFY_CREDENTIAL_PRIVACY, PASSWORD); + CLOSE (CLIENT_MODIFY_CREDENTIAL, REALM); case CLIENT_MODIFY_FILTER: { @@ -25492,6 +25932,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, ? modify_target_data->esxi_credential_id : modify_target_data->esxi_lsc_credential_id, modify_target_data->snmp_credential_id, + modify_target_data->krb5_credential_id, modify_target_data->reverse_lookup_only, modify_target_data->reverse_lookup_unify, modify_target_data->alive_tests, @@ -25741,6 +26182,35 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, log_event_fail ("target", "Target", modify_target_data->target_id, "modified"); break; + case 26: + log_event_fail ("target", "Target", + modify_target_data->target_id, + "modified"); + if (send_find_error_to_client + ("modify_target", "Credential", + modify_target_data->krb5_credential_id, + gmp_parser)) + { + error_send_to_client (error); + return; + } + break; + case 27: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_target", + "Kerberos 5 credential must be of type" + " 'krb5'")); + log_event_fail ("target", "Target", + modify_target_data->target_id, "modified"); + break; + case 28: + SEND_TO_CLIENT_OR_FAIL + (XML_ERROR_SYNTAX ("modify_target", + "Targets cannot have both an SMB and" + " Kerberos 5 credential")); + log_event_fail ("target", "Target", + modify_target_data->target_id, "modified"); + break; case 99: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_target", @@ -25780,6 +26250,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, CLOSE (CLIENT_MODIFY_TARGET, HOSTS); CLOSE (CLIENT_MODIFY_TARGET, NAME); CLOSE (CLIENT_MODIFY_TARGET, PORT_LIST); + CLOSE (CLIENT_MODIFY_TARGET, KRB5_CREDENTIAL); CLOSE (CLIENT_MODIFY_TARGET, SSH_CREDENTIAL); CLOSE (CLIENT_MODIFY_TARGET, SSH_LSC_CREDENTIAL); CLOSE (CLIENT_MODIFY_TARGET, SSH_ELEVATE_CREDENTIAL); @@ -27093,6 +27564,9 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, APPEND (CLIENT_MODIFY_CREDENTIAL_COMMUNITY, &modify_credential_data->community); + APPEND (CLIENT_MODIFY_CREDENTIAL_KDC, + &modify_credential_data->kdc); + APPEND (CLIENT_MODIFY_CREDENTIAL_KEY_PHRASE, &modify_credential_data->key_phrase); @@ -27117,6 +27591,9 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, APPEND (CLIENT_MODIFY_CREDENTIAL_PRIVACY_PASSWORD, &modify_credential_data->privacy_password); + APPEND (CLIENT_MODIFY_CREDENTIAL_REALM, + &modify_credential_data->realm); + case CLIENT_MODIFY_REPORT_CONFIG: modify_report_config_element_text (text, text_len); @@ -27224,6 +27701,9 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, APPEND (CLIENT_CREATE_CREDENTIAL_COPY, &create_credential_data->copy); + APPEND (CLIENT_CREATE_CREDENTIAL_KDC, + &create_credential_data->kdc); + APPEND (CLIENT_CREATE_CREDENTIAL_KEY_PHRASE, &create_credential_data->key_phrase); @@ -27248,6 +27728,9 @@ gmp_xml_handle_text (/* unused */ GMarkupParseContext* context, APPEND (CLIENT_CREATE_CREDENTIAL_PRIVACY_PASSWORD, &create_credential_data->privacy_password); + APPEND (CLIENT_CREATE_CREDENTIAL_REALM, + &create_credential_data->realm); + APPEND (CLIENT_CREATE_CREDENTIAL_TYPE, &create_credential_data->type); diff --git a/src/gmp_report_configs.c b/src/gmp_report_configs.c index 5a471b05b..9fcb44c87 100644 --- a/src/gmp_report_configs.c +++ b/src/gmp_report_configs.c @@ -38,7 +38,7 @@ /** * @brief Collect params from entity. - * + * * @param[in] entity Entity to check for param elements. * * @return Array of params @@ -49,7 +49,7 @@ params_from_entity (entity_t entity) array_t *params; entities_t children; entity_t param_entity; - + params = make_array (); children = entity->entities; while ((param_entity = first_entity (children))) @@ -85,7 +85,7 @@ params_from_entity (entity_t entity) if (param_value) { const char *use_default_str; - + param->value = g_strdup (entity_text (param_value)); use_default_str = entity_attribute (param_value, "use_default"); if (use_default_str) @@ -100,7 +100,7 @@ params_from_entity (entity_t entity) report_config_param_data_free (param); continue; } - + array_add (params, param); } @@ -529,7 +529,7 @@ modify_report_config_run (gmp_parser_t *gmp_parser, GError **error) comment ? comment->text : NULL, params, &error_message); - + switch (ret) { case 0: diff --git a/src/gvmd.c b/src/gvmd.c index 0fbe8051b..f5c0100b0 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -2324,9 +2324,6 @@ gvmd (int argc, char** argv, char *env[]) #endif #if CVSS3_RATINGS == 1 printf ("CVSS3 severity ratings enabled\n"); -#endif -#if COMPLIANCE_REPORTS == 1 - printf ("Compliance reports enabled\n"); #endif printf ("Copyright (C) 2009-2021 Greenbone AG\n"); printf ("License: AGPL-3.0-or-later\n"); @@ -2477,7 +2474,7 @@ gvmd (int argc, char** argv, char *env[]) /* Set number of retries waiting for memory */ set_mem_wait_retries (mem_wait_retries); - + /* Set minimum memory for feed updates */ set_min_mem_feed_update (min_mem_feed_update); diff --git a/src/gvmd_log_conf.cmake_in b/src/gvmd_log_conf.cmake_in index fd0c375a0..e5dcc3d73 100644 --- a/src/gvmd_log_conf.cmake_in +++ b/src/gvmd_log_conf.cmake_in @@ -7,63 +7,63 @@ prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [md manage] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [md gmp] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [md crypt] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [md utils] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [libgvm base] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [libgvm gmp] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [libgvm osp] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [libgvm util] prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 [event syslog] @@ -86,5 +86,5 @@ level=128 prepend=%t %s %p separator=: prepend_time_format=%Y-%m-%d %Hh%M.%S %Z -file=${GVM_LOG_DIR}/gvmd.log +file=${GVMD_LOG_FILE} level=127 diff --git a/src/manage.c b/src/manage.c index c924ca36e..a9a402045 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 @@ -857,6 +860,10 @@ scanner_type_valid (scanner_type_t scanner_type) const char * threat_message_type (const char *threat) { +#if CVSS3_RATINGS == 1 + if (strcasecmp (threat, "Critical") == 0) + return "Alarm"; +#endif if (strcasecmp (threat, "High") == 0) return "Alarm"; if (strcasecmp (threat, "Medium") == 0) @@ -883,8 +890,15 @@ threat_message_type (const char *threat) int severity_in_level (double severity, const char *level) { +#if CVSS3_RATINGS == 1 + if (strcmp (level, "critical") == 0) + return severity >= 9 && severity <= 10; + else if (strcmp (level, "high") == 0) + return severity >= 7 && severity < 9; +#else if (strcmp (level, "high") == 0) return severity >= 7 && severity <= 10; +#endif else if (strcmp (level, "medium") == 0) return severity >= 4 && severity < 7; else if (strcmp (level, "low") == 0) @@ -916,6 +930,10 @@ severity_to_level (double severity, int mode) { if (mode == 1) return "Alarm"; +#if CVSS3_RATINGS == 1 + else if (severity_in_level (severity, "critical")) + return "Critical"; +#endif else if (severity_in_level (severity, "high")) return "High"; else if (severity_in_level (severity, "medium")) @@ -975,7 +993,8 @@ int manage_create_encryption_key (GSList *log_config, const db_conn_info_t *database) { - int ret = manage_option_setup (log_config, database); + int ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) { printf ("Error setting up log config or database connection."); @@ -1039,7 +1058,8 @@ manage_set_encryption_key (GSList *log_config, const db_conn_info_t *database, const char *uid) { - int ret = manage_option_setup (log_config, database); + int ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) { printf ("Error setting up log config or database connection.\n"); @@ -1295,11 +1315,21 @@ severity_data_range_count (const severity_data_t* severity_data, * @param[out] lows The number of Low severity results. * @param[out] mediums The number of Medium severity results. * @param[out] highs The number of High severity results. + * @param[out] criticals The number of Critical severity results. + * Only if CVSS3_RATINGS is enabled. */ void severity_data_level_counts (const severity_data_t *severity_data, - int *errors, int *false_positives, - int *logs, int *lows, int *mediums, int *highs) + int *errors, + int *false_positives, + int *logs, + int *lows, + int *mediums, + int *highs +#if CVSS3_RATINGS == 1 + ,int* criticals +#endif + ) { if (errors) *errors @@ -1336,6 +1366,14 @@ severity_data_level_counts (const severity_data_t *severity_data, = severity_data_range_count (severity_data, level_min_severity ("high"), level_max_severity ("high")); + +#if CVSS3_RATINGS == 1 + if (criticals) + *criticals + = severity_data_range_count (severity_data, + level_min_severity ("critical"), + level_max_severity ("critical")); +#endif } @@ -2391,6 +2429,61 @@ target_osp_snmp_credential (target_t target) return NULL; } +/** + * @brief Get the Kerberos 5 credential of a target as an osp_credential_t + * + * @param[in] target The target to get the credential from. + * + * @return Pointer to a newly allocated osp_credential_t + */ +static osp_credential_t * +target_osp_krb5_credential (target_t target) +{ + credential_t credential; + credential = target_credential (target, "krb5"); + if (credential) + { + iterator_t iter; + osp_credential_t *osp_credential; + + init_credential_iterator_one (&iter, credential); + if (!next (&iter)) + { + g_warning ("%s: Kerberos 5 Credential not found.", __func__); + cleanup_iterator (&iter); + return NULL; + } + if (strcmp (credential_iterator_type (&iter), "krb5")) + { + g_warning ("%s: Kerberos 5 Credential not of type 'krb5'.", + __func__); + cleanup_iterator (&iter); + return NULL; + } + + osp_credential = osp_credential_new ("up", "krb5", NULL); + osp_credential_set_auth_data (osp_credential, + "username", + credential_iterator_login (&iter) + ?: ""); + osp_credential_set_auth_data (osp_credential, + "password", + credential_iterator_password (&iter) + ?: ""); + osp_credential_set_auth_data (osp_credential, + "kdc", + credential_iterator_kdc (&iter) + ?: ""); + osp_credential_set_auth_data (osp_credential, + "realm", + credential_iterator_realm (&iter) + ?: ""); + cleanup_iterator (&iter); + return osp_credential; + } + return NULL; +} + /** * @brief Prepare a report for resuming an OSP scan * @@ -2566,7 +2659,7 @@ launch_osp_openvas_task (task_t task, target_t target, const char *scan_id, GSList *osp_targets, *vts; GHashTable *vts_hash_table; osp_credential_t *ssh_credential, *smb_credential, *esxi_credential; - osp_credential_t *snmp_credential; + osp_credential_t *snmp_credential, *krb5_credential; gchar *max_checks, *max_hosts, *hosts_ordering; GHashTable *scanner_options; int ret, empty; @@ -2658,6 +2751,10 @@ launch_osp_openvas_task (task_t task, target_t target, const char *scan_id, if (snmp_credential) osp_target_add_credential (osp_target, snmp_credential); + krb5_credential = target_osp_krb5_credential (target); + if (krb5_credential) + osp_target_add_credential (osp_target, krb5_credential); + /* Initialize vts table for vulnerability tests and their preferences */ vts = NULL; vts_hash_table @@ -3106,82 +3203,206 @@ set_scanner_connection_retry (int new_retry) /* CVE tasks. */ -/** - * @brief Perform a CVE "scan" on a host. - * - * @param[in] task Task. - * @param[in] report The report to add the host, results and details to. - * @param[in] gvm_host Host. - * - * @return 0 success, 1 failed to get nthlast report for a host. - */ static int -cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) +check_version (const gchar *target, const gchar *start_incl, const gchar *start_excl, const gchar *end_incl, const gchar *end_excl) { - report_host_t report_host; - gchar *ip, *host; - - assert (task); - assert (report); - - host = gvm_host_value_str (gvm_host); - - ip = report_host_ip (host); - if (ip == NULL) - ip = g_strdup (host); + int result; - g_debug ("%s: ip: %s", __func__, ip); + 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; + } + } - /* Get the last report host that applies to the host IP address. */ + if (end_incl != NULL) + { + result = cmp_versions (end_incl, target); + if (result == -5) + return -1; + if (result < 0) + { + return 0; + } + } - if (host_nthlast_report_host (ip, &report_host, 1)) + if (end_excl != NULL) { - g_warning ("%s: Failed to get nthlast report", __func__); - g_free (ip); - return 1; + result = cmp_versions (end_excl, target); + if (result == -5) + return -1; + if (result <= 0) + { + return 0; + } } - g_debug ("%s: report_host: %llu", __func__, report_host); + return (1); +} - if (report_host) - { - iterator_t report_hosts; +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; + iterator_t cpe_match_ranges; - /* Get the report_host for the host. */ + 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; + } - init_report_host_iterator (&report_hosts, 0, NULL, report_host); - if (next (&report_hosts)) + init_cpe_match_string_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_string_iterator_criteria (&cpe_match_ranges)); + vsi = g_strdup (cpe_match_string_iterator_version_start_incl (&cpe_match_ranges)); + vse = g_strdup (cpe_match_string_iterator_version_start_excl (&cpe_match_ranges)); + vei = g_strdup (cpe_match_string_iterator_version_end_incl (&cpe_match_ranges)); + vee = g_strdup (cpe_match_string_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)) { - iterator_t prognosis; - int prognosis_report_host, start_time; - GArray *results; - - /* Add report_host with prognosis results and host details. */ + 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_string_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; + } +} - 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)) +/** + * @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; + + 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) { - const char *app, *cve; - double severity; - gchar *desc; - iterator_t locations_iter; GString *locations; - result_t result; + gchar *desc; - if (prognosis_report_host == 0) - prognosis_report_host = manage_report_host_add (report, - ip, - start_time, - 0); + if (*prognosis_report_host == 0) + *prognosis_report_host = manage_report_host_add (report, + ip, + start_time, + 0); - severity = prognosis_iterator_cvss_double (&prognosis); + 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 = prognosis_iterator_cpe (&prognosis); - cve = prognosis_iterator_cve (&prognosis); - locations = g_string_new(""); + 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); @@ -3201,7 +3422,9 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) } if (locations->len) - g_string_append (locations, ", "); + { + g_string_append (locations, ", "); + } g_string_append (locations, location); insert_report_host_detail (report, ip, "cve", cve, @@ -3217,6 +3440,12 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) 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" @@ -3229,8 +3458,7 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) : "", locations->len ? locations->str : "", locations->len ? ".\n" : "", - prognosis_iterator_description - (&prognosis)); + description); g_debug ("%s: making result with severity %1.1f desc [%s]", __func__, severity, desc); @@ -3241,9 +3469,165 @@ cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) 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. + * + * @param[in] task Task. + * @param[in] report The report to add the host, results and details to. + * @param[in] gvm_host Host. + * + * @return 0 success, 1 failed to get nthlast report for a host. + */ +static int +cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host) +{ + report_host_t report_host; + gchar *ip, *host; + + assert (task); + assert (report); + + host = gvm_host_value_str (gvm_host); + + ip = report_host_ip (host); + if (ip == NULL) + ip = g_strdup (host); + + g_debug ("%s: ip: %s", __func__, ip); + + /* Get the last report host that applies to the host IP address. */ + + if (host_nthlast_report_host (ip, &report_host, 1)) + { + g_warning ("%s: Failed to get nthlast report", __func__); + g_free (ip); + return 1; + } + + g_debug ("%s: report_host: %llu", __func__, report_host); + + if (report_host) + { + iterator_t report_hosts; + + /* Get the report_host for the host. */ + + init_report_host_iterator (&report_hosts, 0, NULL, report_host); + if (next (&report_hosts)) + { + iterator_t prognosis; + int prognosis_report_host, start_time; + GArray *results; + + /* Add report_host with prognosis results and host details. */ + + results = g_array_new (TRUE, TRUE, sizeof (result_t)); + start_time = time (NULL); + prognosis_report_host = 0; + + if (sql_int64_0 ("SELECT count(1) FROM information_schema.tables" + " WHERE table_schema = 'scap'" + " AND table_name = 'cpe_match_nodes';") > 0) + { + // Use new JSON CVE scan + cve_scan_report_host_json (task, report, report_host, ip, + start_time, &prognosis_report_host, + results); } - cleanup_iterator (&prognosis); + else + { + // Use XML CVE scan + init_host_prognosis_iterator (&prognosis, report_host); + while (next (&prognosis)) + { + 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); + + 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); + } + + 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); + } report_add_results_array (report, results); g_array_free (results, TRUE); @@ -3382,12 +3766,12 @@ fork_cve_scan_handler (task_t task, target_t target) gvm_hosts = gvm_hosts_new (hosts); free (hosts); - + if (gvm_hosts_exclude (gvm_hosts, exclude_hosts ?: "") < 0) { set_task_interrupted (task, "Failed to exclude hosts." - " Interrupting scan."); + " Interrupting scan."); set_report_scan_run_status (global_current_report, TASK_STATUS_INTERRUPTED); gvm_hosts_free (gvm_hosts); free (exclude_hosts); @@ -4126,6 +4510,8 @@ credential_full_type (const char* abbreviation) return NULL; else if (strcasecmp (abbreviation, "cc") == 0) return "client certificate"; + else if (strcasecmp (abbreviation, "krb5") == 0) + return "Kerberos 5"; else if (strcasecmp (abbreviation, "pw") == 0) return "password only"; else if (strcasecmp (abbreviation, "snmp") == 0) @@ -5190,12 +5576,12 @@ feed_sync_required () /** * @brief Wait for memory - * + * * @param[in] check_func Function to check memory, should return 1 if enough. * @param[in] retries Number of retries. * @param[in] min_mem Minimum memory in MiB, for logging only * @param[in] action Short descriptor of action waiting for memory. - * + * * @return 0 if enough memory is available, 1 gave up */ static int @@ -5417,7 +5803,8 @@ manage_rebuild_gvmd_data_from_feed (const char *types, return -1; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) { if (error_msg) @@ -6172,7 +6559,7 @@ get_nvt_xml (iterator_t *nvts, int details, int pref_count, if (nvt_iterator_epss_cve (nvts)) { - buffer_xml_append_printf + buffer_xml_append_printf (buffer, "" "" @@ -6185,7 +6572,7 @@ get_nvt_xml (iterator_t *nvts, int details, int pref_count, if (nvt_iterator_has_epss_severity (nvts)) { - buffer_xml_append_printf + buffer_xml_append_printf (buffer, "%0.1f", nvt_iterator_epss_severity (nvts)); @@ -6205,7 +6592,7 @@ get_nvt_xml (iterator_t *nvts, int details, int pref_count, if (nvt_iterator_has_max_epss_severity (nvts)) { - buffer_xml_append_printf + buffer_xml_append_printf (buffer, "%0.1f", nvt_iterator_max_epss_severity (nvts)); @@ -6570,7 +6957,7 @@ set_mem_wait_retries (int new_retries) /** * @brief Check if the minimum memory for feed updates is available - * + * * @return 1 if minimum memory amount is available, 0 if not */ int diff --git a/src/manage.h b/src/manage.h index 0ee2e9c23..ce073b277 100644 --- a/src/manage.h +++ b/src/manage.h @@ -127,7 +127,7 @@ init_manage (GSList*, const db_conn_info_t *, int, int, int, int, manage_connection_forker_t, int); int -init_manage_helper (GSList *, const db_conn_info_t *, int); +init_manage_helper (GSList *, const db_conn_info_t *, int, int); void init_manage_process (const db_conn_info_t*); @@ -902,9 +902,8 @@ int task_last_report (task_t, report_t*); const char * -task_iterator_trend_counts (iterator_t *, int, int, int, double, int, int, int, - double); - +task_iterator_trend_counts (iterator_t *, int, int, int, int, double, int, int, + int, int, double); int task_schedule_periods (task_t); @@ -1065,9 +1064,15 @@ severity_data_add (severity_data_t*, double); void severity_data_add_count (severity_data_t*, double, int); +#if CVSS3_RATINGS == 1 +void +severity_data_level_counts (const severity_data_t*, + int*, int*, int*, int*, int*, int*, int*); +#else void severity_data_level_counts (const severity_data_t*, int*, int*, int*, int*, int*, int*); +#endif /* General task facilities. */ @@ -1337,6 +1342,15 @@ int report_scan_result_count (report_t, const char*, const char*, int, const char*, const char*, int, int, int*); +#if CVSS3_RATINGS == 1 +int +report_counts (const char*, int*, int*, int*, int*, int*, int*, double*, + int, int); + +int +report_counts_id (report_t, int*, int*, int*, int*, int*, int*, double*, + const get_data_t*, const char*); +#else int report_counts (const char*, int*, int*, int*, int*, int*, double*, int, int); @@ -1344,6 +1358,7 @@ report_counts (const char*, int*, int*, int*, int*, int*, double*, int report_counts_id (report_t, int*, int*, int*, int*, int*, double*, const get_data_t*, const char*); +#endif int report_counts_id_no_filt (report_t, int*, int*, int*, int*, int*, int*, @@ -1416,7 +1431,7 @@ int init_result_get_iterator (iterator_t*, const get_data_t *, report_t, const char*, const gchar *); int -init_result_get_iterator_all (iterator_t* iterator, get_data_t *get); +init_result_get_iterator_all (iterator_t* iterator, get_data_t *get); gboolean next_report (iterator_t*, report_t*); @@ -1688,7 +1703,82 @@ 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 *); + +void +init_cve_cpe_match_nodes_iterator (iterator_t*, const char *); + +void +init_cve_reference_iterator (iterator_t*, const char *); + +const char* +cve_reference_iterator_url (iterator_t*); + +const char* +cve_reference_iterator_tags (iterator_t*); + +const char* +cve_reference_iterator_tags_count (iterator_t*); + +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_string_iterator (iterator_t*, long long int); + +const char* +cpe_match_string_iterator_criteria (iterator_t*); + +const char* +cpe_match_string_iterator_match_criteria_id (iterator_t*); + +const char* +cpe_match_string_iterator_status (iterator_t*); + +const char* +cpe_match_string_iterator_version_start_incl (iterator_t*); + +const char* +cpe_match_string_iterator_version_start_excl (iterator_t*); + +const char* +cpe_match_string_iterator_version_end_incl (iterator_t*); + +const char* +cpe_match_string_iterator_version_end_excl (iterator_t*); + +int +cpe_match_string_iterator_vulnerable (iterator_t*); + +void +init_cpe_match_string_matches_iterator (iterator_t*, const char *, const char*); + +const char* +cpe_matches_cpe_name_id (iterator_t*); + +const char* +cpe_matches_cpe_name (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); @@ -1733,7 +1823,7 @@ manage_filter_controls (const gchar *, int *, int *, gchar **, int *); void manage_report_filter_controls (const gchar *, int *, int *, gchar **, int *, - int *, gchar **, gchar **, gchar **, gchar **, + int *, gchar **, gchar **, gchar **, gchar **, gchar **, int *, int *, int *, int *, gchar **); gchar * @@ -1751,7 +1841,8 @@ find_target_with_permission (const char *, target_t *, const char *); int create_target (const char*, const char*, const char*, const char*, const char*, const char *, const char*, credential_t, credential_t, - const char *, credential_t, credential_t, credential_t, + const char *, + credential_t, credential_t, credential_t, credential_t, const char *, const char *, const char *, const char *, target_t*); @@ -1762,7 +1853,7 @@ int modify_target (const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, - const char*); + const char*, const char*); int delete_target (const char*, int); @@ -1812,6 +1903,9 @@ target_iterator_snmp_credential (iterator_t*); int target_iterator_ssh_elevate_credential (iterator_t*); +int +target_iterator_krb5_credential (iterator_t*); + int target_iterator_ssh_trash (iterator_t*); @@ -1827,6 +1921,9 @@ target_iterator_snmp_trash (iterator_t*); int target_iterator_ssh_elevate_trash (iterator_t*); +int +target_iterator_krb5_trash (iterator_t*); + const char* target_iterator_allow_simultaneous_ips (iterator_t*); @@ -2218,7 +2315,7 @@ int create_credential (const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, - const char*, credential_t*); + const char*, const char*, const char*, credential_t*); int copy_credential (const char*, const char*, const char*, @@ -2228,7 +2325,7 @@ int modify_credential (const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, - const char*); + const char*, const char*, const char*); int delete_credential (const char *, int); @@ -2269,6 +2366,12 @@ credential_iterator_privacy_password (iterator_t*); const char* credential_iterator_public_key (iterator_t*); +const char* +credential_iterator_kdc (iterator_t*); + +const char* +credential_iterator_realm (iterator_t*); + const char* credential_iterator_private_key (iterator_t*); @@ -2589,7 +2692,7 @@ init_override_iterator (iterator_t*, const get_data_t*, nvt_t, result_t, task_t); int -init_override_iterator_all (iterator_t* iterator, get_data_t *get); +init_override_iterator_all (iterator_t* iterator, get_data_t *get); const char* override_iterator_nvt_oid (iterator_t*); @@ -3339,6 +3442,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 *); @@ -3355,23 +3464,30 @@ const char* cpe_info_iterator_title (iterator_t*); const char* -cpe_info_iterator_status (iterator_t*); +cpe_info_iterator_deprecated (iterator_t*); const char * cpe_info_iterator_severity (iterator_t*); -const char* -cpe_info_iterator_deprecated_by_id (iterator_t*); - const char* cpe_info_iterator_cve_refs (iterator_t*); const char* -cpe_info_iterator_nvd_id (iterator_t*); +cpe_info_iterator_cpe_name_id (iterator_t*); gchar * cpe_details_xml (const char*); +void +init_cpe_reference_iterator (iterator_t *, const char *); + +const char* +cpe_reference_iterator_href (iterator_t *); + +const char* +cpe_reference_iterator_type (iterator_t *); + + /* CVE. */ const char* diff --git a/src/manage_configs.c b/src/manage_configs.c index d7de250af..1eeba26f7 100644 --- a/src/manage_configs.c +++ b/src/manage_configs.c @@ -343,7 +343,7 @@ should_sync_config_from_path (const char *path, gboolean rebuild, if (resource_id_deprecated ("config", uuid)) { find_config_no_acl (uuid, config); - + if (rebuild) { g_free (uuid); diff --git a/src/manage_license.c b/src/manage_license.c index 89c6038e8..d11d0b4a9 100644 --- a/src/manage_license.c +++ b/src/manage_license.c @@ -82,8 +82,7 @@ manage_update_license_file (const char *new_license, char **error_msg) __func__, broker_address); return 1; } - else - g_debug ("%s: Connected to %s\n", __func__, broker_address); + g_debug ("%s: Connected to %s\n", __func__, broker_address); ret = theia_new_modify_license_cmd ((char *) new_license, &modify_license_cmd); @@ -105,13 +104,11 @@ manage_update_license_file (const char *new_license, char **error_msg) free (client); return 2; } - else - g_debug ("%s: Sent modify.license command" - " (message_id: %s, group_id: %s)\n", - __func__, - modify_license_cmd->message->id, - modify_license_cmd->message->group_id); - + g_debug ("%s: Sent modify.license command" + " (message_id: %s, group_id: %s)\n", + __func__, + modify_license_cmd->message->id, + modify_license_cmd->message->group_id); ret = theia_client_get_info_response (client, THEIA_LICENSE_INFO_TOPIC, "modified.license", @@ -127,8 +124,7 @@ manage_update_license_file (const char *new_license, char **error_msg) free (client); return 3; } - else - g_debug ("%s: Received modified.license response", __func__); + g_debug ("%s: Received modified.license response", __func__); if (failure_modify_license_info) { @@ -142,11 +138,8 @@ manage_update_license_file (const char *new_license, char **error_msg) free (client); return 5; } - else - { - g_message ("%s: Uploaded new license file (%lu bytes)", - __func__, strlen (new_license)); - } + g_message ("%s: Uploaded new license file (%lu bytes)", + __func__, strlen (new_license)); theia_client_disconnect (client); theia_modified_license_info_free (modified_license_info); @@ -207,8 +200,7 @@ manage_get_license (gchar **status, __func__, broker_address); return 1; } - else - g_debug ("%s: Connected to %s\n", __func__, broker_address); + g_debug ("%s: Connected to %s\n", __func__, broker_address); ret = theia_new_get_license_cmd (&get_license_cmd); if (ret) @@ -229,13 +221,11 @@ manage_get_license (gchar **status, free (client); return 2; } - else - g_debug ("%s: Sent get.license command" - " (message_id: %s, group_id: %s)\n", - __func__, - get_license_cmd->message->id, - get_license_cmd->message->group_id); - + g_debug ("%s: Sent get.license command" + " (message_id: %s, group_id: %s)\n", + __func__, + get_license_cmd->message->id, + get_license_cmd->message->group_id); ret = theia_client_get_info_response (client, THEIA_LICENSE_INFO_TOPIC, "got.license", NULL, @@ -250,8 +240,7 @@ manage_get_license (gchar **status, free (client); return 3; } - else - g_debug ("%s: Received got.license response", __func__); + g_debug ("%s: Received got.license response", __func__); theia_client_disconnect (client); diff --git a/src/manage_pg.c b/src/manage_pg.c index dba91d68f..ada46ee6c 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -230,8 +230,15 @@ manage_create_sql_functions () " v := " G_STRINGIFY (SEVERITY_ERROR) ";" " ELSE" " CASE" +#if CVSS3_RATINGS == 1 + " WHEN lower (lvl) = 'critical' THEN" + " v := 10.0;" + " WHEN lower (lvl) = 'high' THEN" + " v := 8.9;" +#else " WHEN lower (lvl) = 'high' THEN" " v := 10.0;" +#endif " WHEN lower (lvl) = 'medium' THEN" " v := 6.9;" " WHEN lower (lvl) = 'low' THEN" @@ -262,6 +269,10 @@ manage_create_sql_functions () " v := " G_STRINGIFY (SEVERITY_ERROR) ";" " ELSE" " CASE" +#if CVSS3_RATINGS == 1 + " WHEN lower (lvl) = 'critical' THEN" + " v := 9.0;" +#endif " WHEN lower (lvl) = 'high' THEN" " v := 7.0;" " WHEN lower (lvl) = 'medium' THEN" @@ -494,6 +505,31 @@ manage_create_sql_functions () "$$ LANGUAGE plpgsql" " IMMUTABLE;"); +#if CVSS3_RATINGS == 1 + sql ("CREATE OR REPLACE FUNCTION order_threat (text)" + " RETURNS integer AS $$" + " BEGIN" + " IF $1 = 'Critical' THEN" + " RETURN 1;" + " ELSIF $1 = 'High' THEN" + " RETURN 2;" + " ELSIF $1 = 'Medium' THEN" + " RETURN 3;" + " ELSIF $1 = 'Low' THEN" + " RETURN 4;" + " ELSIF $1 = 'Log' THEN" + " RETURN 5;" + " ELSIF $1 = 'False Positive' THEN" + " RETURN 6;" + " ELSIF $1 = 'None' THEN" + " RETURN 7;" + " ELSE" + " RETURN 8;" + " END IF;" + " END;" + "$$ LANGUAGE plpgsql" + " IMMUTABLE;"); +#else sql ("CREATE OR REPLACE FUNCTION order_threat (text)" " RETURNS integer AS $$" " BEGIN" @@ -515,7 +551,7 @@ manage_create_sql_functions () " END;" "$$ LANGUAGE plpgsql" " IMMUTABLE;"); - +#endif sql ("CREATE OR REPLACE FUNCTION severity_to_type (double precision)" " RETURNS text AS $$" " BEGIN" @@ -871,13 +907,13 @@ manage_create_sql_functions () " OR qod2 is null" " THEN RETURN 'new';" " WHEN description1 != description2" - " OR severity1 != severity2" + " OR severity1 != severity2" " OR qod1 != qod2" " OR hostname1 != hostname2" " OR path1 != path2" " THEN RETURN 'changed';" " ELSE RETURN 'same';" - " END CASE;" + " END CASE;" "END;" "$$ LANGUAGE plpgsql" " IMMUTABLE;"); @@ -890,7 +926,7 @@ manage_create_sql_functions () " WHEN port = 'package'" " THEN RETURN 'general/tcp';" " ELSE RETURN port;" - " END CASE;" + " END CASE;" "END;" "$$ LANGUAGE plpgsql" " IMMUTABLE;"); @@ -913,7 +949,7 @@ manage_create_sql_functions () " AND description LIKE 'Compliant:%%YES%%') > 0" " THEN RETURN 'yes';" " ELSE RETURN 'undefined';" - " END CASE;" + " END CASE;" "END;" "$$ LANGUAGE plpgsql" " IMMUTABLE;"); @@ -925,7 +961,7 @@ manage_create_sql_functions () " DECLARE count integer := 0;" " BEGIN" " WITH compliance_count AS" - " (SELECT count(*) AS total FROM results WHERE report = report_id" + " (SELECT count(*) AS total FROM results WHERE report = report_id" " AND description LIKE 'Compliant:%%' || compliance || '%%')" " SELECT total FROM compliance_count" " INTO count;" @@ -934,7 +970,7 @@ manage_create_sql_functions () " $$ LANGUAGE plpgsql" " IMMUTABLE;"); - /* Functions in SQL. */ + /* Functions in SQL. */ if (sql_int ("SELECT (EXISTS (SELECT * FROM information_schema.tables" " WHERE table_catalog = '%s'" @@ -1364,6 +1400,10 @@ manage_create_sql_functions () " second_last_report integer;" " severity_a double precision;" " severity_b double precision;" +#if CVSS3_RATINGS == 1 + " critical_a bigint;" + " critical_b bigint;" +#endif " high_a bigint;" " high_b bigint;" " medium_a bigint;" @@ -1399,6 +1439,12 @@ manage_create_sql_functions () " RETURN 'down'::text;" " END IF;" /* Calculate trend. */ +#if CVSS3_RATINGS == 1 + " critical_a := report_severity_count (last_report, $2, $3," + " 'critical');" + " critical_b := report_severity_count (second_last_report, $2, $3," + " 'critical');" +#endif " high_a := report_severity_count (last_report, $2, $3," " 'high');" " high_b := report_severity_count (second_last_report, $2, $3," @@ -1411,7 +1457,13 @@ manage_create_sql_functions () " 'low');" " low_b := report_severity_count (second_last_report, $2, $3," " 'low');" +#if CVSS3_RATINGS == 1 + " IF critical_a > 0 THEN" + " threat_a := 5;" + " ELSEIF high_a > 0 THEN" +#else " IF high_a > 0 THEN" +#endif " threat_a := 4;" " ELSIF medium_a > 0 THEN" " threat_a := 3;" @@ -1420,7 +1472,13 @@ manage_create_sql_functions () " ELSE" " threat_a := 1;" " END IF;" +#if CVSS3_RATINGS == 1 + " IF critical_b > 0 THEN" + " threat_b := 5;" + " ELSEIF high_b > 0 THEN" +#else " IF high_b > 0 THEN" +#endif " threat_b := 4;" " ELSIF medium_b > 0 THEN" " threat_b := 3;" @@ -1436,6 +1494,16 @@ manage_create_sql_functions () " RETURN 'down'::text;" " END IF;" /* Check if the threat count changed. */ +#if CVSS3_RATINGS == 1 + " IF critical_a > 0 THEN" + " IF critical_a > critical_b THEN" + " RETURN 'more'::text;" + " ELSIF critical_a < critical_b THEN" + " RETURN 'less'::text;" + " END IF;" + " RETURN 'same'::text;" + " END IF;" +#endif " IF high_a > 0 THEN" " IF high_a > high_b THEN" " RETURN 'more'::text;" @@ -1574,9 +1642,18 @@ manage_create_sql_functions () " text)" " RETURNS boolean AS $$" " (SELECT CASE lower ($2)" +#if CVSS3_RATINGS == 1 + " WHEN 'critical'" + " THEN $1 >= 9" + " AND $1 <= 10" + " WHEN 'high'" + " THEN $1 >= 7" + " AND $1 < 9" +#else " WHEN 'high'" " THEN $1 >= 7" " AND $1 <= 10" +#endif " WHEN 'medium'" " THEN $1 >= 4" " AND $1 < 7" @@ -1589,6 +1666,8 @@ manage_create_sql_functions () " THEN $1 = 0" " WHEN 'false'" " THEN $1 = -1" + " WHEN 'error'" + " THEN $1 = -3" " ELSE 0::boolean" " END);" "$$ LANGUAGE SQL" @@ -1616,6 +1695,11 @@ manage_create_sql_functions () " THEN (SELECT CASE" " WHEN $2 = 1" " THEN 'Alarm'" +#if CVSS3_RATINGS == 1 + " WHEN severity_in_level ($1::double precision," + " 'critical')" + " THEN 'Critical'" +#endif " WHEN severity_in_level ($1::double precision," " 'high')" " THEN 'High'" @@ -1646,6 +1730,10 @@ manage_create_sql_functions () " THEN (SELECT CASE" " WHEN $2 = 1" " THEN 'Alarm'" +#if CVSS3_RATINGS == 1 + " WHEN severity_in_level ($1, 'critical')" + " THEN 'Critical'" +#endif " WHEN severity_in_level ($1, 'high')" " THEN 'High'" " WHEN severity_in_level ($1, 'medium')" @@ -1832,7 +1920,7 @@ create_view_vulns () " severity, " G_STRINGIFY (QOD_DEFAULT) " AS qod," " 'cve' AS type" - " FROM cves" + " FROM scap.cves" " WHERE uuid in (SELECT * FROM used_nvts)"); else sql ("CREATE OR REPLACE VIEW vulns AS" @@ -1994,7 +2082,7 @@ create_indexes_nvt () " 'nvts', 'cvss_base');"); sql ("SELECT create_index ('nvts_by_solution_type'," " 'nvts', 'solution_type');"); - + sql ("SELECT create_index ('vt_refs_by_vt_oid'," " 'vt_refs', 'vt_oid');"); @@ -3525,26 +3613,51 @@ manage_db_init (const gchar *name) " modification_time integer," " title text," " status text," - " deprecated_by_id INTEGER," " severity DOUBLE PRECISION DEFAULT 0," " cve_refs INTEGER DEFAULT 0," - " nvd_id text);"); + " nvd_id text," + " deprecated integer," + " cpe_name_id text);"); + + sql ("CREATE TABLE scap2.cpe_refs" + " (id SERIAL PRIMARY KEY," + " cpe INTEGER," + " 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," - " cve_id INTEGER DEFAULT 0," - " operator text);"); + " root_id integer DEFAULT 0," + " cve_id integer DEFAULT 0," + " operator text," + " negate integer DEFAULT 0);"); - sql ("CREATE TABLE scap2.cpe_match_range" + sql ("CREATE TABLE scap2.cpe_nodes_match_criteria" " (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);"); + " node_id integer DEFAULT 0," + " vulnerable integer DEFAULT 0," + " match_criteria_id text);"); + + sql ("CREATE TABLE scap2.cpe_match_strings" + " (id SERIAL PRIMARY KEY," + " match_criteria_id text," + " criteria 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," + " status text);"); + + sql ("CREATE TABLE scap2.cpe_matches" + " (id SERIAL PRIMARY KEY," + " match_criteria_id text," + " cpe_name_id text," + " cpe_name text);"); sql ("CREATE TABLE scap2.cpe_details" " (id SERIAL PRIMARY KEY," @@ -3560,6 +3673,11 @@ manage_db_init (const gchar *name) " epss DOUBLE PRECISION," " percentile DOUBLE PRECISION);"); + sql ("CREATE TABLE scap2.cve_references" + " (id SERIAL PRIMARY KEY," + " cve_id INTEGER," + " url text," + " tags text[]);"); /* Init tables. */ @@ -3609,6 +3727,19 @@ manage_db_add_constraints (const gchar *name) sql ("ALTER TABLE scap2.epss_scores" " ALTER cve SET NOT NULL," " ADD UNIQUE (cve);"); + + sql ("ALTER TABLE scap2.cve_references" + " ALTER cve_id SET NOT NULL," + " ALTER url SET NOT NULL," + " ADD UNIQUE (cve_id, url);"); + + sql ("ALTER TABLE scap2.cpe_match_strings" + " ADD UNIQUE (match_criteria_id);"); + + sql ("ALTER TABLE scap2.cpe_matches" + " ALTER match_criteria_id SET NOT NULL," + " ALTER cpe_name_id SET NOT NULL," + " ADD UNIQUE (match_criteria_id, cpe_name_id);"); } else { diff --git a/src/manage_port_lists.c b/src/manage_port_lists.c index 26f7c8cc5..2c66aadf5 100644 --- a/src/manage_port_lists.c +++ b/src/manage_port_lists.c @@ -280,7 +280,7 @@ should_sync_port_list_from_path (const char *path, gboolean rebuild, if (resource_id_deprecated ("port_list", uuid)) { find_port_list_no_acl (uuid, port_list); - + if (rebuild) { return 1; diff --git a/src/manage_report_configs.c b/src/manage_report_configs.c index 277f2592d..ff2c7add2 100644 --- a/src/manage_report_configs.c +++ b/src/manage_report_configs.c @@ -54,7 +54,7 @@ find_report_config_with_permission (const char *uuid, /** * @brief Free a report config parameter data struct. - * + * * @param[in] param The parameter to free. */ void diff --git a/src/manage_report_formats.c b/src/manage_report_formats.c index 8cc94feb0..8e66ad395 100644 --- a/src/manage_report_formats.c +++ b/src/manage_report_formats.c @@ -645,7 +645,7 @@ should_sync_report_format_from_path (const char *path, if (resource_id_deprecated ("report_format", uuid)) { find_report_format_no_acl (uuid, report_format); - + if (rebuild) { g_free (uuid); diff --git a/src/manage_sql.c b/src/manage_sql.c index 2b87ba8ac..4578ce058 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -250,10 +250,17 @@ check_for_updated_scap (); static void check_for_updated_cert (); +#if CVSS3_RATINGS == 1 +static int +report_counts_id_full (report_t, int *, int *, int *, int *, int *, int *, + double *, const get_data_t*, const char* , + int *, int *, int *, int *, int *, int *, double *); +#else static int report_counts_id_full (report_t, int *, int *, int *, int *, int *, double *, const get_data_t*, const char* , int *, int *, int *, int *, int *, double *); +#endif static gboolean find_group_with_permission (const char *, group_t *, const char *); @@ -294,7 +301,7 @@ cache_all_permissions_for_users (GArray*); static void report_cache_counts (report_t, int, int, const char*); -static gchar * +static gchar * reports_extra_where (int, const char *, const char *); static int @@ -340,9 +347,6 @@ setting_dynamic_severity_int (); static char * setting_timezone (); -static int -setting_delta_reports_version_int (); - static double task_severity_double (task_t, int, int, int); @@ -933,13 +937,15 @@ cert_check_time () * * @param[in] log_config Log configuration. * @param[in] database Database. + * @param[in] avoid_db_check_inserts Whether to avoid inserts in DB check. * * @return 0 success, -1 error, -2 database is too old, * -3 database needs to be initialised from server, * -5 database is too new. */ int -manage_option_setup (GSList *log_config, const db_conn_info_t *database) +manage_option_setup (GSList *log_config, const db_conn_info_t *database, + int avoid_db_check_inserts) { int ret; @@ -950,7 +956,8 @@ manage_option_setup (GSList *log_config, const db_conn_info_t *database) } ret = init_manage_helper (log_config, database, - MANAGE_ABSOLUTE_MAX_IPS_PER_TARGET); + MANAGE_ABSOLUTE_MAX_IPS_PER_TARGET, + avoid_db_check_inserts); assert (ret != -4); switch (ret) { @@ -2040,8 +2047,8 @@ filter_control_str (keyword_t **point, const char *column, gchar **string) * @param[out] compliance_levels String describing compliance levels * to include in count (for example, "yniu" for * "yes" (compliant), "n" for "no" (not compliant), - * "i" for "incomplete" and "u" for "undefined" - * (without compliance information). + * "i" for "incomplete" and "u" for "undefined" + * (without compliance information). * All levels if NULL. * @param[out] delta_states String describing delta states to include in count * (for example, "sngc" Same, New, Gone and Changed). @@ -2059,9 +2066,9 @@ manage_report_filter_controls (const gchar *filter, int *first, int *max, gchar **sort_field, int *sort_order, int *result_hosts_only, gchar **min_qod, gchar **levels, gchar **compliance_levels, - gchar **delta_states, gchar **search_phrase, - int *search_phrase_exact, int *notes, - int *overrides, int *apply_overrides, + gchar **delta_states, gchar **search_phrase, + int *search_phrase_exact, int *notes, + int *overrides, int *apply_overrides, gchar **zone) { keyword_t **point; @@ -2221,7 +2228,7 @@ manage_report_filter_controls (const gchar *filter, int *first, int *max, else *apply_overrides = val; } - + if (compliance_levels) { if (filter_control_str ((keyword_t **) split->pdata, @@ -2604,6 +2611,9 @@ keyword_applies_to_column (keyword_t *keyword, const char* column) && (strstr ("False Positive", keyword->string) == NULL) && (strstr ("Error", keyword->string) == NULL) && (strstr ("Alarm", keyword->string) == NULL) +#if CVSS3_RATINGS == 1 + && (strstr ("Critical", keyword->string) == NULL) +#endif && (strstr ("High", keyword->string) == NULL) && (strstr ("Medium", keyword->string) == NULL) && (strstr ("Low", keyword->string) == NULL) @@ -3045,7 +3055,11 @@ filter_clause (const char* type, const char* filter, || strcmp (keyword->string, "log_per_host") == 0 || strcmp (keyword->string, "low_per_host") == 0 || strcmp (keyword->string, "medium_per_host") == 0 - || strcmp (keyword->string, "high_per_host") == 0) + || strcmp (keyword->string, "high_per_host") == 0 +#if CVSS3_RATINGS == 1 + || strcmp (keyword->string, "critical_per_host") == 0 +#endif + ) { gchar *column; column = columns_select_column (select_columns, @@ -3082,6 +3096,9 @@ filter_clause (const char* type, const char* filter, || (strcmp (keyword->string, "published") == 0) || (strcmp (keyword->string, "qod") == 0) || (strcmp (keyword->string, "cves") == 0) +#if CVSS3_RATINGS == 1 + || (strcmp (keyword->string, "critical") == 0) +#endif || (strcmp (keyword->string, "high") == 0) || (strcmp (keyword->string, "medium") == 0) || (strcmp (keyword->string, "low") == 0) @@ -3238,7 +3255,11 @@ filter_clause (const char* type, const char* filter, || strcmp (keyword->string, "log_per_host") == 0 || strcmp (keyword->string, "low_per_host") == 0 || strcmp (keyword->string, "medium_per_host") == 0 - || strcmp (keyword->string, "high_per_host") == 0) + || strcmp (keyword->string, "high_per_host") == 0 +#if CVSS3_RATINGS == 1 + || strcmp (keyword->string, "critical_per_host") == 0 +#endif + ) { gchar *column; column = columns_select_column (select_columns, @@ -3275,6 +3296,9 @@ filter_clause (const char* type, const char* filter, || (strcmp (keyword->string, "published") == 0) || (strcmp (keyword->string, "qod") == 0) || (strcmp (keyword->string, "cves") == 0) +#if CVSS3_RATINGS == 1 + || (strcmp (keyword->string, "critical") == 0) +#endif || (strcmp (keyword->string, "high") == 0) || (strcmp (keyword->string, "medium") == 0) || (strcmp (keyword->string, "low") == 0) @@ -3980,14 +4004,9 @@ valid_type (const char* type) int valid_subtype (const char* type) { - #if COMPLIANCE_REPORTS == 1 return (strcasecmp (type, "audit_report") == 0) || (strcasecmp (type, "audit") == 0) || (strcasecmp (type, "policy") == 0); - #else - return (strcasecmp (type, "audit") == 0) - || (strcasecmp (type, "policy") == 0); - #endif } /** @@ -6167,10 +6186,9 @@ manage_cert_db_version () void set_db_version (int version) { - sql ("DELETE FROM %s.meta WHERE name = 'database_version';", - sql_schema ()); sql ("INSERT INTO %s.meta (name, value)" - " VALUES ('database_version', '%i');", + " VALUES ('database_version', '%i')" + " ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;", sql_schema (), version); } @@ -6416,7 +6434,8 @@ manage_encrypt_all_credentials (GSList *log_config, g_info (" (Re-)encrypting all credentials."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -6457,7 +6476,8 @@ manage_decrypt_all_credentials (GSList *log_config, g_info (" Decrypting all credentials."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -6542,82 +6562,6 @@ set_current_encryption_key_uid (const char *new_uid) g_free (quoted_new_uid); } - - -/* Collation. */ - -/** - * @brief Compare two number strings for collate_ip. - * - * @param[in] one_arg First string. - * @param[in] two_arg Second string. - * - * @return -1, 0 or 1 if first is less than, equal to or greater than second. - */ -static int -collate_ip_compare (const char *one_arg, const char *two_arg) -{ - int one = atoi (one_arg); - int two = atoi (two_arg); - return one == two ? 0 : (one < two ? -1 : 1); -} - -/** - * @brief Collate two IP addresses. - * - * For example, 127.0.0.2 is less than 127.0.0.3 and 127.0.0.10. - * - * Only works correctly for IPv4 addresses. - * - * @param[in] data Dummy for callback. - * @param[in] one_len Length of first IP (a string). - * @param[in] arg_one First string. - * @param[in] two_len Length of second IP (a string). - * @param[in] arg_two Second string. - * - * @return -1, 0 or 1 if first is less than, equal to or greater than second. - */ -static int -collate_ip (void* data, - int one_len, const void* arg_one, - int two_len, const void* arg_two) -{ - int ret, one_dot, two_dot; - char one_a[4], one_b[4], one_c[4], one_d[4]; - char two_a[4], two_b[4], two_c[4], two_d[4]; - const char* one = (const char*) arg_one; - const char* two = (const char*) arg_two; - - if ((sscanf (one, "%3[0-9].%3[0-9].%3[0-9].%n%3[0-9]", - one_a, one_b, one_c, &one_dot, one_d) - == 4) - && (sscanf (two, "%3[0-9].%3[0-9].%3[0-9].%n%3[0-9]", - two_a, two_b, two_c, &two_dot, two_d) - == 4)) - { - ret = collate_ip_compare (one_a, two_a); - if (ret) return ret < 0 ? -1 : 1; - - ret = collate_ip_compare (one_b, two_b); - if (ret) return ret < 0 ? -1 : 1; - - ret = collate_ip_compare (one_c, two_c); - if (ret) return ret < 0 ? -1 : 1; - - /* Ensure that the last number is limited to digits in the arg. */ - one_d[one_len - one_dot] = '\0'; - two_d[two_len - two_dot] = '\0'; - - ret = collate_ip_compare (one_d, two_d); - if (ret) return ret < 0 ? -1 : 1; - - return 0; - } - - ret = strncmp (one, two, MIN (one_len, two_len)); - return ret == 0 ? 0 : (ret < 0 ? -1 : 1); -} - /* Task subject iterators. */ @@ -6796,7 +6740,8 @@ manage_check_alerts (GSList *log_config, const db_conn_info_t *database) g_info (" Checking alerts."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -14406,7 +14351,7 @@ manage_test_alert (const char *alert_id, gchar **script_message) NULL); if (result) report_add_result (report, result); - + result = make_result ( task, "127.0.0.1", "localhost", "general/tcp", @@ -14614,7 +14559,7 @@ condition_met (task_t task, report_t report, alert_t alert, { char *filter_id, *count_string; report_t last_report; - int holes, infos, logs, warnings, false_positives; + int criticals = 0, holes, infos, logs, warnings, false_positives; int count; double severity; @@ -14661,11 +14606,16 @@ condition_met (task_t task, report_t report, alert_t alert, memset (&get, 0, sizeof (get_data_t)); get.type = "result"; get.filt_id = filter_id; +#if CVSS3_RATINGS == 1 + report_counts_id (last_report, &criticals, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + &get, NULL); +#else report_counts_id (last_report, &holes, &infos, &logs, &warnings, &false_positives, &severity, &get, NULL); - - db_count = holes + infos + logs + warnings +#endif + db_count = criticals + holes + infos + logs + warnings + false_positives; g_debug ("%s: count: %i vs %i", __func__, db_count, count); @@ -14682,7 +14632,7 @@ condition_met (task_t task, report_t report, alert_t alert, { char *direction, *filter_id, *count_string; report_t last_report; - int holes, infos, logs, warnings, false_positives; + int criticals = 0, holes, infos, logs, warnings, false_positives; int count; double severity; @@ -14717,11 +14667,16 @@ condition_met (task_t task, report_t report, alert_t alert, get_data_t get; get.type = "result"; get.filt_id = filter_id; - +#if CVSS3_RATINGS == 1 + report_counts_id (last_report, &criticals, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + &get, NULL); +#else report_counts_id (last_report, &holes, &infos, &logs, &warnings, &false_positives, &severity, &get, NULL); - last_count = holes + infos + logs + warnings +#endif + last_count = criticals + holes + infos + logs + warnings + false_positives; second_last_report = 0; @@ -14731,11 +14686,16 @@ condition_met (task_t task, report_t report, alert_t alert, if (second_last_report) { int cmp, second_last_count; - +#if CVSS3_RATINGS == 1 + report_counts_id (second_last_report, &criticals, &holes, &infos, + &logs, &warnings, &false_positives, + &severity, &get, NULL); +#else report_counts_id (second_last_report, &holes, &infos, &logs, &warnings, &false_positives, &severity, &get, NULL); - second_last_count = holes + infos + logs + warnings +#endif + second_last_count = criticals + holes + infos + logs + warnings + false_positives; cmp = last_count - second_last_count; @@ -15107,6 +15067,15 @@ append_to_task_string (task_t task, const char* field, const char* value) /** * @brief Filter columns for task iterator. */ +#if CVSS3_RATINGS == 1 + #define TASK_ITERATOR_FILTER_COLUMNS \ + { GET_ITERATOR_FILTER_COLUMNS, "status", "total", "first_report", \ + "last_report", "threat", "trend", "severity", "schedule", "next_due", \ + "first", "last", "false_positive", "log", "low", "medium", "high", \ + "critical", "hosts", "result_hosts", "fp_per_host", "log_per_host", \ + "low_per_host", "medium_per_host", "high_per_host", "critical_per_host", \ + "target", "usage_type", "first_report_created", "last_report_created", NULL } +#else #define TASK_ITERATOR_FILTER_COLUMNS \ { GET_ITERATOR_FILTER_COLUMNS, "status", "total", "first_report", \ "last_report", "threat", "trend", "severity", "schedule", "next_due", \ @@ -15114,6 +15083,7 @@ append_to_task_string (task_t task, const char* field, const char* value) "hosts", "result_hosts", "fp_per_host", "log_per_host", "low_per_host", \ "medium_per_host", "high_per_host", "target", "usage_type", \ "first_report_created", "last_report_created", NULL } +#endif /** * @brief Task iterator columns. @@ -15157,6 +15127,7 @@ append_to_task_string (task_t task, const char* field, const char* value) /** * @brief Task iterator WHERE columns. */ +#if CVSS3_RATINGS == 1 #define TASK_ITERATOR_WHERE_COLUMNS_INNER \ { \ "task_threat_level (id, opts.override, opts.min_qod)", \ @@ -15248,6 +15219,14 @@ append_to_task_string (task_t task, const char* field, const char* value) "high", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod, 'Critical')" \ + " END", \ + "critical", \ + KEYWORD_TYPE_INTEGER \ + }, \ { \ "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ " report_host_count (task_last_report (id))" \ @@ -15322,6 +15301,18 @@ append_to_task_string (task_t task, const char* field, const char* value) "high_per_host", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'Critical') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "critical_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ { \ "(SELECT name FROM targets WHERE id = target)", \ "target", \ @@ -15342,8 +15333,195 @@ append_to_task_string (task_t task, const char* field, const char* value) " ORDER BY creation_time DESC LIMIT 1)", \ "last_report_created", \ KEYWORD_TYPE_INTEGER \ - } \ - + } +#else +#define TASK_ITERATOR_WHERE_COLUMNS_INNER \ + { \ + "task_threat_level (id, opts.override, opts.min_qod)", \ + "threat", \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "task_trend (id, opts.override, opts.min_qod)", \ + "trend", \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "task_severity (id, opts.override, opts.min_qod)", \ + "severity", \ + KEYWORD_TYPE_DOUBLE \ + }, \ + { \ + "(SELECT schedules.name FROM schedules" \ + " WHERE schedules.id = tasks.schedule)", \ + "schedule", \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "(CASE WHEN schedule_next_time IS NULL" \ + " THEN -1" \ + " WHEN schedule_next_time = 0 AND tasks.schedule > 0" \ + " THEN (SELECT first_time" \ + " FROM schedules" \ + " WHERE schedules.id = tasks.schedule)" \ + " ELSE schedule_next_time" \ + " END)", \ + "next_due", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(SELECT creation_time FROM reports WHERE task = tasks.id" \ + /* TODO 1 == TASK_STATUS_DONE */ \ + " AND scan_run_status = 1" \ + " ORDER BY creation_time ASC LIMIT 1)", \ + "first", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(SELECT creation_time FROM reports WHERE task = tasks.id" \ + /* TODO 1 == TASK_STATUS_DONE */ \ + " AND scan_run_status = 1" \ + " ORDER BY creation_time DESC LIMIT 1)", \ + "last", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'False Positive')" \ + " END", \ + "false_positive", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod, 'Log')" \ + " END", \ + "log", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod, 'Low')" \ + " END", \ + "low", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod, 'Medium')" \ + " END", \ + "medium", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod, 'High')" \ + " END", \ + "high", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_host_count (task_last_report (id))" \ + " END", \ + "hosts", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " report_result_host_count (task_last_report (id), opts.min_qod)" \ + " END", \ + "result_hosts", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'False Positive') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "fp_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'Log') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "log_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'Low') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "low_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'Medium') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "medium_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "CASE WHEN target IS null OR opts.ignore_severity != 0 THEN 0 ELSE" \ + " coalesce (report_severity_count (task_last_report (id)," \ + " opts.override, opts.min_qod," \ + " 'High') * 1.0" \ + " / nullif (report_result_host_count (task_last_report (id),"\ + " opts.min_qod), 0)," \ + " 0)" \ + " END", \ + "high_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(SELECT name FROM targets WHERE id = target)", \ + "target", \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "(SELECT creation_time FROM reports WHERE task = tasks.id" \ + /* TODO 1 == TASK_STATUS_DONE */ \ + " AND scan_run_status = 1" \ + " ORDER BY creation_time ASC LIMIT 1)", \ + "first_report_created", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(SELECT creation_time FROM reports WHERE task = tasks.id" \ + /* TODO 1 == TASK_STATUS_DONE */ \ + " AND scan_run_status = 1" \ + " ORDER BY creation_time DESC LIMIT 1)", \ + "last_report_created", \ + KEYWORD_TYPE_INTEGER \ + } +#endif /** * @brief Task iterator WHERE columns. */ @@ -16098,17 +16276,6 @@ check_db_settings () " 'Roles given access to new resources from feed.'," " '" ROLE_UUID_ADMIN "," ROLE_UUID_USER "');"); - if (sql_int ("SELECT count(*) FROM settings" - " WHERE uuid = '" SETTING_UUID_DELTA_REPORTS_VERSION "'" - " AND " ACL_IS_GLOBAL () ";") - == 0) - sql ("INSERT into settings (uuid, owner, name, comment, value)" - " VALUES" - " ('" SETTING_UUID_DELTA_REPORTS_VERSION "', NULL," - " 'Delta Reports Version'," - " 'Version of the generation of the Delta Reports.'," - " '2' );"); - if (sql_int ("SELECT count(*) FROM settings" " WHERE uuid = '" SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD "'" " AND " ACL_IS_GLOBAL () ";") @@ -16272,7 +16439,7 @@ check_db_versions () else { int supported; - + supported = manage_scap_db_supported_version (); if (scap_db_version != supported) { @@ -16775,11 +16942,11 @@ manage_migrate_relay_sensors () * Only called by init_manage_internal, and ultimately only by the main process. * * @param[in] check_encryption_key Whether to check encryption key. - * + * @param[in] avoid_db_check_inserts Whether to avoid inserts in DB check. * @return 0 success, -1 error. */ static int -check_db (int check_encryption_key) +check_db (int check_encryption_key, int avoid_db_check_inserts) { /* The file locks managed at startup ensure that this is the only Manager * process accessing the db. Nothing else should be accessing the db, access @@ -16790,19 +16957,25 @@ check_db (int check_encryption_key) create_tables (); check_db_sequences (); set_db_version (GVMD_DATABASE_VERSION); - check_db_roles (); - check_db_nvt_selectors (); + if (avoid_db_check_inserts == 0) + { + check_db_roles (); + check_db_nvt_selectors (); + } check_db_nvts (); - check_db_port_lists (); + check_db_port_lists (avoid_db_check_inserts); clean_auth_cache (); - if (check_db_scanners ()) + if (avoid_db_check_inserts == 0 && check_db_scanners ()) goto fail; - if (check_db_report_formats ()) + if (check_db_report_formats (avoid_db_check_inserts)) goto fail; if (check_db_report_formats_trash ()) goto fail; - check_db_permissions (); - check_db_settings (); + if (avoid_db_check_inserts == 0) + { + check_db_permissions (); + check_db_settings (); + } cleanup_schedule_times (); if (check_encryption_key && check_db_encryption_key ()) goto fail; @@ -16969,6 +17142,7 @@ cleanup_tables () * with GMP when an alert occurs. * @param[in] skip_db_check Skip DB check. * @param[in] check_encryption_key Check encryption key if doing DB check. + * @param[in] avoid_db_check_inserts Whether to avoid inserts in DB check. * * @return 0 success, -1 error, -2 database is too old, * -4 max_ips_per_target out of range, -5 database is too new. @@ -16983,7 +17157,8 @@ init_manage_internal (GSList *log_config, int stop_tasks, manage_connection_forker_t fork_connection, int skip_db_check, - int check_encryption_key) + int check_encryption_key, + int avoid_db_check_inserts) { int ret; @@ -17069,7 +17244,7 @@ init_manage_internal (GSList *log_config, * 2 a helper processes (--create-user, --get-users, etc) when the * main process is not running. */ - ret = check_db (check_encryption_key); + ret = check_db (check_encryption_key, avoid_db_check_inserts); if (ret) return ret; @@ -17077,8 +17252,10 @@ init_manage_internal (GSList *log_config, /* Set max_hosts in db, so database server side can access it. */ - sql ("DELETE FROM meta WHERE name = 'max_hosts';"); - sql ("INSERT INTO meta (name, value) VALUES ('max_hosts', %i);", max_hosts); + sql ("INSERT INTO meta (name, value)" + " VALUES ('max_hosts', %i)" + " ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;", + max_hosts); } if (stop_tasks) @@ -17092,7 +17269,7 @@ init_manage_internal (GSList *log_config, if (skip_db_check == 0) /* Requires NVT cache. */ - check_db_configs (); + check_db_configs (avoid_db_check_inserts); sql_close (); gvmd_db_conn_info.name = database->name ? g_strdup (database->name) : NULL; @@ -17146,7 +17323,8 @@ init_manage (GSList *log_config, const db_conn_info_t *database, 1, /* Stop active tasks. */ fork_connection, skip_db_check, - 1); /* Check encryption key if checking db. */ + 1, /* Check encryption key if checking db. */ + 0 /* Do not avoid inserts if checking db. */); } /** @@ -17158,7 +17336,8 @@ init_manage (GSList *log_config, const db_conn_info_t *database, * * @param[in] log_config Log configuration. * @param[in] database Location of database. - * @param[in] max_ips_per_target Max number of IPs per target. + * @param[in] max_ips_per_target Max number of IPs per target. + * @param[in] avoid_db_check_inserts Whether to avoid inserts in DB check. * * @return 0 success, -1 error, -2 database is too old, -3 database needs * to be initialised from server, -4 max_ips_per_target out of range, @@ -17166,7 +17345,7 @@ init_manage (GSList *log_config, const db_conn_info_t *database, */ int init_manage_helper (GSList *log_config, const db_conn_info_t *database, - int max_ips_per_target) + int max_ips_per_target, int avoid_db_check_inserts) { return init_manage_internal (log_config, database, @@ -17183,7 +17362,8 @@ init_manage_helper (GSList *log_config, const db_conn_info_t *database, lockfile_locked ("gvm-serving") ? 1 /* Skip DB check. */ : 0, /* Do DB check. */ - 0); /* Dummy. */ + 0, /* Dummy. */ + avoid_db_check_inserts); } /** @@ -18335,7 +18515,7 @@ task_usage_type (task_t task, char ** usage_type) task); if (usage_type == NULL) return -1; - + return 0; } @@ -20446,6 +20626,339 @@ 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 DISTINCT 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] criteria The criteria for the match nodes. + */ +void +init_cpe_match_nodes_iterator (iterator_t* iterator, const char *criteria) +{ + gchar *quoted_criteria; + quoted_criteria = sql_quote (criteria); + init_iterator (iterator, + "SELECT DISTINCT n.root_id" + " FROM scap.cpe_match_nodes n" + " JOIN scap.cpe_nodes_match_criteria c" + " ON n.id = c.node_id" + " JOIN scap.cpe_match_strings r" + " ON c.match_criteria_id = r.match_criteria_id" + " WHERE criteria like '%s%%';", + quoted_criteria); + g_free (quoted_criteria); +} + +/** + * @brief Initialize an iterator of CPE match nodes root_ids for a CVE. + * + * @param[in] iterator Iterator. + * @param[in] cve The CVE contained in the match nodes. + */ +void +init_cve_cpe_match_nodes_iterator (iterator_t* iterator, const char *cve) +{ + gchar *quoted_cve; + quoted_cve = sql_quote (cve); + init_iterator (iterator, + "SELECT DISTINCT root_id" + " FROM scap.cpe_match_nodes" + " WHERE cve_id = (SELECT id FROM scap.cves" + " WHERE uuid = '%s');", + quoted_cve); + g_free (quoted_cve); +} + +/** + * @brief Initialize an iterator of references for a CVE. + * + * @param[in] iterator Iterator. + * @param[in] cve The CVE with the references. + */ +void +init_cve_reference_iterator (iterator_t* iterator, const char *cve) +{ + gchar *quoted_cve; + quoted_cve = sql_quote (cve); + init_iterator (iterator, + "SELECT url, array_length(tags, 1), tags" + " FROM scap.cve_references" + " WHERE cve_id = (SELECT id FROM scap.cves" + " WHERE uuid = '%s');", + quoted_cve); + g_free (quoted_cve); +} + +/** + * @brief Get a URL from a CVE reference iterator. + * + * @param[in] iterator Iterator. + * + * @return The URL. + */ +DEF_ACCESS (cve_reference_iterator_url, 0); + +/** + * @brief Get the length of the tags array from a CVE reference iterator. + * + * @param[in] iterator Iterator. + * + * @return Length of the tags array. + */ +DEF_ACCESS (cve_reference_iterator_tags_count, 1); + +/** + * @brief Get the tags array from a CVE reference iterator. + * + * @param[in] iterator Iterator. + * + * @return The tags array. + */ +DEF_ACCESS (cve_reference_iterator_tags, 2); + +/** + * @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 root_id = %llu" + " AND root_id <> id;", + 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 strings of an CPE match node. + * + * @param[in] iterator Iterator. + * @param[in] node The match node with match strings. + */ +void +init_cpe_match_string_iterator (iterator_t* iterator, long long int node) +{ + init_iterator (iterator, + "SELECT n.vulnerable, r.criteria, r.match_criteria_id, r.status," + " r.version_start_incl, r.version_start_excl," + " r.version_end_incl, r.version_end_excl" + " FROM scap.cpe_match_strings r" + " JOIN scap.cpe_nodes_match_criteria n" + " ON r.match_criteria_id = n.match_criteria_id" + " WHERE n.node_id = %llu;", + node); +} + +/** + * @brief Return if the match criteria is vulnerable. + * + * @param[in] iterator Iterator. + * + * @return 1 if the match criteria is vulnerable, 0 otherwise. + */ +int +cpe_match_string_iterator_vulnerable (iterator_t* iterator) +{ + return iterator_int64 (iterator, 0); +} + +/** + * @brief Return the criteria of the CPE match string. + * + * @param[in] iterator Iterator. + * + * @return The criteria of the match string. + */ +DEF_ACCESS (cpe_match_string_iterator_criteria, 1); + +/** + * @brief Return the match criteria id of the CPE match string. + * + * @param[in] iterator Iterator. + * + * @return The match criteria id, if any. NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_match_criteria_id, 2); + +/** + * @brief Return the status of the CPE match criteria. + * + * @param[in] iterator Iterator. + * + * @return The status of the CPE match criteria, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_status, 3); + +/** + * @brief Return the start included version of the match criteria. + * + * @param[in] iterator Iterator. + * + * @return The start included version of the match criteria, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_version_start_incl, 4); + +/** + * @brief Return the start excluded version of the match criteria. + * + * @param[in] iterator Iterator. + * + * @return The start excluded version of the match criteria, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_version_start_excl, 5); + +/** + * @brief Return the end included version of the match criteria. + * + * @param[in] iterator Iterator. + * + * @return The end included version of the match criteria, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_version_end_incl, 6); + +/** + * @brief Return the end excluded version of the match criteria. + * + * @param[in] iterator Iterator. + * + * @return The end excluded version of the match criteria, if any. + * NULL otherwise. + */ +DEF_ACCESS (cpe_match_string_iterator_version_end_excl, 7); + +/** + * @brief Initialize an iterator of CPE matches for a match string + * given a match criteria id. + * + * @param[in] iterator Iterator. + * @param[in] match_criteria_id The match criteria id to get the matches for. + * @param[in] schema Schema name, NULL for the default "scap". + */ +void +init_cpe_match_string_matches_iterator (iterator_t* iterator, + const char *match_criteria_id, + const char *schema) +{ + init_iterator (iterator, + "SELECT cpe_name_id, cpe_name" + " FROM %s.cpe_matches" + " WHERE match_criteria_id = '%s'", + schema ? schema : "scap", + match_criteria_id); +} + +/** + * @brief Get the CPE name id from a CPE match string matches iterator. + * + * @param[in] iterator Iterator. + * + * @return The CPE name id. + */ +const char * +cpe_matches_cpe_name_id (iterator_t* iterator) +{ + return iterator_string (iterator, 0); +} + +/** + * @brief Get the CPE name from a CPE match string matches iterator. + * + * @param[in] iterator Iterator. + * + * @return The CPE name id. + */ +const char * +cpe_matches_cpe_name (iterator_t* iterator) +{ + return iterator_string (iterator, 1); +} + /** * @brief Initialise a report host prognosis iterator. * @@ -20894,9 +21407,14 @@ report_cache_counts (report_t report, int clear_original, int clear_overridden, " AND min_qod = %d", report, user, override, min_qod); } - +#if CVSS3_RATINGS == 1 + int criticals; + report_counts_id (report, &criticals, &holes, &infos, &logs, &warnings, + &false_positives, &severity, get, NULL); +#else report_counts_id (report, &holes, &infos, &logs, &warnings, &false_positives, &severity, get, NULL); +#endif get_data_reset (get); g_free (get); @@ -21628,7 +22146,7 @@ report_compliance_by_uuid (const char *report_id, " WHERE report = %llu" " AND description NOT LIKE 'Compliant:%%';", report); - } + } g_free (quoted_uuid); } @@ -21851,6 +22369,16 @@ report_add_results_array (report_t report, GArray *results) /** * @brief Filter columns for report iterator. */ +#if CVSS3_RATINGS == 1 +#define REPORT_ITERATOR_FILTER_COLUMNS \ + { ANON_GET_ITERATOR_FILTER_COLUMNS, "task_id", "name", "creation_time", \ + "date", "status", "task", "severity", "false_positive", "log", "low", \ + "medium", "high", "critical", "hosts", "result_hosts", "fp_per_host", \ + "log_per_host", "low_per_host", "medium_per_host", "high_per_host", \ + "critical_per_host", "duration", "duration_per_host", "start_time", \ + "end_time", "scan_start", "scan_end", "compliance_yes", "compliance_no", \ + "compliance_incomplete", "compliant", NULL } +#else #define REPORT_ITERATOR_FILTER_COLUMNS \ { ANON_GET_ITERATOR_FILTER_COLUMNS, "task_id", "name", "creation_time", \ "date", "status", "task", "severity", "false_positive", "log", "low", \ @@ -21859,7 +22387,7 @@ report_add_results_array (report_t report, GArray *results) "duration_per_host", "start_time", "end_time", "scan_start", "scan_end", \ "compliance_yes", "compliance_no", "compliance_incomplete", \ "compliant", NULL } - +#endif /** * @brief Report iterator columns. */ @@ -21885,6 +22413,7 @@ report_add_results_array (report_t report, GArray *results) /** * @brief Report iterator columns. */ +#if CVSS3_RATINGS == 1 #define REPORT_ITERATOR_WHERE_COLUMNS \ { \ { "run_status_name (scan_run_status)", "status", KEYWORD_TYPE_STRING }, \ @@ -21926,6 +22455,11 @@ report_add_results_array (report_t report, GArray *results) "high", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod, 'Critical')", \ + "critical", \ + KEYWORD_TYPE_INTEGER \ + }, \ { \ "(SELECT name FROM users WHERE users.id = reports.owner)", \ "_owner", \ @@ -21981,6 +22515,14 @@ report_add_results_array (report_t report, GArray *results) "high_per_host", \ KEYWORD_TYPE_INTEGER \ }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'Critical') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "critical_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ { \ "(CASE WHEN (start_time IS NULL or end_time IS NULL)" \ " THEN NULL ELSE end_time - start_time END)", \ @@ -22018,7 +22560,141 @@ report_add_results_array (report_t report, GArray *results) }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } - +#else +#define REPORT_ITERATOR_WHERE_COLUMNS \ + { \ + { "run_status_name (scan_run_status)", "status", KEYWORD_TYPE_STRING }, \ + { \ + "(SELECT uuid FROM tasks WHERE tasks.id = task)", \ + "task_id", \ + KEYWORD_TYPE_STRING \ + }, \ + { "creation_time", "date", KEYWORD_TYPE_INTEGER }, \ + { "(SELECT name FROM tasks WHERE tasks.id = task)", "task" }, \ + { \ + "report_severity (id, opts.override, opts.min_qod)", \ + "severity", \ + KEYWORD_TYPE_DOUBLE \ + }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod," \ + " 'False Positive')", \ + "false_positive", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod, 'Log')", \ + "log", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod, 'Low')", \ + "low", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod, 'Medium')", \ + "medium", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_severity_count (id, opts.override, opts.min_qod, 'High')", \ + "high", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(SELECT name FROM users WHERE users.id = reports.owner)", \ + "_owner", \ + KEYWORD_TYPE_STRING \ + }, \ + { \ + "report_host_count (id)", \ + "hosts", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_result_host_count (id, opts.min_qod)", \ + "result_hosts", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'False Positive') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "fp_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'Log') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "log_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'Low') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "low_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'Medium') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "medium_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "coalesce (report_severity_count (id, opts.override, opts.min_qod," \ + " 'High') * 1.0" \ + " / nullif (report_result_host_count (id, opts.min_qod), 0),"\ + " 0)", \ + "high_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(CASE WHEN (start_time IS NULL or end_time IS NULL)" \ + " THEN NULL ELSE end_time - start_time END)", \ + "duration", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "(CASE WHEN (start_time IS NULL or end_time IS NULL" \ + " or report_result_host_count (id, opts.min_qod) = 0)" \ + " THEN NULL" \ + " ELSE (end_time - start_time)" \ + " / report_result_host_count (id, opts.min_qod) END)", \ + "duration_per_host", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_compliance_count (id, 'YES')", \ + "compliance_yes", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_compliance_count (id, 'NO')", \ + "compliance_no", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_compliance_count (id, 'INCOMPLETE')", \ + "compliance_incomplete", \ + KEYWORD_TYPE_INTEGER \ + }, \ + { \ + "report_compliance_status (id)", \ + "compliant", \ + KEYWORD_TYPE_STRING \ + }, \ + { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ + } +#endif /** * @brief Generate the extra_tables string for a report iterator. * @@ -22038,12 +22714,11 @@ report_iterator_opts_table (int override, int min_qod) min_qod); } -#if COMPLIANCE_REPORTS == 1 /** * @brief Return SQL WHERE for restricting a SELECT to compliance statuses. * * @param[in] compliance String describing compliance statuses of reports - * to include (for example, "yniu" for yes (compliant), + * to include (for example, "yniu" for yes (compliant), * no (not compliant), i (incomplete) and u (undefined)) * All compliance statuses if NULL. * @@ -22096,7 +22771,6 @@ where_compliance_status (const char *compliance) return g_string_free (compliance_sql, FALSE);; } -#endif /** * @brief Generate an extra WHERE clause for selecting reports @@ -22118,7 +22792,7 @@ reports_extra_where (int trash, const gchar *filter, const char *usage_type) { trash_clause = g_strdup_printf (" AND (SELECT hidden FROM tasks" " WHERE tasks.id = task)" - " = 2"); + " = 2"); } else { @@ -22131,32 +22805,30 @@ reports_extra_where (int trash, const gchar *filter, const char *usage_type) g_string_append_printf(extra_where, "%s", trash_clause); g_free (trash_clause); - #if COMPLIANCE_REPORTS == 1 - gchar *usage_type_clause, *compliance_clause = NULL; - gchar *compliance_filter = NULL; - if (usage_type && strcmp (usage_type, "")) - { - gchar *quoted_usage_type; - quoted_usage_type = sql_quote (usage_type); - usage_type_clause = g_strdup_printf (" AND task in (SELECT id from tasks" - " WHERE usage_type='%s')", - quoted_usage_type); + gchar *usage_type_clause, *compliance_clause = NULL; + gchar *compliance_filter = NULL; + if (usage_type && strcmp (usage_type, "")) + { + gchar *quoted_usage_type; + quoted_usage_type = sql_quote (usage_type); + usage_type_clause = g_strdup_printf (" AND task in (SELECT id from tasks" + " WHERE usage_type='%s')", + quoted_usage_type); - g_free (quoted_usage_type); - } - else - usage_type_clause = NULL; + g_free (quoted_usage_type); + } + else + usage_type_clause = NULL; - if (filter) - compliance_filter = filter_term_value(filter, "report_compliance_levels"); + if (filter) + compliance_filter = filter_term_value(filter, "report_compliance_levels"); - compliance_clause = where_compliance_status (compliance_filter ?: "yniu"); + compliance_clause = where_compliance_status (compliance_filter ?: "yniu"); - g_string_append_printf (extra_where, "%s%s", usage_type_clause ?: "", compliance_clause ?: ""); - g_free (compliance_filter); - g_free (compliance_clause); - g_free (usage_type_clause); - #endif + g_string_append_printf (extra_where, "%s%s", usage_type_clause ?: "", compliance_clause ?: ""); + g_free (compliance_filter); + g_free (compliance_clause); + g_free (usage_type_clause); return g_string_free (extra_where, FALSE); } @@ -22178,7 +22850,7 @@ report_count (const get_data_t *get) int ret; extra_tables = report_iterator_opts_table (0, MIN_QOD_DEFAULT); - + const gchar *usage_type = get_data_get_extra (get, "usage_type"); extra_where = reports_extra_where(get->trash, get->filter, usage_type); @@ -22229,7 +22901,7 @@ init_report_iterator (iterator_t* iterator, const get_data_t *get) extra_tables = report_iterator_opts_table (overrides, min_qod); usage_type = get_data_get_extra (get, "usage_type"); - extra_where = reports_extra_where (get->trash, + extra_where = reports_extra_where (get->trash, filter ? filter : get->filter, usage_type); @@ -22332,6 +23004,13 @@ where_levels_auto (const char *levels, const char *new_severity_sql) g_string_append_printf (levels_sql, " AND severity_in_levels (%s", new_severity_sql); +#if CVSS3_RATINGS == 1 + if (strchr (levels, 'c')) + { + g_string_append (levels_sql, ", 'critical'"); + count++; + } +#endif if (strchr (levels, 'h')) { g_string_append (levels_sql, ", 'high'"); @@ -22366,7 +23045,11 @@ where_levels_auto (const char *levels, const char *new_severity_sql) g_string_append (levels_sql, ")"); +#if CVSS3_RATINGS == 1 + if (count == 6) +#else if (count == 5) +#endif { /* All levels. */ g_string_free (levels_sql, TRUE); @@ -22385,7 +23068,7 @@ where_levels_auto (const char *levels, const char *new_severity_sql) /** * @brief Return SQL WHERE for restricting a SELECT to compliance levels. * - * @param[in] levels String describing compliance levels to include in + * @param[in] levels String describing compliance levels to include in * report (for example, "yniu" for "yes, "no", "incomplete" * and "undefined"). All levels if NULL. * @@ -23060,7 +23743,11 @@ results_extra_where (int trash, report_t report, const gchar* host, min_qod = filter_term_min_qod (filter); levels = filter_term_value (filter, "levels"); if (levels == NULL) +#if CVSS3_RATINGS == 1 + levels = g_strdup ("chmlgdf"); +#else levels = g_strdup ("hmlgdf"); +#endif compliance_levels = filter_term_value (filter, "compliance_levels"); // Build clause fragments @@ -23086,7 +23773,7 @@ results_extra_where (int trash, report_t report, const gchar* host, min_qod_clause = where_qod (min_qod); - levels_clause = where_levels_auto (levels ? levels : "hmlgdf", + levels_clause = where_levels_auto (levels, given_new_severity_sql ? given_new_severity_sql : new_severity_sql); @@ -23389,14 +24076,14 @@ init_result_get_iterator_severity (iterator_t* iterator, const get_data_t *get, * @param[in] apply_overrides Whether to apply overrides. * @param[in] dynamic_severity Whether to use dynamic severity. * @param[in] nvts_table NVTS table. - * @param[in] results_table Results table. + * @param[in] results_table Results table. * * @return SQL clause for FROM. */ static gchar * -result_iterator_lateral (int apply_overrides, - int dynamic_severity, - const char *results_table, +result_iterator_lateral (int apply_overrides, + int dynamic_severity, + const char *results_table, const char *nvts_table) { if (apply_overrides && dynamic_severity) @@ -23411,11 +24098,11 @@ result_iterator_lateral (int apply_overrides, " ov_old_severity)" " LIMIT 1)," " (SELECT curr_severity FROM curr LIMIT 1))" - " AS new_severity)", + " AS new_severity)", results_table, nvts_table, results_table, - results_table, + results_table, results_table); if (apply_overrides) @@ -23601,11 +24288,11 @@ result_count (const get_data_t *get, report_t report, const char* host) opts_tables = result_iterator_opts_table (apply_overrides, dynamic_severity); - lateral_clause = result_iterator_lateral (apply_overrides, + lateral_clause = result_iterator_lateral (apply_overrides, dynamic_severity, "results", "nvts"); - + extra_tables = g_strdup_printf (" LEFT OUTER JOIN result_vt_epss" " ON results.nvt = result_vt_epss.vt_id" " LEFT OUTER JOIN nvts" @@ -23677,37 +24364,6 @@ DEF_ACCESS (result_iterator_port, GET_ITERATOR_COLUMN_COUNT + 1); */ DEF_ACCESS (result_iterator_nvt_oid, GET_ITERATOR_COLUMN_COUNT + 2); -/** - * @brief Get the original type from a result iterator. - * - * This is the column 'type'. - * - * @param[in] iterator Iterator. - * - * @return The original type of the result. Caller must only use before calling - * cleanup_iterator. - */ -static -DEF_ACCESS (result_iterator_original_type, GET_ITERATOR_COLUMN_COUNT + 3); - -/** - * @brief Get the type from a result iterator. - * - * This is the overridden type. - * - * @param[in] iterator Iterator. - * - * @return The type of the result. Caller must only use before calling - * cleanup_iterator. - */ -static const char* -result_iterator_type (iterator_t *iterator) -{ - if (iterator->done) return NULL; - /* new_type */ - return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 4); -} - /** * @brief Get the descr from a result iterator. * @@ -25619,6 +26275,8 @@ report_severity_data (report_t report, const char *host, * use report_counts_id instead. * * @param[in] report_id ID of report. + * @param[out] criticals Number of critical messages. + * Only if CVSS3_RATINGS is enabled. * @param[out] holes Number of hole messages. * @param[out] infos Number of info messages. * @param[out] logs Number of log messages. @@ -25631,8 +26289,16 @@ report_severity_data (report_t report, const char *host, * @return 0 on success, -1 on error. */ int -report_counts (const char* report_id, int* holes, int* infos, - int* logs, int* warnings, int* false_positives, double* severity, +report_counts (const char* report_id, +#if CVSS3_RATINGS == 1 + int* criticals, +#endif + int* holes, + int* infos, + int* logs, + int* warnings, + int* false_positives, + double* severity, int override, int min_qod) { report_t report; @@ -25644,8 +26310,13 @@ report_counts (const char* report_id, int* holes, int* infos, // TODO Check if report was found. get = report_results_get_data (1, -1, override, min_qod); +#if CVSS3_RATINGS == 1 + ret = report_counts_id (report, criticals, holes, infos, logs, warnings, + false_positives, severity, get, NULL); +#else ret = report_counts_id (report, holes, infos, logs, warnings, false_positives, severity, get, NULL); +#endif get_data_reset (get); free (get); return ret; @@ -25815,6 +26486,8 @@ cache_report_counts (report_t report, int override, int min_qod, * @brief Get the message counts for a report. * * @param[in] report Report. + * @param[out] criticals Number of critical messages. + * Only if CVSS3_RATINGS is enabled. * @param[out] holes Number of hole messages. * @param[out] infos Number of info messages. * @param[out] logs Number of log messages. @@ -25823,6 +26496,8 @@ cache_report_counts (report_t report, int override, int min_qod, * @param[out] severity Maximum severity of the report. * @param[in] get Get data. * @param[in] host Host to which to limit the count. + * @param[out] filtered_criticals Number of critical messages after filtering. + * Only if CVSS3_RATINGS is enabled. * @param[out] filtered_holes Number of hole messages after filtering. * @param[out] filtered_infos Number of info messages after filtering. * @param[out] filtered_logs Number of log messages after filtering. @@ -25834,13 +26509,26 @@ cache_report_counts (report_t report, int override, int min_qod, * @return 0 on success, -1 on error. */ static int -report_counts_id_full (report_t report, int* holes, int* infos, - int* logs, int* warnings, int* false_positives, +report_counts_id_full (report_t report, +#if CVSS3_RATINGS == 1 + int* criticals, +#endif + int* holes, + int* infos, + int* logs, + int* warnings, + int* false_positives, double* severity, - const get_data_t* get, const char* host, + const get_data_t* get, + const char* host, +#if CVSS3_RATINGS == 1 + int* filtered_criticals, +#endif int* filtered_holes, - int* filtered_infos, int* filtered_logs, - int* filtered_warnings, int* filtered_false_positives, + int* filtered_infos, + int* filtered_logs, + int* filtered_warnings, + int* filtered_false_positives, double* filtered_severity) { const char *filter; @@ -25849,13 +26537,19 @@ report_counts_id_full (report_t report, int* holes, int* infos, int filter_cacheable, unfiltered_requested, filtered_requested, cache_exists; int override, min_qod_int; severity_data_t severity_data, filtered_severity_data; - +#if CVSS3_RATINGS == 1 + unfiltered_requested = (criticals || holes || warnings || infos || logs || false_positives + || severity); + filtered_requested = (filtered_criticals || filtered_holes || filtered_warnings + || filtered_infos || filtered_logs + || filtered_false_positives || filtered_severity); +#else unfiltered_requested = (holes || warnings || infos || logs || false_positives || severity); filtered_requested = (filtered_holes || filtered_warnings || filtered_infos || filtered_logs || filtered_false_positives || filtered_severity); - +#endif if (current_credentials.uuid == NULL || strcmp (current_credentials.uuid, "") == 0) g_warning ("%s: called by NULL or dummy user", __func__); @@ -25947,6 +26641,15 @@ report_counts_id_full (report_t report, int* holes, int* infos, ? &filtered_severity_data : NULL); } +#if CVSS3_RATINGS == 1 + severity_data_level_counts (&severity_data, + NULL, false_positives, + logs, infos, warnings, holes, criticals); + severity_data_level_counts (&filtered_severity_data, + NULL, filtered_false_positives, + filtered_logs, filtered_infos, + filtered_warnings, filtered_holes, filtered_criticals); +#else severity_data_level_counts (&severity_data, NULL, false_positives, logs, infos, warnings, holes); @@ -25954,6 +26657,7 @@ report_counts_id_full (report_t report, int* holes, int* infos, NULL, filtered_false_positives, filtered_logs, filtered_infos, filtered_warnings, filtered_holes); +#endif if (severity) *severity = severity_data.max; @@ -25975,7 +26679,6 @@ report_counts_id_full (report_t report, int* holes, int* infos, return 0; } -#if COMPLIANCE_REPORTS == 1 /** * @brief Get the compliance state from compliance counts. * @@ -26016,19 +26719,19 @@ report_compliance_from_counts (const int* yes_count, * @param[in] get Get data. * @param[out] f_compliance_yes Compliant results count after filtering. * @param[out] f_compliance_no Incompliant results count after filtering. - * @param[out] f_compliance_incomplete Incomplete results count + * @param[out] f_compliance_incomplete Incomplete results count * after filtering. - * @param[out] f_compliance_undefined Undefined results count + * @param[out] f_compliance_undefined Undefined results count * after filtering. * * @return 0 on success, -1 on error. */ static int -report_compliance_f_counts (report_t report, - const get_data_t* get, - int* f_compliance_yes, - int* f_compliance_no, - int* f_compliance_incomplete, +report_compliance_f_counts (report_t report, + const get_data_t* get, + int* f_compliance_yes, + int* f_compliance_no, + int* f_compliance_incomplete, int* f_compliance_undefined) { if (report == 0) @@ -26063,7 +26766,7 @@ report_compliance_f_counts (report_t report, else if (strcasecmp (compliance, "no") == 0) { no_count++; - } + } else if (strcasecmp (compliance, "incomplete") == 0) { incomplete_count++; @@ -26071,7 +26774,7 @@ report_compliance_f_counts (report_t report, else if (strcasecmp (compliance, "undefined") == 0) { undefined_count++; - } + } } @@ -26102,11 +26805,11 @@ report_compliance_f_counts (report_t report, * @return 0 on success, -1 on error. */ static int -report_compliance_counts (report_t report, +report_compliance_counts (report_t report, const get_data_t* get, - int* compliance_yes, + int* compliance_yes, int* compliance_no, - int* compliance_incomplete, + int* compliance_incomplete, int* compliance_undefined) { if (report == 0) @@ -26114,19 +26817,19 @@ report_compliance_counts (report_t report, report_compliance_by_uuid (report_uuid(report), compliance_yes, - compliance_no, + compliance_no, compliance_incomplete, compliance_undefined); return 0; } -#endif - /** * @brief Get only the filtered message counts for a report. * * @param[in] report Report. + * @param[out] criticals Number of critical messages. + * Only if CVSS3_RATINGS is enabled. * @param[out] holes Number of hole messages. * @param[out] infos Number of info messages. * @param[out] logs Number of log messages. @@ -26139,14 +26842,29 @@ report_compliance_counts (report_t report, * @return 0 on success, -1 on error. */ int -report_counts_id (report_t report, int* holes, int* infos, - int* logs, int* warnings, int* false_positives, - double* severity, const get_data_t *get, const char *host) +report_counts_id (report_t report, +#if CVSS3_RATINGS == 1 + int* criticals, +#endif + int* holes, + int* infos, + int* logs, + int* warnings, + int* false_positives, + double* severity, + const get_data_t *get, + const char *host) { int ret; +#if CVSS3_RATINGS == 1 + ret = report_counts_id_full (report, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + get, host, criticals, holes, infos, logs, + warnings, false_positives, severity); +#else ret = report_counts_id_full (report, NULL, NULL, NULL, NULL, NULL, NULL, get, host, holes, infos, logs, warnings, false_positives, severity); +#endif return ret; } @@ -26188,8 +26906,13 @@ report_severity (report_t report, int overrides, int min_qod) { g_debug ("%s: could not get max from cache", __func__); get_data_t *get = report_results_get_data (1, -1, overrides, min_qod); +#if CVSS3_RATINGS == 1 + report_counts_id (report, NULL, NULL, NULL, NULL, + NULL, NULL, &severity, get, NULL); +#else report_counts_id (report, NULL, NULL, NULL, NULL, NULL, &severity, get, NULL); +#endif get_data_reset (get); free (get); } @@ -26660,492 +27383,6 @@ void buffer_results_xml (GString *, iterator_t *, task_t, int, int, int, int, int, int, int, const char *, iterator_t *, int, int, int, int); -/** - * @brief Comparison returns. - */ -typedef enum -{ - COMPARE_RESULTS_CHANGED, - COMPARE_RESULTS_ERROR, - COMPARE_RESULTS_GONE, - COMPARE_RESULTS_NEW, - COMPARE_RESULTS_SAME -} compare_results_t; - -/** - * @brief Return the sort order of two results. - * - * @param[in] results Iterator containing first result. - * @param[in] delta_results Iterator containing second result. - * @param[in] sort_order Whether to sort ascending or descending. - * @param[in] sort_field Field to sort on, or NULL for "type". - * - * @return < 0 if first comes before second, 0 if equal, > 0 if first comes - * after second. - */ -static compare_results_t -result_cmp (iterator_t *results, iterator_t *delta_results, int sort_order, - const char* sort_field) -{ - const char *host, *delta_host, *port, *delta_port; - const char *nvt, *delta_nvt, *name, *delta_name, *descr, *delta_descr; - int ret; - double severity, delta_severity; - - if (sort_field == NULL) - sort_field = "type"; - - g_debug (" delta: %s: sort_order: %i", __func__, sort_order); - g_debug (" delta: %s: sort_field: %s", __func__, sort_field); - - host = result_iterator_host (results); - delta_host = result_iterator_host (delta_results); - - port = result_iterator_port (results); - delta_port = result_iterator_port (delta_results); - - severity = result_iterator_severity_double (results); - delta_severity = result_iterator_severity_double (delta_results); - - nvt = result_iterator_nvt_oid (results); - delta_nvt = result_iterator_nvt_oid (delta_results); - - name = result_iterator_nvt_name (results); - delta_name = result_iterator_nvt_name (delta_results); - - descr = result_iterator_descr (results); - delta_descr = result_iterator_descr (delta_results); - - /* For delta reports to work correctly, the order must be the same as in - * init_delta_iterators, except that description should not be checked - * unless it is the sort_field. - * - * If description is not the sort_field it is checked after the result_cmp - * in compare_results. */ - - /* Check sort_field first, also using sort_order (0 is descending). */ - if (strcmp (sort_field, "host") == 0) - { - ret = collate_ip (NULL, - strlen (host), host, strlen (delta_host), delta_host); - if (sort_order == 0) - ret = -ret; - g_debug (" delta: %s: host (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - host, delta_host, ret); - if (ret) - return ret; - } - else if (strcmp (sort_field, "port") == 0 - || strcmp (sort_field, "location") == 0) - { - ret = strcmp (port, delta_port); - if (sort_order == 0) - ret = -ret; - g_debug (" delta: %s: port (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - port, delta_port, ret); - if (ret) - return ret; - } - else if (strcmp (sort_field, "severity") == 0) - { - if (severity > delta_severity) - ret = sort_order ? 1 : -1; - else if (severity < delta_severity) - ret = sort_order ? -1 : 1; - else - ret = 0; - g_debug (" delta: %s: severity (%s): %f VS %f (%i)", - __func__, sort_order ? "desc" : "asc", - severity, delta_severity, ret); - if (ret) - return ret; - } - /* NVT OID, not name/vulnerability. */ - else if (strcmp (sort_field, "nvt") == 0) - { - ret = strcmp (nvt, delta_nvt); - if (sort_order) - ret = -ret; - g_debug (" delta: %s: nvt (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - nvt, delta_nvt, ret); - if (ret) - return ret; - } - else if (strcmp (sort_field, "description") == 0) - { - ret = strcmp (descr, delta_descr); - if (sort_order == 0) - ret = -ret; - g_debug (" delta: %s: description (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - descr, delta_descr, ret); - if (ret) - return ret; - } - else if (strcmp (sort_field, "type") == 0) - { - const char *type, *delta_type; - - type = result_iterator_type (results); - delta_type = result_iterator_type (delta_results); - - ret = strcmp (type, delta_type); - if (sort_order == 0) - ret = -ret; - g_debug (" delta: %s: type (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - descr, delta_descr, ret); - if (ret) - return ret; - } - else if (strcmp (sort_field, "original_type") == 0) - { - const char *type, *delta_type; - - type = result_iterator_original_type (results); - delta_type = result_iterator_original_type (delta_results); - - ret = strcmp (type, delta_type); - if (sort_order == 0) - ret = -ret; - g_debug (" delta: %s: original_type (%s): %s VS %s (%i)", - __func__, sort_order ? "desc" : "asc", - descr, delta_descr, ret); - if (ret) - return ret; - } - else - { - /* Default to "vulnerability" (a.k.a "name") for unknown sort fields. - * - * Also done in print_report_xml_start, so this is just a safety check. */ - ret = strcmp (name ? name : "", delta_name ? delta_name : ""); - if (sort_order == 0) - ret = -ret; - if (ret) - return ret; - } - - /* Check remaining fields */ - if (strcmp (sort_field, "host")) - { - ret = collate_ip (NULL, - strlen (host), host, strlen (delta_host), delta_host); - g_debug (" delta: %s: host: %s VS %s (%i)", - __func__, host, delta_host, ret); - if (ret) - return ret; - } - if (strcmp (sort_field, "port") - && strcmp (sort_field, "location")) - { - ret = strcmp (port, delta_port); - g_debug (" delta: %s: port: %s VS %s (%i)", - __func__, port, delta_port, ret); - if (ret) - return ret; - } - if (strcmp (sort_field, "severity")) - { - if (severity > delta_severity) - ret = 1; - else if (severity < delta_severity) - ret = -1; - else - ret = 0; - g_debug (" delta: %s: severity: %f VS %f (%i)", - __func__, severity, delta_severity, ret); - if (ret) - return ret; - } - if (strcmp (sort_field, "nvt")) - { - ret = strcmp (nvt, delta_nvt); - g_debug (" delta: %s: nvt: %s VS %s (%i)", - __func__, nvt, delta_nvt, ret); - if (ret) - return ret; - } - - return 0; -} - -/** - * @brief Test if two strings are equal, ignoring whitespace. - * - * @param[in] one First string. - * @param[in] two Second string. - * - * @return 1 if equal, else 0. - */ -static int -streq_ignore_ws (const gchar *one, const gchar *two) -{ - if (one == NULL) - return two == NULL; - if (two == NULL) - return 0; - - while (1) - { - /* Skip space in both. */ - while (isspace (*one)) - one++; - while (isspace (*two)) - two++; - - /* Check for end. */ - if (*one == '\0') - break; - if (*two == '\0') - return 0; - - /* Compare. */ - if (*one != *two) - return 0; - - /* Next. */ - one++; - two++; - } - if (*two) - return 0; - return 1; -} - -/** - * @brief Compare two results. - * - * @param[in] results Iterator containing first result. - * @param[in] delta_results Iterator containing second result. - * @param[in] sort_order Whether to sort ascending or descending. - * @param[in] sort_field Field to sort on, or NULL for "type". - * - * @return Result of comparison. - */ -static compare_results_t -compare_results (iterator_t *results, iterator_t *delta_results, int sort_order, - const char* sort_field) -{ - int ret; - const char *descr, *delta_descr; - - g_debug (" delta: %s", __func__); - - ret = result_cmp (results, delta_results, sort_order, sort_field); - if (ret > 0) - /* The delta result sorts first, so it is new. */ - return COMPARE_RESULTS_NEW; - if (ret < 0) - /* The 'results' result sorts first, so it has gone. */ - return COMPARE_RESULTS_GONE; - - descr = result_iterator_descr (results); - delta_descr = result_iterator_descr (delta_results); - - g_debug (" delta: %s: descr: %s VS %s (%i)", - __func__, - descr ? descr : "NULL", - delta_descr ? delta_descr : "NULL", - (descr && delta_descr) ? strcmp (descr, delta_descr) : 0); - - /* This comparison ignores whitespace to match the diff output created by - * strdiff in gmp.c. The down side of this is that the comparison may be - * affected by the locale. - * - * An alternate would be to use the strdiff result as the comparison, but - * strdiff is only called for the results on the page (and not for the - * rest of the results, which must also be compared for the counts). - * Using strdiff for all results could also be slow, because it's running - * the diff command. */ - if (descr && delta_descr && (streq_ignore_ws (descr, delta_descr) == 0)) - return COMPARE_RESULTS_CHANGED; - - return COMPARE_RESULTS_SAME; -} - -/** - * @brief Compare two results, optionally writing associated XML to a buffer. - * - * This is called with buffer NULL to compare results after the page limit - * (filter keyword "max") is reached. These results need to be compared to be - * included in the counts. - * - * @param[in] buffer Buffer. NULL to skip writing to buffer. - * @param[in] results Iterator containing first result. - * @param[in] delta_results Iterator containing second result. - * @param[in] task Task associated with report. - * @param[in] notes Whether to include notes. - * @param[in] notes_details If notes, Whether to include details. - * @param[in] overrides Whether to include overrides. - * @param[in] overrides_details If overrides, Whether to include details. - * @param[in] sort_order Whether to sort ascending or descending. - * @param[in] sort_field Field to sort on, or NULL for "type". - * @param[in] changed Whether to include changed results. - * @param[in] gone Whether to include gone results. - * @param[in] new Whether to include new results. - * @param[in] same Whether to include same results. - * @param[in] max_results Value to decrement if result is buffered. - * @param[in] first_result Skip result and decrement if positive. - * @param[in] used 0 if used, 1 if skipped. - * @param[in] would_use 0 if would use (first_result aside), 1 if skipped. - * - * @return Result of comparison. - */ -static compare_results_t -compare_and_buffer_results (GString *buffer, iterator_t *results, - iterator_t *delta_results, task_t task, int notes, - int notes_details, int overrides, - int overrides_details, int sort_order, - const char* sort_field, int changed, int gone, - int new, int same, int *max_results, - int *first_result, int *used, int *would_use) -{ - compare_results_t state; - state = compare_results (results, delta_results, sort_order, sort_field); - *used = 0; - *would_use = 0; - switch (state) - { - case COMPARE_RESULTS_CHANGED: - if (changed) - { - *would_use = 1; - if (*first_result) - { - g_debug (" delta: skip"); - (*first_result)--; - break; - } - *used = 1; - (*max_results)--; - if (buffer) - buffer_results_xml (buffer, - results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "changed", - delta_results, - /* This is the only case that uses 1. */ - 1, /* Whether result is "changed". */ - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - } - break; - - case COMPARE_RESULTS_GONE: - if (gone) - { - *would_use = 1; - if (*first_result) - { - g_debug (" delta: skip"); - (*first_result)--; - break; - } - *used = 1; - (*max_results)--; - if (buffer) - buffer_results_xml (buffer, - results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "gone", - delta_results, - 0, - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - } - break; - - case COMPARE_RESULTS_NEW: - if (new) - { - *would_use = 1; - if (*first_result) - { - g_debug (" delta: skip"); - (*first_result)--; - break; - } - *used = 1; - (*max_results)--; - if (buffer) - buffer_results_xml (buffer, - delta_results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "new", - delta_results, - 0, - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - } - break; - - case COMPARE_RESULTS_SAME: - if (same) - { - *would_use = 1; - if (*first_result) - { - g_debug (" delta: skip"); - (*first_result)--; - break; - } - *used = 1; - (*max_results)--; - if (buffer) - buffer_results_xml (buffer, - results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "same", - delta_results, - 0, - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - } - break; - - default: - return COMPARE_RESULTS_ERROR; - } - - return state; -} - /** * @brief Write XML to a file or close stream and return. * @@ -27839,7 +28076,7 @@ print_report_host_details_xml (report_host_t report_host, FILE *stream, * @return 0 on success, -1 error. */ static int -print_report_host_tls_certificates_xml (report_host_t report_host, +print_report_host_tls_certificates_xml (report_host_t report_host, const char *host_ip, FILE *stream) { @@ -27860,15 +28097,15 @@ print_report_host_tls_certificates_xml (report_host_t report_host, " AND (source_description = 'SSL/TLS Certificate'" " OR source_description = 'SSL Certificate')", report_host); - - while (next (&tls_certs)) + + while (next (&tls_certs)) { const char *certificate_prefixed, *certificate_b64; gsize certificate_size; unsigned char *certificate; const char *scanner_fpr_prefixed, *scanner_fpr; gchar *quoted_scanner_fpr; - char *ssldetails; + char *ssldetails; iterator_t ports; gboolean valid; time_t now; @@ -27931,7 +28168,7 @@ print_report_host_tls_certificates_xml (report_host_t report_host, now = time (NULL); - if((expiration_time >= now || expiration_time == -1) + if((expiration_time >= now || expiration_time == -1) && (activation_time <= now || activation_time == -1)) { valid = TRUE; @@ -27981,7 +28218,7 @@ print_report_host_tls_certificates_xml (report_host_t report_host, g_free (serial); free (hostname); - + init_iterator (&ports, "SELECT value FROM report_host_details" " WHERE report_host = %llu" @@ -27989,7 +28226,7 @@ print_report_host_tls_certificates_xml (report_host_t report_host, " AND value LIKE '%%:%%:%s'", report_host, quoted_scanner_fpr); - + PRINT (stream, ""); while (next (&ports)) @@ -28008,10 +28245,10 @@ print_report_host_tls_certificates_xml (report_host_t report_host, PRINT (stream, ""); PRINT (stream, ""); - + g_free (quoted_scanner_fpr); - cleanup_iterator (&ports); - + cleanup_iterator (&ports); + } cleanup_iterator (&tls_certs); @@ -28389,6 +28626,8 @@ host_summary_append (GString *host_summary_buffer, const char *host, * @param[in] lean Whether to return lean report. * @param[in] host_summary_buffer Host sumary buffer. * @param[in] f_host_ports Hashtable for host ports. + * @param[in] f_host_criticals Hashtable for host criticals. + * Only available if CVSS3_RATINGS is enabled. * @param[in] f_host_holes Hashtable for host holes. * @param[in] f_host_warnings Hashtable for host host warnings. * @param[in] f_host_infos Hashtable for host infos. @@ -28409,6 +28648,9 @@ print_report_host_xml (FILE *stream, int lean, GString *host_summary_buffer, GHashTable *f_host_ports, +#if CVSS3_RATINGS == 1 + GHashTable *f_host_criticals, +#endif GHashTable *f_host_holes, GHashTable *f_host_warnings, GHashTable *f_host_infos, @@ -28444,58 +28686,63 @@ print_report_host_xml (FILE *stream, host_iterator_asset_uuid (hosts)); else if (lean == 0) PRINT (stream, - ""); + ""); - #if COMPLIANCE_REPORTS == 1 - if (strcmp (usage_type, "audit") == 0) - { - int yes_count, no_count, incomplete_count, undefined_count; - - yes_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_compliant, current_host)); - no_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_notcompliant, current_host)); - incomplete_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_incomplete, current_host)); - undefined_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_undefined, current_host)); - - PRINT (stream, - "%s" - "%s" - "%d" - "" - "%d" - "%d" - "%d" - "%d" - "%d" - "" - "%s", - host_iterator_start_time (hosts), - host_iterator_end_time (hosts) - ? host_iterator_end_time (hosts) - : "", - ports_count, - (yes_count + no_count + incomplete_count + undefined_count), - yes_count, - no_count, - incomplete_count, - undefined_count, - report_compliance_from_counts (&yes_count, - &no_count, - &incomplete_count, - &undefined_count)); - } else - #endif + if (strcmp (usage_type, "audit") == 0) + { + int yes_count, no_count, incomplete_count, undefined_count; + + yes_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_compliant, current_host)); + no_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_notcompliant, current_host)); + incomplete_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_incomplete, current_host)); + undefined_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_undefined, current_host)); + + PRINT (stream, + "%s" + "%s" + "%d" + "" + "%d" + "%d" + "%d" + "%d" + "%d" + "" + "%s", + host_iterator_start_time (hosts), + host_iterator_end_time (hosts) + ? host_iterator_end_time (hosts) + : "", + ports_count, + (yes_count + no_count + incomplete_count + undefined_count), + yes_count, + no_count, + incomplete_count, + undefined_count, + report_compliance_from_counts (&yes_count, + &no_count, + &incomplete_count, + &undefined_count)); + } + else { int holes_count, warnings_count, infos_count; int logs_count, false_positives_count; + int criticals_count = 0; +#if CVSS3_RATINGS == 1 + criticals_count + = GPOINTER_TO_INT + (g_hash_table_lookup ( f_host_criticals, current_host)); +#endif holes_count = GPOINTER_TO_INT (g_hash_table_lookup ( f_host_holes, current_host)); @@ -28511,7 +28758,7 @@ print_report_host_xml (FILE *stream, false_positives_count = GPOINTER_TO_INT (g_hash_table_lookup ( f_host_false_positives, - current_host)); + current_host)); PRINT (stream, "%s" @@ -28519,9 +28766,15 @@ print_report_host_xml (FILE *stream, "%d" "" "%d" - "%d" - "%d" - "%d" +#if CVSS3_RATINGS == 1 + "%d" +#endif + "%d" + "%d" + "%d" + "%d" + "%d" + "%d" "%d" "%d" "", @@ -28530,11 +28783,17 @@ print_report_host_xml (FILE *stream, ? host_iterator_end_time (hosts) : "", ports_count, - (holes_count + warnings_count + infos_count + (criticals_count + holes_count + warnings_count + infos_count + logs_count + false_positives_count), +#if CVSS3_RATINGS == 1 + criticals_count, +#endif holes_count, + holes_count, + warnings_count, warnings_count, infos_count, + infos_count, logs_count, false_positives_count); } @@ -28552,12 +28811,11 @@ print_report_host_xml (FILE *stream, } /** - * @brief Init delta iterators for print_report_xml. + * @brief Init delta iterator for print_report_xml. * * @param[in] report The report. * @param[in] results Report result iterator. * @param[in] delta Delta report. - * @param[in] delta_results Delta report result iterator. * @param[in] get GET command data. * @param[in] term Filter term. * @param[out] sort_field Sort field. @@ -28565,116 +28823,9 @@ print_report_host_xml (FILE *stream, * @return 0 on success, -1 error. */ static int -init_delta_iterators (report_t report, iterator_t *results, report_t delta, - iterator_t *delta_results, const get_data_t *get, - const char *term, const char *sort_field) -{ - int res; - gchar *order; - get_data_t delta_get; - - /* - * Order must be the same as in result_cmp, except for description - * which isn't checked there. - */ - if ((strcmp (sort_field, "name") == 0) - || (strcmp (sort_field, "vulnerability") == 0)) - order = g_strdup (", host, port, severity, nvt, description"); - else if (strcmp (sort_field, "host") == 0) - order = g_strdup (", port, severity, nvt, description"); - else if ((strcmp (sort_field, "port") == 0) - || (strcmp (sort_field, "location") == 0)) - order = g_strdup (", host, severity, nvt, description"); - else if (strcmp (sort_field, "severity") == 0) - order = g_strdup (", host, port, nvt, description"); - else if (strcmp (sort_field, "nvt") == 0) - order = g_strdup (", host, port, severity, description"); - else - order = g_strdup (", host, port, severity, nvt, description"); - - delta_get = *get; - delta_get.filt_id = NULL; - delta_get.filter = g_strdup_printf ("rows=-1 first=1 sort=%s %s", - sort_field, term); - ignore_max_rows_per_page = 1; - -#if 0 - /* For debugging. */ - - iterator_t results2; - - res = init_result_get_iterator (results, &delta_get, report, NULL, order); - if (res) - return -1; - - res = init_result_get_iterator (&results2, &delta_get, delta, NULL, order); - if (res) - return -1; - - g_debug (" delta: %s: REPORT 1:", __func__); - while (next (results)) - g_debug (" delta: %s: %s %s %s %s %.30s", - __func__, - result_iterator_nvt_name (results), - result_iterator_host (results), - result_iterator_type (results), - result_iterator_port (results), - result_iterator_descr (results)); - cleanup_iterator (results); - g_debug (" delta: %s: REPORT 1 END", __func__); - - g_debug (" delta: %s: REPORT 2:", __func__); - while (next (&results2)) - g_debug (" delta: %s: %s %s %s %s %.30s", - __func__, - result_iterator_nvt_name (&results2), - result_iterator_host (&results2), - result_iterator_type (&results2), - result_iterator_port (&results2), - result_iterator_descr (&results2)); - cleanup_iterator (&results2); - g_debug (" delta: %s: REPORT 2 END", __func__); -#endif - - res = init_result_get_iterator (results, &delta_get, report, NULL, order); - if (res) - { - ignore_max_rows_per_page = 0; - g_free (order); - return -1; - } - - res = init_result_get_iterator (delta_results, &delta_get, delta, NULL, order); - if (res) - { - ignore_max_rows_per_page = 0; - g_free (order); - return -1; - } - - g_free (delta_get.filter); - ignore_max_rows_per_page = 0; - g_free (order); - - return 0; -} - -/** - * @brief Init v2 delta iterator for print_report_xml. - * - * @param[in] report The report. - * @param[in] results Report result iterator. - * @param[in] delta Delta report. - * @param[in] get GET command data. - * @param[in] term Filter term. - * @param[out] sort_field Sort field. - * - * @return 0 on success, -1 error. - */ -static int -init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, - const get_data_t *get, const char *term, - const char *sort_field) +init_delta_iterator (report_t report, iterator_t *results, report_t delta, + const get_data_t *get, const char *term, + const char *sort_field) { int ret; static const char *filter_columns[] = RESULT_ITERATOR_FILTER_COLUMNS; @@ -28729,7 +28880,7 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, " ON results.nvt = nvts.oid %s," " LATERAL %s AS lateral_new_severity", opts_tables, - lateral_clause); + lateral_clause); g_free (lateral_clause); @@ -28753,24 +28904,24 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, extra_with = g_strdup_printf(" comparison AS (" " WITH r1a as (SELECT results.id, description, host, report, port," - " severity, nvt, results.qod, results.uuid, hostname," + " severity, nvt, results.qod, results.uuid, hostname," " path, r1_lateral.new_severity as new_severity " " FROM results " " LEFT JOIN (SELECT cvss_base, oid AS nvts_oid FROM nvts)" " AS nvts_cols" " ON nvts_cols.nvts_oid = results.nvt" - " %s, LATERAL %s AS r1_lateral" + " %s, LATERAL %s AS r1_lateral" " WHERE report = %llu)," - " r2a as (SELECT results.*, r2_lateral.new_severity AS new_severity" - " FROM results" + " r2a as (SELECT results.*, r2_lateral.new_severity AS new_severity" + " FROM results" " LEFT JOIN (SELECT cvss_base, oid AS nvts_oid FROM nvts)" - " AS nvts_cols" - " ON nvts_cols.nvts_oid = results.nvt" - " %s, LATERAL %s AS r2_lateral" + " AS nvts_cols" + " ON nvts_cols.nvts_oid = results.nvt" + " %s, LATERAL %s AS r2_lateral" " WHERE report = %llu)," " r1 as (SELECT DISTINCT ON (r1a.id) r1a.*, r2a.id as r2id, row_number() over w1 as r1_rank" " FROM r1a LEFT JOIN r2a ON r1a.host = r2a.host" - " AND normalize_port(r1a.port) = normalize_port(r2a.port)" + " AND normalize_port(r1a.port) = normalize_port(r2a.port)" " AND r1a.nvt = r2a.nvt " " AND (r1a.new_severity = 0) = (r2a.new_severity = 0)" " AND (r1a.description = r2a.description)" @@ -28779,15 +28930,15 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, " ORDER BY r1a.id)," " r2 as (SELECT DISTINCT ON (r2a.id) r2a.*, r1a.id as r1id, row_number() over w2 as r2_rank" " FROM r2a LEFT JOIN r1a ON r2a.host = r1a.host" - " AND normalize_port(r2a.port) = normalize_port(r1a.port)" + " AND normalize_port(r2a.port) = normalize_port(r1a.port)" " AND r2a.nvt = r1a.nvt " " AND (r2a.new_severity = 0) = (r1a.new_severity = 0)" " AND (r2a.description = r1a.description)" " WINDOW w2 AS (PARTITION BY r2a.host, normalize_port(r2a.port)," " r2a.nvt, r2a.new_severity = 0, r1a.id is null ORDER BY r1a.id)" " ORDER BY r2a.id)" - " (SELECT r1.id AS result1_id," - " r2.id AS result2_id," + " (SELECT r1.id AS result1_id," + " r2.id AS result2_id," " compare_results(" " r1.description," " r2.description," @@ -28811,13 +28962,13 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, " r2.owner AS delta_owner," " r2.path AS delta_path," " r2.host AS delta_host," - RESULT_HOSTNAME_SQL("r2.hostname", "r2.host", "r2.report") + RESULT_HOSTNAME_SQL("r2.hostname", "r2.host", "r2.report") " AS delta_hostname," " r2.nvt_version AS delta_nvt_version" " FROM r1" " FULL OUTER JOIN r2" " ON r1.host = r2.host" - " AND normalize_port(r1.port) = normalize_port(r2.port)" + " AND normalize_port(r1.port) = normalize_port(r2.port)" " AND r1.nvt = r2.nvt " " AND (r1.new_severity = 0) = (r2.new_severity = 0)" " AND ((r1id IS NULL AND r2id IS NULL) OR" @@ -28867,7 +29018,6 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, * * @param[in] out File stream to write to. * @param[in] results Report result iterator. - * @param[in] delta_results Delta report result iterator. * @param[in] delta_states String describing delta states to include in count * (for example, "sngc" Same, New, Gone and Changed). * All levels if NULL. @@ -28883,746 +29033,31 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, * @param[in] result_hosts_only Whether to only include hosts with results. * @param[in] orig_filtered_result_count Result count. * @param[in] filtered_result_count Result count. - * @param[in] orig_f_holes Result count. - * @param[in] f_holes Result count. - * @param[in] orig_f_infos Result count. - * @param[in] f_infos Result count. - * @param[in] orig_f_logs Result count. - * @param[in] f_logs Result count. - * @param[in] orig_f_warnings Result count. - * @param[in] f_warnings Result count. - * @param[in] orig_f_false_positives Result count. - * @param[in] f_false_positives Result count. - * @param[in] result_hosts Result hosts. + * @param[in] orig_f_criticals Result count. + * Only available if CVSS3_RATINGS is enabled. + * @param[in] f_criticals Result count. + * Only available if CVSS3_RATINGS is enabled. + * @param[in] orig_f_infos Result count. + * @param[in] f_holes Result count. + * @param[in] orig_f_infos Result count. + * @param[in] f_infos Result count. + * @param[in] orig_f_logs Result count. + * @param[in] f_logs Result count. + * @param[in] orig_f_warnings Result count. + * @param[in] f_warnings Result count. + * @param[in] orig_f_false_positives Result count. + * @param[in] f_false_positives Result count. + * @param[in] f_compliance_yes filtered compliant count. + * @param[in] f_compliance_no filtered incompliant count. + * @param[in] f_compliance_incomplete filtered incomplete count. + * @param[in] f_compliance_undefined filtered undefined count. + * @param[in] f_compliance_count total filtered compliance count. + * @param[in] result_hosts Result hosts. * * @return 0 on success, -1 error. */ static int print_report_delta_xml (FILE *out, iterator_t *results, - iterator_t *delta_results, const char *delta_states, - int first_result, int max_results, task_t task, - int notes, int notes_details, int overrides, - int overrides_details, int sort_order, - const char *sort_field, int result_hosts_only, - int *orig_filtered_result_count, - int *filtered_result_count, - int *orig_f_holes, int *f_holes, - int *orig_f_infos, int *f_infos, - int *orig_f_logs, int *f_logs, - int *orig_f_warnings, int *f_warnings, - int *orig_f_false_positives, int *f_false_positives, - array_t *result_hosts) -{ - gboolean done, delta_done; - int changed, gone, new, same; - /* A tree of host, tree pairs, where the inner tree is a sorted tree - * of port, threat pairs. */ - GTree *ports; - gchar *msg; - - *orig_f_holes = *f_holes; - *orig_f_infos = *f_infos; - *orig_f_logs = *f_logs; - *orig_f_warnings = *f_warnings; - *orig_f_false_positives = *f_false_positives; - *orig_filtered_result_count = *filtered_result_count; - - changed = (strchr (delta_states, 'c') != NULL); - gone = (strchr (delta_states, 'g') != NULL); - new = (strchr (delta_states, 'n') != NULL); - same = (strchr (delta_states, 's') != NULL); - - ports = g_tree_new_full ((GCompareDataFunc) strcmp, NULL, g_free, - (GDestroyNotify) free_host_ports); - - /* Compare the results in the two iterators, which are sorted. */ - - g_debug (" delta: %s: start", __func__); - g_debug (" delta: %s: sort_field: %s", __func__, sort_field); - g_debug (" delta: %s: sort_order: %i", __func__, sort_order); - g_debug (" delta: %s: max_results: %i", __func__, max_results); - done = !next (results); - delta_done = !next (delta_results); - while (1) - { - GString *buffer; - compare_results_t state; - int used, would_use; - - if (max_results == 0) - break; - - if (done) - { - if (delta_done) - break; - if (new) - /* Extra results in 'delta_results'. */ - do - { - const char *level; - - g_debug (" delta: %s: extra from report 2: %s", - __func__, - result_iterator_nvt_oid (results)); - - if (first_result) - { - g_debug (" delta: skip"); - first_result--; - continue; - } - - /* Increase the result count. */ - level = result_iterator_level (delta_results); - (*orig_filtered_result_count)++; - (*filtered_result_count)++; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)++; - (*f_holes)++; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)++; - (*f_warnings)++; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)++; - (*f_infos)++; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)++; - (*f_logs)++; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)++; - (*f_false_positives)++; - } - - g_debug (" delta: %s: extra from report 2: %s", - __func__, - result_iterator_nvt_oid (delta_results)); - buffer = g_string_new (""); - buffer_results_xml (buffer, - delta_results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "new", - NULL, - 0, - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - if (fprintf (out, "%s", buffer->str) < 0) - return -1; - g_string_free (buffer, TRUE); - if (result_hosts_only) - array_add_new_string (result_hosts, - result_iterator_host (delta_results)); - add_port (ports, delta_results); - max_results--; - if (max_results == 0) - break; - } - while (next (delta_results)); - delta_done = TRUE; - break; - } - - if (delta_done) - { - /* Extra results in 'results'. */ - if (gone) - do - { - g_debug (" delta: %s: extra from report 1: %s", - __func__, - result_iterator_nvt_oid (results)); - if (first_result) - { - g_debug (" delta: skip"); - first_result--; - continue; - } - buffer = g_string_new (""); - buffer_results_xml (buffer, - results, - task, - notes, - notes_details, - overrides, - overrides_details, - 0, - 0, - 0, - "gone", - NULL, - 0, - -1, - 0, /* Lean. */ - 0); /* Delta fields. */ - if (fprintf (out, "%s", buffer->str) < 0) - return -1; - g_string_free (buffer, TRUE); - if (result_hosts_only) - array_add_new_string (result_hosts, - result_iterator_host (results)); - add_port (ports, results); - max_results--; - if (max_results == 0) - break; - } - while (next (results)); - else - do - { - const char *level; - - /* Decrease the result count. */ - level = result_iterator_level (results); - (*orig_filtered_result_count)--; - (*filtered_result_count)--; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)--; - (*f_holes)--; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)--; - (*f_warnings)--; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)--; - (*f_infos)--; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)--; - (*f_logs)--; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)--; - (*f_false_positives)--; - } - } - while (next (results)); - done = TRUE; - break; - } - - /* Compare the two results. */ - - buffer = g_string_new (""); - state = compare_and_buffer_results (buffer, - results, - delta_results, - task, - notes, - notes_details, - overrides, - overrides_details, - sort_order, - sort_field, - changed, - gone, - new, - same, - &max_results, - &first_result, - &used, - &would_use); - if (state == COMPARE_RESULTS_ERROR) - { - g_warning ("%s: compare_and_buffer_results failed", - __func__); - return -1; - } - if (fprintf (out, "%s", buffer->str) < 0) - return -1; - g_string_free (buffer, TRUE); - - if ((used == 0) - && ((state == COMPARE_RESULTS_GONE) - || (state == COMPARE_RESULTS_SAME) - || (state == COMPARE_RESULTS_CHANGED))) - { - const char *level; - - /* Decrease the result count. */ - level = result_iterator_level (results); - (*filtered_result_count)--; - if (strcmp (level, "High") == 0) - { - (*f_holes)--; - } - else if (strcmp (level, "Medium") == 0) - { - (*f_warnings)--; - } - else if (strcmp (level, "Low") == 0) - { - (*f_infos)--; - } - else if (strcmp (level, "Log") == 0) - { - (*f_logs)--; - } - else if (strcmp (level, "False Positive") == 0) - { - (*f_false_positives)--; - } - } - - if ((would_use == 0) - && ((state == COMPARE_RESULTS_GONE) - || (state == COMPARE_RESULTS_SAME) - || (state == COMPARE_RESULTS_CHANGED))) - { - const char *level; - - /* Decrease the result count. */ - level = result_iterator_level (results); - (*orig_filtered_result_count)--; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)--; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)--; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)--; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)--; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)--; - } - } - - /* Move on to the next. */ - - if (state == COMPARE_RESULTS_GONE) - { - /* "Used" just the 'results' result. */ - if (used) - { - if (result_hosts_only) - array_add_new_string (result_hosts, - result_iterator_host (results)); - add_port (ports, results); - } - done = !next (results); - } - else if ((state == COMPARE_RESULTS_SAME) - || (state == COMPARE_RESULTS_CHANGED)) - { - /* "Used" both results. */ - if (used) - { - if (result_hosts_only) - array_add_new_string (result_hosts, - result_iterator_host (results)); - add_port (ports, results); - } - done = !next (results); - delta_done = !next (delta_results); - } - else if (state == COMPARE_RESULTS_NEW) - { - if (would_use) - { - const char *level; - - /* Would have "used" just the 'delta_results' result, on - * an earlier page. */ - - /* Increase the result count. */ - level = result_iterator_level (delta_results); - (*orig_filtered_result_count)++; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)++; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)++; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)++; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)++; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)++; - } - } - - if (used) - { - const char *level; - - /* "Used" just the 'delta_results' result. */ - - /* Increase the result count. */ - level = result_iterator_level (delta_results); - (*filtered_result_count)++; - if (strcmp (level, "High") == 0) - { - (*f_holes)++; - } - else if (strcmp (level, "Medium") == 0) - { - (*f_warnings)++; - } - else if (strcmp (level, "Low") == 0) - { - (*f_infos)++; - } - else if (strcmp (level, "Log") == 0) - { - (*f_logs)++; - } - else if (strcmp (level, "False Positive") == 0) - { - (*f_false_positives)++; - } - - if (result_hosts_only) - array_add_new_string (result_hosts, - result_iterator_host - (delta_results)); - - add_port (ports, delta_results); - } - delta_done = !next (delta_results); - } - else - assert (0); - } - - /* Compare remaining results, for the filtered report counts. */ - - g_debug (" delta: %s: counting rest", __func__); - while (1) - { - compare_results_t state; - int used, would_use; - - if (done) - { - if (delta_done) - break; - if (new) - /* Extra results in 'delta_results'. */ - do - { - const char *level; - - g_debug (" delta: %s: extra from report 2: %s", - __func__, - result_iterator_nvt_oid (delta_results)); - - /* Increase the result count. */ - level = result_iterator_level (delta_results); - (*orig_filtered_result_count)++; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)++; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)++; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)++; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)++; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)++; - } - } - while (next (delta_results)); - break; - } - - if (delta_done) - { - /* Extra results in 'results'. */ - if (gone) - do - { - g_debug (" delta: %s: extra from report 1: %s", - __func__, - result_iterator_nvt_oid (results)); - - /* It's in the count already. */ - } - while (next (results)); - else - do - { - const char *level; - - /* Decrease the result count. */ - level = result_iterator_level (results); - (*orig_filtered_result_count)--; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)--; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)--; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)--; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)--; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)--; - } - } - while (next (results)); - break; - } - - /* Compare the two results. */ - - state = compare_and_buffer_results (NULL, - results, - delta_results, - task, - notes, - notes_details, - overrides, - overrides_details, - sort_order, - sort_field, - changed, - gone, - new, - same, - &max_results, - &first_result, - &used, - &would_use); - if (state == COMPARE_RESULTS_ERROR) - { - g_warning ("%s: compare_and_buffer_results failed", - __func__); - return -1; - } - - if (state == COMPARE_RESULTS_NEW) - { - if (used) - { - const char *level; - - /* "Used" just the 'delta_results' result. */ - - /* Increase the result count. */ - level = result_iterator_level (delta_results); - (*orig_filtered_result_count)++; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)++; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)++; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)++; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)++; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)++; - } - } - } - else if (used) - { - /* It's in the count already. */ - } - else - { - const char *level; - - /* Decrease the result count. */ - level = result_iterator_level (results); - (*orig_filtered_result_count)--; - if (strcmp (level, "High") == 0) - { - (*orig_f_holes)--; - } - else if (strcmp (level, "Medium") == 0) - { - (*orig_f_warnings)--; - } - else if (strcmp (level, "Low") == 0) - { - (*orig_f_infos)--; - } - else if (strcmp (level, "Log") == 0) - { - (*orig_f_logs)--; - } - else if (strcmp (level, "False Positive") == 0) - { - (*orig_f_false_positives)--; - } - } - - /* Move on to the next. */ - - if (state == COMPARE_RESULTS_GONE) - { - /* "Used" just the 'results' result. */ - done = !next (results); - } - else if ((state == COMPARE_RESULTS_SAME) - || (state == COMPARE_RESULTS_CHANGED)) - { - /* "Used" both results. */ - done = !next (results); - delta_done = !next (delta_results); - } - else if (state == COMPARE_RESULTS_NEW) - { - /* "Used" just the 'delta_results' result. */ - delta_done = !next (delta_results); - } - else - assert (0); - } - msg = g_markup_printf_escaped (""); - if (fprintf (out, "%s", msg) < 0) - { - g_free (msg); - fclose (out); - return -1; - } - g_free (msg); - - /* Write ports to file. */ - - msg = g_markup_printf_escaped ("", - /* Add 1 for 1 indexing. */ - first_result + 1, - max_results); - if (fprintf (out, "%s", msg) < 0) - { - g_free (msg); - fclose (out); - return -1; - } - g_free (msg); - if (sort_field == NULL || strcmp (sort_field, "port")) - { - if (sort_order) - g_tree_foreach (ports, print_host_ports_by_severity_asc, out); - else - g_tree_foreach (ports, print_host_ports_by_severity_desc, out); - } - else if (sort_order) - g_tree_foreach (ports, print_host_ports, out); - else - g_tree_foreach (ports, print_host_ports_desc, out); - g_tree_destroy (ports); - msg = g_markup_printf_escaped (""); - if (fprintf (out, "%s", msg) < 0) - { - g_free (msg); - fclose (out); - return -1; - } - g_free (msg); - - return 0; -} - -/** - * @brief Print v2 delta results for print_report_xml. - * - * @param[in] out File stream to write to. - * @param[in] results Report result iterator. - * @param[in] delta_states String describing delta states to include in count - * (for example, "sngc" Same, New, Gone and Changed). - * All levels if NULL. - * @param[in] first_result First result. - * @param[in] max_results Max results. - * @param[in] task The task. - * @param[in] notes Whether to include notes. - * @param[in] notes_details Whether to include note details. - * @param[in] overrides Whether to include overrides. - * @param[in] overrides_details Whether to include override details. - * @param[in] sort_order Sort order. - * @param[in] sort_field Sort field. - * @param[in] result_hosts_only Whether to only include hosts with results. - * @param[in] orig_filtered_result_count Result count. - * @param[in] filtered_result_count Result count. - * @param[in] orig_f_holes Result count. - * @param[in] f_holes Result count. - * @param[in] orig_f_infos Result count. - * @param[in] f_infos Result count. - * @param[in] orig_f_logs Result count. - * @param[in] f_logs Result count. - * @param[in] orig_f_warnings Result count. - * @param[in] f_warnings Result count. - * @param[in] orig_f_false_positives Result count. - * @param[in] f_false_positives Result count. - * @param[in] f_compliance_yes filtered compliant count. - * @param[in] f_compliance_no filtered incompliant count. - * @param[in] f_compliance_incomplete filtered incomplete count. - * @param[in] f_compliance_undefined filtered undefined count. - * @param[in] f_compliance_count total filtered compliance count. - * @param[in] result_hosts Result hosts. - * - * @return 0 on success, -1 error. - */ -static int -print_v2_report_delta_xml (FILE *out, iterator_t *results, const char *delta_states, int first_result, int max_results, task_t task, int notes, int notes_details, int overrides, @@ -29630,20 +29065,25 @@ print_v2_report_delta_xml (FILE *out, iterator_t *results, const char *sort_field, int result_hosts_only, int *orig_filtered_result_count, int *filtered_result_count, +#if CVSS3_RATINGS == 1 + int *orig_f_criticals, int *f_criticals, +#endif int *orig_f_holes, int *f_holes, int *orig_f_infos, int *f_infos, int *orig_f_logs, int *f_logs, int *orig_f_warnings, int *f_warnings, int *orig_f_false_positives, int *f_false_positives, int *f_compliance_yes, int *f_compliance_no, - int *f_compliance_incomplete, + int *f_compliance_incomplete, int *f_compliance_undefined, int *f_compliance_count, array_t *result_hosts) { GString *buffer = g_string_new (""); GTree *ports; - *orig_f_holes = *f_holes; +#if CVSS3_RATINGS == 1 + *orig_f_criticals = *f_criticals; +#endif *orig_f_infos = *f_infos; *orig_f_logs = *f_logs; *orig_f_warnings = *f_warnings; @@ -29663,36 +29103,42 @@ print_v2_report_delta_xml (FILE *out, iterator_t *results, if (strchr (delta_states, state[0]) == NULL) continue; - #if COMPLIANCE_REPORTS == 1 - if (strcmp (usage_type, "audit") == 0) - { - const char* compliance; - compliance = result_iterator_compliance (results); - (*f_compliance_count)++; - if (strcasecmp (compliance, "yes") == 0) - { - (*f_compliance_yes)++; - } - else if (strcasecmp (compliance, "no") == 0) - { - (*f_compliance_no)++; - } - else if (strcasecmp (compliance, "incomplete") == 0) - { - (*f_compliance_incomplete)++; - } - else if (strcasecmp (compliance, "undefined") == 0) - { - (*f_compliance_undefined)++; - } - } else - #endif + if (strcmp (usage_type, "audit") == 0) + { + const char* compliance; + compliance = result_iterator_compliance (results); + (*f_compliance_count)++; + if (strcasecmp (compliance, "yes") == 0) + { + (*f_compliance_yes)++; + } + else if (strcasecmp (compliance, "no") == 0) + { + (*f_compliance_no)++; + } + else if (strcasecmp (compliance, "incomplete") == 0) + { + (*f_compliance_incomplete)++; + } + else if (strcasecmp (compliance, "undefined") == 0) + { + (*f_compliance_undefined)++; + } + } + else { const char *level; /* Increase the result count. */ level = result_iterator_level (results); (*orig_filtered_result_count)++; (*filtered_result_count)++; +#if CVSS3_RATINGS == 1 + if (strcmp (level, "Critical") == 0) + { + (*orig_f_criticals)++; + (*f_criticals)++; + } +#endif if (strcmp (level, "High") == 0) { (*orig_f_holes)++; @@ -29732,12 +29178,12 @@ print_v2_report_delta_xml (FILE *out, iterator_t *results, 0, state, NULL, - (strcmp (state, "changed") == 0), + (strcmp (state, "changed") == 0), -1, 0, /* Lean. */ 0); /* Delta fields. */ - - if (fprintf (out, "%s", buffer->str) < 0) + + if (fprintf (out, "%s", buffer->str) < 0) { g_string_free (buffer, TRUE); g_tree_destroy (ports); @@ -29751,7 +29197,7 @@ print_v2_report_delta_xml (FILE *out, iterator_t *results, } g_string_free (buffer, TRUE); g_free (usage_type); - + if (fprintf (out, "") < 0) { g_tree_destroy (ports); @@ -29834,9 +29280,9 @@ print_report_xml_start (report_t report, report_t delta, task_t task, array_t *result_hosts; int reuse_result_iterator; iterator_t results, delta_results; - int holes, infos, logs, warnings, false_positives; - int f_holes, f_infos, f_logs, f_warnings, f_false_positives; - int orig_f_holes, orig_f_infos, orig_f_logs; + int criticals = 0, holes, infos, logs, warnings, false_positives; + int f_criticals = 0, f_holes, f_infos, f_logs, f_warnings, f_false_positives; + int orig_f_criticals, orig_f_holes, orig_f_infos, orig_f_logs; int orig_f_warnings, orig_f_false_positives, orig_filtered_result_count; int search_phrase_exact, apply_overrides, count_filtered; double severity, f_severity; @@ -29849,14 +29295,15 @@ print_report_xml_start (report_t report, report_t delta, task_t task, GHashTable *f_host_logs, *f_host_false_positives; GHashTable *f_host_compliant, *f_host_notcompliant; GHashTable *f_host_incomplete, *f_host_undefined; + #if CVSS3_RATINGS == 1 + GHashTable *f_host_criticals = NULL; + #endif task_status_t run_status; gchar *tsk_usage_type = NULL; int f_compliance_yes, f_compliance_no; int f_compliance_incomplete, f_compliance_undefined; int f_compliance_count; - int delta_reports_version = 0; - /* Init some vars to prevent warnings from older compilers. */ max_results = -1; levels = NULL; @@ -29869,7 +29316,7 @@ print_report_xml_start (report_t report, report_t delta, task_t task, f_compliance_count = 0; orig_filtered_result_count = 0; orig_f_false_positives = orig_f_warnings = orig_f_logs = orig_f_infos = 0; - orig_f_holes = 0; + orig_f_holes = orig_f_criticals = 0; f_host_ports = NULL; f_host_holes = NULL; f_host_warnings = NULL; @@ -29931,8 +29378,8 @@ print_report_xml_start (report_t report, report_t delta, task_t task, &first_result, &max_results, &sort_field, &sort_order, &result_hosts_only, &min_qod, &levels, &compliance_levels, - &delta_states, &search_phrase, - &search_phrase_exact, ¬es, + &delta_states, &search_phrase, + &search_phrase_exact, ¬es, &overrides, &apply_overrides, &zone); } else @@ -29943,19 +29390,18 @@ print_report_xml_start (report_t report, report_t delta, task_t task, &first_result, &max_results, &sort_field, &sort_order, &result_hosts_only, &min_qod, &levels, &compliance_levels, - &delta_states, &search_phrase, + &delta_states, &search_phrase, &search_phrase_exact, ¬es, &overrides, &apply_overrides, &zone); } - if (delta) { - delta_reports_version = setting_delta_reports_version_int (); - g_debug ("%s: delta reports version %d", __func__, delta_reports_version); - } - max_results = manage_max_rows (max_results); + #if CVSS3_RATINGS == 1 + levels = levels ? levels : g_strdup ("chmlgdf"); + #else levels = levels ? levels : g_strdup ("hmlgdf"); + #endif if (task && (task_uuid (task, &tsk_uuid) || task_usage_type(task, &tsk_usage_type))) { @@ -30062,28 +29508,32 @@ print_report_xml_start (report_t report, report_t delta, task_t task, ""); } - count_filtered = (delta == 0 && ignore_pagination && get->details) - || (delta_reports_version == 2); + count_filtered = (delta || (ignore_pagination && get->details)); if (report) { /* Get total counts of full results. */ - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit")) - #endif + if (strcmp (tsk_usage_type, "audit")) { if (delta == 0) - { - int total_holes, total_infos, total_logs; + { + int total_criticals = 0, total_holes, total_infos, total_logs; int total_warnings, total_false_positives; get_data_t *all_results_get; all_results_get = report_results_get_data (1, -1, 0, 0); +#if CVSS3_RATINGS == 1 + report_counts_id (report, &total_criticals, &total_holes, + &total_infos, &total_logs, &total_warnings, + &total_false_positives, NULL, all_results_get, + NULL); +#else report_counts_id (report, &total_holes, &total_infos, &total_logs, &total_warnings, &total_false_positives, NULL, all_results_get, NULL); - total_result_count = total_holes + total_infos +#endif + total_result_count = total_criticals + total_holes + total_infos + total_logs + total_warnings + total_false_positives; get_data_reset (all_results_get); @@ -30103,13 +29553,18 @@ print_report_xml_start (report_t report, report_t delta, task_t task, { /* Beware, we're using the full variables temporarily here, but * report_counts_id counts the filtered results. */ +#if CVSS3_RATINGS == 1 + report_counts_id (report, &criticals, &holes, &infos, &logs, &warnings, + &false_positives, NULL, get, NULL); +#else report_counts_id (report, &holes, &infos, &logs, &warnings, &false_positives, NULL, get, NULL); +#endif - filtered_result_count = holes + infos + logs + warnings + filtered_result_count = criticals + holes + infos + logs + warnings + false_positives; - } + } } /* Get report run status. */ @@ -30147,56 +29602,6 @@ print_report_xml_start (report_t report, report_t delta, task_t task, g_free (term); term = clean; - if (delta - && sort_field - && (delta_reports_version == 1) - /* These are all checked in result_cmp. */ - && strcmp (sort_field, "name") - && strcmp (sort_field, "vulnerability") - && strcmp (sort_field, "host") - && strcmp (sort_field, "port") - && strcmp (sort_field, "location") - && strcmp (sort_field, "severity") - && strcmp (sort_field, "nvt") - && strcmp (sort_field, "description") - && strcmp (sort_field, "type") - && strcmp (sort_field, "original_type")) - { - gchar *new_term; - - if ((strcmp (sort_field, "task") == 0) - || (strcmp (sort_field, "task_id") == 0) - || (strcmp (sort_field, "report_id") == 0)) - { - /* These don't affect delta report, so sort by vulnerability. */ - g_free (sort_field); - sort_field = g_strdup ("vulnerability"); - } - else - { - /* The remaining filterable fields for the result iterator, all of - * which may be used as a sort field. These could be added to - * result_cmp. For now sort by vulnerability. */ -#if 0 - "uuid", "comment", "created", "modified", "_owner", - "cvss_base", "nvt_version", "original_severity", "date", - "solution_type", "qod", "qod_type", "cve", "hostname", "path" -#endif - g_free (sort_field); - sort_field = g_strdup ("vulnerability"); - } - - /* Adjust "term" to match sort_field, because "term" will be used in the - * REPORT XML FILTERS (sent by buffer_get_filter_xml below). */ - new_term = g_strdup_printf ("sort=%s %s", - sort_field, - term); - g_free (term); - term = new_term; - /* Similarly, the order will now be ascending. */ - sort_order = 1; - } - if (filter_term_return) *filter_term_return = g_strdup (term); @@ -30208,23 +29613,25 @@ print_report_xml_start (report_t report, report_t delta, task_t task, filters_extra_buffer = g_string_new (""); - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit") == 0) - { - compliance_levels = compliance_levels ? compliance_levels : g_strdup ("yniu"); - - if (strchr (compliance_levels, 'y')) - g_string_append (filters_extra_buffer, "Yes"); - if (strchr (compliance_levels, 'n')) - g_string_append (filters_extra_buffer, "No"); - if (strchr (compliance_levels, 'i')) - g_string_append (filters_extra_buffer, "Incomplete"); - if (strchr (compliance_levels, 'u')) - g_string_append (filters_extra_buffer, "Undefined"); - } - else - #endif + if (strcmp (tsk_usage_type, "audit") == 0) + { + compliance_levels = compliance_levels ? compliance_levels : g_strdup ("yniu"); + + if (strchr (compliance_levels, 'y')) + g_string_append (filters_extra_buffer, "Yes"); + if (strchr (compliance_levels, 'n')) + g_string_append (filters_extra_buffer, "No"); + if (strchr (compliance_levels, 'i')) + g_string_append (filters_extra_buffer, "Incomplete"); + if (strchr (compliance_levels, 'u')) + g_string_append (filters_extra_buffer, "Undefined"); + } + else { +#if CVSS3_RATINGS == 1 + if (strchr (levels, 'c')) + g_string_append (filters_extra_buffer, "Critical"); +#endif if (strchr (levels, 'h')) g_string_append (filters_extra_buffer, "High"); if (strchr (levels, 'm')) @@ -30500,60 +29907,73 @@ print_report_xml_start (report_t report, report_t delta, task_t task, } /* Prepare result counts. */ - #if COMPLIANCE_REPORTS == 1 - int compliance_yes, compliance_no; - int compliance_incomplete, compliance_undefined; - int total_compliance_count = 0; + int compliance_yes, compliance_no; + int compliance_incomplete, compliance_undefined; + int total_compliance_count = 0; - if (strcmp (tsk_usage_type, "audit") == 0) - { - report_compliance_counts (report, get, &compliance_yes, &compliance_no, - &compliance_incomplete, &compliance_undefined); + if (strcmp (tsk_usage_type, "audit") == 0) + { + report_compliance_counts (report, get, &compliance_yes, &compliance_no, + &compliance_incomplete, &compliance_undefined); - total_compliance_count = compliance_yes - + compliance_no - + compliance_incomplete - + compliance_undefined; + total_compliance_count = compliance_yes + + compliance_no + + compliance_incomplete + + compliance_undefined; - f_compliance_yes = f_compliance_no = 0; - f_compliance_incomplete = f_compliance_undefined = 0; + f_compliance_yes = f_compliance_no = 0; + f_compliance_incomplete = f_compliance_undefined = 0; - if (count_filtered == 0) - { - report_compliance_f_counts (report, - get, - &f_compliance_yes, - &f_compliance_no, - &f_compliance_incomplete, - &f_compliance_undefined); + if (count_filtered == 0) + { + report_compliance_f_counts (report, + get, + &f_compliance_yes, + &f_compliance_no, + &f_compliance_incomplete, + &f_compliance_undefined); - f_compliance_count = f_compliance_yes - + f_compliance_no - + f_compliance_incomplete - + f_compliance_undefined; - } - } else - #endif - { + f_compliance_count = f_compliance_yes + + f_compliance_no + + f_compliance_incomplete + + f_compliance_undefined; + } + } + else + { if (count_filtered) { /* We're getting all the filtered results, so we can count them as we * print them, to save time. */ - +#if CVSS3_RATINGS == 1 + report_counts_id_full (report, &criticals, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + get, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL); +#else report_counts_id_full (report, &holes, &infos, &logs, - &warnings, &false_positives, &severity, - get, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + &warnings, &false_positives, &severity, + get, NULL, NULL, NULL, NULL, NULL, + NULL, NULL); +#endif - f_holes = f_infos = f_logs = f_warnings = 0; + f_criticals = f_holes = f_infos = f_logs = f_warnings = 0; f_false_positives = f_severity = 0; } else - report_counts_id_full (report, &holes, &infos, &logs, - &warnings, &false_positives, &severity, - get, NULL, - &f_holes, &f_infos, &f_logs, &f_warnings, - &f_false_positives, &f_severity); - } +#if CVSS3_RATINGS == 1 + report_counts_id_full (report, &criticals, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + get, NULL, + &f_criticals, &f_holes, &f_infos, &f_logs, + &f_warnings, &f_false_positives, &f_severity); +#else + report_counts_id_full (report, &holes, &infos, &logs, + &warnings, &false_positives, &severity, + get, NULL, &f_holes, &f_infos, &f_logs, + &f_warnings, &f_false_positives, &f_severity); +#endif + } /* Results. */ @@ -30562,27 +29982,12 @@ print_report_xml_start (report_t report, report_t delta, task_t task, if (delta && get->details) { - if (delta_reports_version == 1) + if (init_delta_iterator (report, &results, delta, + get, term, sort_field)) { - if (init_delta_iterators (report, &results, delta, - &delta_results, get, - term, sort_field)) - { - g_free (term); - g_hash_table_destroy (f_host_ports); - return -1; - } g_free (term); - } - else - { - if (init_v2_delta_iterator (report, &results, delta, - get, term, sort_field)) - { - g_free (term); - g_hash_table_destroy (f_host_ports); - return -1; - } + g_hash_table_destroy (f_host_ports); + return -1; } } else if (get->details) @@ -30618,80 +30023,84 @@ print_report_xml_start (report_t report, report_t delta, task_t task, /* Quiet erroneous compiler warning. */ result_hosts = NULL; - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit") == 0) - { - f_host_compliant = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - f_host_notcompliant = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - f_host_incomplete = g_hash_table_new_full (g_str_hash, g_str_equal, + if (strcmp (tsk_usage_type, "audit") == 0) + { + f_host_compliant = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_notcompliant = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - f_host_undefined = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - } else - #endif - { - f_host_holes = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - f_host_warnings = g_hash_table_new_full (g_str_hash, g_str_equal, + f_host_incomplete = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_undefined = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + } + else + { +#if CVSS3_RATINGS == 1 + f_host_criticals = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - f_host_infos = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - f_host_logs = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - f_host_false_positives = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - } +#endif + f_host_holes = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_warnings = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_infos = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_logs = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + f_host_false_positives = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + } if (delta && get->details) { - if (delta_reports_version == 1) - { - if (print_report_delta_xml (out, &results, &delta_results, - delta_states, - ignore_pagination ? 0 : first_result, - ignore_pagination ? -1 : max_results, - task, notes, - notes_details, overrides, - overrides_details, sort_order, - sort_field, result_hosts_only, - &orig_filtered_result_count, - &filtered_result_count, - &orig_f_holes, &f_holes, - &orig_f_infos, &f_infos, - &orig_f_logs, &f_logs, - &orig_f_warnings, &f_warnings, - &orig_f_false_positives, - &f_false_positives, - result_hosts)) - goto failed_delta_report; - } - else - { - if (print_v2_report_delta_xml (out, &results, delta_states, - ignore_pagination ? 0 : first_result, - ignore_pagination ? -1 : max_results, - task, notes, - notes_details, overrides, - overrides_details, sort_order, - sort_field, result_hosts_only, - &orig_filtered_result_count, - &filtered_result_count, - &orig_f_holes, &f_holes, - &orig_f_infos, &f_infos, - &orig_f_logs, &f_logs, - &orig_f_warnings, &f_warnings, - &orig_f_false_positives, - &f_false_positives, - &f_compliance_yes, - &f_compliance_no, - &f_compliance_incomplete, - &f_compliance_undefined, - &f_compliance_count, - result_hosts)) - goto failed_delta_report; - } +#if CVSS3_RATINGS == 1 + if (print_report_delta_xml (out, &results, delta_states, + ignore_pagination ? 0 : first_result, + ignore_pagination ? -1 : max_results, + task, notes, + notes_details, overrides, + overrides_details, sort_order, + sort_field, result_hosts_only, + &orig_filtered_result_count, + &filtered_result_count, + &orig_f_criticals, &f_criticals, + &orig_f_holes, &f_holes, + &orig_f_infos, &f_infos, + &orig_f_logs, &f_logs, + &orig_f_warnings, &f_warnings, + &orig_f_false_positives, + &f_false_positives, + &f_compliance_yes, + &f_compliance_no, + &f_compliance_incomplete, + &f_compliance_undefined, + &f_compliance_count, + result_hosts)) +#else + if (print_report_delta_xml (out, &results, delta_states, + ignore_pagination ? 0 : first_result, + ignore_pagination ? -1 : max_results, + task, notes, + notes_details, overrides, + overrides_details, sort_order, + sort_field, result_hosts_only, + &orig_filtered_result_count, + &filtered_result_count, + &orig_f_holes, &f_holes, + &orig_f_infos, &f_infos, + &orig_f_logs, &f_logs, + &orig_f_warnings, &f_warnings, + &orig_f_false_positives, + &f_false_positives, + &f_compliance_yes, + &f_compliance_no, + &f_compliance_incomplete, + &f_compliance_undefined, + &f_compliance_count, + result_hosts)) +#endif + goto failed_delta_report; } else if (get->details) { @@ -30726,244 +30135,278 @@ print_report_xml_start (report_t report, report_t delta, task_t task, array_add_new_string (result_hosts, result_iterator_host (&results)); - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit") == 0) - { - const char* compliance; - compliance = result_iterator_compliance (&results); - - if (strcasecmp (compliance, "yes") == 0) - { - f_host_result_counts = f_host_compliant; - if (count_filtered) - f_compliance_yes++; - } - else if (strcasecmp (compliance, "no") == 0) - { - f_host_result_counts = f_host_notcompliant; - if (count_filtered) - f_compliance_no++; - } - else if (strcasecmp (compliance, "incomplete") == 0) - { - f_host_result_counts = f_host_incomplete; - if (count_filtered) - f_compliance_incomplete++; - } - else if (strcasecmp (compliance, "undefined") == 0) - { - f_host_result_counts = f_host_undefined; - if (count_filtered) - f_compliance_undefined++; - } - else - { - f_host_result_counts = NULL; - } + if (strcmp (tsk_usage_type, "audit") == 0) + { + const char* compliance; + compliance = result_iterator_compliance (&results); - if (f_host_result_counts) - { - const char *result_host = result_iterator_host (&results); - int result_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_result_counts, - result_host)); - - g_hash_table_replace (f_host_result_counts, - g_strdup (result_host), - GINT_TO_POINTER (result_count + 1)); + if (strcasecmp (compliance, "yes") == 0) + { + f_host_result_counts = f_host_compliant; + if (count_filtered) + f_compliance_yes++; + } + else if (strcasecmp (compliance, "no") == 0) + { + f_host_result_counts = f_host_notcompliant; + if (count_filtered) + f_compliance_no++; + } + else if (strcasecmp (compliance, "incomplete") == 0) + { + f_host_result_counts = f_host_incomplete; + if (count_filtered) + f_compliance_incomplete++; + } + else if (strcasecmp (compliance, "undefined") == 0) + { + f_host_result_counts = f_host_undefined; + if (count_filtered) + f_compliance_undefined++; + } + else + { + f_host_result_counts = NULL; } - } else - #endif - { - double result_severity; - result_severity = result_iterator_severity_double (&results); - if (result_severity > f_severity) - f_severity = result_severity; - - level = result_iterator_level (&results); - if (strcasecmp (level, "log") == 0) - { - f_host_result_counts = f_host_logs; - if (count_filtered) - f_logs++; - } - else if (strcasecmp (level, "high") == 0) - { - f_host_result_counts = f_host_holes; - if (count_filtered) - f_holes++; - } - else if (strcasecmp (level, "medium") == 0) - { - f_host_result_counts = f_host_warnings; - if (count_filtered) - f_warnings++; - } - else if (strcasecmp (level, "low") == 0) - { - f_host_result_counts = f_host_infos; - if (count_filtered) - f_infos++; - } - else if (strcasecmp (level, "false positive") == 0) - { - f_host_result_counts = f_host_false_positives; - if (count_filtered) - f_false_positives++; + if (f_host_result_counts) + { + const char *result_host = result_iterator_host (&results); + int result_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_result_counts, + result_host)); + + g_hash_table_replace (f_host_result_counts, + g_strdup (result_host), + GINT_TO_POINTER (result_count + 1)); } - else - f_host_result_counts = NULL; + } + else + { + double result_severity; + result_severity = result_iterator_severity_double (&results); + if (result_severity > f_severity) + f_severity = result_severity; - if (f_host_result_counts) - { - const char *result_host = result_iterator_host (&results); - int result_count - = GPOINTER_TO_INT - (g_hash_table_lookup (f_host_result_counts, result_host)); - - g_hash_table_replace (f_host_result_counts, - g_strdup (result_host), - GINT_TO_POINTER (result_count + 1)); - } - } + level = result_iterator_level (&results); + + if (strcasecmp (level, "log") == 0) + { + f_host_result_counts = f_host_logs; + if (count_filtered) + f_logs++; + } +#if CVSS3_RATINGS == 1 + else if (strcasecmp (level, "critical") == 0) + { + f_host_result_counts = f_host_criticals; + if (count_filtered) + f_criticals++; + } +#endif + else if (strcasecmp (level, "high") == 0) + { + f_host_result_counts = f_host_holes; + if (count_filtered) + f_holes++; + } + else if (strcasecmp (level, "medium") == 0) + { + f_host_result_counts = f_host_warnings; + if (count_filtered) + f_warnings++; + } + else if (strcasecmp (level, "low") == 0) + { + f_host_result_counts = f_host_infos; + if (count_filtered) + f_infos++; + } + else if (strcasecmp (level, "false positive") == 0) + { + f_host_result_counts = f_host_false_positives; + if (count_filtered) + f_false_positives++; + } + else + f_host_result_counts = NULL; + if (f_host_result_counts) + { + const char *result_host = result_iterator_host (&results); + int result_count + = GPOINTER_TO_INT + (g_hash_table_lookup (f_host_result_counts, result_host)); + + g_hash_table_replace (f_host_result_counts, + g_strdup (result_host), + GINT_TO_POINTER (result_count + 1)); + } + } } PRINT (out, ""); } if (get->details) cleanup_iterator (&results); - if (delta && get->details && delta_reports_version == 1) - cleanup_iterator (&delta_results); /* Print result counts and severity. */ - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit") == 0) - { - if (delta) + if (strcmp (tsk_usage_type, "audit") == 0) + { + if (delta) + PRINT (out, + "" + "%i" + "%i" + "%i" + "%i" + "%i" + "", + f_compliance_count, + (strchr (compliance_levels, 'y') ? f_compliance_yes : 0), + (strchr (compliance_levels, 'n') ? f_compliance_no : 0), + (strchr (compliance_levels, 'i') ? f_compliance_incomplete : 0), + (strchr (compliance_levels, 'u') ? f_compliance_undefined : 0)); + else + { + if (count_filtered) + f_compliance_count = f_compliance_yes + + f_compliance_no + + f_compliance_incomplete + + f_compliance_undefined; PRINT (out, - "" - "%i" - "%i" - "%i" - "%i" - "%i" - "", - f_compliance_count, - (strchr (compliance_levels, 'y') ? f_compliance_yes : 0), - (strchr (compliance_levels, 'n') ? f_compliance_no : 0), - (strchr (compliance_levels, 'i') ? f_compliance_incomplete : 0), - (strchr (compliance_levels, 'u') ? f_compliance_undefined : 0)); - else - { - if (count_filtered) - f_compliance_count = f_compliance_yes - + f_compliance_no - + f_compliance_incomplete - + f_compliance_undefined; - PRINT (out, - "" - "%i" - "%i" - "%i" - "%i%i" - "%i%i" - "%i%i" - "%i%i" - "", - total_compliance_count, - total_compliance_count, - f_compliance_count, - compliance_yes, - (strchr (compliance_levels, 'y') ? f_compliance_yes : 0), - compliance_no, - (strchr (compliance_levels, 'n') ? f_compliance_no : 0), - compliance_incomplete, - (strchr (compliance_levels, 'i') ? f_compliance_incomplete : 0), - compliance_undefined, - (strchr (compliance_levels, 'i') ? f_compliance_undefined : 0)); - - PRINT (out, - "" - "%s" - "%s" - "", - report_compliance_from_counts (&compliance_yes, - &compliance_no, - &compliance_incomplete, - &compliance_undefined), - report_compliance_from_counts (&f_compliance_yes, - &f_compliance_no, - &f_compliance_incomplete, - &f_compliance_undefined)); - } - } else - #endif - { - if (delta) - /** @todo The f_holes, etc. vars are setup to give the page count. */ - PRINT (out, - "" - "%i" - "%i" - "%i" - "%i" - "%i" - "" - "%i" - "" - "", - orig_filtered_result_count, - (strchr (levels, 'h') ? orig_f_holes : 0), - (strchr (levels, 'l') ? orig_f_infos : 0), - (strchr (levels, 'g') ? orig_f_logs : 0), - (strchr (levels, 'm') ? orig_f_warnings : 0), - (strchr (levels, 'f') ? orig_f_false_positives : 0)); - else - { - if (count_filtered) - filtered_result_count = f_holes + f_infos + f_logs - + f_warnings + false_positives; + "" + "%i" + "%i" + "%i" + "%i%i" + "%i%i" + "%i%i" + "%i%i" + "", + total_compliance_count, + total_compliance_count, + f_compliance_count, + compliance_yes, + (strchr (compliance_levels, 'y') ? f_compliance_yes : 0), + compliance_no, + (strchr (compliance_levels, 'n') ? f_compliance_no : 0), + compliance_incomplete, + (strchr (compliance_levels, 'i') ? f_compliance_incomplete : 0), + compliance_undefined, + (strchr (compliance_levels, 'i') ? f_compliance_undefined : 0)); + PRINT (out, + "" + "%s" + "%s" + "", + report_compliance_from_counts (&compliance_yes, + &compliance_no, + &compliance_incomplete, + &compliance_undefined), + report_compliance_from_counts (&f_compliance_yes, + &f_compliance_no, + &f_compliance_incomplete, + &f_compliance_undefined)); + } + } + else + { + if (delta) + /** @todo The f_holes, etc. vars are setup to give the page count. */ PRINT (out, "" - "%i" - "%i" "%i" - "%i%i" - "%i%i" - "%i%i" - "%i%i" +#if CVSS3_RATINGS == 1 + "%i" +#endif + "%i" + "%i" + "%i" + "%i" + "%i" + "%i" + "%i" "" - "%i" "%i" "" "", - total_result_count, - total_result_count, - filtered_result_count, - holes, - (strchr (levels, 'h') ? f_holes : 0), - infos, - (strchr (levels, 'l') ? f_infos : 0), - logs, - (strchr (levels, 'g') ? f_logs : 0), - warnings, - (strchr (levels, 'm') ? f_warnings : 0), - false_positives, - (strchr (levels, 'f') ? f_false_positives : 0)); + orig_filtered_result_count, +#if CVSS3_RATINGS == 1 + (strchr (levels, 'c') ? orig_f_criticals : 0), +#endif + (strchr (levels, 'h') ? orig_f_holes : 0), + (strchr (levels, 'h') ? orig_f_holes : 0), + (strchr (levels, 'l') ? orig_f_infos : 0), + (strchr (levels, 'l') ? orig_f_infos : 0), + (strchr (levels, 'g') ? orig_f_logs : 0), + (strchr (levels, 'm') ? orig_f_warnings : 0), + (strchr (levels, 'm') ? orig_f_warnings : 0), + (strchr (levels, 'f') ? orig_f_false_positives : 0)); + else + { + if (count_filtered) + filtered_result_count = f_criticals + f_holes + f_infos + f_logs + + f_warnings + false_positives; - PRINT (out, - "" - "%1.1f" - "%1.1f" - "", - severity, - f_severity); - } - } + PRINT (out, + "" + "%i" + "%i" + "%i" +#if CVSS3_RATINGS == 1 + "" + "%i" + "%i" + "" +#endif + "%i%i" + "%i%i" + "%i%i" + "%i%i" + "%i%i" + "%i%i" + "%i%i" + "" + "%i" + "%i" + "" + "", + total_result_count, + total_result_count, + filtered_result_count, +#if CVSS3_RATINGS == 1 + criticals, + (strchr (levels, 'c') ? f_criticals : 0), +#endif + holes, + (strchr (levels, 'h') ? f_holes : 0), + holes, + (strchr (levels, 'h') ? f_holes : 0), + infos, + (strchr (levels, 'l') ? f_infos : 0), + infos, + (strchr (levels, 'l') ? f_infos : 0), + logs, + (strchr (levels, 'g') ? f_logs : 0), + warnings, + (strchr (levels, 'm') ? f_warnings : 0), + warnings, + (strchr (levels, 'm') ? f_warnings : 0), + false_positives, + (strchr (levels, 'f') ? f_false_positives : 0)); + + PRINT (out, + "" + "%1.1f" + "%1.1f" + "", + severity, + f_severity); + } + } if (host_summary) { @@ -30986,33 +30429,46 @@ print_report_xml_start (report_t report, report_t delta, task_t task, iterator_t hosts; init_report_host_iterator (&hosts, report, result_host, 0); present = next (&hosts); - if (delta && (present == FALSE) && delta_reports_version == 1) - { - cleanup_iterator (&hosts); - init_report_host_iterator (&hosts, delta, result_host, 0); - present = next (&hosts); - } if (present) { - if (print_report_host_xml (out, - &hosts, - result_host, - tsk_usage_type, - lean, - host_summary_buffer, - f_host_ports, - f_host_holes, - f_host_warnings, - f_host_infos, - f_host_logs, - f_host_false_positives, - f_host_compliant, - f_host_notcompliant, - f_host_incomplete, - f_host_undefined)) - +#if CVSS3_RATINGS == 1 + if (print_report_host_xml (out, + &hosts, + result_host, + tsk_usage_type, + lean, + host_summary_buffer, + f_host_ports, + f_host_criticals, + f_host_holes, + f_host_warnings, + f_host_infos, + f_host_logs, + f_host_false_positives, + f_host_compliant, + f_host_notcompliant, + f_host_incomplete, + f_host_undefined)) +#else + if (print_report_host_xml (out, + &hosts, + result_host, + tsk_usage_type, + lean, + host_summary_buffer, + f_host_ports, + f_host_holes, + f_host_warnings, + f_host_infos, + f_host_logs, + f_host_false_positives, + f_host_compliant, + f_host_notcompliant, + f_host_incomplete, + f_host_undefined)) +#endif { - goto failed_print_report_host; + goto failed_print_report_host; } } cleanup_iterator (&hosts); @@ -31024,42 +30480,64 @@ print_report_xml_start (report_t report, report_t delta, task_t task, init_report_host_iterator (&hosts, report, NULL, 0); while (next (&hosts)) { +#if CVSS3_RATINGS == 1 if (print_report_host_xml (out, - &hosts, - NULL, - tsk_usage_type, - lean, - host_summary_buffer, - f_host_ports, - f_host_holes, - f_host_warnings, - f_host_infos, - f_host_logs, - f_host_false_positives, - f_host_compliant, - f_host_notcompliant, - f_host_incomplete, - f_host_undefined)) + &hosts, + NULL, + tsk_usage_type, + lean, + host_summary_buffer, + f_host_ports, + f_host_criticals, + f_host_holes, + f_host_warnings, + f_host_infos, + f_host_logs, + f_host_false_positives, + f_host_compliant, + f_host_notcompliant, + f_host_incomplete, + f_host_undefined)) +#else + if (print_report_host_xml (out, + &hosts, + NULL, + tsk_usage_type, + lean, + host_summary_buffer, + f_host_ports, + f_host_holes, + f_host_warnings, + f_host_infos, + f_host_logs, + f_host_false_positives, + f_host_compliant, + f_host_notcompliant, + f_host_incomplete, + f_host_undefined)) +#endif goto failed_print_report_host; } cleanup_iterator (&hosts); } - #if COMPLIANCE_REPORTS == 1 - if (strcmp (tsk_usage_type, "audit") == 0) - { - g_hash_table_destroy (f_host_compliant); - g_hash_table_destroy (f_host_notcompliant); - g_hash_table_destroy (f_host_incomplete); - g_hash_table_destroy (f_host_undefined); - } else - #endif - { - g_hash_table_destroy (f_host_holes); - g_hash_table_destroy (f_host_warnings); - g_hash_table_destroy (f_host_infos); - g_hash_table_destroy (f_host_logs); - g_hash_table_destroy (f_host_false_positives); - } + if (strcmp (tsk_usage_type, "audit") == 0) + { + g_hash_table_destroy (f_host_compliant); + g_hash_table_destroy (f_host_notcompliant); + g_hash_table_destroy (f_host_incomplete); + g_hash_table_destroy (f_host_undefined); + } + else + { +#if CVSS3_RATINGS == 1 + g_hash_table_destroy (f_host_criticals); +#endif + g_hash_table_destroy (f_host_holes); + g_hash_table_destroy (f_host_warnings); + g_hash_table_destroy (f_host_infos); + g_hash_table_destroy (f_host_logs); + g_hash_table_destroy (f_host_false_positives); + } g_hash_table_destroy (f_host_ports); /* Print TLS certificates */ @@ -31079,7 +30557,7 @@ print_report_xml_start (report_t report, report_t delta, task_t task, { report_host_t report_host = host_iterator_report_host(&hosts); - if (print_report_host_tls_certificates_xml(report_host, + if (print_report_host_tls_certificates_xml(report_host, result_host, out)) { @@ -31099,15 +30577,15 @@ print_report_xml_start (report_t report, report_t delta, task_t task, const char *host; iterator_t hosts; init_report_host_iterator (&hosts, report, NULL, 0); - + PRINT (out, ""); - + while (next (&hosts)) { report_host_t report_host = host_iterator_report_host(&hosts); host = host_iterator_host (&hosts); - if (print_report_host_tls_certificates_xml(report_host, + if (print_report_host_tls_certificates_xml(report_host, host, out)) { @@ -31157,36 +30635,39 @@ print_report_xml_start (report_t report, report_t delta, task_t task, return 0; failed_delta_report: - fclose (out); - g_free (sort_field); - g_free (levels); - g_free (search_phrase); - g_free (min_qod); - g_free (delta_states); - cleanup_iterator (&results); - cleanup_iterator (&delta_results); + fclose (out); + g_free (sort_field); + g_free (levels); + g_free (search_phrase); + g_free (min_qod); + g_free (delta_states); + cleanup_iterator (&results); + cleanup_iterator (&delta_results); failed_print_report_host: if (host_summary_buffer) g_string_free (host_summary_buffer, TRUE); tz_revert (zone, tz, old_tz_override); g_hash_table_destroy (f_host_ports); - #if COMPLIANCE_REPORTS == 1 - g_free (compliance_levels); - if (strcmp (tsk_usage_type, "audit") == 0) + + g_free (compliance_levels); + if (strcmp (tsk_usage_type, "audit") == 0) { g_hash_table_destroy (f_host_compliant); g_hash_table_destroy (f_host_notcompliant); g_hash_table_destroy (f_host_incomplete); g_hash_table_destroy (f_host_undefined); - } else - #endif - { - g_hash_table_destroy (f_host_holes); - g_hash_table_destroy (f_host_warnings); - g_hash_table_destroy (f_host_infos); - g_hash_table_destroy (f_host_logs); - g_hash_table_destroy (f_host_false_positives); - } + } + else + { +#if CVSS3_RATINGS == 1 + g_hash_table_destroy (f_host_criticals); +#endif + g_hash_table_destroy (f_host_holes); + g_hash_table_destroy (f_host_warnings); + g_hash_table_destroy (f_host_infos); + g_hash_table_destroy (f_host_logs); + g_hash_table_destroy (f_host_false_positives); + } return -1; } @@ -32130,20 +31611,23 @@ parse_osp_report (task_t task, report_t report, const char *report_xml) /** * @brief Return the trend of a task, given counts. * - * @param[in] holes_a Number of holes on earlier report. - * @param[in] warns_a Number of warnings on earlier report. - * @param[in] infos_a Number of infos on earlier report. - * @param[in] severity_a Severity of earlier report. - * @param[in] holes_b Number of holes on later report. - * @param[in] warns_b Number of warnings on later report. - * @param[in] infos_b Number of infos on later report. - * @param[in] severity_b Severity of later report. + * @param[in] criticals_a Number of criticals on earlier report. + * @param[in] holes_a Number of holes on earlier report. + * @param[in] warns_a Number of warnings on earlier report. + * @param[in] infos_a Number of infos on earlier report. + * @param[in] severity_a Severity of earlier report. + * @param[in] criticals_b Number of criticals on later report. + * @param[in] holes_b Number of holes on later report. + * @param[in] warns_b Number of warnings on later report. + * @param[in] infos_b Number of infos on later report. + * @param[in] severity_b Severity of later report. * * @return "up", "down", "more", "less", "same" or if too few reports "". */ static const char * -task_trend_calc (int holes_a, int warns_a, int infos_a, double severity_a, - int holes_b, int warns_b, int infos_b, double severity_b) +task_trend_calc (int criticals_a, int holes_a, int warns_a, int infos_a, + double severity_a, int criticals_b, int holes_b, int warns_b, + int infos_b, double severity_b) { int threat_a, threat_b; @@ -32157,7 +31641,9 @@ task_trend_calc (int holes_a, int warns_a, int infos_a, double severity_a, /* Calculate trend. */ - if (holes_a > 0) + if (criticals_a > 0) + threat_a = 5; + else if (holes_a > 0) threat_a = 4; else if (warns_a > 0) threat_a = 3; @@ -32166,7 +31652,9 @@ task_trend_calc (int holes_a, int warns_a, int infos_a, double severity_a, else threat_a = 1; - if (holes_b > 0) + if (criticals_b > 0) + threat_b = 5; + else if (holes_b > 0) threat_b = 4; else if (warns_b > 0) threat_b = 3; @@ -32185,6 +31673,15 @@ task_trend_calc (int holes_a, int warns_a, int infos_a, double severity_a, /* Check if the threat count changed in the highest level. */ + if (criticals_a) + { + if (criticals_a > criticals_b) + return "more"; + if (criticals_a < criticals_b) + return "less"; + return "same"; + } + if (holes_a) { if (holes_a > holes_b) @@ -32218,22 +31715,25 @@ task_trend_calc (int holes_a, int warns_a, int infos_a, double severity_a, /** * @brief Return the trend of a task, given counts. * - * @param[in] iterator Task iterator. - * @param[in] holes_a Number of holes on earlier report. - * @param[in] warns_a Number of warnings on earlier report. - * @param[in] infos_a Number of infos on earlier report. - * @param[in] severity_a Severity score of earlier report. - * @param[in] holes_b Number of holes on later report. - * @param[in] warns_b Number of warnings on later report. - * @param[in] infos_b Number of infos on later report. + * @param[in] iterator Task iterator. + * @param[in] criticals_a Number of criticals on earlier report. + * @param[in] holes_a Number of holes on earlier report. + * @param[in] warns_a Number of warnings on earlier report. + * @param[in] infos_a Number of infos on earlier report. + * @param[in] severity_a Severity score of earlier report. + * @param[in] criticals_b Number of criticals on later report. + * @param[in] holes_b Number of holes on later report. + * @param[in] warns_b Number of warnings on later report. + * @param[in] infos_b Number of infos on later report. * @param[in] severity_b Severity score of later report. * * @return "up", "down", "more", "less", "same" or if too few reports "". */ const char * -task_iterator_trend_counts (iterator_t *iterator, int holes_a, int warns_a, - int infos_a, double severity_a, int holes_b, - int warns_b, int infos_b, double severity_b) +task_iterator_trend_counts (iterator_t *iterator, int criticals_a, int holes_a, + int warns_a, int infos_a, double severity_a, + int criticals_b, int holes_b, int warns_b, + int infos_b, double severity_b) { /* Ensure there are enough reports. */ if (task_iterator_finished_reports (iterator) <= 1) @@ -32244,8 +31744,8 @@ task_iterator_trend_counts (iterator_t *iterator, int holes_a, int warns_a, if (task_iterator_run_status (iterator) == TASK_STATUS_RUNNING) return ""; - return task_trend_calc (holes_a, warns_a, infos_a, severity_a, - holes_b, warns_b, infos_b, severity_b); + return task_trend_calc (criticals_a, holes_a, warns_a, infos_a, severity_a, + criticals_b, holes_b, warns_b, infos_b, severity_b); } /** @@ -33879,6 +33379,8 @@ target_login_port (target_t target, const char* type) * 10 invalid SMB credential type, 11 invalid ESXi credential type, * 12 invalid SNMP credential type, 13 port range or port list required, * 14 SSH elevate credential without an SSH credential, + * 15 elevate credential must be different from the SSH credential, + * 16 invalid Kerberos 5 credential type, * 99 permission denied, -1 error. */ int @@ -33889,6 +33391,7 @@ create_target (const char* name, const char* asset_hosts_filter, credential_t ssh_elevate_credential, const char* ssh_port, credential_t smb_credential, credential_t esxi_credential, credential_t snmp_credential, + credential_t krb5_credential, const char *reverse_lookup_only, const char *reverse_lookup_unify, const char *alive_tests, const char *allow_simultaneous_ips, @@ -34153,6 +33656,23 @@ create_target (const char* name, const char* asset_hosts_filter, new_target, snmp_credential, "0"); } + if (krb5_credential) + { + gchar *type = credential_type (krb5_credential); + if (strcmp (type, "krb5")) + { + sql_rollback (); + g_free (type); + return 16; + } + g_free (type); + + sql ("INSERT INTO targets_login_data" + " (target, type, credential, port)" + " VALUES (%llu, 'krb5', %llu, %s);", + new_target, krb5_credential, "0"); + } + sql_commit (); return 0; @@ -34350,6 +33870,7 @@ delete_target (const char *target_id, int ultimate) * @param[in] smb_credential_id SMB credential. * @param[in] esxi_credential_id ESXi credential. * @param[in] snmp_credential_id SNMP credential. + * @param[in] krb5_credential_id Kerberos 5 credential. * @param[in] reverse_lookup_only Scanner preference reverse_lookup_only. * @param[in] reverse_lookup_unify Scanner preference reverse_lookup_unify. * @param[in] alive_tests Alive tests. @@ -34368,6 +33889,9 @@ delete_target (const char *target_id, int ultimate) * 22 failed to find SSH elevate cred, 23 invalid SSH elevate * credential type, 24 SSH elevate credential without SSH credential, * 25 SSH elevate credential equals SSH credential, + * 26 failed to find Kerberos 5 credential, + * 27 invalid Kerberos 5 credential type, + * 28 cannot use both SMB and Kerberos 5 credential, * 99 permission denied, -1 error. */ int @@ -34377,6 +33901,7 @@ modify_target (const char *target_id, const char *name, const char *hosts, const char *ssh_elevate_credential_id, const char *ssh_port, const char *smb_credential_id, const char *esxi_credential_id, const char* snmp_credential_id, + const char *krb5_credential_id, const char *reverse_lookup_only, const char *reverse_lookup_unify, const char *alive_tests, const char *allow_simultaneous_ips) @@ -34384,6 +33909,8 @@ modify_target (const char *target_id, const char *name, const char *hosts, target_t target; credential_t ssh_credential = 0; credential_t ssh_elevate_credential = 0; + credential_t smb_credential; + credential_t krb5_credential; assert (target_id); @@ -34617,8 +34144,6 @@ modify_target (const char *target_id, const char *name, const char *hosts, if (smb_credential_id) { - credential_t smb_credential; - if (target_in_use (target)) { sql_rollback (); @@ -34656,6 +34181,8 @@ modify_target (const char *target_id, const char *name, const char *hosts, else set_target_login_data (target, "smb", 0, 0); } + else + smb_credential = target_smb_credential (target); if (esxi_credential_id) { @@ -34760,6 +34287,55 @@ modify_target (const char *target_id, const char *name, const char *hosts, } } + if (krb5_credential_id) + { + if (target_in_use (target)) + { + sql_rollback (); + return 15; + } + + krb5_credential = 0; + if (strcmp (krb5_credential_id, "0")) + { + gchar *type; + if (find_credential_with_permission (krb5_credential_id, + &krb5_credential, + "get_credentials")) + { + sql_rollback (); + return -1; + } + + if (krb5_credential == 0) + { + sql_rollback (); + return 26; + } + + type = credential_type (krb5_credential); + if (strcmp (type, "krb5")) + { + sql_rollback (); + g_free (type); + return 27; + } + g_free (type); + + set_target_login_data (target, "krb5", krb5_credential, 0); + } + else + set_target_login_data (target, "krb5", 0, 0); + } + else + krb5_credential = target_krb5_credential (target); + + if (smb_credential && krb5_credential) + { + sql_rollback (); + return 28; + } + if (exclude_hosts) { gchar *quoted_exclude_hosts, *quoted_hosts, *clean, *clean_exclude; @@ -34923,6 +34499,12 @@ modify_target (const char *target_id, const char *name, const char *hosts, NULL, \ KEYWORD_TYPE_INTEGER }, \ { "0", NULL, KEYWORD_TYPE_INTEGER }, \ + { "(SELECT credential FROM targets_login_data" \ + " WHERE target = targets.id" \ + " AND type = CAST ('krb5' AS text))", \ + NULL, \ + KEYWORD_TYPE_INTEGER }, \ + { "0", NULL, KEYWORD_TYPE_INTEGER }, \ { "allow_simultaneous_ips", \ NULL, \ KEYWORD_TYPE_INTEGER }, \ @@ -34971,6 +34553,15 @@ modify_target (const char *target_id, const char *name, const char *hosts, "ssh_elevate_credential", \ KEYWORD_TYPE_STRING \ }, \ + { \ + "(SELECT name FROM credentials" \ + " WHERE credentials.id" \ + " = (SELECT credential FROM targets_login_data" \ + " WHERE target = targets.id" \ + " AND type = CAST ('krb5' AS text)))", \ + "krb5_credential", \ + KEYWORD_TYPE_STRING \ + }, \ { "hosts", NULL, KEYWORD_TYPE_STRING }, \ { "max_hosts (hosts, exclude_hosts)", \ "ips", \ @@ -35048,6 +34639,12 @@ modify_target (const char *target_id, const char *name, const char *hosts, { "trash_target_credential_location (id, CAST ('elevate' AS text))", \ NULL, \ KEYWORD_TYPE_INTEGER }, \ + { "target_credential (id, 1, CAST ('krb5' AS text))", \ + NULL, \ + KEYWORD_TYPE_INTEGER }, \ + { "trash_target_credential_location (id, CAST ('krb5' AS text))", \ + NULL, \ + KEYWORD_TYPE_INTEGER }, \ { "allow_simultaneous_ips", \ NULL, \ KEYWORD_TYPE_INTEGER }, \ @@ -35402,6 +34999,38 @@ target_iterator_ssh_elevate_trash (iterator_t* iterator) return ret; } +/** + * @brief Get the Kerberos 5 LSC credential from a target iterator. + * + * @param[in] iterator Iterator. + * + * @return Kerberos 5 LSC credential. + */ +int +target_iterator_krb5_credential (iterator_t* iterator) +{ + int ret; + if (iterator->done) return -1; + ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 20); + return ret; +} + +/** + * @brief Get the Kerberos 5 LSC credential location from a target iterator. + * + * @param[in] iterator Iterator. + * + * @return Kerberos 5 LSC credential. + */ +int +target_iterator_krb5_trash (iterator_t* iterator) +{ + int ret; + if (iterator->done) return -1; + ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 21); + return ret; +} + /** * @brief Get the allow_simultaneous_ips value from a target iterator. * @@ -35410,7 +35039,7 @@ target_iterator_ssh_elevate_trash (iterator_t* iterator) * @return allow_simult_ips_same_host or NULL if iteration is complete. */ DEF_ACCESS (target_iterator_allow_simultaneous_ips, - GET_ITERATOR_COLUMN_COUNT + 20); + GET_ITERATOR_COLUMN_COUNT + 22); /** * @brief Return the UUID of a tag. @@ -35673,6 +35302,19 @@ target_ssh_elevate_credential (target_t target) return target_credential (target, "elevate"); } +/** + * @brief Return the Kerberos 5 credential associated with a target, if any. + * + * @param[in] target Target. + * + * @return Kerberos 5 credential if any, else 0. + */ +credential_t +target_krb5_credential (target_t target) +{ + return target_credential (target, "krb5"); +} + /** * @brief Return the port list associated with a target, if any. * @@ -36904,6 +36546,8 @@ validate_credential_username_for_format (const gchar *username, * @param[in] auth_algorithm SNMP authentication algorithm, or NULL. * @param[in] privacy_password SNMP privacy password. * @param[in] privacy_algorithm SNMP privacy algorithm. + * @param[in] kdc Kerberos KDC (key distribution centers). + * @param[in] realm Kerberos realm. * @param[in] given_type Credential type or NULL. * @param[in] allow_insecure Whether to allow insecure uses. * @param[out] credential Created Credential. @@ -36917,6 +36561,7 @@ validate_credential_username_for_format (const gchar *username, * 14 privacy algorithm missing, * 15 invalid auth algorithm, 16 invalid privacy algorithm, * 17 invalid certificate, 18 cannot determine type, + * 19 key distribution center missing, 20 realm missing, * 99 permission denied, -1 error. */ int @@ -36926,6 +36571,7 @@ create_credential (const char* name, const char* comment, const char* login, const char* certificate, const char* community, const char* auth_algorithm, const char* privacy_password, const char* privacy_algorithm, + const char* kdc, const char *realm, const char* given_type, const char* allow_insecure, credential_t *credential) { @@ -36972,7 +36618,8 @@ create_credential (const char* name, const char* comment, const char* login, && strcmp (given_type, "snmp") && strcmp (given_type, "smime") && strcmp (given_type, "up") - && strcmp (given_type, "usk")) + && strcmp (given_type, "usk") + && strcmp (given_type, "krb5")) { sql_rollback (); return 4; @@ -36987,6 +36634,8 @@ create_credential (const char* name, const char* comment, const char* login, quoted_type = g_strdup ("cc"); else if (login && key_private) quoted_type = g_strdup ("usk"); + else if (login && given_password && (realm || kdc)) + quoted_type = g_strdup ("krb5"); else if (login && given_password) quoted_type = g_strdup ("up"); else if (login && key_private == NULL && given_password == NULL) @@ -36994,6 +36643,7 @@ create_credential (const char* name, const char* comment, const char* login, else { g_warning ("%s: Cannot determine type of new credential", __func__); + sql_rollback (); return 18; } @@ -37007,7 +36657,8 @@ create_credential (const char* name, const char* comment, const char* login, && (strcmp (quoted_type, "cc") == 0 || strcmp (quoted_type, "pgp") == 0 || strcmp (quoted_type, "smime") == 0 - || strcmp (quoted_type, "snmp") == 0)) + || strcmp (quoted_type, "snmp") == 0 + || strcmp (quoted_type, "krb5") == 0)) ret = 10; // Type does not support autogenerate using_snmp_v3 = 0; @@ -37021,7 +36672,8 @@ create_credential (const char* name, const char* comment, const char* login, ret = 5; else if (given_password == NULL && auto_generate == 0 && (strcmp (quoted_type, "up") == 0 - || strcmp (quoted_type, "pw") == 0)) + || strcmp (quoted_type, "pw") == 0 + || strcmp (quoted_type, "krb5") == 0)) // (username) password requires a password ret = 6; else if (key_private == NULL && auto_generate == 0 @@ -37035,6 +36687,12 @@ create_credential (const char* name, const char* comment, const char* login, else if (key_public == NULL && auto_generate == 0 && strcmp (quoted_type, "pgp") == 0) ret = 9; + else if (kdc == NULL && auto_generate == 0 + && strcmp (quoted_type, "krb5") == 0) + ret = 19; + else if (realm == NULL && auto_generate == 0 + && strcmp (quoted_type, "krb5") == 0) + ret = 20; else if (strcmp (quoted_type, "snmp") == 0) { if (login || given_password || auth_algorithm @@ -37110,9 +36768,10 @@ create_credential (const char* name, const char* comment, const char* login, "username", login); } + if (kdc) + set_credential_data (new_credential, "kdc", kdc); if (key_public) set_credential_data (new_credential, "public_key", key_public); - if (certificate) { gchar *certificate_truncated; @@ -37133,6 +36792,8 @@ create_credential (const char* name, const char* comment, const char* login, if (privacy_algorithm) set_credential_data (new_credential, "privacy_algorithm", privacy_algorithm); + if (realm) + set_credential_data (new_credential, "realm", realm); g_free (quoted_type); @@ -37150,7 +36811,10 @@ create_credential (const char* name, const char* comment, const char* login, if (key_private) key_private_truncated = truncate_private_key (key_private); else - return 3; + { + sql_rollback (); + return 3; + } generated_key_public = gvm_ssh_public_from_private (key_private_truncated @@ -37160,6 +36824,7 @@ create_credential (const char* name, const char* comment, const char* login, if (generated_key_public == NULL) { g_free (key_private_truncated); + sql_rollback (); return 3; } g_free (generated_key_public); @@ -37411,6 +37076,8 @@ copy_credential (const char* name, const char* comment, * @param[in] auth_algorithm Authentication algorithm of Credential. * @param[in] privacy_password Privacy password of Credential. * @param[in] privacy_algorithm Privacy algorithm of Credential. + * @param[in] kdc Kerberos KDC (key distribution centers). + * @param[in] realm Kerberos realm. * @param[in] allow_insecure Whether to allow insecure use. * * @return 0 success, 1 failed to find credential, 2 credential with new name @@ -37430,6 +37097,7 @@ modify_credential (const char *credential_id, const char* certificate, const char* community, const char* auth_algorithm, const char* privacy_password, const char* privacy_algorithm, + const char* kdc, const char* realm, const char* allow_insecure) { credential_t credential; @@ -37705,6 +37373,15 @@ modify_credential (const char *credential_id, { set_credential_data (credential, "secret", ""); } + else if (strcmp (type, "krb5") == 0) + { + if (password) + set_credential_password (credential, password); + if (kdc) + set_credential_data (credential, "kdc", kdc); + if (realm) + set_credential_data (credential, "realm", realm); + } else { g_warning ("%s: Unknown credential type: %s", __func__, type); @@ -37900,6 +37577,14 @@ delete_credential (const char *credential_id, int ultimate) " WHERE credential = credentials.id AND type = 'public_key')", \ NULL, \ KEYWORD_TYPE_STRING }, \ + { "(SELECT value FROM credentials_data" \ + " WHERE credential = credentials.id AND type = 'kdc')" , \ + "kdc", \ + KEYWORD_TYPE_STRING }, \ + { "(SELECT value FROM credentials_data" \ + " WHERE credential = credentials.id AND type = 'realm')", \ + "realm", \ + KEYWORD_TYPE_STRING }, \ /* private data */ \ { "(SELECT value FROM credentials_data" \ " WHERE credential = credentials.id AND type = 'secret')", \ @@ -38482,20 +38167,20 @@ credential_iterator_encrypted_data (iterator_t* iterator, const char* type) if (iterator->done) return NULL; - secret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 7); + secret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 9); if (type == NULL) { g_warning ("%s: NULL data type given", __func__); return NULL; } else if (strcmp (type, "password") == 0) - unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 8); + unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 10); else if (strcmp (type, "private_key") == 0) - unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 9); + unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 11); else if (strcmp (type, "community") == 0) - unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 10); + unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 12); else if (strcmp (type, "privacy_password") == 0) - unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 11); + unencrypted = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 13); else { g_warning ("%s: unknown data type \"%s\"", __func__, type); @@ -38596,6 +38281,27 @@ DEF_ACCESS (credential_iterator_privacy_algorithm, DEF_ACCESS (credential_iterator_public_key, GET_ITERATOR_COLUMN_COUNT + 6); +/** + * @brief Get the key distribution center from an LSC credential iterator. + * + * @param[in] iterator Iterator. + * + * @return Key distribution center, or NULL if iteration is complete. Freed by + * cleanup_iterator. + */ +DEF_ACCESS (credential_iterator_kdc, + GET_ITERATOR_COLUMN_COUNT + 7); + +/** + * @brief Get the realm from an LSC credential iterator. + * + * @param[in] iterator Iterator. + * + * @return Realm, or NULL if iteration is complete. Freed by cleanup_iterator. + */ +DEF_ACCESS (credential_iterator_realm, + GET_ITERATOR_COLUMN_COUNT + 8); + /** * @brief Get the password from a Credential iterator. * @@ -39212,8 +38918,14 @@ create_note (const char* active, const char* nvt, const char* text, if (text == NULL) return -1; - if (threat && strcmp (threat, "High") && strcmp (threat, "Medium") - && strcmp (threat, "Low") && strcmp (threat, "Log") + if (threat +#if CVSS3_RATINGS == 1 + && strcmp (threat, "Critical") +#endif + && strcmp (threat, "High") + && strcmp (threat, "Medium") + && strcmp (threat, "Low") + && strcmp (threat, "Log") && strcmp (threat, "")) return -1; @@ -39234,6 +38946,10 @@ create_note (const char* active, const char* nvt, const char* text, { if (strcmp (threat, "Alarm") == 0) severity_dbl = 0.1; +#if CVSS3_RATINGS == 1 + else if (strcmp (threat, "Critical") == 0) + severity_dbl = 0.1; +#endif else if (strcmp (threat, "High") == 0) severity_dbl = 0.1; else if (strcmp (threat, "Medium") == 0) @@ -39468,9 +39184,16 @@ modify_note (const gchar *note_id, const char *active, const char *nvt, if (nvt && !nvt_exists (nvt)) return 4; - if (threat && strcmp (threat, "High") && strcmp (threat, "Medium") - && strcmp (threat, "Low") && strcmp (threat, "Log") - && strcmp (threat, "Alarm") && strcmp (threat, "")) + if (threat +#if CVSS3_RATINGS == 1 + && strcmp (threat, "Critical") +#endif + && strcmp (threat, "High") + && strcmp (threat, "Medium") + && strcmp (threat, "Low") + && strcmp (threat, "Log") + && strcmp (threat, "Alarm") + && strcmp (threat, "")) return -1; if (port && validate_results_port (port)) @@ -39494,6 +39217,10 @@ modify_note (const gchar *note_id, const char *active, const char *nvt, { if (strcmp (threat, "Alarm") == 0) severity_dbl = 0.1; +#if CVSS3_RATINGS == 1 + else if (strcmp (threat, "Critical") == 0) + severity_dbl = 0.1; +#endif else if (strcmp (threat, "High") == 0) severity_dbl = 0.1; else if (strcmp (threat, "Medium") == 0) @@ -40200,15 +39927,29 @@ create_override (const char* active, const char* nvt, const char* text, if (port && validate_results_port (port)) return 2; - if (threat && strcmp (threat, "High") && strcmp (threat, "Medium") - && strcmp (threat, "Low") && strcmp (threat, "Log") - && strcmp (threat, "Alarm") && strcmp (threat, "")) + if (threat +#if CVSS3_RATINGS == 1 + && strcmp (threat, "Critical") +#endif + && strcmp (threat, "High") + && strcmp (threat, "Medium") + && strcmp (threat, "Low") + && strcmp (threat, "Log") + && strcmp (threat, "Alarm") + && strcmp (threat, "")) return -1; - if (new_threat && strcmp (new_threat, "High") && strcmp (new_threat, "Medium") - && strcmp (new_threat, "Low") && strcmp (new_threat, "Log") + if (new_threat +#if CVSS3_RATINGS == 1 + && strcmp (new_threat, "Critical") +#endif + && strcmp (new_threat, "High") + && strcmp (new_threat, "Medium") + && strcmp (new_threat, "Low") + && strcmp (new_threat, "Log") && strcmp (new_threat, "False Positive") - && strcmp (new_threat, "Alarm") && strcmp (new_threat, "")) + && strcmp (new_threat, "Alarm") + && strcmp (new_threat, "")) return -1; severity_dbl = 0.0; @@ -40224,6 +39965,10 @@ create_override (const char* active, const char* nvt, const char* text, { if (strcmp (threat, "Alarm") == 0) severity_dbl = 0.1; +#if CVSS3_RATINGS == 1 + else if (strcmp (threat, "Critical") == 0) + severity_dbl = 0.1; +#endif else if (strcmp (threat, "High") == 0) severity_dbl = 0.1; else if (strcmp (threat, "Medium") == 0) @@ -40256,8 +40001,15 @@ create_override (const char* active, const char* nvt, const char* text, { if (strcmp (new_threat, "Alarm") == 0) new_severity_dbl = 10.0; +#if CVSS3_RATINGS == 1 + else if (strcmp (new_threat, "Critical") == 0) + new_severity_dbl = 10.0; + else if (strcmp (new_threat, "High") == 0) + new_severity_dbl = 8.9; +#else else if (strcmp (new_threat, "High") == 0) new_severity_dbl = 10.0; +#endif else if (strcmp (new_threat, "Medium") == 0) new_severity_dbl = 5.0; else if (strcmp (new_threat, "Low") == 0) @@ -40574,6 +40326,10 @@ modify_override (const gchar *override_id, const char *active, const char *nvt, { if (strcmp (threat, "Alarm") == 0) severity_dbl = 0.1; +#if CVSS3_RATINGS == 1 + else if (strcmp (threat, "Critical") == 0) + severity_dbl = 0.1; +#endif else if (strcmp (threat, "High") == 0) severity_dbl = 0.1; else if (strcmp (threat, "Medium") == 0) @@ -40606,8 +40362,15 @@ modify_override (const gchar *override_id, const char *active, const char *nvt, { if (strcmp (new_threat, "Alarm") == 0) new_severity_dbl = 10.0; +#if CVSS3_RATINGS == 1 + else if (strcmp (new_threat, "Critical") == 0) + new_severity_dbl = 10.0; + else if (strcmp (new_threat, "High") == 0) + new_severity_dbl = 8.9; +#else else if (strcmp (new_threat, "High") == 0) new_severity_dbl = 10.0; +#endif else if (strcmp (new_threat, "Medium") == 0) new_severity_dbl = 5.0; else if (strcmp (new_threat, "Low") == 0) @@ -41479,7 +41242,8 @@ manage_create_scanner (GSList *log_config, const db_conn_info_t *database, g_info (" Creating scanner."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -41668,7 +41432,8 @@ manage_delete_scanner (GSList *log_config, const db_conn_info_t *database, return 3; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -41736,7 +41501,8 @@ manage_modify_scanner (GSList *log_config, const db_conn_info_t *database, g_info (" Modifying scanner."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -41955,7 +41721,8 @@ manage_verify_scanner (GSList *log_config, const db_conn_info_t *database, g_info (" Verifying scanner."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -43440,7 +43207,8 @@ manage_get_scanners (GSList *log_config, const db_conn_info_t *database) g_info (" Getting scanners."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -47379,7 +47147,8 @@ manage_get_roles (GSList *log_config, const db_conn_info_t *database, g_info (" Getting roles."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -48865,7 +48634,7 @@ modify_filter (const char *filter_id, const char *name, const char *comment, return 4; db_type = type_db_name (type); - if (db_type && !((strcmp (db_type, "") == 0) || valid_type (db_type))) + if (db_type && !((strcmp (db_type, "") == 0) || valid_type (db_type))) { if (!valid_subtype (type)) return 3; @@ -52884,21 +52653,6 @@ setting_auto_cache_rebuild_int () current_credentials.uuid); } -/** - * @brief Return user setting as int. - * - * @return User setting. - */ -static int -setting_delta_reports_version_int () -{ - int version; - - setting_value_int (SETTING_UUID_DELTA_REPORTS_VERSION, &version); - - return version; -} - /** * @brief Initialise a setting iterator, including observed settings. * @@ -53494,10 +53248,8 @@ modify_setting (const gchar *uuid, const gchar *name, setting_name = g_strdup ("Alerts Filter"); else if (strcmp (uuid, "0f040d06-abf9-43a2-8f94-9de178b0e978") == 0) setting_name = g_strdup ("Assets Filter"); - #if COMPLIANCE_REPORTS == 1 - else if (strcmp (uuid, "45414da7-55f0-44c1-abbb-6b7d1126fbdf") == 0) - setting_name = g_strdup ("Audit Reports Filter"); - #endif + else if (strcmp (uuid, "45414da7-55f0-44c1-abbb-6b7d1126fbdf") == 0) + setting_name = g_strdup ("Audit Reports Filter"); else if (strcmp (uuid, "1a9fbd91-0182-44cd-bc88-a13a9b3b1bef") == 0) setting_name = g_strdup ("Configs Filter"); else if (strcmp (uuid, "186a5ac8-fe5a-4fb1-aa22-44031fb339f3") == 0) @@ -53621,10 +53373,8 @@ modify_setting (const gchar *uuid, const gchar *name, setting_name = g_strdup ("Reports Top Dashboard Configuration"); /* Audit Reports dashboard settings */ - #if COMPLIANCE_REPORTS == 1 - else if (strcmp (uuid, "8083d77b-05bb-4b17-ab39-c81175cb512c") == 0) - setting_name = g_strdup ("Audit Reports Top Dashboard Configuration"); - #endif + else if (strcmp (uuid, "8083d77b-05bb-4b17-ab39-c81175cb512c") == 0) + setting_name = g_strdup ("Audit Reports Top Dashboard Configuration"); /* Results dashboard settings */ else if (strcmp (uuid, "0b8ae70d-d8fc-4418-8a72-e65ac8d2828e") == 0) setting_name = g_strdup ("Results Top Dashboard Configuration"); @@ -53806,8 +53556,6 @@ setting_name (const gchar *uuid) return "Feed Import Owner"; if (strcmp (uuid, SETTING_UUID_FEED_IMPORT_ROLES) == 0) return "Feed Import Roles"; - if (strcmp (uuid, SETTING_UUID_DELTA_REPORTS_VERSION) == 0) - return "Delta Reports Version"; if (strcmp (uuid, SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD) == 0) return "SecInfo SQL Buffer Threshold"; @@ -53847,8 +53595,6 @@ setting_description (const gchar *uuid) return "User who is given ownership of new resources from feed."; if (strcmp (uuid, SETTING_UUID_FEED_IMPORT_ROLES) == 0) return "Roles given access to new resources from feed."; - if (strcmp (uuid, SETTING_UUID_DELTA_REPORTS_VERSION) == 0) - return "Version of the generation of the Delta Reports."; if (strcmp (uuid, SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD) == 0) return "Buffer size threshold in MiB for running buffered SQL statements" " in SecInfo updates before the end of the file being processed."; @@ -53939,12 +53685,6 @@ setting_verify (const gchar *uuid, const gchar *value, const gchar *user) g_strfreev (split); } - if (strcmp (uuid, SETTING_UUID_DELTA_REPORTS_VERSION) == 0) - { - if (strcmp(value, "1") != 0 && strcmp(value, "2") != 0) - return 1; - } - if (strcmp (uuid, SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD) == 0) { int threshold; @@ -54047,14 +53787,14 @@ manage_modify_setting (GSList *log_config, const db_conn_info_t *database, && strcmp (uuid, SETTING_UUID_LSC_DEB_MAINTAINER) && strcmp (uuid, SETTING_UUID_FEED_IMPORT_OWNER) && strcmp (uuid, SETTING_UUID_FEED_IMPORT_ROLES) - && strcmp (uuid, SETTING_UUID_DELTA_REPORTS_VERSION) && strcmp (uuid, SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD)) { fprintf (stderr, "Error in setting UUID.\n"); return 3; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -54075,7 +53815,6 @@ manage_modify_setting (GSList *log_config, const db_conn_info_t *database, if ((strcmp (uuid, SETTING_UUID_DEFAULT_CA_CERT) == 0) || (strcmp (uuid, SETTING_UUID_FEED_IMPORT_OWNER) == 0) || (strcmp (uuid, SETTING_UUID_FEED_IMPORT_ROLES) == 0) - || (strcmp (uuid, SETTING_UUID_DELTA_REPORTS_VERSION) == 0) || (strcmp (uuid, SETTING_UUID_SECINFO_SQL_BUFFER_THRESHOLD) == 0)) { sql_rollback (); @@ -54209,7 +53948,8 @@ manage_create_user (GSList *log_config, const db_conn_info_t *database, g_info (" Creating user."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -54299,7 +54039,8 @@ manage_delete_user (GSList *log_config, const db_conn_info_t *database, g_info (" Deleting user."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -54364,7 +54105,8 @@ manage_get_users (GSList *log_config, const db_conn_info_t *database, g_info (" Getting users."); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -54468,7 +54210,8 @@ manage_set_password (GSList *log_config, const db_conn_info_t *database, return -1; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return ret; @@ -57289,7 +57032,7 @@ tag_add_resources_list (tag_t tag, const char *type, array_t *uuids, resource_permission = g_strdup ("get_info"); else if (type_is_asset_subtype (type)) resource_permission = g_strdup ("get_assets"); - else if (type_is_report_subtype (type)) + else if (type_is_report_subtype (type)) { resource_permission = g_strdup ("get_reports"); type = g_strdup("report"); @@ -57387,18 +57130,16 @@ tag_add_resources_filter (tag_t tag, const char *type, const char *filter) { get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); } - #if COMPLIANCE_REPORTS == 1 - else if (strcasecmp (type, "audit_report") == 0) - { - type = g_strdup ("report"); - resources_get.type = g_strdup (type); - get_data_set_extra (&resources_get, "usage_type", g_strdup ("audit")); - } - else if (strcasecmp (type, "report") == 0) - { - get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); - } - #endif + else if (strcasecmp (type, "audit_report") == 0) + { + type = g_strdup ("report"); + resources_get.type = g_strdup (type); + get_data_set_extra (&resources_get, "usage_type", g_strdup ("audit")); + } + else if (strcasecmp (type, "report") == 0) + { + get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); + } gchar *columns; @@ -57570,20 +57311,18 @@ tag_remove_resources_filter (tag_t tag, const char *type, const char *filter) { get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); } - #if COMPLIANCE_REPORTS == 1 - else if (strcasecmp (type, "audit_report") == 0) - { - type = g_strdup ("report"); - resources_get.type = g_strdup (type); - get_data_set_extra (&resources_get, - "usage_type", - g_strdup ("audit")); - } - else if (strcasecmp (type, "report") == 0) - { - get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); - } - #endif + else if (strcasecmp (type, "audit_report") == 0) + { + type = g_strdup ("report"); + resources_get.type = g_strdup (type); + get_data_set_extra (&resources_get, + "usage_type", + g_strdup ("audit")); + } + else if (strcasecmp (type, "report") == 0) + { + get_data_set_extra (&resources_get, "usage_type", g_strdup ("scan")); + } gchar *columns; @@ -57605,7 +57344,7 @@ tag_remove_resources_filter (tag_t tag, const char *type, const char *filter) g_free (resources_get.filter); g_free (resources_get.type); if (resources_get.extra_params) - g_hash_table_destroy (resources_get.extra_params); + g_hash_table_destroy (resources_get.extra_params); return -1; } } @@ -57614,7 +57353,7 @@ tag_remove_resources_filter (tag_t tag, const char *type, const char *filter) g_free (resources_get.filter); g_free (resources_get.type); if (resources_get.extra_params) - g_hash_table_destroy (resources_get.extra_params); + g_hash_table_destroy (resources_get.extra_params); ret = 2; while (next (&resources)) @@ -57731,11 +57470,11 @@ create_tag (const char * name, const char * comment, const char * value, if (strcmp (lc_resource_type, "") && valid_db_resource_type (lc_resource_type) == 0) { - if (!valid_subtype (lc_resource_type)) + if (!valid_subtype (lc_resource_type)) { g_free (lc_resource_type); sql_rollback (); - return -1; + return -1; } } @@ -57969,7 +57708,7 @@ modify_tag (const char *tag_id, const char *name, const char *comment, if (!valid_subtype (lc_resource_type)) { sql_rollback (); - return -1; + return -1; } } @@ -58941,7 +58680,7 @@ type_extra_where (const char *type, int trash, const char *filter, usage_type = g_hash_table_lookup (extra_params, "usage_type"); else usage_type = NULL; - + extra_where = reports_extra_where (trash, filter, usage_type); } else if (strcasecmp (type, "RESULT") == 0) @@ -59078,9 +58817,9 @@ type_build_select (const char *type, const char *columns_str, original = opts_table; - lateral_clause = result_iterator_lateral (overrides, - dynamic, - "results", + lateral_clause = result_iterator_lateral (overrides, + dynamic, + "results", "nvts"); opts_table = g_strdup_printf (" LEFT OUTER JOIN result_vt_epss" @@ -59483,7 +59222,15 @@ manage_optimize (GSList *log_config, const db_conn_info_t *database, return 1; } - ret = manage_option_setup (log_config, database); + int avoid_db_check_inserts = 0; + /* The optimize=cleanup-sequences option may be used if a sequence has + * already reached its maximum value, so avoid any inserts that may cause + * a sequence maximum error. * + */ + if (strcasecmp (name, "cleanup-sequences") == 0) + avoid_db_check_inserts = 1; + + ret = manage_option_setup (log_config, database, avoid_db_check_inserts); if (ret) return ret; diff --git a/src/manage_sql.h b/src/manage_sql.h index b9db9cb99..c7181ac4a 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -137,11 +137,6 @@ */ #define SETTING_UUID_FEED_IMPORT_ROLES "ff000362-338f-11ea-9051-28d24461215b" -/** - * @brief UUID of 'Delta Reports Version' setting. - */ -#define SETTING_UUID_DELTA_REPORTS_VERSION "985a0c05-2140-4e66-9989-ce9a0906a5a9" - /** * @brief UUID of 'SecInfo SQL Buffer Threshold' setting. */ @@ -358,6 +353,7 @@ credential_t target_ssh_credential (target_t); credential_t target_smb_credential (target_t); credential_t target_esxi_credential (target_t); credential_t target_ssh_elevate_credential (target_t); +credential_t target_krb5_credential (target_t); int create_current_report (task_t, char **, task_status_t); @@ -453,7 +449,7 @@ void check_alerts (); int -manage_option_setup (GSList *, const db_conn_info_t *); +manage_option_setup (GSList *, const db_conn_info_t *, int); void manage_option_cleanup (); diff --git a/src/manage_sql_configs.c b/src/manage_sql_configs.c index 28e2bb10e..07e25734e 100644 --- a/src/manage_sql_configs.c +++ b/src/manage_sql_configs.c @@ -4532,12 +4532,17 @@ update_config (config_t config, const gchar *name, /** * @brief Check configs, for startup. + * + * @param[in] avoid_db_check_inserts Whether to avoid inserts. */ void -check_db_configs () +check_db_configs (int avoid_db_check_inserts) { migrate_predefined_configs (); + if (avoid_db_check_inserts) + return; + if (sync_configs_with_feed (FALSE) <= -1) g_warning ("%s: Failed to sync configs with feed", __func__); diff --git a/src/manage_sql_configs.h b/src/manage_sql_configs.h index 888d4e4fb..901878423 100644 --- a/src/manage_sql_configs.h +++ b/src/manage_sql_configs.h @@ -97,7 +97,7 @@ update_config (config_t, const gchar *, const gchar *, const gchar *, int, const array_t*, const array_t*, const gchar *); void -check_db_configs (); +check_db_configs (int); void check_whole_only_in_configs (); diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 04e9cf3c8..73aab286c 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -2654,7 +2654,8 @@ manage_rebuild (GSList *log_config, const db_conn_info_t *database) return -1; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) { feed_lockfile_unlock (&lockfile); @@ -2727,7 +2728,8 @@ manage_dump_vt_verification (GSList *log_config, return -1; } - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) { feed_lockfile_unlock (&lockfile); diff --git a/src/manage_sql_port_lists.c b/src/manage_sql_port_lists.c index c24abaea6..b56b9fcc2 100644 --- a/src/manage_sql_port_lists.c +++ b/src/manage_sql_port_lists.c @@ -2652,12 +2652,17 @@ update_port_list (port_list_t port_list, const gchar *name, /** * @brief Check port lists, for startup. + * + * @param[in] avoid_db_check_inserts Whether to avoid inserts. */ void -check_db_port_lists () +check_db_port_lists (int avoid_db_check_inserts) { migrate_predefined_port_lists (); + if (avoid_db_check_inserts) + return; + if (sync_port_lists_with_feed (FALSE) <= -1) g_warning ("%s: Failed to sync port lists with feed", __func__); diff --git a/src/manage_sql_port_lists.h b/src/manage_sql_port_lists.h index 9d20c199c..0539cf253 100644 --- a/src/manage_sql_port_lists.h +++ b/src/manage_sql_port_lists.h @@ -74,6 +74,6 @@ update_port_list (port_list_t, const gchar *, const gchar *, array_t *, const gchar *); void -check_db_port_lists (); +check_db_port_lists (int); #endif /* not _GVMD_MANAGE_SQL_PORT_LISTS_H */ diff --git a/src/manage_sql_report_configs.c b/src/manage_sql_report_configs.c index 88d8fc542..3599d3f3a 100644 --- a/src/manage_sql_report_configs.c +++ b/src/manage_sql_report_configs.c @@ -242,7 +242,7 @@ create_report_config (const char *name, const char *comment, g_free (quoted_comment); g_free (quoted_report_format_id); - for (int i = 0; g_ptr_array_index (params, i); i++) + for (int i = 0; g_ptr_array_index (params, i); i++) { report_config_param_data_t *param; param = g_ptr_array_index (params, i); @@ -266,7 +266,7 @@ create_report_config (const char *name, const char *comment, /** * @brief Modify a report config. - * + * * @param[in] report_config_id UUID of report config to modify. * @param[in] new_name Name of report config. * @param[in] new_comment Comment of report config. @@ -352,7 +352,7 @@ modify_report_config (const char *report_config_id, return 3; } - for (int i = 0; g_ptr_array_index (params, i); i++) + for (int i = 0; g_ptr_array_index (params, i); i++) { report_config_param_data_t *param; param = g_ptr_array_index (params, i); @@ -797,7 +797,7 @@ report_config_iterator_report_format_readable (iterator_t* iterator) if (iterator->done) return 0; - report_format_id + report_format_id = report_config_iterator_report_format_id (iterator); if (report_format_id) @@ -855,7 +855,7 @@ init_report_config_param_iterator (iterator_t *iterator, int trash) { report_format_t report_format; - + report_format = report_config_report_format (report_config); init_iterator (iterator, diff --git a/src/manage_sql_report_formats.c b/src/manage_sql_report_formats.c index 1579b3a71..0a1b49b39 100644 --- a/src/manage_sql_report_formats.c +++ b/src/manage_sql_report_formats.c @@ -2409,10 +2409,10 @@ report_format_param_type_min (report_format_t report_format, const char *name) /** * @brief Checks if the value of a report format param is a valid option. - * + * * @param[in] param The report format param to check. * @param[in] value The value to check. - * + * * @return 1 if the value is one of the allowed options, 0 if not. */ static int @@ -2983,7 +2983,7 @@ report_format_iterator_trust_time (iterator_t* iterator) * * @return Time report format was verified. */ -int +int report_format_iterator_configurable (iterator_t* iterator) { int ret; @@ -4895,16 +4895,21 @@ check_db_trash_report_formats () /** * @brief Ensure the predefined report formats exist. * + * @param[in] avoid_db_check_inserts Whether to avoid inserts. + * * @return 0 success, -1 error. */ int -check_db_report_formats () +check_db_report_formats (int avoid_db_check_inserts) { if (migrate_predefined_report_formats ()) return -1; - if (sync_report_formats_with_feed (FALSE) <= -1) - g_warning ("%s: Failed to sync report formats with feed", __func__); + if (avoid_db_check_inserts == 0) + { + if (sync_report_formats_with_feed (FALSE) <= -1) + g_warning ("%s: Failed to sync report formats with feed", __func__); + } if (check_db_trash_report_formats ()) return -1; diff --git a/src/manage_sql_report_formats.h b/src/manage_sql_report_formats.h index 1ea556752..de7a04be2 100644 --- a/src/manage_sql_report_formats.h +++ b/src/manage_sql_report_formats.h @@ -83,7 +83,7 @@ int migrate_predefined_report_formats (); int -check_db_report_formats (); +check_db_report_formats (int); int check_db_report_formats_trash (); diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 4464edc79..e479ec085 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include #include #include @@ -377,6 +379,72 @@ inserts_run (inserts_t *inserts, gboolean finalize) inserts_free_statements (inserts); } +/** + * @brief Get the string value for a specified key from a JSON object. + * + * @param[in] object JSON object + * @param[in] key The key of the string in the JSON object. + * + * @return The string out of the JSON object with key "key", if any. + * NULL otherwise. + */ +static char* +json_object_item_string (cJSON *object, char *key) +{ + cJSON *value_json; + + value_json = cJSON_GetObjectItemCaseSensitive(object, key); + if (cJSON_IsString(value_json)) + return value_json->valuestring; + return NULL; +} + +/** + * @brief Get the double value for a specified key from a JSON object. + * + * @param[in] object JSON object + * @param[in] key The key of the double value in the JSON object. + * @param[in] fallback The fallback value if the double value is not + * available. + * + * @return The double value out of the JSON object with key "key", if any. + * The fallback value otherwise. + */ +static double +json_object_item_double (cJSON *object, char *key, double fallback) +{ + cJSON *value_json; + + value_json = cJSON_GetObjectItemCaseSensitive(object, key); + if (cJSON_IsNumber(value_json)) + return value_json->valuedouble; + return fallback; +} + +/** + * @brief Get the boolean value for a specified key from a JSON object. + * + * @param[in] object JSON object + * @param[in] key The key of the boolean value in the JSON object. + * @param[in] fallback The fallback value if the boolean value is not + * available. + * + * @return The boolean value out of the JSON object with key "key", if any. + * The fallback value otherwise. + */ +static int +json_object_item_boolean (cJSON *object, char *key, int fallback) +{ + cJSON *value_json; + + value_json = cJSON_GetObjectItemCaseSensitive(object, key); + if (cJSON_IsTrue(value_json)) + return 1; + else if (cJSON_IsFalse(value_json)) + return 0; + return fallback; +} + /* CPE data. */ @@ -495,14 +563,14 @@ init_cpe_info_iterator_all (iterator_t* iterator, get_data_t *get) DEF_ACCESS (cpe_info_iterator_title, GET_ITERATOR_COLUMN_COUNT); /** - * @brief Get the status from a CPE iterator. + * @brief Get the deprecation status from a CPE iterator. * * @param[in] iterator Iterator. * - * @return The Status of the CPE, or NULL if iteration is complete. Freed by - * cleanup_iterator. + * @return The deprecation status of the CPE, or NULL if iteration is complete. + * Freed by cleanup_iterator. */ -DEF_ACCESS (cpe_info_iterator_status, GET_ITERATOR_COLUMN_COUNT + 1); +DEF_ACCESS (cpe_info_iterator_deprecated, GET_ITERATOR_COLUMN_COUNT + 1); /** * @brief Get the highest severity Score of all CVE's referencing this cpe. @@ -512,7 +580,7 @@ DEF_ACCESS (cpe_info_iterator_status, GET_ITERATOR_COLUMN_COUNT + 1); * @return The highest severity score of the CPE, * or NULL if iteration is complete. Freed by cleanup_iterator. */ -DEF_ACCESS (cpe_info_iterator_severity, GET_ITERATOR_COLUMN_COUNT + 3); +DEF_ACCESS (cpe_info_iterator_severity, GET_ITERATOR_COLUMN_COUNT + 2); /** * @brief Get the Number of CVE's referencing this cpe from a CPE iterator. @@ -522,17 +590,17 @@ DEF_ACCESS (cpe_info_iterator_severity, GET_ITERATOR_COLUMN_COUNT + 3); * @return The Number of references to the CPE, or NULL if iteration is * complete. Freed by cleanup_iterator. */ -DEF_ACCESS (cpe_info_iterator_cve_refs, GET_ITERATOR_COLUMN_COUNT + 4); +DEF_ACCESS (cpe_info_iterator_cve_refs, GET_ITERATOR_COLUMN_COUNT + 3); /** - * @brief Get the NVD ID for this CPE. + * @brief Get the NVD assigned cpeNameId for this CPE. * * @param[in] iterator Iterator. * * @return The NVD ID of this CPE, or NULL if iteration is * complete. Freed by cleanup_iterator. */ -DEF_ACCESS (cpe_info_iterator_nvd_id, GET_ITERATOR_COLUMN_COUNT + 5); +DEF_ACCESS (cpe_info_iterator_cpe_name_id, GET_ITERATOR_COLUMN_COUNT + 4); /** * @brief Get the XML details / raw data for a given CPE ID. @@ -553,6 +621,44 @@ cpe_details_xml (const char *cpe_id) { return details_xml; } +/** + * @brief Initialise a CPE refrerences iterator. + * + * @param[in] iterator Iterator. + * @param[in] cpe CPE to get references of. + */ +void +init_cpe_reference_iterator (iterator_t *iterator, const char *cpe) +{ + gchar *quoted_cpe; + quoted_cpe = sql_quote (cpe); + init_iterator (iterator, + "SELECT ref, type FROM cpe_refs" + " WHERE cpe = (SELECT id FROM cpes WHERE uuid = '%s');", + quoted_cpe); + g_free (quoted_cpe); +} + +/** + * @brief Get the reference URL from CPE reference iterator. + * + * @param[in] iterator Iterator. + * + * @return The reference URL, or NULL if iteration is complete. Freed by + * cleanup_iterator. + */ +DEF_ACCESS (cpe_reference_iterator_href, 0); + +/** + * @brief Get the reference type from CPE reference iterator. + * + * @param[in] iterator Iterator. + * + * @return The reference type, or NULL if iteration is complete. Freed by + * cleanup_iterator. + */ +DEF_ACCESS (cpe_reference_iterator_type, 1); + /* CVE data. */ @@ -580,6 +686,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. * @@ -891,7 +1019,7 @@ init_cert_bund_adv_info_iterator (iterator_t* iterator, get_data_t *get, } /** - * @brief Initialise an CERT-Bund advisory (cert_bund_adv) info iterator not + * @brief Initialise an CERT-Bund advisory (cert_bund_adv) info iterator not * limited to a name. * * @param[in] iterator Iterator. @@ -1115,7 +1243,7 @@ init_dfn_cert_adv_info_iterator (iterator_t* iterator, get_data_t *get, } /** - * @brief Initialise an DFN-CERT advisory (dfn_cert_adv) info iterator + * @brief Initialise an DFN-CERT advisory (dfn_cert_adv) info iterator * not limited to a name. * * @param[in] iterator Iterator. @@ -1895,6 +2023,29 @@ update_cert_bund_advisories (int last_cert_update) /* SCAP update: CPEs. */ +/** + * @brief Convert a CPE name from formatted string to URI and SQL quote it. + * + * @param[in] name Name. + * + * @return URI converted uoted name. + */ +static gchar * +fs_to_uri_convert_and_quote_cpe_name (const char *name) +{ + gchar *name_converted, *name_decoded, *name_tilde, *quoted_name; + + name_converted = fs_cpe_to_uri_cpe (name); + name_decoded = g_uri_unescape_string (name_converted, NULL); + name_tilde = string_replace (name_decoded, + "~", "%7E", "%7e", NULL); + g_free (name_decoded); + g_free (name_converted); + quoted_name = sql_quote (name_tilde); + g_free (name_tilde); + return quoted_name; +} + /** * @brief Decode and SQL quote a CPE name. * @@ -1917,7 +2068,7 @@ decode_and_quote_cpe_name (const char *name) } /** - * @brief Insert a SCAP CPE. + * @brief Insert a SCAP CPE from XML. * * @param[in] inserts Pointer to SQL buffer. * @param[in] cpe_item CPE item XML element. @@ -1930,7 +2081,7 @@ static int insert_scap_cpe (inserts_t *inserts, element_t cpe_item, element_t item_metadata, int modification_time) { - gchar *name, *status, *deprecated, *nvd_id; + gchar *name, *status, *nvd_id; gchar *quoted_name, *quoted_title, *quoted_status, *quoted_nvd_id; element_t title; int first; @@ -1952,27 +2103,12 @@ insert_scap_cpe (inserts_t *inserts, element_t cpe_item, element_t item_metadata return -1; } - deprecated = element_attribute (item_metadata, - "deprecated-by-nvd-id"); - if (deprecated - && (g_regex_match_simple ("^[0-9]+$", (gchar *) deprecated, 0, 0) - == 0)) - { - g_warning ("%s: invalid deprecated-by-nvd-id: %s", - __func__, - deprecated); - g_free (name); - g_free (status); - return -1; - } - nvd_id = element_attribute (item_metadata, "nvd-id"); if (nvd_id == NULL) { g_warning ("%s: nvd_id missing", __func__); g_free (name); g_free (status); - g_free (deprecated); return -1; } @@ -2012,7 +2148,7 @@ insert_scap_cpe (inserts_t *inserts, element_t cpe_item, element_t item_metadata first = inserts_check_size (inserts); g_string_append_printf (inserts->statement, - "%s ('%s', '%s', '%s', %i, %i, '%s', %s, '%s')", + "%s ('%s', '%s', '%s', %i, %i, '%s', '%s')", first ? "" : ",", quoted_name, quoted_name, @@ -2020,7 +2156,6 @@ insert_scap_cpe (inserts_t *inserts, element_t cpe_item, element_t item_metadata modification_time, modification_time, quoted_status, - deprecated ? deprecated : "NULL", quoted_nvd_id); inserts->current_chunk_size++; @@ -2029,7 +2164,6 @@ insert_scap_cpe (inserts_t *inserts, element_t cpe_item, element_t item_metadata g_free (quoted_name); g_free (quoted_status); g_free (quoted_nvd_id); - g_free (deprecated); return 0; } @@ -2081,152 +2215,600 @@ insert_scap_cpe_details (inserts_t *inserts, element_t cpe_item) } /** - * @brief Update SCAP CPEs from a file. + * @brief Try to skip to the products list in a CPEs JSON parser. * - * @param[in] path Path to file. + * @param[in] parser Parser to skip elements in. + * @param[in] event Parser event structure. * * @return 0 success, -1 error. */ static int -update_scap_cpes_from_file (const gchar *path) +scap_cpes_json_skip_to_products (gvm_json_pull_parser_t *parser, + gvm_json_pull_event_t *event) { - int ret; - element_t cpe_item; - inserts_t inserts; - xml_file_iterator_t file_iterator; - gchar *error_message = NULL; - - file_iterator = xml_file_iterator_new (); - ret = xml_file_iterator_init_from_file_path (file_iterator, path, 1); - switch (ret) + gvm_json_pull_parser_next (parser, event); + if (event->type == GVM_JSON_PULL_EVENT_ERROR) { - case 0: - break; - case 2: - g_warning ("%s: Could not open file '%s' for XML file iterator: %s", - __func__, path, strerror(errno)); - xml_file_iterator_free (file_iterator); - return -1; - case 3: - g_warning ("%s: Could not create parser context for XML file iterator", - __func__); - xml_file_iterator_free (file_iterator); - return -1; - default: - g_warning ("%s: Could not initialize XML file iterator", - __func__); - xml_file_iterator_free (file_iterator); - return -1; + g_warning ("%s: Parser error: %s", __func__, event->error_message); + return -1; } - - sql_begin_immediate (); - - inserts_init (&inserts, - CPE_MAX_CHUNK_SIZE, - setting_secinfo_sql_buffer_threshold_bytes (), - "INSERT INTO scap2.cpes" - " (uuid, name, title, creation_time," - " modification_time, status, deprecated_by_id," - " nvd_id)" - " VALUES", - " ON CONFLICT (uuid) DO UPDATE" - " SET name = EXCLUDED.name," - " title = EXCLUDED.title," - " creation_time = EXCLUDED.creation_time," - " modification_time = EXCLUDED.modification_time," - " status = EXCLUDED.status," - " deprecated_by_id = EXCLUDED.deprecated_by_id," - " nvd_id = EXCLUDED.nvd_id"); - - cpe_item = xml_file_iterator_next (file_iterator, &error_message); - if (error_message) + else if (event->type != GVM_JSON_PULL_EVENT_OBJECT_START) { - g_warning ("%s: could not get first CPE XML element: %s", - __func__, error_message); - g_free (error_message); - goto fail; + g_warning ("%s: CPEs file content is not a JSON object.", __func__); + return -1; } - while (cpe_item) - { - gchar *modification_date; - int modification_time; - element_t item_metadata; - if (strcmp (element_name (cpe_item), "cpe-item")) + gboolean products_found = FALSE; + while (!products_found) + { + gvm_json_pull_parser_next (parser, event); + gvm_json_path_elem_t *path_tail = g_queue_peek_tail (event->path); + if (event->type == GVM_JSON_PULL_EVENT_ARRAY_START && path_tail && + path_tail->key && strcmp (path_tail->key, "products") == 0) { - element_free (cpe_item); - cpe_item = xml_file_iterator_next (file_iterator, &error_message); - if (error_message) - { - g_warning ("%s: could not get next CPE XML element: %s", - __func__, error_message); - g_free (error_message); - goto fail; - } - continue; + products_found = TRUE; } - - item_metadata = element_child (cpe_item, "meta:item-metadata"); - if (item_metadata == NULL) + else if (event->type == GVM_JSON_PULL_EVENT_ERROR) { - g_warning ("%s: item-metadata missing", __func__); - goto fail; + g_warning ("%s: Parser error: %s", __func__, event->error_message); + return -1; } - - modification_date = element_attribute (item_metadata, - "modification-date"); - if (modification_date == NULL) + else if (event->type == GVM_JSON_PULL_EVENT_OBJECT_END) { - g_warning ("%s: modification-date missing", __func__); - goto fail; + g_warning ("%s: Unexpected json object end.", __func__); + return -1; } + } + gvm_json_pull_parser_next (parser, event); - modification_time = parse_iso_time (modification_date); - g_free (modification_date); - - if (insert_scap_cpe (&inserts, cpe_item, item_metadata, - modification_time)) - goto fail; + return 0; +} - element_free (cpe_item); - cpe_item = xml_file_iterator_next (file_iterator, &error_message); - if (error_message) - { - g_warning ("%s: could not get next CPE XML element: %s", - __func__, error_message); - g_free (error_message); - error_message = NULL; - goto fail; - } - } +/** + * @brief Insert a SCAP CPE from JSON. + * + * @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, inserts_t *deprecated_by_inserts, + cJSON *product_item) +{ + cJSON *cpe_item; + char *name, *cpe_name_id, *last_modified, *title_text; + gchar *quoted_name, *quoted_title, *quoted_cpe_name_id; + cJSON *titles, *title; + time_t modification_time; + int deprecated; + int first; - inserts_run (&inserts, TRUE); - sql_commit (); - sql_begin_immediate(); + assert (inserts); - if (xml_file_iterator_rewind (file_iterator)) + cpe_item = cJSON_GetObjectItemCaseSensitive (product_item, "cpe"); + if (! cJSON_IsObject (cpe_item)) { - g_warning ("%s: Could not create parser context for XML file iterator" - " for details.", + g_warning ("%s: 'cpe' field in product missing or not an object", __func__); - goto fail; + return -1; } - // Extract and save details XML. - inserts_init (&inserts, - CPE_MAX_CHUNK_SIZE, - setting_secinfo_sql_buffer_threshold_bytes (), - "INSERT INTO scap2.cpe_details" - " (cpe_id, details_xml)" - " VALUES", - " ON CONFLICT (cpe_id) DO UPDATE" - " SET details_xml = EXCLUDED.details_xml"); - cpe_item = xml_file_iterator_next (file_iterator, &error_message); - if (error_message) + name = json_object_item_string (cpe_item, "cpeName"); + if (name == NULL) { - g_warning ("%s: could not get first CPE XML element for details: %s", - __func__, error_message); - g_free (error_message); + g_warning ("%s: 'cpeName' field missing or not a string", __func__); + return -1; + } + + cpe_name_id = json_object_item_string (cpe_item, "cpeNameId"); + if (cpe_name_id == NULL) + { + g_warning ("%s: 'cpeNameId' field missing or not a string", __func__); + return -1; + } + + last_modified = json_object_item_string (cpe_item, "lastModified"); + if (last_modified == NULL) + { + g_warning ("%s: 'lastModified' field missing or not a string", __func__); + return -1; + } + modification_time = parse_iso_time (last_modified); + + titles = cJSON_GetObjectItemCaseSensitive (cpe_item, "titles"); + if (! cJSON_IsArray (titles)) + { + g_warning ("%s: 'titles' field missing or not an array", __func__); + return -1; + } + + title_text = NULL; + cJSON_ArrayForEach (title, titles) + { + gchar *lang = json_object_item_string (title, "lang"); + if (lang && strcmp (lang, "en") == 0) + { + title_text = json_object_item_string (title, "title"); + break; + } + } + + deprecated = json_object_item_boolean (cpe_item, "deprecated", -1); + if (deprecated == -1) + { + g_warning ("%s: 'deprecated' field missing or not a boolean", __func__); + return -1; + } + + quoted_name = fs_to_uri_convert_and_quote_cpe_name (name); + if (deprecated) + { + cJSON *deprecated_by_array, *deprecated_by_item; + 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; + } + + cJSON_ArrayForEach (deprecated_by_item, deprecated_by_array) + { + char *deprecated_by_id; + 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); + + 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_cpe_name_id = sql_quote (cpe_name_id); + quoted_title = sql_quote (title_text ? title_text : ""); + + first = inserts_check_size (inserts); + + g_string_append_printf (inserts->statement, + "%s ('%s', '%s', '%s', %li, %li, %d, '%s')", + first ? "" : ",", + quoted_name, + quoted_name, + quoted_title, + modification_time, + modification_time, + deprecated, + quoted_cpe_name_id); + + inserts->current_chunk_size++; + + g_free (quoted_title); + g_free (quoted_name); + g_free (quoted_cpe_name_id); + + return 0; +} + +/** + * @brief Insert a SCAP CPE from JSON. + * + * @param[in] inserts Pointer to SQL buffer. + * @param[in] product_item JSON object from the products list. + * + * @return 0 success, -1 error. + */ +static int +handle_json_cpe_refs (inserts_t *inserts, cJSON *product_item) +{ + cJSON *cpe_item, *refs, *refs_item; + gchar *name, *quoted_name; + + assert (inserts); + + cpe_item = cJSON_GetObjectItemCaseSensitive (product_item, "cpe"); + if (! cJSON_IsObject (cpe_item)) + { + g_warning ("%s: 'cpe' field in product missing or not an object", + __func__); + return -1; + } + + name = json_object_item_string (cpe_item, "cpeName"); + if (name == NULL) + { + g_warning ("%s: 'cpeName' field missing or not a string", __func__); + return -1; + } + + refs = cJSON_GetObjectItemCaseSensitive (cpe_item, "refs"); + if (! cJSON_IsArray (refs)) + { + g_debug ("%s: 'refs' field missing or not an array", __func__); + return 0; + } + + quoted_name = fs_to_uri_convert_and_quote_cpe_name (name); + cJSON_ArrayForEach (refs_item, refs) + { + int first; + char *ref, *type; + gchar *quoted_ref, *quoted_type; + ref = json_object_item_string (refs_item, "ref"); + if (ref == NULL) + { + g_warning ("%s: 'ref' field missing or not a string", __func__); + g_free (quoted_name); + return -1; + } + type = json_object_item_string (refs_item, "type"); + quoted_ref = sql_quote (ref ? ref : ""); + quoted_type = sql_quote (type ? type : ""); + + first = inserts_check_size (inserts); + + g_string_append_printf (inserts->statement, + "%s ('%s', '%s', '%s')", + first ? "" : ",", + quoted_name, + quoted_ref, + quoted_type); + + inserts->current_chunk_size++; + g_free (quoted_ref); + g_free (quoted_type); + } + g_free (quoted_name); + + return 0; +} + +/** + * @brief Update SCAP CPEs from a JSON file. + * + * @param[in] path Path to file. + * + * @return 0 success, -1 error. + */ +static int +update_scap_cpes_from_json_file (const gchar *path) +{ + inserts_t inserts, deprecated_by_inserts; + gvm_json_pull_parser_t parser; + gvm_json_pull_event_t event; + FILE *cpe_file; + + int fd = open (path, O_RDONLY); + + if (fd < 0) + { + g_warning ("%s: Failed to open CPE file '%s': %s", + __func__, path, strerror(errno)); + return -1; + } + + g_info ("Updating %s", path); + + cpe_file = gvm_gzip_open_file_reader_fd (fd); + if (cpe_file == NULL) + { + g_warning ("%s: Failed to open CPE file: %s", + __func__, + strerror (errno)); + return -1; + } + + gvm_json_pull_parser_init (&parser, cpe_file); + gvm_json_pull_event_init (&event); + if (scap_cpes_json_skip_to_products (&parser, &event)) + { + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_file); + return -1; + } + + sql_begin_immediate (); + inserts_init (&inserts, + CPE_MAX_CHUNK_SIZE, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpes" + " (uuid, name, title, creation_time," + " modification_time, deprecated," + " cpe_name_id)" + " VALUES", + " ON CONFLICT (uuid) DO UPDATE" + " SET name = EXCLUDED.name," + " title = EXCLUDED.title," + " creation_time = EXCLUDED.creation_time," + " modification_time = EXCLUDED.modification_time," + " deprecated = EXCLUDED.deprecated," + " 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; + cJSON *entry = gvm_json_pull_expand_container (&parser, &error_message); + if (error_message) + { + g_warning ("%s: Error expanding CVE item: %s", __func__, error_message); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + cJSON_Delete (entry); + fclose (cpe_file); + sql_commit (); + return -1; + } + if (handle_json_cpe_item (&inserts, &deprecated_by_inserts, entry)) + { + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + cJSON_Delete (entry); + fclose (cpe_file); + sql_commit (); + return -1; + } + cJSON_Delete (entry); + 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); + + // Reset and insert refs + fclose (cpe_file); + fd = open (path, O_RDONLY); + + if (fd < 0) + { + g_warning ("%s: Failed to open CPE file '%s': %s", + __func__, path, strerror(errno)); + return -1; + } + + cpe_file = gvm_gzip_open_file_reader_fd (fd); + if (cpe_file == NULL) + { + g_warning ("%s: Failed to open CPE file: %s", + __func__, + strerror (errno)); + return -1; + } + gvm_json_pull_parser_init (&parser, cpe_file); + + if (scap_cpes_json_skip_to_products (&parser, &event)) + { + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_file); + return -1; + } + + sql_begin_immediate (); + inserts_init (&inserts, 10, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpe_refs (cpe, ref, type)" + " SELECT scap2.cpes.id, new_refs.ref, new_refs.type" + " FROM scap2.cpes JOIN (VALUES ", + ") AS new_refs (cpe_name, ref, type)" + " ON scap2.cpes.name = cpe_name;"); + + while (event.type == GVM_JSON_PULL_EVENT_OBJECT_START) + { + gchar *error_message; + cJSON *entry = gvm_json_pull_expand_container (&parser, &error_message); + if (error_message) + { + g_warning ("%s: Error expanding CVE item: %s", __func__, error_message); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + cJSON_Delete (entry); + fclose (cpe_file); + sql_commit (); + return -1; + } + if (handle_json_cpe_refs (&inserts, entry)) + { + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + cJSON_Delete (entry); + fclose (cpe_file); + sql_commit (); + return -1; + } + cJSON_Delete (entry); + gvm_json_pull_parser_next (&parser, &event); + } + inserts_run (&inserts, TRUE); + sql_commit (); + gvm_json_pull_parser_cleanup (&parser); + + fclose (cpe_file); + return 0; +} + +/** + * @brief Update SCAP CPEs from an XML file. + * + * @param[in] path Path to file. + * + * @return 0 success, -1 error. + */ +static int +update_scap_cpes_from_xml_file (const gchar *path) +{ + int ret; + element_t cpe_item; + inserts_t inserts; + xml_file_iterator_t file_iterator; + gchar *error_message = NULL; + + file_iterator = xml_file_iterator_new (); + ret = xml_file_iterator_init_from_file_path (file_iterator, path, 1); + switch (ret) + { + case 0: + break; + case 2: + g_warning ("%s: Could not open file '%s' for XML file iterator: %s", + __func__, path, strerror(errno)); + xml_file_iterator_free (file_iterator); + return -1; + case 3: + g_warning ("%s: Could not create parser context for XML file iterator", + __func__); + xml_file_iterator_free (file_iterator); + return -1; + default: + g_warning ("%s: Could not initialize XML file iterator", + __func__); + xml_file_iterator_free (file_iterator); + return -1; + } + + sql_begin_immediate (); + + inserts_init (&inserts, + CPE_MAX_CHUNK_SIZE, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpes" + " (uuid, name, title, creation_time," + " modification_time, status," + " nvd_id)" + " VALUES", + " ON CONFLICT (uuid) DO UPDATE" + " SET name = EXCLUDED.name," + " title = EXCLUDED.title," + " creation_time = EXCLUDED.creation_time," + " modification_time = EXCLUDED.modification_time," + " status = EXCLUDED.status," + " nvd_id = EXCLUDED.nvd_id"); + + cpe_item = xml_file_iterator_next (file_iterator, &error_message); + if (error_message) + { + g_warning ("%s: could not get first CPE XML element: %s", + __func__, error_message); + g_free (error_message); + goto fail; + } + while (cpe_item) + { + gchar *modification_date; + int modification_time; + element_t item_metadata; + + if (strcmp (element_name (cpe_item), "cpe-item")) + { + element_free (cpe_item); + cpe_item = xml_file_iterator_next (file_iterator, &error_message); + if (error_message) + { + g_warning ("%s: could not get next CPE XML element: %s", + __func__, error_message); + g_free (error_message); + goto fail; + } + continue; + } + + item_metadata = element_child (cpe_item, "meta:item-metadata"); + if (item_metadata == NULL) + { + g_warning ("%s: item-metadata missing", __func__); + goto fail; + } + + modification_date = element_attribute (item_metadata, + "modification-date"); + if (modification_date == NULL) + { + g_warning ("%s: modification-date missing", __func__); + goto fail; + } + + modification_time = parse_iso_time (modification_date); + g_free (modification_date); + + if (insert_scap_cpe (&inserts, cpe_item, item_metadata, + modification_time)) + goto fail; + + element_free (cpe_item); + cpe_item = xml_file_iterator_next (file_iterator, &error_message); + if (error_message) + { + g_warning ("%s: could not get next CPE XML element: %s", + __func__, error_message); + g_free (error_message); + error_message = NULL; + goto fail; + } + } + + inserts_run (&inserts, TRUE); + sql_commit (); + sql_begin_immediate(); + + if (xml_file_iterator_rewind (file_iterator)) + { + g_warning ("%s: Could not create parser context for XML file iterator" + " for details.", + __func__); + goto fail; + } + + // Extract and save details XML. + inserts_init (&inserts, + CPE_MAX_CHUNK_SIZE, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpe_details" + " (cpe_id, details_xml)" + " VALUES", + " ON CONFLICT (cpe_id) DO UPDATE" + " SET details_xml = EXCLUDED.details_xml"); + cpe_item = xml_file_iterator_next (file_iterator, &error_message); + if (error_message) + { + g_warning ("%s: could not get first CPE XML element for details: %s", + __func__, error_message); + g_free (error_message); error_message = NULL; goto fail; } @@ -2287,21 +2869,49 @@ update_scap_cpes () int ret; full_path = g_build_filename (GVM_SCAP_DATA_DIR, - "official-cpe-dictionary_v2.2.xml", + "nvd-cpes.json.gz", NULL); + if (g_stat (full_path, &state)) + { + g_free (full_path); + full_path = g_build_filename (GVM_SCAP_DATA_DIR, + "nvd-cpes.json", + NULL); + } if (g_stat (full_path, &state)) { - g_warning ("%s: No CPE dictionary found at %s", + g_warning ("%s: No JSON CPE dictionary found at %s", __func__, full_path); g_free (full_path); - return -1; + + full_path = g_build_filename (GVM_SCAP_DATA_DIR, + "official-cpe-dictionary_v2.2.xml", + NULL); + + if (g_stat (full_path, &state)) + { + g_warning ("%s: No CPE dictionary found at %s", + __func__, + full_path); + g_free (full_path); + return -1; + } + + ret = update_scap_cpes_from_xml_file (full_path); + if (ret) + return -1; + + return 0; } g_info ("Updating CPEs"); - ret = update_scap_cpes_from_file (full_path); + ret = update_scap_cpes_from_json_file (full_path); + + g_free (full_path); + if (ret) return -1; @@ -2395,7 +3005,7 @@ insert_cve_products (element_t list, resource_t cve, product_element = element_next (product_element); } - + /* Add new CPEs. */ first_product = first_affected = 1; @@ -2421,7 +3031,7 @@ insert_cve_products (element_t list, resource_t cve, if (first_product == 0) { - /* Run the SQL for inserting new CPEs and add them to hashed_cpes + /* Run the SQL for inserting new CPEs and add them to hashed_cpes * so they can be looked up quickly when adding affected_products. */ iterator_t inserted_cpes; @@ -2657,180 +3267,264 @@ insert_cve_from_entry (element_t entry, element_t last_modified, return 0; } -/** - * @brief Get the string value for a specified key from a JSON object. - * - * @param[in] object JSON object - * @param[in] key The key of the string in the JSON object. - * - * @return The string out of the JSON object with key "key", if any. - * NULL otherwise. - */ -static char* -json_object_item_string (cJSON *object, char *key) -{ - cJSON *value_json; - - value_json = cJSON_GetObjectItemCaseSensitive(object, key); - if (cJSON_IsString(value_json)) - return value_json->valuestring; - return NULL; -} - -/** - * @brief Get the double value for a specified key from a JSON object. - * - * @param[in] object JSON object - * @param[in] key The key of the double value in the JSON object. - * @param[in] fallback The fallback value if the double value is not - * available. - * - * @return The double value out of the JSON object with key "key", if any. - * The fallback value otherwise. - */ -static double -json_object_item_double (cJSON *object, char *key, double fallback) -{ - cJSON *value_json; - - value_json = cJSON_GetObjectItemCaseSensitive(object, key); - if (cJSON_IsNumber(value_json)) - return value_json->valuedouble; - return 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. * @param[in] cve_id The id of the CVE to which the tree belongs. * @param[in] operator The operator for the match rules. + * @param[in] negate Whether the operator is negated. * * @return The (database) id of the node. */ static resource_t -save_node (resource_t parent_id, resource_t cve_id, char *operator) +save_node (resource_t cve_id, char *operator, gboolean negate) { return sql_int64_0 ("INSERT INTO scap2.cpe_match_nodes" - " (parent_id, cve_id, operator)" + " (cve_id, operator, negate)" " VALUES" - " (%llu, %llu, '%s')" + " (%llu, '%s', %d)" " RETURNING scap2.cpe_match_nodes.id;", - parent_id, cve_id, - operator); + operator, + negate ? 1 : 0); } /** - * @brief Add match rules to a node of a match rule tree* + * @brief Set the root id for a node of a cve match rule tree. * - * @param[in] id The id of the node the rules belong to. - * @param[in] match_rules The JSON object that contains the rules. + * @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 -add_cpe_match_rules (result_t id, cJSON *match_rules) +set_root_id (long int id, long int root_id) { - cJSON *match_rule; - cJSON *ver_se; - cJSON *cpe_js; - - gboolean vulnerable = FALSE; - char * cpe = NULL; - char * version_start_incl = NULL; - char * version_start_excl = NULL; - char * version_end_incl = NULL; - char * version_end_excl = NULL; - - cJSON_ArrayForEach(match_rule, match_rules) - { - char *quoted_cpe; - vulnerable = FALSE; - cpe = NULL; - version_start_incl = NULL; - version_start_excl = NULL; - version_end_incl = NULL; - version_end_excl = NULL; - - if (cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(match_rule, "vulnerable"))) - 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); - ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionStartIncluding"); - if (ver_se != NULL) - version_start_incl = ver_se->valuestring; - ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionStartExcluding"); - if (ver_se != NULL) - version_start_excl = ver_se->valuestring; - ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionEndIncluding"); - if (ver_se != NULL) - version_end_incl = ver_se->valuestring; - ver_se = cJSON_GetObjectItemCaseSensitive(match_rule, "versionEndExcluding"); - if (ver_se != NULL) - version_end_excl = ver_se->valuestring; - - sql - ("INSERT INTO scap2.cpe_match_range" - " (node_id, vulnerable, cpe," - " version_start_incl, version_start_excl," - " version_end_incl, version_end_excl)" - " VALUES" - " (%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 ("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. + * @brief Handle the references of a CVE. * - * @param[in] parent_id The parent_id of the nodes to insert - * (0 for the root node). - * @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. + * @param[in] cve_db_id The id of the CVE the references belong to. + * @param[in] cve_id The id of the CVE. + * @param[in] reference_json JSON array containing the references. + * + * @return 0 on success, -1 on error. */ -static void -load_nodes (resource_t parent_id, resource_t cveid, cJSON *nodes) +static int +handle_cve_references (resource_t cve_db_id, char * cve_id, + cJSON* reference_json) { - cJSON *node; - resource_t id; - cJSON *operator; - cJSON *cpe_match_rules; - cJSON *child_nodes; - - node = NULL; - id = 0; - operator = NULL; - cpe_match_rules = NULL; - child_nodes = NULL; - - if (nodes == NULL) - return; + cJSON *reference_data; + cJSON *tags; + + cJSON_ArrayForEach (reference_data, reference_json) + { + GString *tags_string; + char *url_value = json_object_item_string (reference_data, "url"); + if (url_value == NULL) + { + g_warning ("%s: url missing in reference for %s.", + __func__, cve_id); + return -1; + } + + tags = cJSON_GetObjectItemCaseSensitive (reference_data, "tags"); + if (cJSON_IsArray (tags)) + { + array_t *tags_array = make_array (); + tags_string = g_string_new ("{"); + + for (int i = 0; i < cJSON_GetArraySize (tags); i++) + { + cJSON *tag = cJSON_GetArrayItem (tags, i); + if (!cJSON_IsString (tag)) + { + g_warning ("%s: tag for %s is NULL or not a string.", + __func__, cve_id); + return -1; + } + if ((strcmp (tag->valuestring, "(null)") == 0) + || strlen (tag->valuestring) == 0) + { + g_warning ("%s: tag for %s is empty string or NULL.", + __func__, cve_id); + return -1; + } + array_add (tags_array, tag->valuestring); + } + + for (int i = 0; i < tags_array->len; i++) + { + gchar *tag = g_ptr_array_index (tags_array, i); + gchar *quoted_tag = sql_quote (tag); + + g_string_append (tags_string, quoted_tag); + + if (i < tags_array->len - 1) + g_string_append (tags_string, ","); + + g_free (quoted_tag); + } + g_string_append (tags_string, "}"); + g_ptr_array_free (tags_array, TRUE); + } + + gchar *quoted_url = sql_quote (url_value); + + sql ("INSERT INTO scap2.cve_references" + " (cve_id, url, tags)" + " VALUES" + " (%llu, '%s', '%s')" + " ON CONFLICT (cve_id, url) DO UPDATE" + " SET tags = EXCLUDED.tags;", + cve_db_id, + quoted_url, + tags_string->str ?: "{}"); + + g_free (quoted_url); + if (tags_string) + g_string_free (tags_string, TRUE); + } + return 0; +} + +/** + * @brief Handle the configurations of a CVE. + * + * @param[in] cve_db_id The id of the CVE the configurations belong to. + * @param[in] cve_id The id of the CVE. + * @param[in] configurations_json JSON array containing the configurations. + * + * @return 0 on success, -1 on error. + */ +static int +handle_cve_configurations (resource_t cve_db_id, char * cve_id, + cJSON* configurations_json) +{ + cJSON *configuration_item; + GString *software = g_string_new (""); + + cJSON_ArrayForEach (configuration_item, configurations_json) + { + cJSON *nodes_array, *node_item; + resource_t id, root_id; + char *config_operator; + int negate; + + nodes_array = cJSON_GetObjectItemCaseSensitive (configuration_item, + "nodes"); + if (!cJSON_IsArray (nodes_array)) + { + g_warning ("%s: 'nodes' field missing or not an array for %s.", + __func__, cve_id); + return -1; + } + + root_id = -1; + config_operator = json_object_item_string (configuration_item, + "operator"); + if (config_operator) + { + negate = json_object_item_boolean (configuration_item, "negate", 0); + id = save_node (cve_db_id, config_operator, negate); + set_root_id (id, id); + root_id = id; + } + + char *node_operator; + cJSON_ArrayForEach(node_item, nodes_array) + { + node_operator = json_object_item_string (node_item, "operator"); + if (node_operator == NULL) + { + g_warning ("%s: operator missing for %s.", __func__, cve_id); + return -1; + } + + negate = json_object_item_boolean (node_item, "negate", 0); + + cJSON *cpe_matches_array; + cpe_matches_array = cJSON_GetObjectItemCaseSensitive (node_item, + "cpeMatch"); + if (!cJSON_IsArray (cpe_matches_array)) + { + g_warning ("%s: cpeMatch missing or not an array for %s.", + __func__, cve_id); + return -1; + } + + id = save_node (cve_db_id, node_operator, negate); + + if (root_id < 0) + root_id = id; + + set_root_id (id, root_id); + + cJSON *cpe_match_item; + cJSON_ArrayForEach (cpe_match_item, cpe_matches_array) + { + char *match_criteria_id; + int vulnerable; + gchar *quoted_match_criteria_id; + + vulnerable = json_object_item_boolean (cpe_match_item, + "vulnerable", -1); + if (vulnerable == -1) + { + g_warning ("%s: vulnerable missing in cpeMatch for %s.", + __func__, cve_id); + return -1; + } + match_criteria_id = json_object_item_string (cpe_match_item, + "matchCriteriaId"); + if (match_criteria_id == NULL) + { + g_warning ("%s: matchCriteriaId missing in cpeMatch for %s.", + __func__, cve_id); + return -1; + } + quoted_match_criteria_id = sql_quote (match_criteria_id); - cJSON_ArrayForEach(node, nodes) - { - operator = cJSON_GetObjectItemCaseSensitive(node, "operator"); - if (operator) - id = save_node (parent_id, cveid, operator->valuestring); - 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); + sql ("INSERT INTO scap2.cpe_nodes_match_criteria" + " (node_id, vulnerable, match_criteria_id)" + " VALUES" + " (%llu, %d, '%s')", + id, + vulnerable ? 1 : 0, + quoted_match_criteria_id); + + if (vulnerable) + { + iterator_t cpe_matches; + init_cpe_match_string_matches_iterator ( + &cpe_matches, + quoted_match_criteria_id, + "scap2" + ); + while (next (&cpe_matches)) + g_string_append_printf (software, "%s ", cpe_matches_cpe_name (&cpe_matches)); + cleanup_iterator (&cpe_matches); + } + g_free (quoted_match_criteria_id); + } + } } + if (software->len > 0) + { + gchar *quoted_software = sql_quote (software->str); + sql ("UPDATE scap2.cves" + " SET products = '%s'" + " WHERE id = %llu;", + quoted_software, cve_db_id); + g_free (quoted_software); + } + g_string_free (software, TRUE); + + return 0; } /** @@ -2845,23 +3539,26 @@ static int handle_json_cve_item (cJSON *item) { cJSON *cve_json; - cJSON *cve_data_meta_json; - - char *cve_id; + char *cve_id, *vector; + double score_dbl; resource_t cve_db_id; - cve_json = cJSON_GetObjectItemCaseSensitive(item, "cve"); - cve_data_meta_json = cJSON_GetObjectItemCaseSensitive(cve_json, "CVE_data_meta"); - cve_id = json_object_item_string (cve_data_meta_json, "ID"); + cve_json = cJSON_GetObjectItemCaseSensitive (item, "cve"); + if (!cJSON_IsObject (cve_json)) + { + g_warning ("%s: 'cve' field is missing or not an object.", __func__); + return -1; + } + cve_id = json_object_item_string (cve_json, "id"); if (cve_id == NULL) { - g_warning("%s: ID missing.", __func__); + g_warning ("%s: cve id missing.", __func__); return -1; } char *published; time_t published_time; - published = json_object_item_string (item, "publishedDate"); + published = json_object_item_string (cve_json, "published"); if (published == NULL) { g_warning("%s: publishedDate missing for %s.", __func__, cve_id); @@ -2871,94 +3568,116 @@ handle_json_cve_item (cJSON *item) char *modified; time_t modified_time; - modified = json_object_item_string (item, "lastModifiedDate"); + modified = json_object_item_string (cve_json, "lastModified"); if (modified == NULL) { - g_warning("%s: lastModifiedDate missing for %s.", __func__, cve_id); + g_warning ("%s: lastModifiedDate missing for %s.", __func__, cve_id); return -1; } modified_time = parse_iso_time (modified); - cJSON *impact_json; - cJSON *base_metric_json; - char * cvss_key; - cJSON *cvss_json; - char * vector; - double score_dbl; + cJSON *metrics_json; + cJSON *best_cvss_metric_item = NULL; + gboolean cvss_metric_is_primary = FALSE; - impact_json = cJSON_GetObjectItemCaseSensitive(item, "impact"); - if (impact_json == NULL) + metrics_json = cJSON_GetObjectItemCaseSensitive (cve_json, "metrics"); + if (!cJSON_IsObject (metrics_json)) { - g_warning("%s: Impact missing for %s.", __func__, cve_id); + g_warning ("%s: Metrics missing or not an object for %s.", + __func__, cve_id); return -1; } - base_metric_json = cJSON_GetObjectItemCaseSensitive(impact_json, "baseMetricV4"); - if (base_metric_json != NULL) - cvss_key = "cvssV4"; - else + + const char *cvss_metric_keys[] = { + "cvssMetricV40", + "cvssMetricV31", + "cvssMetricV30", + "cvssMetricV2"}; + + score_dbl = SEVERITY_MISSING; + vector = NULL; + + for (int i = 0; i < 4; i++) { - base_metric_json = cJSON_GetObjectItemCaseSensitive(impact_json, "baseMetricV3"); - if (base_metric_json != NULL) - cvss_key = "cvssV3"; - else + cJSON *cvss_metric_array + = cJSON_GetObjectItemCaseSensitive (metrics_json, cvss_metric_keys[i]); + if (cJSON_IsArray (cvss_metric_array) + && cJSON_GetArraySize (cvss_metric_array) > 0) { - base_metric_json = cJSON_GetObjectItemCaseSensitive(impact_json, "baseMetricV2"); - if (base_metric_json != NULL) - cvss_key = "cvssV2"; - else - cvss_key = NULL; + cJSON *cvss_metric_item; + cJSON_ArrayForEach (cvss_metric_item, cvss_metric_array) + { + char *source_type + = json_object_item_string (cvss_metric_item, "type"); + if (source_type == NULL) + { + g_warning ("%s: type missing in CVSS metric for %s.", + __func__, cve_id); + return -1; + } + if (strcmp (source_type, "Primary") == 0) + cvss_metric_is_primary = TRUE; + + if (cvss_metric_is_primary) + { + best_cvss_metric_item = cvss_metric_item; + break; + } + else if (best_cvss_metric_item == NULL) + best_cvss_metric_item = cvss_metric_item; + } + + if (cvss_metric_is_primary) + break; } } - if (cvss_key != NULL) + + if (best_cvss_metric_item) { - cvss_json = cJSON_GetObjectItemCaseSensitive(base_metric_json, cvss_key); - if (cvss_json == NULL) + cJSON *cvss_json + = cJSON_GetObjectItemCaseSensitive (best_cvss_metric_item, "cvssData"); + if (!cJSON_IsObject (cvss_json)) { - g_warning("%s: %s missing for %s.", __func__, cvss_key, cve_id); + g_warning ("%s: cvssData missing or not an object for %s.", + __func__, cve_id); return -1; } - score_dbl = json_object_item_double (cvss_json, "baseScore", SEVERITY_MISSING); + + score_dbl = json_object_item_double (cvss_json, + "baseScore", + SEVERITY_MISSING); if (score_dbl == SEVERITY_MISSING) { - g_warning("%s: baseScore missing in %s for %s.", __func__, cvss_key, cve_id); + g_warning ("%s: baseScore missing for %s.", __func__, cve_id); return -1; } + vector = json_object_item_string (cvss_json, "vectorString"); if (vector == NULL) { - g_warning("%s: vectorString missing for %s.", __func__, cve_id); + g_warning ("%s: vectorString missing for %s.", __func__, cve_id); return -1; } } - else - { - score_dbl = SEVERITY_MISSING; - vector = NULL; - } - cJSON *description_json; - cJSON *description_data_json; + cJSON *descriptions_json; cJSON *description_item_json; char *description_value; - description_json = cJSON_GetObjectItemCaseSensitive(cve_json, "description"); - if (description_json == NULL) - { - g_warning("%s: description missing for %s.", __func__, cve_id); - return -1; - } - - description_data_json = cJSON_GetObjectItemCaseSensitive(description_json, "description_data"); - if (description_data_json == NULL) + descriptions_json = cJSON_GetObjectItemCaseSensitive (cve_json, + "descriptions"); + if (!cJSON_IsArray (descriptions_json)) { - g_warning("%s: description_data missing for %s.", __func__, cve_id); + g_warning ("%s: descriptions for %s is missing or not an array.", + __func__, cve_id); return -1; } - cJSON_ArrayForEach (description_item_json, description_data_json) + cJSON_ArrayForEach (description_item_json, descriptions_json) { char *lang = json_object_item_string (description_item_json, "lang"); - if (lang != NULL && strcmp(lang, "en") == 0) - description_value = json_object_item_string (description_item_json, "value"); + if (lang != NULL && strcmp (lang, "en") == 0) + description_value = json_object_item_string (description_item_json, + "value"); } char *quoted_description = sql_quote (description_value); @@ -2990,24 +3709,30 @@ handle_json_cve_item (cJSON *item) g_free (quoted_description); - cJSON *configurations_json; - cJSON *nodes_json; - - configurations_json = - cJSON_GetObjectItemCaseSensitive(item, "configurations"); - if (configurations_json == NULL) + cJSON *configurations_array; + configurations_array = cJSON_GetObjectItemCaseSensitive (cve_json, + "configurations"); + if (!cJSON_IsArray (configurations_array)) { - g_warning("%s: configurations missing for %s.", __func__, cve_id); + g_warning ("%s: configurations for %s is missing or not an array.", + __func__, cve_id); return -1; } - nodes_json = - cJSON_GetObjectItemCaseSensitive(configurations_json, "nodes"); - if (nodes_json == NULL) + + if (handle_cve_configurations (cve_db_id, cve_id, configurations_array)) + return -1; + + cJSON *references_array; + references_array = cJSON_GetObjectItemCaseSensitive (cve_json, "references"); + if (!cJSON_IsArray (references_array)) { - g_warning("%s: nodes missing for %s.", __func__, cve_id); + g_warning ("%s: references for %s is missing or not an array.", + __func__, cve_id); return -1; } - load_nodes (0, cve_db_id, nodes_json); + + if (handle_cve_references (cve_db_id, cve_id, references_array)) + return -1; return 0; } @@ -3046,7 +3771,7 @@ update_cve_json (const gchar *cve_path, GHashTable *hashed_cpes) g_info ("Updating %s", full_path); - cve_file = fdopen (fd, "r"); + cve_file = gvm_gzip_open_file_reader_fd (fd); if (cve_file == NULL) { g_warning ("%s: Failed to open CVE file: %s", @@ -3070,7 +3795,7 @@ update_cve_json (const gchar *cve_path, GHashTable *hashed_cpes) gvm_json_pull_parser_next (&parser, &event); gvm_json_path_elem_t *path_tail = g_queue_peek_tail (event.path); if (event.type == GVM_JSON_PULL_EVENT_ARRAY_START && path_tail - && path_tail->key && strcmp (path_tail->key, "CVE_Items") == 0) + && path_tail->key && strcmp (path_tail->key, "vulnerabilities") == 0) { cve_items_found = TRUE; } @@ -3098,7 +3823,7 @@ update_cve_json (const gchar *cve_path, GHashTable *hashed_cpes) entry = gvm_json_pull_expand_container (&parser, &error_message); if (error_message) { - g_warning ("%s: Error expanding CVE item: %s", __func__, error_message); + g_warning ("%s: Error expanding vulnerability item: %s", __func__, error_message); gvm_json_pull_event_cleanup (&event); gvm_json_pull_parser_cleanup (&parser); cJSON_Delete (entry); @@ -3283,7 +4008,8 @@ update_scap_cves () gboolean read_json = FALSE; while ((cve_path = g_dir_read_name (dir))) { - if (fnmatch ("nvdcve-1.1-*.json", cve_path, 0) == 0) + if (fnmatch ("nvdcve-2.0-*.json.gz", cve_path, 0) == 0 || + fnmatch ("nvdcve-2.0-*.json", cve_path, 0) == 0) { read_json = TRUE; break; @@ -3294,7 +4020,9 @@ update_scap_cves () count = 0; while ((cve_path = g_dir_read_name (dir))) { - if ((fnmatch ("nvdcve-1.1-*.json", cve_path, 0) == 0) && read_json) + if ((fnmatch ("nvdcve-2.0-*.json.gz", cve_path, 0) == 0 || + fnmatch ("nvdcve-2.0-*.json", cve_path, 0) == 0) + && read_json) { if (update_cve_json (cve_path, hashed_cpes)) { @@ -3327,6 +4055,369 @@ update_scap_cves () return 0; } +/** + * @brief Update SCAP affected products. + * + * Assume that the databases are attached. + */ +static void +update_scap_affected_products () +{ + g_info ("Updating affected products"); + + sql ("INSERT INTO scap2.affected_products" + " SELECT DISTINCT scap2.cpe_match_nodes.cve_id, scap2.cpes.id" + " FROM scap2.cpe_match_nodes, scap2.cpe_nodes_match_criteria," + " scap2.cpe_matches, scap2.cpes" + " WHERE scap2.cpe_match_nodes.id = scap2.cpe_nodes_match_criteria.node_id" + " AND scap2.cpe_nodes_match_criteria.vulnerable = 1" + " AND scap2.cpe_nodes_match_criteria.match_criteria_id =" + " scap2.cpe_matches.match_criteria_id" + " AND scap2.cpe_matches.cpe_name_id = scap2.cpes.cpe_name_id;"); +} + +/** + * @brief Insert a SCAP CPE match string from JSON. + * + * @param[in] inserts Pointer to SQL buffer for match string entries. + * @param[in] matches_inserts Pointer to SQL buffer for match string matches. + * @param[in] match_string_item JSON object from the matchStrings list. + * + * @return 0 success, -1 error. + */ +static int +handle_json_cpe_match_string (inserts_t *inserts, inserts_t *matches_inserts, + cJSON *match_string_item) +{ + cJSON *match_string, *matches_array; + char *criteria, *match_criteria_id, *status, *ver_se; + gchar *quoted_version_start_incl, *quoted_version_start_excl; + gchar *quoted_version_end_incl, *quoted_version_end_excl; + gchar *quoted_criteria, *quoted_match_criteria_id; + int first; + + assert (inserts); + assert (matches_inserts); + + match_string = cJSON_GetObjectItemCaseSensitive (match_string_item, + "matchString"); + if (!cJSON_IsObject (match_string)) + { + g_warning ("%s: 'matchString' field is missing or not an object", + __func__); + return -1; + } + + criteria = json_object_item_string (match_string, "criteria"); + if (criteria == NULL) + { + g_warning ("%s: 'criteria' field missing or not a string", __func__); + return -1; + } + + match_criteria_id = json_object_item_string (match_string, + "matchCriteriaId"); + if (match_criteria_id == NULL) + { + g_warning ("%s: 'matchCriteriaId' field missing or not a string", + __func__); + return -1; + } + + status = json_object_item_string (match_string, "status"); + if (status == NULL) + { + g_warning ("%s: 'status' field missing or not a string", __func__); + return -1; + } + + ver_se = json_object_item_string (match_string, "versionStartIncluding"); + if (ver_se == NULL) + quoted_version_start_incl = g_strdup ("NULL"); + else + quoted_version_start_incl = g_strdup_printf ("'%s'", ver_se); + + ver_se = json_object_item_string (match_string, "versionStartExcluding"); + if (ver_se == NULL) + quoted_version_start_excl = g_strdup ("NULL"); + else + quoted_version_start_excl = g_strdup_printf ("'%s'", ver_se); + + ver_se = json_object_item_string (match_string, "versionEndIncluding"); + if (ver_se == NULL) + quoted_version_end_incl = g_strdup ("NULL"); + else + quoted_version_end_incl = g_strdup_printf ("'%s'", ver_se); + + ver_se = json_object_item_string (match_string, "versionEndExcluding"); + if (ver_se == NULL) + quoted_version_end_excl = g_strdup ("NULL"); + else + quoted_version_end_excl = g_strdup_printf ("'%s'", ver_se); + + quoted_match_criteria_id = sql_quote (match_criteria_id); + quoted_criteria = fs_to_uri_convert_and_quote_cpe_name (criteria); + + first = inserts_check_size (inserts); + + g_string_append_printf (inserts->statement, + "%s ('%s', '%s', %s, %s, %s, %s, '%s')", + first ? "" : ",", + quoted_match_criteria_id, + quoted_criteria, + quoted_version_start_incl, + quoted_version_start_excl, + quoted_version_end_incl, + quoted_version_end_excl, + status); + + inserts->current_chunk_size++; + + g_free (quoted_criteria); + g_free (quoted_version_start_incl); + g_free (quoted_version_start_excl); + g_free (quoted_version_end_incl); + g_free (quoted_version_end_excl); + + matches_array = cJSON_GetObjectItemCaseSensitive (match_string, "matches"); + + if (cJSON_IsArray (matches_array) && cJSON_GetArraySize (matches_array) > 0) + { + cJSON *match_item; + cJSON_ArrayForEach (match_item, matches_array) + { + char *cpe_name_id, *cpe_name; + gchar *quoted_cpe_name_id, *quoted_cpe_name; + + cpe_name_id = json_object_item_string (match_item, "cpeNameId"); + if (cpe_name_id == NULL) + { + g_warning ("%s: 'cpeNameId' field missing or not a string", + __func__); + g_free (quoted_match_criteria_id); + return -1; + } + + cpe_name = json_object_item_string (match_item, "cpeName"); + if (cpe_name == NULL) + { + g_warning ("%s: 'cpe_name' field missing or not a string", + __func__); + g_free (quoted_match_criteria_id); + return -1; + } + + quoted_cpe_name_id = sql_quote (cpe_name_id); + quoted_cpe_name = fs_to_uri_convert_and_quote_cpe_name (cpe_name); + + first = inserts_check_size (matches_inserts); + + g_string_append_printf (matches_inserts->statement, + "%s ('%s', '%s', '%s')", + first ? "" : ",", + quoted_match_criteria_id, + quoted_cpe_name_id, + quoted_cpe_name); + + matches_inserts->current_chunk_size++; + + g_free (quoted_cpe_name_id); + g_free (quoted_cpe_name); + } + } + + g_free (quoted_match_criteria_id); + return 0; +} + +/** + * @brief Updates the CPE match strings in the SCAP database. + * + * @return 0 success, -1 error. + */ +static int +update_scap_cpe_match_strings () +{ + gchar *current_json_path; + FILE *cpe_match_strings_file; + gvm_json_pull_event_t event; + gvm_json_pull_parser_t parser; + inserts_t inserts, matches_inserts; + + current_json_path = g_build_filename (GVM_SCAP_DATA_DIR, + "cpe_match_strings.json.gz", + NULL); + int fd = open(current_json_path, O_RDONLY); + + if (fd < 0 && errno == ENOENT) + { + g_free (current_json_path); + current_json_path = g_build_filename (GVM_SCAP_DATA_DIR, + "cpe_match_strings.json", + NULL); + fd = open(current_json_path, O_RDONLY); + } + + if (fd < 0) + { + int ret; + if (errno == ENOENT) + { + g_info ("%s: CPE match strings file '%s' not found", + __func__, current_json_path); + ret = 0; + } + else + { + g_warning ("%s: Failed to open CPE match strings file: %s", + __func__, strerror (errno)); + ret = -1; + } + g_free (current_json_path); + return ret; + } + + cpe_match_strings_file = gvm_gzip_open_file_reader_fd (fd); + + if (cpe_match_strings_file == NULL) + { + g_warning ("%s: Failed to convert file descriptor to FILE*: %s", + __func__, + strerror (errno)); + g_free (current_json_path); + close (fd); + return -1; + } + + g_info ("Updating CPE match strings from %s", current_json_path); + g_free (current_json_path); + + gvm_json_pull_event_init (&event); + gvm_json_pull_parser_init (&parser, cpe_match_strings_file); + + gvm_json_pull_parser_next (&parser, &event); + + if (event.type == GVM_JSON_PULL_EVENT_OBJECT_START) + { + gboolean cpe_match_strings_found = FALSE; + while (!cpe_match_strings_found) + { + gvm_json_pull_parser_next (&parser, &event); + gvm_json_path_elem_t *path_tail = g_queue_peek_tail (event.path); + if (event.type == GVM_JSON_PULL_EVENT_ARRAY_START + && path_tail && strcmp (path_tail->key, "matchStrings") == 0) + { + cpe_match_strings_found = TRUE; + } + else if (event.type == GVM_JSON_PULL_EVENT_ERROR) + { + g_warning ("%s: Parser error: %s", __func__, event.error_message); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + else if (event.type == GVM_JSON_PULL_EVENT_OBJECT_END + && g_queue_is_empty (event.path)) + { + g_warning ("%s: Unexpected json object end. Missing matchStrings field", + __func__); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + } + + sql_begin_immediate (); + inserts_init (&inserts, + CPE_MAX_CHUNK_SIZE, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpe_match_strings" + " (match_criteria_id, criteria, version_start_incl," + " version_start_excl, version_end_incl, version_end_excl," + " status)" + " VALUES ", + " ON CONFLICT (match_criteria_id) DO UPDATE" + " SET criteria = EXCLUDED.criteria," + " version_start_incl = EXCLUDED.version_start_incl," + " version_start_excl = EXCLUDED.version_start_excl," + " version_end_incl = EXCLUDED.version_end_incl," + " version_end_excl = EXCLUDED.version_end_excl," + " status = EXCLUDED.status"); + + inserts_init (&matches_inserts, 10, + setting_secinfo_sql_buffer_threshold_bytes (), + "INSERT INTO scap2.cpe_matches" + " (match_criteria_id, cpe_name_id, cpe_name)" + " VALUES ", + ""); + + gvm_json_pull_parser_next (&parser, &event); + while (event.type == GVM_JSON_PULL_EVENT_OBJECT_START) + { + gchar *error_message; + cJSON *cpe_match_string_item + = gvm_json_pull_expand_container (&parser, &error_message); + if (error_message) + { + g_warning ("%s: Error expanding match string item: %s", + __func__, error_message); + cJSON_Delete (cpe_match_string_item); + inserts_free (&inserts); + inserts_free (&matches_inserts); + sql_commit (); + g_warning ("Update of CPE match strings failed"); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + if (handle_json_cpe_match_string (&inserts, + &matches_inserts, + cpe_match_string_item)) + { + cJSON_Delete (cpe_match_string_item); + inserts_free (&inserts); + inserts_free (&matches_inserts); + sql_commit (); + g_warning ("Update of CPE match strings failed"); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + cJSON_Delete (cpe_match_string_item); + gvm_json_pull_parser_next (&parser, &event); + } + } + else if (event.type == GVM_JSON_PULL_EVENT_ERROR) + { + g_warning ("%s: Parser error: %s", __func__, event.error_message); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + else + { + g_warning ("%s: CVE match strings file is not a JSON object.", + __func__); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return -1; + } + + inserts_run (&inserts, TRUE); + inserts_run (&matches_inserts, TRUE); + sql_commit (); + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (cpe_match_strings_file); + return 0; +} + /** * @brief Adds a EPSS score entry to an SQL inserts buffer. * @@ -3365,7 +4456,7 @@ if (failure_condition) { \ /** * @brief Updates the base EPSS scores table in the SCAP database. - * + * * @return 0 success, -1 error. */ static int @@ -3380,10 +4471,19 @@ update_epss_scores () inserts_t inserts; current_json_path = g_build_filename (GVM_SCAP_DATA_DIR, - "epss-scores-current.json", + "epss-scores-current.json.gz", NULL); int fd = open(current_json_path, O_RDONLY); + if (fd < 0 && errno == ENOENT) + { + g_free (current_json_path); + current_json_path = g_build_filename (GVM_SCAP_DATA_DIR, + "epss-scores-current.json", + NULL); + fd = open(current_json_path, O_RDONLY); + } + if (fd < 0) { int ret; @@ -3403,7 +4503,7 @@ update_epss_scores () return ret; } - epss_scores_file = fdopen(fd, "r"); + epss_scores_file = gvm_gzip_open_file_reader_fd (fd); if (epss_scores_file == NULL) { g_warning ("%s: Failed to convert file descriptor to FILE*: %s", @@ -4220,7 +5320,7 @@ update_vt_scap_extra_data () " WHERE epss_candidates.vt_oid = nvts.oid" " AND epss_candidates.rank = 1;"); } - + /** * @brief Update CERT data that depends on SCAP. */ @@ -4521,6 +5621,15 @@ update_scap (gboolean reset_scap_db) return -1; } + g_debug ("%s: update cpe match strings", __func__); + setproctitle ("Syncing SCAP: Updating CPE Match Strings"); + + if (update_scap_cpe_match_strings () == -1) + { + abort_scap_update (); + return -1; + } + g_debug ("%s: update cves", __func__); setproctitle ("Syncing SCAP: Updating CVEs"); @@ -4530,6 +5639,11 @@ update_scap (gboolean reset_scap_db) return -1; } + g_debug ("%s: update affected_products", __func__); + setproctitle ("Syncing SCAP: Updating affected products"); + + update_scap_affected_products (); + g_debug ("%s: updating user defined data", __func__); g_debug ("%s: update epss", __func__); @@ -4649,7 +5763,8 @@ manage_rebuild_scap (GSList *log_config, const db_conn_info_t *database) g_info (" Rebuilding SCAP data"); - ret = manage_option_setup (log_config, database); + ret = manage_option_setup (log_config, database, + 0 /* avoid_db_check_inserts */); if (ret) return -1; diff --git a/src/manage_sql_secinfo.h b/src/manage_sql_secinfo.h index 5e8ad4761..71f00c091 100644 --- a/src/manage_sql_secinfo.h +++ b/src/manage_sql_secinfo.h @@ -101,8 +101,8 @@ * @brief Filter columns for CVE iterator. */ #define CPE_INFO_ITERATOR_FILTER_COLUMNS \ - { GET_ITERATOR_FILTER_COLUMNS, "title", "status", \ - "deprecated_by_id", "severity", "cves", "nvd_id", \ + { GET_ITERATOR_FILTER_COLUMNS, "title", "deprecated", \ + "severity", "cves", "cpe_name_id", \ NULL } /** @@ -114,11 +114,10 @@ { "''", "_owner", KEYWORD_TYPE_STRING }, \ { "0", NULL, KEYWORD_TYPE_INTEGER }, \ { "title", NULL, KEYWORD_TYPE_STRING }, \ - { "status", NULL, KEYWORD_TYPE_STRING }, \ - { "deprecated_by_id", NULL, KEYWORD_TYPE_INTEGER }, \ + { "deprecated", NULL, KEYWORD_TYPE_INTEGER }, \ { "severity", NULL, KEYWORD_TYPE_DOUBLE }, \ { "cve_refs", "cves", KEYWORD_TYPE_INTEGER }, \ - { "nvd_id", NULL, KEYWORD_TYPE_INTEGER }, \ + { "cpe_name_id", NULL, KEYWORD_TYPE_STRING }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } diff --git a/src/manage_sql_tests.c b/src/manage_sql_tests.c index d6b5e4e1a..a547b983c 100644 --- a/src/manage_sql_tests.c +++ b/src/manage_sql_tests.c @@ -61,104 +61,6 @@ Ensure (manage_sql, validate_results_port_validates) FAIL ("udp"); } -#define CMP(one, two, ret) assert_that (streq_ignore_ws (one, two), is_equal_to (ret)) - -#define EQ2(one, two) CMP(one, two, 1); CMP(two, one, 1) -#define EQ(string) CMP(string, string, 1) - -Ensure (manage_sql, streq_ignore_ws_finds_equal) -{ - EQ ("abc"); - EQ (" abc"); - EQ ("abc "); - EQ ("ab c"); - EQ (""); - EQ ("."); - EQ (" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-=_)(*&^%$#@!~\"':}{<>?"); - EQ ("three little words"); -} - -Ensure (manage_sql, streq_ignore_ws_finds_equal_despite_ws) -{ - EQ2 ("abc", " abc"); - EQ2 ("abc", "abc "); - EQ2 ("abc", "ab c"); - EQ2 ("abc", " a b c "); - - EQ2 ("abc", "\nabc"); - EQ2 ("abc", "abc\n"); - EQ2 ("abc", "ab\nc"); - EQ2 ("abc", "\na\nb\n\n\n\nc\n"); - - EQ2 ("abc", "\tabc"); - EQ2 ("abc", "abc\t"); - EQ2 ("abc", "ab\tc"); - EQ2 ("abc", "\ta\tb\t\t\t\tc\t"); - - EQ2 ("abcd", "\ta\nb \t\nc \t\t\n\nd\t\n "); - - EQ2 ("", " "); - EQ2 ("", "\t"); - EQ2 ("", "\n"); - EQ2 ("", " "); - EQ2 ("", "\t\t"); - EQ2 ("", "\n\n"); - EQ2 ("", " \n\t \n\n\t\t"); - - EQ2 (" \n\t \n\n\t\t", " \n\t \n\n\t\t"); -} - -#define DIFF(one, two) CMP(one, two, 0); CMP(two, one, 0) - -Ensure (manage_sql, streq_ignore_ws_finds_diff) -{ - DIFF ("abc", "abcd"); - DIFF ("abc", "dabc"); - DIFF ("abc", "abdc"); - DIFF ("abc", "xyz"); - DIFF ("abc", ""); - DIFF ("abc", "."); - DIFF ("abc", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-=_)(*&^%$#@!~\"':}{<>?"); -} - -Ensure (manage_sql, streq_ignore_ws_finds_diff_incl_ws) -{ - DIFF ("zabc", " abc"); - DIFF ("zabc", "abc "); - DIFF ("zabc", "ab c"); - DIFF ("zabc", " a b c "); - - DIFF ("zabc", "\nabc"); - DIFF ("zabc", "abc\n"); - DIFF ("zabc", "ab\nc"); - DIFF ("zabc", "\na\nb\n\n\n\nc\n"); - - DIFF ("zabc", "\tabc"); - DIFF ("zabc", "abc\t"); - DIFF ("zabc", "ab\tc"); - DIFF ("zabc", "\ta\tb\t\t\t\tc\t"); - - DIFF ("zabcd", "\ta\nb \t\nc \t\t\n\nd\t\n "); - - DIFF ("a", " "); - DIFF ("a", "\t"); - DIFF ("a", "\n"); - DIFF ("a", " "); - DIFF ("a", "\t\t"); - DIFF ("a", "\n\n"); - DIFF ("a", " \n\t \n\n\t\t"); - - DIFF ("a \n\t \n\n\t\t", " \n\t \n\n\t\t"); - DIFF (" \n\t \na\n\t\t", " \n\t \n\n\t\t"); - DIFF (" \n\t \n\n\t\ta", " \n\t \n\n\t\t"); -} - -Ensure (manage_sql, streq_ignore_ws_handles_null) -{ - EQ (NULL); - DIFF ("abc", NULL); -} - /* Test suite. */ int @@ -170,12 +72,6 @@ main (int argc, char **argv) add_test_with_context (suite, manage_sql, validate_results_port_validates); - add_test_with_context (suite, manage_sql, streq_ignore_ws_finds_equal); - add_test_with_context (suite, manage_sql, streq_ignore_ws_finds_equal_despite_ws); - add_test_with_context (suite, manage_sql, streq_ignore_ws_finds_diff); - add_test_with_context (suite, manage_sql, streq_ignore_ws_finds_diff_incl_ws); - add_test_with_context (suite, manage_sql, streq_ignore_ws_handles_null); - if (argc > 1) return run_single_test (suite, argv[1], create_text_reporter ()); diff --git a/src/manage_sql_tls_certificates.c b/src/manage_sql_tls_certificates.c index e51f33eee..5fa63dcd6 100644 --- a/src/manage_sql_tls_certificates.c +++ b/src/manage_sql_tls_certificates.c @@ -1747,9 +1747,9 @@ cleanup_tls_certificate_encoding () if (g_utf8_validate (subject_dn, -1, NULL) == FALSE || g_utf8_validate (issuer_dn, -1, NULL) == FALSE) { - gchar *quoted_subject_dn + gchar *quoted_subject_dn = sql_ascii_escape_and_quote (subject_dn, NULL); - gchar *quoted_issuer_dn + gchar *quoted_issuer_dn = sql_ascii_escape_and_quote (issuer_dn, NULL); sql ("UPDATE tls_certificates" diff --git a/src/manage_utils.c b/src/manage_utils.c index 674eb0008..569ac8e36 100644 --- a/src/manage_utils.c +++ b/src/manage_utils.c @@ -210,8 +210,11 @@ level_min_severity (const char *level) return SEVERITY_FP; else if (strcasecmp (level, "Error") == 0) return SEVERITY_ERROR; - - if (strcasecmp (level, "high") == 0) +#if CVSS3_RATINGS == 1 + else if (strcasecmp (level, "critical") == 0) + return 9.0; +#endif + else if (strcasecmp (level, "high") == 0) return 7.0; else if (strcasecmp (level, "medium") == 0) return 4.0; @@ -240,9 +243,15 @@ level_max_severity (const char *level) return SEVERITY_FP; else if (strcasecmp (level, "Error") == 0) return SEVERITY_ERROR; - - if (strcasecmp (level, "high") == 0) +#if CVSS3_RATINGS == 1 + else if (strcasecmp (level, "critical") == 0) + return 10.0; + else if (strcasecmp (level, "high") == 0) + return 8.9; +#else + else if (strcasecmp (level, "high") == 0) return 10.0; +#endif else if (strcasecmp (level, "medium") == 0) return 6.9; else if (strcasecmp (level, "low") == 0) diff --git a/src/schema_formats/HTML/HTML.xsl b/src/schema_formats/HTML/HTML.xsl index d27a54606..8a349f4a2 100644 --- a/src/schema_formats/HTML/HTML.xsl +++ b/src/schema_formats/HTML/HTML.xsl @@ -579,12 +579,14 @@ along with this program. If not, see .
  • - + + + select="($line-element/ele[id=$element-name-or-id]|$line-element/ele[name=$element-name-or-id])[1]"/> - <> + <>
    ()
    @@ -611,6 +613,7 @@ along with this program. If not, see .
    + <> diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 3218e237a..97b37fec4 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -68,7 +68,6 @@ along with this program. If not, see . xsd:token { pattern = "y?n?i?u?" } - @IF_COMPLIANCE_REPORTS@ compliance_status A compliance status @@ -76,7 +75,6 @@ along with this program. If not, see . xsd:token { pattern = "yes|no|incomplete|undefined" } - @ENDIF_COMPLIANCE_REPORTS@ ctime A date and time, in the C `ctime' format @@ -117,6 +115,19 @@ along with this program. If not, see . text + @IF_CVSS3_RATINGS@ + + levels + A string selecting severity levels that may include the characters c, h, m, l, g and f + + The meanings of the letters for each level are: "c" for "critical", + "h" for "high", "m" for "medium", "l" for "low", "g" for "log" and + "f" for "false positive". + + xsd:token { pattern = "c?h?m?l?g?f?" } + + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ levels A string selecting severity levels that may include the characters h, m, l, g and f @@ -127,6 +138,7 @@ along with this program. If not, see . xsd:token { pattern = "h?m?l?g?f?" } + @ENDIF_NOT_CVSS3_RATINGS@ name A name @@ -2025,16 +2037,12 @@ along with this program. If not, see . permissions user_tags scan_run_status - @IF_COMPLIANCE_REPORTS@ - @ENDIF_COMPLIANCE_REPORTS@ result_count severity - @IF_COMPLIANCE_REPORTS@ compliance_count compliance - @ENDIF_COMPLIANCE_REPORTS@ task ports results @@ -2237,6 +2245,9 @@ along with this program. If not, see . Level filter + @IF_CVSS3_RATINGS@ + Critical + @ENDIF_CVSS3_RATINGS@ High Medium Low @@ -2372,10 +2383,22 @@ along with this program. If not, see . text full filtered + @IF_CVSS3_RATINGS@ + critical + @ENDIF_CVSS3_RATINGS@ hole + @IF_CVSS3_RATINGS@ + high + @ENDIF_CVSS3_RATINGS@ info + @IF_CVSS3_RATINGS@ + low + @ENDIF_CVSS3_RATINGS@ log warning + @IF_CVSS3_RATINGS@ + medium + @ENDIF_CVSS3_RATINGS@ full @@ -2387,10 +2410,35 @@ along with this program. If not, see . Number of results after filtering integer + @IF_CVSS3_RATINGS@ + + critical + + Number of "critical" results (threat level critical) + + + full + filtered + + + full + Total number of results + integer + + + filtered + Number of results after filtering + integer + + + @ENDIF_CVSS3_RATINGS@ hole Number of "hole" results (threat level High) + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use high instead + @ENDIF_CVSS3_RATINGS@ full @@ -2407,10 +2455,56 @@ along with this program. If not, see . integer + @IF_CVSS3_RATINGS@ + + high + + Number of "high" results (threat level High) + + + full + filtered + + + full + Total number of results + integer + + + filtered + Number of results after filtering + integer + + + @ENDIF_CVSS3_RATINGS@ info Number of "info" results (threat level Low) + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use low instead + @ENDIF_CVSS3_RATINGS@ + + + full + filtered + + + full + Total number of results + integer + + + filtered + Number of results after filtering + integer + + + @IF_CVSS3_RATINGS@ + + low + + Number of "low" results (threat level Low) full @@ -2427,6 +2521,7 @@ along with this program. If not, see . integer + @ENDIF_CVSS3_RATINGS@ log @@ -2451,6 +2546,9 @@ along with this program. If not, see . warning Number of "warning" results (threat level Medium) + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use medium instead + @ENDIF_CVSS3_RATINGS@ full @@ -2467,8 +2565,29 @@ along with this program. If not, see . integer + @IF_CVSS3_RATINGS@ + + medium + + Number of "medium" results (threat level Medium) + + + full + filtered + + + full + Total number of results + integer + + + filtered + Number of results after filtering + integer + + + @ENDIF_CVSS3_RATINGS@ - @IF_COMPLIANCE_REPORTS@ compliance_count Counts of compliance results. Only for reports of an audit task. @@ -2577,7 +2696,6 @@ along with this program. If not, see . - @ENDIF_COMPLIANCE_REPORTS@ severity @@ -2595,7 +2713,6 @@ along with this program. If not, see . Maximum severity of the report after filtering - @IF_COMPLIANCE_REPORTS@ compliance @@ -2613,7 +2730,6 @@ along with this program. If not, see . Compliance of the report after filtering ("yes", "no", "incomplete" or "undefined") - @ENDIF_COMPLIANCE_REPORTS@ task @@ -2875,15 +2991,11 @@ along with this program. If not, see . start end port_count - @IF_COMPLIANCE_REPORTS@ - @ENDIF_COMPLIANCE_REPORTS@ result_count - @IF_COMPLIANCE_REPORTS@ compliance_count host_compliance - @ENDIF_COMPLIANCE_REPORTS@ detail @@ -2929,10 +3041,22 @@ along with this program. If not, see . page + @IF_CVSS3_RATINGS@ + critical + @ENDIF_CVSS3_RATINGS@ hole - warning + @IF_CVSS3_RATINGS@ + high + @ENDIF_CVSS3_RATINGS@ info + @IF_CVSS3_RATINGS@ + low + @ENDIF_CVSS3_RATINGS@ log + warning + @IF_CVSS3_RATINGS@ + medium + @ENDIF_CVSS3_RATINGS@ false_positive @@ -2940,9 +3064,30 @@ along with this program. If not, see . Total number of results for current host on current page integer + @IF_CVSS3_RATINGS@ + + critical + + Number of "critical" results (level "Critical") + + + page + + + page + Number of results on current page + integer + + + @ENDIF_CVSS3_RATINGS@ hole - Number of "hole" results (level "High") + + Number of "hole" results (level "High") + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use high instead + @ENDIF_CVSS3_RATINGS@ + page @@ -2952,9 +3097,30 @@ along with this program. If not, see . integer + @IF_CVSS3_RATINGS@ + + high + + Number of "high" results (level "High") + + + page + + + page + Number of results on current page + integer + + + @ENDIF_CVSS3_RATINGS@ warning - Number of "warning" results (level "Medium") + + Number of "warning" results (level "Medium") + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use medium instead + @ENDIF_CVSS3_RATINGS@ + page @@ -2964,9 +3130,30 @@ along with this program. If not, see . integer + @IF_CVSS3_RATINGS@ + + medium + + Number of "medium" results (level "Medium") + + + page + + + page + Number of results on current page + integer + + + @ENDIF_CVSS3_RATINGS@ info - Number of "info" results (level "Low") + + Number of "info" results (level "Low") + @IF_CVSS3_RATINGS@ + ,will be deprecated. Use low instead + @ENDIF_CVSS3_RATINGS@ + page @@ -2976,6 +3163,20 @@ along with this program. If not, see . integer + @IF_CVSS3_RATINGS@ + + low + Number of "low" results (level "Low") + + page + + + page + Number of results on current page + integer + + + @ENDIF_CVSS3_RATINGS@ log Number of "log" results @@ -3001,7 +3202,6 @@ along with this program. If not, see . - @IF_COMPLIANCE_REPORTS@ compliance_count Only for audit reports @@ -3071,7 +3271,6 @@ along with this program. If not, see . Only for audit reports. Host compliance compliance_status - @ENDIF_COMPLIANCE_REPORTS@ detail A detail associated with the host @@ -4003,12 +4202,14 @@ along with this program. If not, see . copy allow_insecure certificate + kdc key login password auth_algorithm community privacy + realm type @@ -4044,6 +4245,11 @@ along with this program. If not, see . text + + kdc + text + The Kerberos KDC (key distribution center(s)) + key @@ -4130,11 +4336,17 @@ along with this program. If not, see . + + realm + text + The Kerberos realm + type The type of credential to create

    cc: Client certificate

    +

    krb5: Kerberos 5

    pgp: PGP encryption key

    pw: Password only

    smime: S/MIME certificate

    @@ -4145,6 +4357,7 @@ along with this program. If not, see . cc + krb5 pgp pw smime @@ -5700,7 +5913,12 @@ END:VCALENDAR exclude_hosts ssh_credential ssh_elevate_credential - smb_credential + + + krb5_credential + smb_credential + + esxi_credential snmp_credential ssh_lsc_credential @@ -5790,6 +6008,17 @@ END:VCALENDAR
    + + krb5_credential + Kerberos 5 login credentials for target + + + id + uuid + 1 + + + smb_credential SMB login credentials for target @@ -10927,6 +11156,8 @@ END:VCALENDAR certificate + kdc + realm owner @@ -11053,6 +11284,7 @@ END:VCALENDAR The type of the credential

    cc: Client certificate

    +

    krb5: Kerberos 5

    pgp: PGP encryption key

    pw: Password only

    smime: S/MIME certificate

    @@ -11063,6 +11295,7 @@ END:VCALENDAR cc + krb5 pgp pw smime @@ -11215,6 +11448,16 @@ END:VCALENDAR certificate text
    + + kdc + text + The Kerberos KDC (key distribution center(s)) + + + realm + text + The Kerberos realm +
    filters @@ -11761,7 +12004,7 @@ END:VCALENDAR filter filters sort - filters + filters2 filter_count @@ -12018,6 +12261,7 @@ END:VCALENDAR + filters2 filters @@ -12785,9 +13029,9 @@ END:VCALENDAR Number of CVEs referencing this CPE - nvd_id - integer - NVD ID of the CVE + cpe_name_id + uuid + NVD assigned cpeNameId of the CPE @@ -13012,18 +13256,20 @@ END:VCALENDAR cpe - nvd_id + cpe_name_id title severity cve_refs - status + deprecated + deprecated_by cves + references raw_data A CPE info element - nvd_id - The NVD ID of the CPE + cpe_name_id + NVD assigned cpeNameId of the CPE text @@ -13050,10 +13296,22 @@ END:VCALENDAR - status - The status of this CPE + deprecated + Whether the CPE is deprecated - text + boolean + + + + deprecated_by + Another CPE the current one is deprecated by + + + cpe_id + uuid + CPE id the current CPE is deprecated by + 1 + @@ -13070,6 +13328,26 @@ END:VCALENDAR + + references + References of this CPE. Only when details were requested + + reference + + + reference + Reference of the CPE. Text contains type + + + href + text + Reference URL + 1 + + text + + + raw_data Source representation of the information. Only when details were requested @@ -13095,6 +13373,8 @@ END:VCALENDAR epss nvts cert + configuration_nodes + references raw_data A CVE info element @@ -13215,6 +13495,169 @@ END:VCALENDAR + + configuration_nodes + List of configuration nodes. Only when details were requested + + node + + + node + A configuration node for the CVE + + operator + negate + match_string + node + + + operator + The operator for the match criteria + + text + + + + negate + A true or false value, whether the operator is negated + + text + + + + match_string + The match string for the node + + criteria + vulnerable + version_start_including + version_start_excluding + version_end_including + version_end_excluding + matched_cpes + + + criteria + A CPE match criteria + + text + + + + vulnerable + A true or false value, whether matching CPEs are considered vulnerable + + text + + + + version_start_including + From version (including) + + text + + + + version_start_excluding + From version (excluding) + + text + + + + version_end_including + Up to version (including) + + text + + + + version_end_excluding + Up to version (exluding) + + text + + + + matched_cpes + List of matching CPEs + + name + deprecated + deprecated_by + + + name + Name of the matching CPE + + text + + + + deprecated + A true or false value, whether the CPE is deprecated + + text + + + + deprecated_by + CPE ID the current CPE is deprecated by. Only when the CPE is deprecated + + + cpe_id + uuid + CPE ID the current CPE is deprecated by + + + + + + + node + Nodes can contain other nested nodes + + node + + + + + + references + References of this CVE. Only when details were requested + + reference + + + reference + Reference of the CVE + + url + tags + + + url + The URL of the reference + + text + + + + tags + List of tags for the reference + + tag + + + tag + Tag for a reference + + text + + + + + raw_data Source representation of the information. Only when details were requested @@ -13653,6 +14096,7 @@ END:VCALENDAR model model_type + sensor model @@ -17995,13 +18439,11 @@ END:VCALENDAR integer Minimum QoD of the results - @IF_COMPLIANCE_REPORTS@ - @ENDIF_COMPLIANCE_REPORTS@ tag text @@ -18092,6 +18534,13 @@ END:VCALENDAR integer Number of high severity results + @IF_CVSS3_RATINGS@ + + critical + integer + Number of critical severity results + + @ENDIF_CVSS3_RATINGS@ hosts integer @@ -18127,6 +18576,13 @@ END:VCALENDAR integer Number of high severity results per host with results + @IF_CVSS3_RATINGS@ + + critical_per_host + integer + Number of critical severity results per host with results + + @ENDIF_CVSS3_RATINGS@ start_time iso_time @@ -18147,7 +18603,6 @@ END:VCALENDAR iso_time Scan end time - @IF_COMPLIANCE_REPORTS@ compliance_yes integer @@ -18168,7 +18623,6 @@ END:VCALENDAR compliance_status Compliance state of the report. Can be yes, no, incomplete or undefined - @ENDIF_COMPLIANCE_REPORTS@ @@ -18238,7 +18692,6 @@ END:VCALENDAR
    boolean - @IF_COMPLIANCE_REPORTS@ usage_type Optional usage type to limit the reports to. Affects total count unlike filter @@ -18250,7 +18703,6 @@ END:VCALENDAR
    - @ENDIF_COMPLIANCE_REPORTS@ @@ -18438,6 +18890,9 @@ END:VCALENDAR first=1 rows=-1 sort=name + @IF_CVSS3_RATINGS@ + Critical + @ENDIF_CVSS3_RATINGS@ High Medium Low @@ -18482,14 +18937,27 @@ END:VCALENDAR 10 10 + @IF_CVSS3_RATINGS@ + + 0 + 0 + 0 0 + + 0 + 0 + 7 7 + + 7 + 7 + 0 0 @@ -18498,6 +18966,29 @@ END:VCALENDAR 3 3 + + 3 + 3 + + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + + 0 + 0 + + + 7 + 7 + + + 0 + 0 + + + 3 + 3 + + @ENDIF_NOT_CVSS3_RATINGS@ dik mm @@ -21628,6 +22119,7 @@ END:VCALENDAR ssh_credential smb_credential esxi_credential + krb5_credential snmp_credential ssh_elevate_credential permissions @@ -21791,7 +22283,7 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the credential @@ -21827,7 +22319,7 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the credential @@ -21858,7 +22350,38 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the credential + + + + trash + Whether the LSC credential is in the trashcan + boolean + + + + krb5_credential + + + id + + A UUID if there is a credential, otherwise the empty string + + uuid_or_empty + 1 + + name + permissions + trash + + + name + The name of the Kerberos 5 LSC credential + name + + + permissions + Permissions the user has on the credential @@ -21923,7 +22446,7 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the credential @@ -21956,7 +22479,7 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the port_list @@ -22411,6 +22934,13 @@ END:VCALENDAR integer Number of high severity results + @IF_CVSS3_RATINGS@ + + critical + integer + Number of critical severity results + + @ENDIF_CVSS3_RATINGS@ hosts integer @@ -22446,6 +22976,13 @@ END:VCALENDAR integer Number of high severity results per host with results + @IF_CVSS3_RATINGS@ + + critical_per_host + integer + Number of critical severity results per host with results + + @ENDIF_CVSS3_RATINGS@ target name @@ -22798,7 +23335,7 @@ END:VCALENDAR permissions - Permissions the user has on the task + Permissions the user has on the scanner @@ -22971,15 +23508,11 @@ END:VCALENDAR timestamp scan_end - @IF_COMPLIANCE_REPORTS@ - @ENDIF_COMPLIANCE_REPORTS@ result_count severity - @IF_COMPLIANCE_REPORTS@ compliance_count - @ENDIF_COMPLIANCE_REPORTS@ timestamp @@ -22995,9 +23528,20 @@ END:VCALENDAR false_positive log + @IF_CVSS3_RATINGS@ + info + low + warning + medium + hole + high + critical + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ info warning hole + @ENDIF_NOT_CVSS3_RATINGS@ false_positive @@ -23010,22 +23554,52 @@ END:VCALENDAR info integer + @IF_CVSS3_RATINGS@ + This will be deprecated. Use low instead + @ENDIF_CVSS3_RATINGS@ + @IF_CVSS3_RATINGS@ + + low + integer + + @ENDIF_CVSS3_RATINGS@ warning integer + @IF_CVSS3_RATINGS@ + This will be deprecated. Use medium instead + @ENDIF_CVSS3_RATINGS@ + + @IF_CVSS3_RATINGS@ + + medium + integer + @ENDIF_CVSS3_RATINGS@ hole integer + @IF_CVSS3_RATINGS@ + This will be deprecated. Use high instead + @ENDIF_CVSS3_RATINGS@ + + @IF_CVSS3_RATINGS@ + + high + integer + + + critical + integer + @ENDIF_CVSS3_RATINGS@ severity severity Maximum severity of the report - @IF_COMPLIANCE_REPORTS@ compliance_count Complaince counts. Only for audit tasks @@ -23052,7 +23626,6 @@ END:VCALENDAR integer - @ENDIF_COMPLIANCE_REPORTS@ @@ -23253,10 +23826,22 @@ END:VCALENDAR Mon Feb 1 19:11:20 2010 + @IF_CVSS3_RATINGS@ + 0 0 + 0 7 + 7 0 3 + 3 + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + 0 + 7 + 0 + 3 + @ENDIF_NOT_CVSS3_RATINGS@ 5.0 @@ -23328,10 +23913,22 @@ END:VCALENDAR Mon Feb 1 19:11:20 2010 + @IF_CVSS3_RATINGS@ + 0 0 + 0 7 + 7 0 3 + 3 + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + 0 + 7 + 0 + 3 + @ENDIF_NOT_CVSS3_RATINGS@ 5.0 @@ -23344,20 +23941,44 @@ END:VCALENDAR Mon Feb 1 18:51:38 2010 Done + @IF_CVSS3_RATINGS@ + 0 0 + 0 7 + 7 0 3 + 3 + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + 0 + 7 + 0 + 3 + @ENDIF_NOT_CVSS3_RATINGS@ Mon Feb 1 19:11:20 2010 Done + @IF_CVSS3_RATINGS@ + 0 0 + 0 7 + 7 0 3 + 3 + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + 0 + 7 + 0 + 3 + @ENDIF_NOT_CVSS3_RATINGS@ 5.0 @@ -23448,11 +24069,24 @@ END:VCALENDAR 2019-04-24T14:26:01+02:00 2019-04-24T14:50:59+02:00 + @IF_CVSS3_RATINGS@ + 0 1 + 1 0 + 0 77 8 + 8 0 + @ENDIF_CVSS3_RATINGS@ + @IF_NOT_CVSS3_RATINGS@ + 1 + 0 + 77 + 8 + 0 + @ENDIF_NOT_CVSS3_RATINGS@ 9.0 @@ -26573,12 +27207,14 @@ END:VCALENDAR name allow_insecure certificate + kdc key login password community auth_algorithm privacy + realm name @@ -26606,6 +27242,11 @@ END:VCALENDAR text + + kdc + text + The Kerberos KDC (key distribution center(s)) + key @@ -26692,6 +27333,11 @@ END:VCALENDAR + + realm + text + The Kerberos realm + @@ -27935,7 +28581,12 @@ END:VCALENDAR exclude_hosts ssh_credential ssh_elevate_credential - smb_credential + + + krb5_credential + smb_credential + + esxi_credential snmp_credential ssh_lsc_credential @@ -28007,6 +28658,17 @@ END:VCALENDAR + + krb5_credential + Kerberos 5 login credentials for target + + + id + uuid + 1 + + + esxi_credential ESXi credential to use on target diff --git a/src/schema_formats/rnc.xsl b/src/schema_formats/rnc.xsl index 02c50816f..90ab354b2 100644 --- a/src/schema_formats/rnc.xsl +++ b/src/schema_formats/rnc.xsl @@ -182,6 +182,10 @@ response + + + + diff --git a/src/sql_pg.c b/src/sql_pg.c index cf8ed82c8..7f87cc1c9 100644 --- a/src/sql_pg.c +++ b/src/sql_pg.c @@ -607,7 +607,7 @@ sql_rollback () * * @param[in] table The table to lock. * @param[in] lock_timeout The lock timeout in milliseconds, 0 for unlimited. - * + * * @return 1 if locked, 0 if failed / timed out. */ int @@ -615,10 +615,10 @@ sql_table_lock_wait (const char *table, int lock_timeout) { int old_lock_timeout = sql_int ("SHOW lock_timeout;"); sql ("SET LOCAL lock_timeout = %d;", lock_timeout); - + // This requires the gvmd functions to be defined first. int ret = sql_int ("SELECT try_exclusive_lock_wait ('%s');", table); - + sql ("SET LOCAL lock_timeout = %d;", old_lock_timeout); return ret; } diff --git a/src/utils.c b/src/utils.c index 5db841129..32588497b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1029,7 +1029,7 @@ wait_for_pid (pid_t pid, const char *context) /** * @brief Get the available physical memory in bytes. - * + * * @return The available memory */ guint64 @@ -1041,7 +1041,7 @@ phys_mem_available () /** * @brief Get the total physical memory in bytes. - * + * * @return The total memory */ guint64 diff --git a/src/utils_tests.c b/src/utils_tests.c index ad6b8aa3f..46ff41bb4 100644 --- a/src/utils_tests.c +++ b/src/utils_tests.c @@ -109,25 +109,25 @@ Ensure (utils, gvm_sleep_sleep_for_1) assert_that (timespec_subtract (&end, &start), is_greater_than (NANOSECONDS - 1)); } -Ensure (utils, strescape_check_utf_8_no_exceptions) +Ensure (utils, strescape_check_utf_8_no_exceptions) { const char *utf8_input = "Äöü\n123\\UTF-8\x04"; const char *utf8_expected = "Äöü\\n123\\\\UTF-8\\004"; const char *cp850_input = "\x8E\x94\x81\n123\\CP850\x04"; const char *cp850_expected = "\\216\\224\\201\\n123\\\\CP850\\004"; - + assert_that (g_utf8_validate (utf8_input, -1, NULL), is_true); gchar *output = strescape_check_utf8 (utf8_input, NULL); - assert_that (output, is_equal_to_string (utf8_expected)); + assert_that (output, is_equal_to_string (utf8_expected)); g_free (output); assert_that (g_utf8_validate (cp850_input, -1, NULL), is_false); output = strescape_check_utf8 (cp850_input, NULL); - assert_that (output, is_equal_to_string (cp850_expected)); + assert_that (output, is_equal_to_string (cp850_expected)); g_free (output); } -Ensure (utils, strescape_check_utf_8_with_exceptions) +Ensure (utils, strescape_check_utf_8_with_exceptions) { const char *utf8_input = "Äöü\n123\\UTF-8\x04"; const char *utf8_expected = "Äöü\n123\\\\UTF-8\\004"; @@ -136,12 +136,12 @@ Ensure (utils, strescape_check_utf_8_with_exceptions) assert_that (g_utf8_validate (utf8_input, -1, NULL), is_true); gchar *output = strescape_check_utf8 (utf8_input, "\t\n\r"); - assert_that (output, is_equal_to_string (utf8_expected)); + assert_that (output, is_equal_to_string (utf8_expected)); g_free (output); assert_that (g_utf8_validate (cp850_input, -1, NULL), is_false); output = strescape_check_utf8 (cp850_input, "\t\n\r"); - assert_that (output, is_equal_to_string (cp850_expected)); + assert_that (output, is_equal_to_string (cp850_expected)); g_free (output); } @@ -164,7 +164,7 @@ main (int argc, char **argv) add_test_with_context (suite, utils, parse_iso_time_tz_with_z); add_test_with_context (suite, utils, parse_iso_time_tz_with_fallback_tz); add_test_with_context (suite, utils, parse_iso_time_tz_variants); - + add_test_with_context (suite, utils, strescape_check_utf_8_no_exceptions); add_test_with_context (suite, utils, strescape_check_utf_8_with_exceptions);