diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5e8c79c0..79884d46e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ pkg_check_modules (LIBGVM_BASE REQUIRED libgvm_base>=22.12) pkg_check_modules (LIBGVM_UTIL REQUIRED libgvm_util>=22.12) pkg_check_modules (LIBGVM_OSP REQUIRED libgvm_osp>=22.12) pkg_check_modules (LIBGVM_GMP REQUIRED libgvm_gmp>=22.12) +pkg_check_modules (LIBGVM_OPENVASD REQUIRED libgvm_openvasd>=22.12) pkg_check_modules (GNUTLS REQUIRED gnutls>=3.2.15) pkg_check_modules (GLIB REQUIRED glib-2.0>=2.42) pkg_check_modules (LIBBSD REQUIRED libbsd) @@ -91,7 +92,7 @@ else (WITH_LIBTHEIA) set (OPT_THEIA_TGT "") endif (WITH_LIBTHEIA) -include_directories (${LIBGVM_GMP_INCLUDE_DIRS} +include_directories (${LIBGVM_GMP_INCLUDE_DIRS} ${LIBGVM_OPENVASD_INCLUDE_DIRS} ${LIBGVM_BASE_INCLUDE_DIRS} ${LIBGVM_UTIL_INCLUDE_DIRS} ${LIBGVM_OSP_INCLUDE_DIRS} ${LIBBSD_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS}) @@ -313,34 +314,34 @@ add_executable (gvmd target_link_libraries (gvmd m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) target_link_libraries (manage-test cgreen m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) target_link_libraries (manage-sql-test cgreen m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) target_link_libraries (manage-utils-test cgreen m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) target_link_libraries (gmp-tickets-test cgreen m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) target_link_libraries (utils-test cgreen m ${GNUTLS_LDFLAGS} ${GPGME_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} ${LINKER_HARDENING_FLAGS} ${LINKER_DEBUG_FLAGS} ${PostgreSQL_LIBRARIES} ${LIBBSD_LDFLAGS} ${CJSON_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} - ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_GMP_LDFLAGS} - ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) -target_link_libraries (gvm-pg-server ${LIBBSD_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS}) + ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBGVM_OSP_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} + ${LIBGVM_GMP_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS} ${OPT_THEIA_TGT}) +target_link_libraries (gvm-pg-server ${LIBBSD_LDFLAGS} ${GLIB_LDFLAGS} ${GTHREAD_LDFLAGS} ${LIBGVM_BASE_LDFLAGS} ${LIBGVM_OPENVASD_LDFLAGS} ${LIBGVM_UTIL_LDFLAGS} ${LIBICAL_LDFLAGS} ${LINKER_HARDENING_FLAGS}) set_target_properties (gvmd PROPERTIES LINKER_LANGUAGE C) set_target_properties (manage-test PROPERTIES LINKER_LANGUAGE C) diff --git a/src/gmp.c b/src/gmp.c index b90c1ff54..42225940c 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -16816,6 +16816,61 @@ handle_get_scanners (gmp_parser_t *gmp_parser, GError **error) g_free (desc); g_slist_free (params); } + if ((scanner_iterator_type (&scanners) == SCANNER_TYPE_OPENVASD) + && get_scanners_data->get.details) + { + char *s_name = NULL, *s_ver = NULL; + char *d_name = NULL, *d_ver = NULL; + char *p_name = NULL, *p_ver = NULL, *desc = NULL; + GSList *params = NULL, *nodes; + + if (!openvasd_get_details_from_iterator (&scanners, &desc, ¶ms)) + { + SENDF_TO_CLIENT_OR_FAIL + ("Openvasd0.1" + "OpenVAS23.4.1" + "SCANNER API0.1" + "Openvasd Sensor"); + + SENDF_TO_CLIENT_OR_FAIL (""); + nodes = params; + while (nodes) + { + openvasd_param_t *param = nodes->data; + g_warning("%s%s" + "%s%s" + "osp_%s%d", + openvasd_param_id (param), openvasd_param_name(param), + openvasd_param_default (param), openvasd_param_desc (param), + openvasd_param_type (param), openvasd_param_mandatory (param)); + SENDF_TO_CLIENT_OR_FAIL + ("%s%s" + "%s%s" + "osp_%s%d", + openvasd_param_id (param), openvasd_param_name(param), + openvasd_param_default (param), openvasd_param_desc (param), + openvasd_param_type (param), 1); + + osp_param_free (nodes->data); + nodes = nodes->next; + } + SENDF_TO_CLIENT_OR_FAIL (""); + } + else + SENDF_TO_CLIENT_OR_FAIL + ("" + "" + "" + ""); + g_free (s_name); + g_free (s_ver); + g_free (d_name); + g_free (d_ver); + g_free (p_name); + g_free (p_ver); + g_free (desc); + g_slist_free (params); + } else if (get_scanners_data->get.details) { SENDF_TO_CLIENT_OR_FAIL diff --git a/src/gvmd.c b/src/gvmd.c index 0fbe8051b..c58ec12c7 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -1106,11 +1106,15 @@ handle_sigabrt_simple (int signal) static int update_nvt_cache_osp (const gchar *update_socket) { +#ifdef OPENVASD + setproctitle ("Openvasd: Updating NVT cache"); +#else setproctitle ("OSP: Updating NVT cache"); - +#endif return manage_update_nvts_osp (update_socket); } + /** * @brief Update NVT cache in forked child, retrying if scanner loading. * @@ -2836,6 +2840,8 @@ gvmd (int argc, char** argv, char *env[]) type = SCANNER_TYPE_OPENVAS; else if (!strcasecmp (scanner_type, "OSP-Sensor")) type = SCANNER_TYPE_OSP_SENSOR; + else if (!strcasecmp (scanner_type, "Openvasd")) + type = SCANNER_TYPE_OPENVASD; else { type = atoi (scanner_type); @@ -2878,6 +2884,8 @@ gvmd (int argc, char** argv, char *env[]) type = SCANNER_TYPE_OPENVAS; else if (!strcasecmp (scanner_type, "OSP-Sensor")) type = SCANNER_TYPE_OSP_SENSOR; + else if (!strcasecmp (scanner_type, "Openvasd")) + type = SCANNER_TYPE_OPENVASD; else { type = atoi (scanner_type); diff --git a/src/manage.c b/src/manage.c index fca82209f..6c4e53953 100644 --- a/src/manage.c +++ b/src/manage.c @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -4016,6 +4017,11 @@ slave_get_relay (const char *original_host, return ret; } + +/* Prototype */ +static int +run_openvasd_task (task_t task, int from, char **report_id); + /** * @brief Start or resume a task. * @@ -4078,6 +4084,9 @@ run_task (const char *task_id, char **report_id, int from) || scanner_type (scanner) == SCANNER_TYPE_OSP_SENSOR) return run_osp_task (task, from, report_id); + if (scanner_type (scanner) == SCANNER_TYPE_OPENVASD) + return run_openvasd_task (task, from, report_id); + return -1; // Unknown scanner type } @@ -4204,6 +4213,9 @@ stop_task_internal (task_t task) return 0; } +static int +stop_openvasd_task (task_t task); + /** * @brief Initiate stopping a task. * @@ -4230,6 +4242,9 @@ stop_task (const char *task_id) || scanner_type (task_scanner (task)) == SCANNER_TYPE_OSP_SENSOR) return stop_osp_task (task); + if (scanner_type (task_scanner (task)) == SCANNER_TYPE_OPENVASD) + return stop_openvasd_task (task); + return stop_task_internal (task); } @@ -7419,6 +7434,50 @@ nvts_feed_info_internal (const gchar *update_socket, return 0; } +/** + * @brief Get VTs feed information from a scanner. + * + * @param[in] scanner_uuid The uuid of the scanner to be used. + * @param[out] vts_version Output of scanner feed version. + * + * @return 0 success, 1 connection to scanner failed, 2 scanner still starting, + * -1 other error. + */ +static int +nvts_feed_info_internal_from_openvasd (const gchar *scanner_uuid, + gchar **vts_version) +{ + scanner_t scan; + openvasd_connector_t connector = NULL; + openvasd_resp_t resp = NULL; + int ret; + if (find_resource_no_acl ("scanner", scanner_uuid, &scan)) + return -1; + + connector = openvasd_scanner_connect (scan, NULL); + if (!connector) + return 1; + + resp = openvasd_get_health_ready (connector); + if (resp->code == -1) + { + g_warning ("%s: failed to connect to %s:%d", __func__, + scanner_host (scan), scanner_port (scan)); + ret = 1; + } + else if (resp->code == 503) + ret = 2; + else + { + *vts_version = g_strdup (resp->header); + ret = 0; + } + + openvasd_response_cleanup (resp); + openvasd_connector_free (connector); + return ret; +} + /** * @brief Get VTs feed information from the scanner using VT update socket. * @@ -7434,11 +7493,17 @@ int nvts_feed_info (gchar **vts_version, gchar **feed_name, gchar **feed_vendor, gchar **feed_home) { +#if OPENVASD == 1 + return nvts_feed_info_internal_from_openvasd (SCANNER_UUID_OPENVASD_DEFAULT, + vts_version); +#else return nvts_feed_info_internal (get_osp_vt_update_socket (), vts_version, feed_name, feed_vendor, feed_home); + +#endif } /** @@ -7498,10 +7563,30 @@ nvts_check_feed (int *lockfile_in_use, int *self_test_exit_error, char **self_test_error_msg) { +#if OPENVASD == 1 + int ret = 0; + char *vts_version = NULL; + + ret = nvts_feed_info_internal_from_openvasd (SCANNER_UUID_OPENVASD_DEFAULT, + &vts_version); + self_test_exit_error = 0; + *self_test_error_msg = NULL; + if (ret == 0 && vts_version) + lockfile_in_use = 0; + else if (ret == 2) + { + ret = 0; + *lockfile_in_use = 1; + } + + return ret; + +#else return nvts_check_feed_internal (get_osp_vt_update_socket (), lockfile_in_use, self_test_exit_error, self_test_error_msg); +#endif } /** @@ -8201,3 +8286,870 @@ delete_resource (const char *type, const char *resource_id, int ultimate) assert (0); return -1; } + +/* Openvasd */ + +/** + * @brief Stop an Openvasd task. + * + * @param[in] task The task. + * + * @return 0 on success, else -1. + */ +static int +stop_openvasd_task (task_t task) +{ + int ret = 0; + report_t scan_report; + char *scan_id; + task_t previous_task; + report_t previous_report; + + scanner_t scanner; + openvasd_resp_t response; + openvasd_connector_t connector = NULL; + + previous_task = current_scanner_task; + previous_report = global_current_report; + scan_report = task_running_report (task); + scan_id = report_uuid (scan_report); + if (!scan_id) + { + ret = -1; + goto end_stop_openvasd; + } + scanner = task_scanner (task); + connector = openvasd_scanner_connect (scanner, scan_id); + if (!connector) + { + ret = -1; + goto end_stop_openvasd; + } + + current_scanner_task = task; + global_current_report = task_running_report (task); + set_task_run_status (task, TASK_STATUS_STOP_REQUESTED); + response = openvasd_stop_scan (connector); + if (response->code < 0) + { + ret = -1; + g_free (scan_id); + goto end_stop_openvasd; + } + response = openvasd_delete_scan (connector); + g_free (scan_id); +end_stop_openvasd: + openvasd_connector_free (connector); + set_task_end_time_epoch (task, time (NULL)); + set_task_run_status (task, TASK_STATUS_STOPPED); + if (scan_report) + { + set_scan_end_time_epoch (scan_report, time (NULL)); + set_report_scan_run_status (scan_report, TASK_STATUS_STOPPED); + } + current_scanner_task = previous_task; + global_current_report = previous_report; + + return ret; +} + +/** + * @brief Prepare a report for resuming an OSP scan + * + * @param[in] task The task of the scan. + * @param[in] scan_id The scan uuid. + * @param[out] error Error return. + * + * @return 0 scan finished or still running, + * 1 scan must be started, + * -1 error + */ +static int +prepare_openvasd_scan_for_resume (task_t task, const char *scan_id, + char **error) +{ + openvasd_connector_t connection; + + openvasd_scan_status_t status; + openvasd_resp_t response; + + assert (task); + assert (scan_id); + assert (global_current_report); + assert (error); + + connection = openvasd_scanner_connect (task_scanner (task), scan_id); + if (!connection) + { + *error = g_strdup ("Could not connect to Openvasd Scanner"); + return -1; + } + status = openvasd_parsed_scan_status (connection); + + if (status->status == OPENVASD_SCAN_STATUS_ERROR) + { + if (status->response_code == 404) + { + g_debug ("%s: Scan %s not found", __func__, scan_id); + openvasd_connector_free (connection); + trim_partial_report (global_current_report); + return 1; + } + g_warning ("%s: Error getting status of scan %s: %ld", + __func__, scan_id, status->response_code); + openvasd_connector_free (connection); + return -1; + } + else if (status->status == OPENVASD_SCAN_STATUS_RUNNING + || status->status == OPENVASD_SCAN_STATUS_REQUESTED) + { + g_debug ("%s: Scan %s queued or running", __func__, scan_id); + /* It would be possible to simply continue getting the results + * from the scanner, but gvmd may have crashed while receiving + * or storing the results, so some may be missing. */ + response = openvasd_stop_scan (connection); + if (response->code != 204) + { + *error = g_strdup_printf ("Failed to stop old report: %ld", + response->code); + openvasd_connector_free (connection); + openvasd_response_cleanup(response); + return -1; + } + response = openvasd_delete_scan (connection); + if (response->code != 204) + { + *error = g_strdup_printf ("Failed to delete old report: %ld", + response->code); + openvasd_response_cleanup(response); + openvasd_connector_free (connection); + return -1; + } + openvasd_connector_free (connection); + trim_partial_report (global_current_report); + return 1; + } + else if (status->status == OPENVASD_SCAN_STATUS_SUCCEEDED) + { + /* OSP can't stop an already finished/interrupted scan, + * but it must be delete to be resumed. */ + g_debug ("%s: Scan %s finished", __func__, scan_id); + response = openvasd_delete_scan (connection); + if (response->code != 204) + { + *error = g_strdup_printf ("Failed to delete old report: %ld", + response->code); + openvasd_response_cleanup(response); + openvasd_connector_free (connection); + return -1; + } + openvasd_connector_free (connection); + trim_partial_report (global_current_report); + return 1; + } + else if (status->status == OPENVASD_SCAN_STATUS_STOPPED + || status->status == OPENVASD_SCAN_STATUS_FAILED) + { + g_debug ("%s: Scan %s stopped or interrupted", + __func__, scan_id); + response = openvasd_delete_scan (connection); + if (response->code != 204) + { + *error = g_strdup_printf ("Failed to delete old report: %ld", + response->code); + openvasd_response_cleanup(response); + openvasd_connector_free (connection); + return -1; + } + openvasd_connector_free (connection); + trim_partial_report (global_current_report); + return 1; + } + + g_warning ("%s: Unexpected scanner status %d", __func__, status->status); + *error = g_strdup_printf ("Unexpected scanner status %d", status->status); + openvasd_connector_free (connection); + + return -1; +} + +/** + * @brief Launch an OpenVAS via Openvasd task. + * + * @param[in] task The task. + * @param[in] target The target. + * @param[in] scan_id The scan uuid. + * @param[in] from 0 start from beginning, 1 continue from stopped, + * 2 continue if stopped else start from beginning. + * @param[out] error Error return. + * + * @return An http code on success, -1 if error. + */ +static int +launch_openvasd_openvas_task (task_t task, target_t target, const char *scan_id, + int from, char **error) +{ + openvasd_connector_t connection; + char *hosts_str, *ports_str, *exclude_hosts_str, *finished_hosts_str; + gchar *clean_hosts, *clean_exclude_hosts, *clean_finished_hosts_str; + int alive_test, reverse_lookup_only, reverse_lookup_unify; + int arp = 0, icmp = 0, tcp_ack = 0, tcp_syn = 0, consider_alive = 0; + openvasd_target_t *openvasd_target; + GSList *openvasd_targets, *vts; + GHashTable *vts_hash_table; + openvasd_credential_t *ssh_credential, *smb_credential, *esxi_credential; + openvasd_credential_t *snmp_credential; + gchar *max_checks, *max_hosts, *hosts_ordering; + GHashTable *scanner_options; + openvasd_resp_t response; + int ret, empty; + config_t config; + iterator_t scanner_prefs_iter, families, prefs; + + connection = NULL; + config = task_config (task); + + alive_test = 0; + reverse_lookup_unify = 0; + reverse_lookup_only = 0; + + /* Prepare the report */ + if (from) + { + ret = prepare_openvasd_scan_for_resume (task, scan_id, error); + if (ret == 0) + return 0; + else if (ret == -1) + return -1; + finished_hosts_str = report_finished_hosts_str (global_current_report); + clean_finished_hosts_str = clean_hosts_string (finished_hosts_str); + } + else + { + finished_hosts_str = NULL; + clean_finished_hosts_str = NULL; + } + + /* Set up target(s) */ + hosts_str = target_hosts (target); + ports_str = target_port_range (target); + exclude_hosts_str = target_exclude_hosts (target); + + clean_hosts = clean_hosts_string (hosts_str); + clean_exclude_hosts = clean_hosts_string (exclude_hosts_str); + + alive_test = 0; + if (target_alive_tests (target) > 0) + alive_test = target_alive_tests (target); + + if (target_reverse_lookup_only (target) != NULL) + reverse_lookup_only = atoi (target_reverse_lookup_only (target)); + + if (target_reverse_lookup_unify (target) != NULL) + reverse_lookup_unify = atoi (target_reverse_lookup_unify (target)); + + if (finished_hosts_str) + { + gchar *new_exclude_hosts; + + new_exclude_hosts = g_strdup_printf ("%s,%s", + clean_exclude_hosts, + clean_finished_hosts_str); + free (clean_exclude_hosts); + clean_exclude_hosts = new_exclude_hosts; + } + + openvasd_target = openvasd_target_new (scan_id, clean_hosts, ports_str, + clean_exclude_hosts, + reverse_lookup_unify, + reverse_lookup_only); + if (finished_hosts_str) + openvasd_target_set_finished_hosts (openvasd_target, finished_hosts_str); + + if (alive_test & ALIVE_TEST_ARP) + arp = 1; + if (alive_test & ALIVE_TEST_ICMP) + icmp = 1; + if (alive_test & ALIVE_TEST_TCP_ACK_SERVICE) + tcp_ack = 1; + if (alive_test & ALIVE_TEST_TCP_SYN_SERVICE) + tcp_syn = 1; + if (alive_test & ALIVE_TEST_CONSIDER_ALIVE) + consider_alive = 1; + + openvasd_target_add_alive_test_methods (openvasd_target, icmp, tcp_syn, + tcp_ack, arp, consider_alive); + + free (hosts_str); + free (ports_str); + free (exclude_hosts_str); + free (finished_hosts_str); + g_free (clean_hosts); + g_free (clean_exclude_hosts); + g_free (clean_finished_hosts_str); + openvasd_targets = g_slist_append (NULL, openvasd_target); + + ssh_credential = (openvasd_credential_t *) target_osp_ssh_credential (target); + if (ssh_credential) + openvasd_target_add_credential (openvasd_target, ssh_credential); + + smb_credential = (openvasd_credential_t *) target_osp_smb_credential (target); + if (smb_credential) + openvasd_target_add_credential (openvasd_target, smb_credential); + + esxi_credential = + (openvasd_credential_t *) target_osp_esxi_credential (target); + if (esxi_credential) + openvasd_target_add_credential (openvasd_target, esxi_credential); + + snmp_credential = + (openvasd_credential_t *) target_osp_snmp_credential (target); + if (snmp_credential) + openvasd_target_add_credential (openvasd_target, snmp_credential); + + /* Initialize vts table for vulnerability tests and their preferences */ + vts = NULL; + vts_hash_table + = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + /* Value is freed in vts list. */ + NULL); + + /* Setup of vulnerability tests (without preferences) */ + init_family_iterator (&families, 0, NULL, 1); + empty = 1; + while (next (&families)) + { + const char *family = family_iterator_name (&families); + if (family) + { + iterator_t nvts; + init_nvt_iterator (&nvts, 0, config, family, NULL, 1, NULL); + while (next (&nvts)) + { + const char *oid; + openvasd_vt_single_t *new_vt; + + empty = 0; + oid = nvt_iterator_oid (&nvts); + new_vt = openvasd_vt_single_new (oid); + + vts = g_slist_prepend (vts, new_vt); + g_hash_table_replace (vts_hash_table, g_strdup (oid), new_vt); + } + cleanup_iterator (&nvts); + } + } + cleanup_iterator (&families); + + if (empty) { + if (error) + *error = g_strdup ("Exiting because VT list is empty " + "(e.g. feed not synced yet)"); + g_slist_free_full (openvasd_targets, (GDestroyNotify) openvasd_target_free); + // Credentials are freed with target + g_slist_free_full (vts, (GDestroyNotify) openvasd_vt_single_free); + return -1; + } + + /* Setup general scanner preferences */ + scanner_options + = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + init_preference_iterator (&scanner_prefs_iter, config, "SERVER_PREFS"); + while (next (&scanner_prefs_iter)) + { + const char *name, *value; + name = preference_iterator_name (&scanner_prefs_iter); + value = preference_iterator_value (&scanner_prefs_iter); + if (name && value && !g_str_has_prefix (name, "timeout.")) + { + const char *openvasd_value; + + // Workaround for boolean scanner preferences + if (strcmp (value, "0") == 0) + openvasd_value = "no"; + else if (strcmp (value, "1") == 0) + openvasd_value = "yes"; + else + openvasd_value = value; + g_hash_table_replace (scanner_options, + g_strdup (name), + g_strdup (openvasd_value)); + } + /* Timeouts are stored as SERVER_PREFS, but are actually + script preferences. This prefs is converted into a + script preference to be sent to the scanner. */ + else if (name && value && g_str_has_prefix (name, "timeout.")) + { + char **oid = NULL; + openvasd_vt_single_t *openvasd_vt = NULL; + + oid = g_strsplit (name, ".", 2); + openvasd_vt = g_hash_table_lookup (vts_hash_table, oid[1]); + if (openvasd_vt) + openvasd_vt_single_add_value (openvasd_vt, "0", value); + g_strfreev (oid); + } + + } + cleanup_iterator (&scanner_prefs_iter); + + /* Setup user-specific scanner preference */ + add_user_scan_preferences (scanner_options); + + /* Setup general task preferences */ + max_checks = task_preference_value (task, "max_checks"); + g_hash_table_insert (scanner_options, g_strdup ("max_checks"), + max_checks ? max_checks : g_strdup (MAX_CHECKS_DEFAULT)); + + max_hosts = task_preference_value (task, "max_hosts"); + g_hash_table_insert (scanner_options, g_strdup ("max_hosts"), + max_hosts ? max_hosts : g_strdup (MAX_HOSTS_DEFAULT)); + + hosts_ordering = task_hosts_ordering (task); + if (hosts_ordering) + g_hash_table_insert (scanner_options, g_strdup ("hosts_ordering"), + hosts_ordering); + + /* Setup VT preferences */ + init_preference_iterator (&prefs, config, "PLUGINS_PREFS"); + while (next (&prefs)) + { + const char *full_name, *value; + openvasd_vt_single_t *openvasd_vt; + gchar **split_name; + + full_name = preference_iterator_name (&prefs); + value = preference_iterator_value (&prefs); + split_name = g_strsplit (full_name, ":", 4); + + openvasd_vt = NULL; + if (split_name && split_name[0] && split_name[1] && split_name[2]) + { + const char *oid = split_name[0]; + const char *pref_id = split_name[1]; + const char *type = split_name[2]; + gchar *openvasd_value = NULL; + + if (strcmp (type, "checkbox") == 0) + { + if (strcmp (value, "yes") == 0) + openvasd_value = g_strdup ("1"); + else + openvasd_value = g_strdup ("0"); + } + else if (strcmp (type, "radio") == 0) + { + gchar** split_value; + split_value = g_strsplit (value, ";", 2); + openvasd_value = g_strdup (split_value[0]); + g_strfreev (split_value); + } + else if (strcmp (type, "file") == 0) + openvasd_value = g_base64_encode ((guchar*) value, strlen (value)); + + openvasd_vt = g_hash_table_lookup (vts_hash_table, oid); + if (openvasd_vt) + openvasd_vt_single_add_value (openvasd_vt, pref_id, + openvasd_value ? openvasd_value : value); + g_free (openvasd_value); + } + + g_strfreev (split_name); + } + cleanup_iterator (&prefs); + g_hash_table_destroy (vts_hash_table); + + /* Start the scan */ + connection = openvasd_scanner_connect (task_scanner (task), scan_id); + if (!connection) + { + if (error) + *error = g_strdup ("Could not connect to Scanner"); + g_slist_free_full (openvasd_targets, + (GDestroyNotify) openvasd_target_free); + // Credentials are freed with target + g_slist_free_full (vts, (GDestroyNotify) openvasd_vt_single_free); + g_hash_table_destroy (scanner_options); + return -1; + } + + gchar *scan_config = NULL; + scan_config = + openvasd_build_scan_config_json(openvasd_target, scanner_options, vts); + + response = openvasd_start_scan (connection, scan_config); + openvasd_target_free(openvasd_target); + // Credentials are freed with target + g_slist_free_full (vts, (GDestroyNotify) openvasd_vt_single_free); + g_hash_table_destroy (scanner_options); + ret = response->code; + openvasd_response_cleanup (response); + + return ret; +} + +/** + * @brief Handle an ongoing Openvasd scan, until success or failure. + * + * @param[in] task The task. + * @param[in] report The report. + * @param[in] scan_id The UUID of the scan on the scanner. + * + * @return 0 if success, -1 if error, -2 if scan was stopped, + * -3 if the scan was interrupted, -4 already stopped. + */ +static int +handle_openvasd_scan (task_t task, report_t report, const char *scan_id) +{ + int rc; + scanner_t scanner; + gboolean started, queued_status_updated; + int retry, connection_retry; + openvasd_resp_t response; + openvasd_connector_t connector; + + scanner = task_scanner (task); + connector = openvasd_scanner_connect (scanner, scan_id); + response = NULL; + started = FALSE; + queued_status_updated = FALSE; + connection_retry = get_scanner_connection_retry (); + + retry = connection_retry; + rc = -1; + while (retry >= 0) + { + int run_status, progress; + + run_status = task_run_status (task); + if (run_status == TASK_STATUS_STOPPED + || run_status == TASK_STATUS_STOP_REQUESTED) + { + rc = -4; + break; + } + + progress = openvasd_get_scan_progress (connector); + + if (progress < 0 || progress > 100) + { + if (retry > 0 && progress == -1) + { + retry--; + g_warning ("Connection lost with the scanner." + "Trying again in 1 second."); + gvm_sleep (1); + continue; + } + else if (progress == -2) + { + rc = -2; + break; + } + result_t result = make_osp_result + (task, "", "", "", + threat_message_type ("Error"), + "Erroneous scan progress value", "", "", + QOD_DEFAULT, NULL, NULL); + report_add_result (report, result); + response = openvasd_delete_scan(connector); + rc = -1; + break; + } + else + { + /* Get the full openvasd report. */ + progress = openvasd_get_scan_progress (connector); + + if (progress < 0 || progress > 100) + { + if (retry > 0 && progress == -1) + { + retry--; + g_warning ("Connection lost with the scanner. " + "Trying again in 1 second."); + gvm_sleep (1); + continue; + } + else if (progress == -2) + { + rc = -2; + break; + } + result_t result = make_osp_result + (task, "", "", "", + threat_message_type ("Error"), + "Erroneous scan progress value", "", "", + QOD_DEFAULT, NULL, NULL); + report_add_result (report, result); + rc = -1; + break; + } + else + { + GSList *results = NULL; + static unsigned long result_start = 0; + static unsigned long result_end = -1; // get up to the end + openvasd_status_t current_status; + time_t start_time, end_time; + openvasd_scan_status_t openvasd_scan_status; + + set_report_slave_progress (report, progress); + + openvasd_parsed_results (connector, result_start, + result_end, &results); + result_start += g_slist_length (results); + + gvm_sleep(1); + openvasd_scan_status = openvasd_parsed_scan_status (connector); + start_time = openvasd_scan_status->start_time; + end_time = openvasd_scan_status->end_time; + current_status = openvasd_scan_status->status; + progress = openvasd_scan_status->progress; + g_free (openvasd_scan_status); + + if (g_slist_length(results)) + { + parse_openvasd_report (task, report, results, start_time, + end_time); + g_slist_free_full (results, + (GDestroyNotify) openvasd_result_free); + } + if (current_status == OPENVASD_SCAN_STATUS_STORED) + { + if (queued_status_updated == FALSE) + { + set_task_run_status (task, TASK_STATUS_QUEUED); + set_report_scan_run_status (global_current_report, + TASK_STATUS_QUEUED); + queued_status_updated = TRUE; + } + } + else if (current_status == OPENVASD_SCAN_STATUS_FAILED) + { + result_t result = make_osp_result + (task, "", "", "", + threat_message_type ("Error"), + "Task interrupted unexpectedly", "", "", + QOD_DEFAULT, NULL, NULL); + report_add_result (report, result); + response = openvasd_delete_scan (connector); + rc = -3; + break; + } + else if (progress >= 0 && progress < 100 + && current_status == OPENVASD_SCAN_STATUS_STOPPED) + { + if (retry > 0) + { + retry--; + g_warning ("Connection lost with the scanner. " + "Trying again in 1 second."); + gvm_sleep (1); + continue; + } + + result_t result = make_osp_result + (task, "", "", "", + threat_message_type ("Error"), + "Scan stopped unexpectedly by the server", "", "", + QOD_DEFAULT, NULL, NULL); + report_add_result (report, result); + response = openvasd_delete_scan (connector); + rc = -1; + break; + } + else if (progress == 100 + && current_status == OPENVASD_SCAN_STATUS_SUCCEEDED) + { + response = openvasd_delete_scan (connector); + rc = response->code; + break; + } + else if (current_status == OPENVASD_SCAN_STATUS_RUNNING + && started == FALSE) + { + set_task_run_status (task, TASK_STATUS_RUNNING); + set_report_scan_run_status (global_current_report, + TASK_STATUS_RUNNING); + started = TRUE; + } + } + } + + retry = connection_retry; + gvm_sleep (5); + } + openvasd_response_cleanup (response); + openvasd_connector_free(connector); + return rc; +} + + +/** + * @brief Fork a child to handle an Openvasd scan's fetching and inserting. + * + * @param[in] task The task. + * @param[in] target The target. + * @param[in] from 0 start from beginning, 1 continue from stopped, + * 2 continue if stopped else start from beginning. + * @param[out] report_id_return UUID of the report. + * + * @return Parent returns with 0 if success, -1 if failure. Child process + * doesn't return and simply exits. + */ +static int +fork_openvasd_scan_handler (task_t task, target_t target, int from, + char **report_id_return) +{ + char *report_id, *error = NULL; + int rc; + + assert (task); + assert (target); + + if (report_id_return) + *report_id_return = NULL; + + if (run_osp_scan_get_report (task, from, &report_id)) + return -1; + + current_scanner_task = task; + set_task_run_status (task, TASK_STATUS_REQUESTED); + + switch (fork ()) + { + case 0: + init_sentry (); + break; + case -1: + /* Parent, failed to fork. */ + global_current_report = 0; + g_warning ("%s: Failed to fork: %s", + __func__, + strerror (errno)); + set_task_interrupted (task, + "Error forking scan handler." + " Interrupting scan."); + set_report_scan_run_status (global_current_report, + TASK_STATUS_INTERRUPTED); + global_current_report = (report_t) 0; + current_scanner_task = 0; + g_free (report_id); + return -9; + default: + /* Parent, successfully forked. */ + global_current_report = 0; + current_scanner_task = 0; + if (report_id_return) + *report_id_return = report_id; + else + g_free (report_id); + return 0; + } + + /* Child: Re-open DB after fork and periodically check scan progress. + * If progress == 100%: Parse the report results and other info then exit(0). + * Else, exit(1) in error cases like connection to scanner failure. + */ + reinit_manage_process (); + manage_session_init (current_credentials.uuid); + + rc = launch_openvasd_openvas_task (task, target, report_id, from, &error); + + if (rc < 0) + { + result_t result; + + g_warning ("Openvasd start_scan %s: %s", report_id, error); + result = make_osp_result (task, "", "", "", + threat_message_type ("Error"), + error, "", "", QOD_DEFAULT, NULL, NULL); + report_add_result (global_current_report, result); + set_task_run_status (task, TASK_STATUS_DONE); + set_report_scan_run_status (global_current_report, TASK_STATUS_DONE); + set_task_end_time_epoch (task, time (NULL)); + set_scan_end_time_epoch (global_current_report, time (NULL)); + + g_free (error); + g_free (report_id); + gvm_close_sentry (); + exit (-1); + } + + setproctitle ("Openvasd: Handling scan %s", report_id); + + rc = handle_openvasd_scan (task, global_current_report, report_id); + g_free (report_id); + + if (rc >= 0) + { + set_task_run_status (task, TASK_STATUS_PROCESSING); + set_report_scan_run_status (global_current_report, + TASK_STATUS_PROCESSING); + hosts_set_identifiers (global_current_report); + hosts_set_max_severity (global_current_report, NULL, NULL); + hosts_set_details (global_current_report); + set_task_run_status (task, TASK_STATUS_DONE); + set_report_scan_run_status (global_current_report, TASK_STATUS_DONE); + } + else if (rc == -1 || rc == -2) + { + set_task_run_status (task, TASK_STATUS_STOPPED); + set_report_scan_run_status (global_current_report, TASK_STATUS_STOPPED); + } + else if (rc == -3) + { + set_task_run_status (task, TASK_STATUS_INTERRUPTED); + set_report_scan_run_status (global_current_report, + TASK_STATUS_INTERRUPTED); + } + + set_task_end_time_epoch (task, time (NULL)); + set_scan_end_time_epoch (global_current_report, time (NULL)); + global_current_report = 0; + current_scanner_task = (task_t) 0; + gvm_close_sentry (); + exit (rc); +} + + +/** + * @brief Start a task on an Openvasd scanner. + * + * @param[in] task The task. + * @param[in] from 0 start from beginning, 1 continue from stopped, + * 2 continue if stopped else start from beginning. + * @param[out] report_id The report ID. + * + * @return 0 success, 99 permission denied, -1 error. + */ +static int +run_openvasd_task (task_t task, int from, char **report_id) +{ + target_t target; + + target = task_target (task); + if (target) + { + char *uuid; + target_t found; + + uuid = target_uuid (target); + if (find_target_with_permission (uuid, &found, "get_targets")) + { + g_free (uuid); + return -1; + } + g_free (uuid); + if (found == 0) + return 99; + } + + if (fork_openvasd_scan_handler (task, target, from, report_id)) + { + g_warning ("Couldn't fork Openvasd scan handler"); + return -1; + } + return 0; +} diff --git a/src/manage.h b/src/manage.h index df8f144a4..5be9849b1 100644 --- a/src/manage.h +++ b/src/manage.h @@ -39,6 +39,7 @@ #include #include #include +#include #include /** @@ -328,7 +329,8 @@ typedef enum scanner_type SCANNER_TYPE_CVE = 3, /* 4 was removed (SCANNER_TYPE_GMP). */ SCANNER_TYPE_OSP_SENSOR = 5, - SCANNER_TYPE_MAX = 6, + SCANNER_TYPE_OPENVASD = 6, + SCANNER_TYPE_MAX = 7, } scanner_type_t; int @@ -4047,4 +4049,9 @@ get_vt_verification_collation (); void set_vt_verification_collation (const char *); +/* Openvasd*/ +openvasd_connector_t +openvasd_scanner_connect (scanner_t, const char *); + + #endif /* not _GVMD_MANAGE_H */ diff --git a/src/manage_sql.c b/src/manage_sql.c index fc1bf3905..ea7d7d8ff 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -24,6 +24,8 @@ /** * @brief Enable extra GNU functions. */ +#include "manage.h" +#include #define _GNU_SOURCE #include "debug_utils.h" @@ -67,6 +69,8 @@ #include #include #include +#include +#include #include #include @@ -82,6 +86,7 @@ #include #include #include +#include #include "manage_report_configs.h" #undef G_LOG_DOMAIN @@ -20074,14 +20079,17 @@ nvt_severity (const char *nvt_id, const char *type) { char *severity = NULL; - if (strcasecmp (type, "Alarm") == 0 && nvt_id) + if ((strcasecmp (type, "alarm") == 0 || strcasecmp (type, "Alarm") == 0) && nvt_id) severity = sql_string ("SELECT coalesce(cvss_base, '0.0')" " FROM nvts WHERE uuid = '%s';", nvt_id); - else if (strcasecmp (type, "Alarm") == 0) + else if (strcasecmp (type, "Alarm") == 0 + || strcasecmp (type, "alarm") == 0) g_warning ("%s result type requires an NVT", type); - else if (strcasecmp (type, "Log Message") == 0) + else if (strcasecmp (type, "Log Message") == 0 + || strcasecmp (type, "log") == 0) severity = g_strdup (G_STRINGIFY (SEVERITY_LOG)); - else if (strcasecmp (type, "Error Message") == 0) + else if (strcasecmp (type, "Error Message") == 0 + || strcasecmp (type, "error") == 0) severity = g_strdup (G_STRINGIFY (SEVERITY_ERROR)); else g_warning ("Invalid result nvt type %s", type); @@ -42279,7 +42287,7 @@ create_scanner (const char* name, const char *comment, const char *host, if (!host || !port || !type) return 2; - if (*host == '/') + if (*host == '/' || *host == 'h') { unix_socket = 1; ca_pub = NULL; @@ -43507,6 +43515,7 @@ osp_scanner_connect (scanner_t scanner) return connection; } + /** * @brief Get an OSP Scanner's get_version info. * @@ -43570,6 +43579,48 @@ osp_get_details_from_iterator (iterator_t *iterator, char **desc, return 0; } +/** + * @brief Get an Openvasd Scanner's get_scanner_preferences info. + * + * @param[in] iterator Scanner object iterator. + * @param[out] desc Scanner description. + * @param[out] params Scanner parameters. + * + * @return 0 success, 1 for failure. + */ +int +openvasd_get_details_from_iterator (iterator_t *iterator, char **desc, + GSList **params) +{ + int port; + openvasd_connector_t connection; + const char *server, *ca_pub, *key_pub, *key_priv; + + assert (iterator); + server = scanner_iterator_host (iterator); + port = scanner_iterator_port (iterator); + ca_pub = scanner_iterator_ca_pub (iterator); + key_pub = scanner_iterator_key_pub (iterator); + key_priv = scanner_iterator_key_priv (iterator); + + connection = openvasd_connector_new(); + + openvasd_connector_builder (connection, OPENVASD_SERVER, server); + openvasd_connector_builder (connection, OPENVASD_CA_CERT, ca_pub); + openvasd_connector_builder (connection, OPENVASD_KEY, key_priv); + openvasd_connector_builder (connection, OPENVASD_CERT, key_pub); + openvasd_connector_builder (connection, OPENVASD_PORT, (void *) &port); + + if (!connection) + return 1; + + *desc = g_strdup_printf("Openvasd Sensor on htt://%s:%d", server, port); + if (openvasd_parsed_scans_preferences (connection, params) < 0) + return 1; + openvasd_connector_free (connection); + return 0; +} + /** * @brief Verify a scanner. * @@ -43605,6 +43656,11 @@ verify_scanner (const char *scanner_id, char **version) return 2; return 0; } + else if (scanner_iterator_type (&scanner) == SCANNER_TYPE_OPENVASD) + { + cleanup_iterator (&scanner); + return 0; + } else if (scanner_iterator_type (&scanner) == SCANNER_TYPE_CVE) { if (version) @@ -43662,6 +43718,9 @@ manage_get_scanners (GSList *log_config, const db_conn_info_t *database) case SCANNER_TYPE_OSP_SENSOR: scanner_type_str = "OSP-Sensor"; break; + case SCANNER_TYPE_OPENVASD: + scanner_type_str = "Openvasd"; + break; default: scanner_type_str = NULL; } @@ -60189,3 +60248,357 @@ cleanup_ids_for_table (const char *table) free (sequence_name); return 0; } + + +/** + * @brief Create a new connection to an OSP scanner. + * + * @param[in] scanner Scanner. + * + * @return New connection if success, NULL otherwise. + */ +openvasd_connector_t +openvasd_scanner_connect (scanner_t scanner, const char *scan_id) +{ + int port; + openvasd_connector_t connection; + char *server, *ca_pub, *key_pub, *key_priv; + + assert (scanner); + server = scanner_host (scanner); + port = scanner_port (scanner); + ca_pub = scanner_ca_pub (scanner); + key_pub = scanner_key_pub (scanner); + key_priv = scanner_key_priv (scanner); + + connection = openvasd_connector_new(); + + openvasd_connector_builder (connection, OPENVASD_SERVER, server); + openvasd_connector_builder (connection, OPENVASD_CA_CERT, ca_pub); + openvasd_connector_builder (connection, OPENVASD_KEY, key_priv); + openvasd_connector_builder (connection, OPENVASD_CERT, key_pub); + openvasd_connector_builder (connection, OPENVASD_PORT, (void *) &port); + + if (scan_id && scan_id[0] != '\0') + openvasd_connector_builder (connection, OPENVASD_SCAN_ID, scan_id); + + g_free (server); + g_free (ca_pub); + g_free (key_pub); + g_free (key_priv); + + return connection; +} + +/** + * @brief Generate the hash value for the fields of the result and + * check if openvasd result for report already exists + * + * @param[in] report Report. + * @param[in] task Task. + * @param[in] r_entity entity of the result. + * @param[out] entity_hash_value The generated hash value of r_entity. + * + * @return "1" if openvasd result already exists, else "0" + */ +static int +check_openvasd_result_exists (report_t report, task_t task, + openvasd_result_t res, char **entity_hash_value, + GHashTable *hashed_openvasd_results) +{ + GString *result_string; + int return_value = 0; + char *port_str = NULL; + if (res->port == 0 && res->detail_value && *res->detail_value) + port_str = g_strdup ("general/Host_Details"); + else if (res->port > 0) + { + char buf[6]; + snprintf (buf, sizeof(buf) , "%d", res->port); + port_str = g_strdup (buf); + } + else + port_str = ""; + + result_string = g_string_new (""); + g_string_append_printf (result_string, "host:%s\n" + "hostname:%s\n" + "type:%s\n" + "description:%s\n" + "port:%s",res->ip_address, res->hostname, + res->type, res->message, port_str); + + *entity_hash_value = get_md5_hash_from_string (result_string->str); + if (g_hash_table_contains (hashed_openvasd_results, *entity_hash_value)) + { + return_value = 1; + } + else + { + g_hash_table_insert (hashed_openvasd_results, + g_strdup(*entity_hash_value), + GINT_TO_POINTER(1)); + if (sql_int ("SELECT EXISTS" + " (SELECT * FROM results" + " WHERE report = %llu and hash_value = '%s');", + report, *entity_hash_value)) + { + const char *desc, *type, *severity = NULL, *host; + const char *hostname, *port = NULL, *path = NULL; + gchar *quoted_desc, *quoted_type, *quoted_host; + gchar *quoted_hostname, *quoted_port, *quoted_path; + double severity_double = 0.0; + int qod_int = QOD_DEFAULT; + + host = res->ip_address; + hostname = res->hostname; + type = res->type; + desc = res->message; + qod_int = QOD_DEFAULT; + + if (!severity || !strcmp (severity, "")) + { + if (!strcmp (type, severity_to_type (SEVERITY_ERROR))) + severity_double = SEVERITY_ERROR; + else + { + g_debug ("%s: Result without severity", __func__); + return 0; + } + } + else + { + severity_double = strtod (severity, NULL); + } + + quoted_host = sql_quote (host ?: ""); + quoted_hostname = sql_quote (hostname ?: ""); + quoted_type = sql_quote (type ?: ""); + quoted_desc = sql_quote (desc ?: ""); + quoted_port = sql_quote (port ?: ""); + quoted_path = sql_quote (path ?: ""); + + if (sql_int ("SELECT EXISTS" + " (SELECT * FROM results" + " WHERE report = %llu and hash_value = '%s'" + " and host = '%s' and hostname = '%s'" + " and type = '%s' and description = '%s'" + " and port = '%s' and severity = %1.1f" + " and qod = %d and path = '%s'" + " );", + report, *entity_hash_value, + quoted_host, quoted_hostname, + quoted_type, quoted_desc, + quoted_port, severity_double, + qod_int, quoted_path)) + { + g_info ("Captured duplicate result, report: %llu hash_value: %s", + report, *entity_hash_value); + g_debug ("Entity string: %s", result_string->str); + return_value = 1; + } + + g_free (quoted_host); + g_free (quoted_hostname); + g_free (quoted_type); + g_free (quoted_desc); + g_free (quoted_port); + g_free (quoted_path); + } + } + if (return_value) + { + g_debug ("Captured duplicate result, report: %llu hash_value: %s", + report, *entity_hash_value); + g_debug ("Entity string: %s", result_string->str); + } + g_string_free (result_string, TRUE); + return return_value; +} + +/* Struct to be sent as user data to the GFunc for adding results */ +struct report_aux { + GArray *results_array; + report_t report; + task_t task; + GHashTable *hash_results; + GHashTable *hash_hostdetails; +}; + +static void +add_openvasd_result_to_report (openvasd_result_t res, gpointer *results_aux) +{ + + struct report_aux *rep_aux = *results_aux; + result_t result; + char *type, *name, *severity, *host, *hostname, *test_id; + char *port = NULL, *path = NULL; + char *desc = NULL, *nvt_id = NULL, *severity_str = NULL; + int qod_int; + + type = res->type; + name = NULL; + severity = NULL; + test_id = res->oid; + host = res->ip_address; + hostname = res->hostname; + + if (res && res->port == 0 && !strcmp (type, "host_detail") && + res->detail_value && *res->detail_value) + port = g_strdup ("general/Host_Details"); + else if (res->port > 0) + { + char buf[6]; + snprintf(buf, sizeof(buf) , "%d", res->port); + port = g_strdup (buf); + } + + /* Add report host if it doesn't exist. */ + manage_report_host_add (rep_aux->report, host, 0, 0); + if (!strcmp (type, "host_detail")) + { + gchar *hash_value = NULL; + if (!check_host_detail_exists (rep_aux->report, host, "openvasd", "", + "Openvasd Host Detail", res->detail_name, + res->detail_value, &hash_value, + rep_aux->hash_hostdetails)) + { + insert_report_host_detail (rep_aux->report, host, "openvasd", "", + "Openvasd Host Detail", res->detail_name, + res->detail_value, hash_value); + } + desc = res->message; + g_free (hash_value); + g_free (port); + return; + } + else if (g_str_has_prefix (test_id, "1.3.6.1.4.1.25623.1.")) + { + nvt_id = g_strdup (test_id); + severity_str = nvt_severity (test_id, type); + desc = res->message; + } + else + { + nvt_id = g_strdup (name); + desc = res->message; + } + qod_int = QOD_DEFAULT; + if (port && strcmp (port, "general/Host_Details") == 0) + { + /* TODO: This should probably be handled by the "Host Detail" + * result type with extra source info in OSP. + */ + if (manage_report_host_detail (rep_aux->report, host, desc, + rep_aux->hash_hostdetails)) + g_warning ("%s: Failed to add report detail for host '%s': %s", + __func__, host, desc); + } + else if (host && desc && (strcmp (type, "host_start") == 0)) + { + set_scan_host_start_time_ctime (rep_aux->report, host, desc); + } + else if (host && desc && (strcmp (type, "host_end") == 0)) + { + set_scan_host_end_time_ctime (rep_aux->report, host, desc); + add_assets_from_host_in_report (rep_aux->report, host); + } + else + { + char *hash_value; + if (!check_openvasd_result_exists (rep_aux->report, rep_aux->task, res, + &hash_value, rep_aux->hash_results)) + { + result = make_osp_result (rep_aux->task, + host ?: "", + hostname ?: "", + nvt_id ?: "", + type ?: "", + desc ?: "", + port ?: "", + severity_str ?: severity, + qod_int, + path ?: "", + hash_value); + g_array_append_val (rep_aux->results_array, result); + } + g_free (hash_value); + } + + g_free (port); + g_free (nvt_id); + + return; +} + +/** + * @brief Parse Openvasd results. + * + * @param[in] task Task. + * @param[in] report Report. + * @param[in] results Openvasd results. + */ +void +parse_openvasd_report (task_t task, report_t report, GSList *results, + time_t start_time, time_t end_time) +{ + char *defs_file = NULL; + gboolean has_results = FALSE; + GArray *results_array = NULL; + GHashTable *hashed_openvasd_results = NULL; + GHashTable *hashed_host_details = NULL; + struct report_aux *rep_aux; + + assert (task); + assert (report); + + hashed_openvasd_results = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + + hashed_host_details = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + + sql_begin_immediate (); + /* Set the report's start and end times. */ + + if (start_time) + set_scan_start_time_epoch (report, start_time); + + if (end_time) + set_scan_end_time_epoch (report, end_time); + + if (g_slist_length (results)) + has_results = TRUE; + + defs_file = task_definitions_file (task); + + results_array = g_array_new(TRUE, TRUE, sizeof(result_t)); + rep_aux = g_malloc0 (sizeof (struct report_aux)); + rep_aux->report = report; + rep_aux->task = task; + rep_aux->results_array = results_array; + rep_aux->hash_results = hashed_openvasd_results; + rep_aux->hash_hostdetails = hashed_host_details; + + g_slist_foreach(results, (GFunc) add_openvasd_result_to_report, &rep_aux); + + if (has_results) + { + sql ("UPDATE reports SET modification_time = m_now() WHERE id = %llu;", + report); + report_add_results_array (report, results_array); + } + + sql_commit (); + if (results_array && has_results) + g_array_free (results_array, TRUE); + + g_hash_table_destroy (hashed_openvasd_results); + g_hash_table_destroy (hashed_host_details); + g_free (defs_file); + g_free (rep_aux); +} diff --git a/src/manage_sql.h b/src/manage_sql.h index b9db9cb99..f867c75d3 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -25,6 +25,7 @@ #define _GVMD_MANAGE_SQL_H #include +#include #include "manage.h" #include "manage_utils.h" @@ -97,6 +98,11 @@ */ #define SCANNER_UUID_DEFAULT "08b69003-5fc2-4037-a479-93b440211c73" +/** + * @brief UUID of 'Openvasd Default' scanner. + */ +#define SCANNER_UUID_OPENVASD_DEFAULT "8154d8e3-30ee-4959-9151-1863c89a8e62" + /** * @brief UUID of 'CVE' scanner. */ @@ -442,6 +448,8 @@ init_get_iterator (iterator_t*, const char *, const get_data_t *, column_t *, column_t *, const char **, int, const char *, const char *, int); +int openvasd_get_details_from_iterator (iterator_t *, char **, GSList **); + gchar * columns_build_select (column_t *); @@ -542,4 +550,6 @@ cleanup_nvt_sequences (); int cleanup_ids_for_table (const char *); +void +parse_openvasd_report (task_t, report_t, GSList *, time_t, time_t); #endif /* not _GVMD_MANAGE_SQL_H */ diff --git a/src/manage_sql_configs.c b/src/manage_sql_configs.c index 28e2bb10e..034bb3f31 100644 --- a/src/manage_sql_configs.c +++ b/src/manage_sql_configs.c @@ -2762,6 +2762,8 @@ create_task_check_scanner_type (scanner_t scanner) return 1; if (stype == SCANNER_TYPE_OSP_SENSOR) return 1; + if (stype == SCANNER_TYPE_OPENVASD) + return 1; return 0; } @@ -2831,6 +2833,9 @@ modify_task_check_config_scanner (task_t task, const char *config_id, if (stype == SCANNER_TYPE_OSP_SENSOR) return 0; + if (stype == SCANNER_TYPE_OPENVASD) + return 0; + /* Default Scanner with OpenVAS Config. */ if (scanner == 0) return 0; diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 04e9cf3c8..17e74ee01 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -26,6 +26,13 @@ /** * @brief Enable extra GNU functions. */ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#define _FILE_OFFSET_BITS 64 +#include + +#include +#include "glibconfig.h" +#include "manage.h" #define _GNU_SOURCE #include @@ -35,6 +42,8 @@ #include #include +#include +#include #include #include "manage_sql_nvts.h" @@ -1452,6 +1461,7 @@ insert_nvt_preference (gpointer nvt_preference, gpointer rebuild) return; preference = (preference_t*) nvt_preference; + manage_nvt_preference_add (preference->name, preference->value, preference->nvt_oid, preference->id, preference->type, preference->pref_name, @@ -1594,6 +1604,91 @@ update_preferences_from_vt (element_t vt, const gchar *oid, GList **preferences) return 0; } +/** + * @brief Update NVT from an NVTI structure + * + * @param[in] vt OSP GET_VTS VT element. + * @param[in] oid OID of NVT. + * @param[in] preferences All NVT preferences. + * + * @return 0 success, -1 error. + */ +static int +update_preferences_from_json_nvt (nvti_t *nvti, GList **preferences) +{ + assert (preferences); + + int prefs_count = nvti_pref_len(nvti); + for (int j = 0; j < prefs_count; j++) + { + int id; + char *char_id, *type, *name, *def; + const nvtpref_t *pref = NULL; + + pref = nvti_pref (nvti, j); + + id = nvtpref_id (pref); + char_id = g_strdup_printf ("%d", id); + type = g_strdup (nvtpref_type (pref)); + name = g_strdup (nvtpref_name (pref)); + def = g_strdup (nvtpref_default (pref)); + + if (type == NULL) + { + GString *debug = g_string_new (""); + g_warning ("%s: PARAM missing type attribute for OID: %s", + __func__, nvti_oid(nvti)); + g_string_free (debug, TRUE); + } + else if (id < 0) + { + GString *debug = g_string_new (""); + g_warning ("%s: PARAM missing id attribute for OID: %s", + __func__, nvti_oid(nvti)); + g_string_free (debug, TRUE); + } + else if (name == NULL) + { + GString *debug = g_string_new (""); + g_warning ("%s: PARAM missing NAME for OID: %s", + __func__, nvti_oid (nvti)); + g_string_free (debug, TRUE); + } + else + { + gchar *full_name; + preference_t *preference; + + full_name = g_strdup_printf ("%s:%d:%s:%s", + nvti_oid (nvti), + id, + type, + name); + + blank_control_chars (full_name); + preference = g_malloc0 (sizeof (preference_t)); + preference->free_strings = 1; + preference->name = full_name; + if (def) + preference->value = g_strdup (def); + else + preference->value = g_strdup (""); + preference->nvt_oid = g_strdup (nvti_oid (nvti)); + preference->id = g_strdup (char_id); + preference->type = g_strdup (type); + preference->pref_name = g_strdup (name); + *preferences = g_list_prepend (*preferences, preference); + } + + g_free (char_id); + g_free (name); + g_free (type); + g_free (def); + } + + return 0; +} + /** * @brief Create NVTI structure from VT XML. * @@ -1618,6 +1713,7 @@ nvti_from_vt (element_t vt) nvti_free (nvti); return NULL; } + nvti_set_oid (nvti, id); g_free (id); @@ -2053,6 +2149,295 @@ update_nvts_from_vts (element_t *get_vts_response, return 0; } + +/** + * @brief Struct containing the stream buffer. + */ +struct FILESTREAM { + char *stream_buffer; + size_t size_of_buffer; + size_t last_read; + size_t last_write; +}; + +/** + * @brief Hook function to read the stream file cookie + */ +static ssize_t +readcookie (void *stream_cookie, char *buf, size_t size) +{ + struct FILESTREAM *stream = stream_cookie; + size_t to_read = stream->last_write - stream->last_read; + if (to_read < 0) + to_read = 0; + + if (to_read > size) + to_read = size; + memcpy (buf, &stream->stream_buffer[stream->last_read], to_read); + + stream->last_read += to_read; + return to_read; +} + +/** + * @brief Hook function to close the stream file cookie + */ +static int +closecookie(void *filestream) +{ + struct FILESTREAM *stream = filestream; + g_free(stream->stream_buffer); + stream->size_of_buffer = 0; + stream->stream_buffer = NULL; + return 0; +} + +/** + * @brief Hook function to write the stream file cookie + */ +static ssize_t +writecookie (void *stream_cookie, const char *buf, size_t size) +{ + struct FILESTREAM *stream = stream_cookie; + size_t next_size = stream->last_write + size; + if (next_size > stream->size_of_buffer) + { + stream->size_of_buffer = next_size + GVM_JSON_PULL_PARSE_BUFFER_LIMIT; + stream->stream_buffer = g_realloc (stream->stream_buffer, + stream->size_of_buffer); + if (stream->stream_buffer == NULL) + { + g_message ("%s: Buffer overflow", __func__); + return 0; + } + } + + memcpy (&(stream->stream_buffer[stream->last_write]), buf, size); + stream->last_write+=size; + + return size; +} + +/** + * @brief Move non read data to beggining of the buffer + */ +static int move_buffer_data(struct FILESTREAM *filestream){ + char *auxbuf; + size_t non_read_chars_count = filestream->last_write - filestream->last_read; + + auxbuf = g_malloc0 (sizeof(char) * filestream->size_of_buffer); + if (auxbuf == NULL) + return -1; + + memcpy (auxbuf, &filestream->stream_buffer[filestream->last_read], + non_read_chars_count); + memset (filestream->stream_buffer, '\0', filestream->size_of_buffer); + memcpy (filestream->stream_buffer, auxbuf, non_read_chars_count); + + filestream->last_read = 0; + filestream->last_write = non_read_chars_count; + + g_free(auxbuf); + + return 0; +} + +/** + * @brief Update NVTs from Json response chunk by chunk + * + * @param[in] conn Openvasd connector + * @param[in] scanner_feed_version Version of feed from scanner. + * @param[in] rebuild Whether we're rebuilding the tables. + * + * @return 0 success, 1 VT integrity check failed, -1 error + */ +static int +update_nvts_from_json_vts (openvasd_connector_t connector, + const gchar *scanner_feed_version, + int rebuild) +{ + GList *preferences; + int count_modified_vts, count_new_vts; + time_t feed_version_epoch; + batch_t *vt_refs_batch, *vt_sevs_batch; + + count_modified_vts = 0; + count_new_vts = 0; + + feed_version_epoch = nvts_feed_version_epoch(); + + //osp_vt_hash = element_attribute (vts, "sha256_hash"); + + sql_begin_immediate (); + + if (rebuild) { + sql ("DROP TABLE IF EXISTS vt_refs_rebuild;"); + sql ("DROP TABLE IF EXISTS vt_severities_rebuild;"); + sql ("DROP TABLE IF EXISTS nvt_preferences_rebuild;"); + sql ("DROP TABLE IF EXISTS nvts_rebuild;"); + + create_tables_nvt ("_rebuild"); + } + else if (sql_int ("SELECT coalesce ((SELECT CAST (value AS INTEGER)" + " FROM meta" + " WHERE name = 'checked_preferences')," + " 0);") + == 0) + /* We're in the first NVT sync after migrating preference names. + * + * If a preference was removed from an NVT then the preference will be in + * nvt_preferences in the old format, but we will not get a new version + * of the preference name from the sync. For example "Alle Dateien + * Auflisten" was removed from 1.3.6.1.4.1.25623.1.0.94023. + * + * If a preference was not in the migrator then the new version of the + * preference would be inserted alongside the old version, resulting in a + * duplicate when the name of the old version was corrected. + * + * To solve both cases, we remove all nvt_preferences. */ + sql ("TRUNCATE nvt_preferences;"); + + vt_refs_batch = batch_start (vt_ref_insert_size); + vt_sevs_batch = batch_start (vt_sev_insert_size); + + int running = 0; + openvasd_resp_t resp; + gvm_json_pull_event_t event; + gvm_json_pull_parser_t parser; + FILE *stream = NULL; + struct FILESTREAM *filestream; + nvti_t *nvti = NULL; + + resp = openvasd_get_vt_stream_init (connector); + if (resp->code < 0) + { + g_warning ("%s: failed to get VTs", __func__); + return -1; + } + + cookie_io_functions_t cookiehooks = { + .read = readcookie, + .write = writecookie, + .seek = NULL, + .close = closecookie, + }; + + filestream = g_malloc0 (sizeof(struct FILESTREAM)); + filestream->size_of_buffer = GVM_JSON_PULL_PARSE_BUFFER_LIMIT; + filestream->stream_buffer = + g_malloc0 (sizeof(char) * filestream->size_of_buffer); + + stream = fopencookie (filestream, "a+", cookiehooks); + + gvm_json_pull_parser_init_full (&parser, stream, + GVM_JSON_PULL_PARSE_BUFFER_LIMIT, + GVM_JSON_PULL_READ_BUFFER_SIZE * 8); + gvm_json_pull_event_init (&event); + + // First run for initial data in the stream + running = openvasd_get_vt_stream (connector); + fwrite (openvasd_vt_stream_str (connector), 1, + openvasd_vt_stream_len (connector), stream); + + openvasd_reset_vt_stream (connector); + int break_flag = 0; + while (running) + { + size_t non_read_count = 0; + // Ensure a big chunk of data. + // Realloc is expensive therefore we realloc with bigger chuncks + while (running > 0 && openvasd_vt_stream_len (connector) < GVM_JSON_PULL_READ_BUFFER_SIZE * 8) + running = openvasd_get_vt_stream (connector); + + if (openvasd_vt_stream_len (connector) > 0) + { + move_buffer_data (filestream); + fwrite (openvasd_vt_stream_str (connector), 1, openvasd_vt_stream_len (connector), stream); + openvasd_reset_vt_stream (connector); + } + + non_read_count = filestream->last_write - filestream->last_read; + // While streaming, parse some VTs and continue for a new chunk. + // If the stream is not running anymore, parse the remaining VTs. + while ((running && non_read_count > GVM_JSON_PULL_READ_BUFFER_SIZE * 8) || !running) + { + nvti = openvasd_parse_vt (&parser, &event); + if (nvti == NULL) + { + break_flag = 1; + break; + } + if (nvti_creation_time (nvti) > feed_version_epoch) + count_new_vts += 1; + else + count_modified_vts += 1; + + insert_nvt (nvti, rebuild, vt_refs_batch, vt_sevs_batch); + + preferences = NULL; + if (update_preferences_from_json_nvt (nvti, &preferences)) + { + sql_rollback (); + return -1; + } + if (rebuild == 0) + sql ("DELETE FROM nvt_preferences%s WHERE name LIKE '%s:%%';", + rebuild ? "_rebuild" : "", + nvti_oid (nvti)); + insert_nvt_preferences_list (preferences, rebuild); + g_list_free_full (preferences, (GDestroyNotify) preference_free); + + g_free(nvti); + non_read_count = filestream->last_write - filestream->last_read; + } + if (break_flag) + break; + } + + gvm_json_pull_event_cleanup (&event); + gvm_json_pull_parser_cleanup (&parser); + fclose (stream); + + openvasd_response_cleanup (resp); + + batch_end (vt_refs_batch); + batch_end (vt_sevs_batch); + + if (rebuild) { + sql ("DROP VIEW IF EXISTS results_autofp;"); + sql ("DROP VIEW vulns;"); + sql ("DROP TABLE nvts, nvt_preferences, vt_refs, vt_severities;"); + + sql ("ALTER TABLE vt_refs_rebuild RENAME TO vt_refs;"); + sql ("ALTER TABLE vt_severities_rebuild RENAME TO vt_severities;"); + sql ("ALTER TABLE nvt_preferences_rebuild RENAME TO nvt_preferences;"); + sql ("ALTER TABLE nvts_rebuild RENAME TO nvts;"); + + create_view_vulns (); + create_view_result_vt_epss (); + } + + set_nvts_check_time (count_new_vts, count_modified_vts); + + set_nvts_feed_version (scanner_feed_version); + + if (check_config_families ()) + g_warning ("%s: Error updating config families." + " One or more configs refer to an outdated family of an NVT.", + __func__); + update_all_config_caches (); + + g_info ("Updating VTs in database ... %i new VTs, %i changed VTs", + count_new_vts, count_modified_vts); + + sql_commit (); + + g_warning ("%s: No SHA-256 hash received from scanner, skipping check.", + __func__); + + return 0; +} + /** * @brief Check that preference names are in the new format. * @@ -2229,6 +2614,7 @@ nvt_severity_iterator_score (iterator_t *iterator) */ DEF_ACCESS (nvt_severity_iterator_value, 4); + /** * @brief Update VTs via OSP. * @@ -2397,6 +2783,195 @@ update_nvt_cache_osp (const gchar *update_socket, gchar *db_feed_version, return 0; } +/** + * @brief Update VTs via Openvasd. + * + * @param[in] openvasd_uuid UUID of Openvasd to connect to. + * @param[in] db_feed_version Feed version from meta table. + * @param[in] scanner_feed_version Feed version from scanner. + * @param[in] rebuild Whether to rebuild the NVT tables from scratch. + * + * @return 0 success, 1 VT integrity check failed, -1 error. + */ +static int +update_nvt_cache_openvasd (gchar* openvasd_uuid, gchar *db_feed_version, + gchar *scanner_feed_version, int rebuild) +{ + openvasd_connector_t connector = NULL; + openvasd_resp_t resp; + scanner_t scan; + + time_t old_nvts_last_modified; + int ret; + + if (rebuild + || db_feed_version == NULL + || strcmp (db_feed_version, "") == 0 + || strcmp (db_feed_version, "0") == 0) + old_nvts_last_modified = 0; + else + old_nvts_last_modified + = (time_t) sql_int64_0 ("SELECT max(modification_time) FROM nvts"); + + + /* Update NVTs. */ + if (find_resource_no_acl ("scanner", SCANNER_UUID_OPENVASD_DEFAULT, &scan)) + return -1; + + connector = openvasd_scanner_connect (scan, NULL); + if (!connector) + { + g_warning ("%s: failed to connect to scanner (%s)", __func__, + openvasd_uuid); + return -1; + } + + ret = update_nvts_from_json_vts (connector, scanner_feed_version, rebuild); + + if (ret) + { + openvasd_connector_free (connector); + return ret; + } + + /* Update scanner preferences */ + // TODO: update scanner preferences + + resp = openvasd_get_vts (connector); + if (resp->code != 200) + { + g_warning ("%s: failed to get scanner preferences", __func__); + return -1; + } + GSList *scan_prefs = NULL; + + openvasd_parsed_scans_preferences (connector, &scan_prefs); + g_debug ("There %d scan preferences", g_slist_length (scan_prefs)); + openvasd_connector_free (connector); + + GString *prefs_sql; + GSList *point; + int first; + + point = scan_prefs; + first = 1; + + prefs_sql = g_string_new ("INSERT INTO nvt_preferences (name, value)" + " VALUES"); + while (point) + { + openvasd_param_t *param; + gchar *quoted_name, *quoted_value; + + param = point->data; + quoted_name = sql_quote (openvasd_param_id (param)); + quoted_value = sql_quote (openvasd_param_default (param)); + + g_string_append_printf (prefs_sql, + "%s ('%s', '%s')", + first ? "" : ",", + quoted_name, + quoted_value); + first = 0; + point = g_slist_next (point); + g_free (quoted_name); + g_free (quoted_value); + } + g_slist_free_full (scan_prefs, (GDestroyNotify) openvasd_param_free); + + g_string_append (prefs_sql, + " ON CONFLICT (name)" + " DO UPDATE SET value = EXCLUDED.value;"); + + if (first == 0) + { + sql ("%s", prefs_sql->str); + } + + g_string_free (prefs_sql, TRUE); + + /* Update the cache of report counts. */ + + reports_clear_count_cache_dynamic (); + + /* Tell the main process to update its NVTi cache. */ + sql ("UPDATE %s.meta SET value = 1 WHERE name = 'update_nvti_cache';", + sql_schema ()); + + g_info ("Updating VTs in database ... done (%i VTs).", + sql_int ("SELECT count (*) FROM nvts;")); + + if (sql_int ("SELECT coalesce ((SELECT CAST (value AS INTEGER)" + " FROM meta" + " WHERE name = 'checked_preferences')," + " 0);") + == 0) + { + check_old_preference_names ("config_preferences"); + check_old_preference_names ("config_preferences_trash"); + + /* Force update of names in new format in case hard-coded names + * used by migrators are outdated */ + old_nvts_last_modified = 0; + + sql ("INSERT INTO meta (name, value)" + " VALUES ('checked_preferences', 1)" + " ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;"); + } + + check_preference_names (0, old_nvts_last_modified); + check_preference_names (1, old_nvts_last_modified); + + check_whole_only_in_configs (); + + return 0; +} + +/** + * @brief Get VTs feed information from a scanner. + * + * @param[in] scanner_uuid The uuid of the scanner to be used. + * @param[out] vts_version Output of scanner feed version. + * + * @return 0 success, 1 connection to scanner failed, 2 scanner still starting, + * -1 other error. + */ +static int +nvts_feed_info_internal_from_openvasd (const gchar *scanner_uuid, + gchar **vts_version) +{ + scanner_t scan; + openvasd_connector_t connector = NULL; + openvasd_resp_t resp = NULL; + int ret; + if (find_resource_no_acl ("scanner", scanner_uuid, &scan)) + return -1; + + connector = openvasd_scanner_connect (scan, NULL); + if (!connector) + return 1; + + resp = openvasd_get_health_ready (connector); + if (resp->code == -1) + { + g_warning ("%s: failed to connect to %s:%d", __func__, + scanner_host (scan), scanner_port (scan)); + ret = 1; + } + else if (resp->code == 503) + ret = 2; + else + { + *vts_version = g_strdup (resp->header); + ret = 0; + } + + openvasd_response_cleanup (resp); + openvasd_connector_free (connector); + return ret; +} + + /** * @brief Get the VTs feed version from an OSP scanner. * @@ -2453,7 +3028,8 @@ nvts_feed_version_status_internal (const gchar *update_socket, gchar **db_feed_version_out, gchar **scanner_feed_version_out) { - gchar *db_feed_version, *scanner_feed_version; + gchar *db_feed_version = NULL; + gchar *scanner_feed_version = NULL; if (db_feed_version_out) *db_feed_version_out = NULL; @@ -2465,12 +3041,19 @@ nvts_feed_version_status_internal (const gchar *update_socket, if (db_feed_version_out && db_feed_version) *db_feed_version_out = g_strdup (db_feed_version); +#if OPENVASD == 1 + nvts_feed_info_internal_from_openvasd (SCANNER_UUID_OPENVASD_DEFAULT, + &scanner_feed_version); +#else scanner_feed_version = osp_scanner_feed_version (update_socket); +#endif + g_debug ("%s: scanner_feed_version: %s", __func__, scanner_feed_version); if (scanner_feed_version == NULL) { g_free (db_feed_version); return -1; } + if (scanner_feed_version_out && scanner_feed_version) *scanner_feed_version_out = g_strdup (scanner_feed_version); @@ -2532,9 +3115,14 @@ manage_update_nvt_cache_osp (const gchar *update_socket) scanner_feed_version, db_feed_version, sql_int ("SELECT count (*) FROM nvts;")); +#if OPENVASD == 1 + ret = update_nvt_cache_openvasd (SCANNER_UUID_OPENVASD_DEFAULT, + db_feed_version, + scanner_feed_version, 0); +#else ret = update_nvt_cache_osp (update_socket, db_feed_version, scanner_feed_version, 0); - +#endif g_free (db_feed_version); g_free (scanner_feed_version); return ret; @@ -2571,8 +3159,35 @@ manage_sync_nvts (int (*fork_update_nvt_cache) (pid_t*)) int update_or_rebuild_nvts (int update) { + gchar *db_feed_version = NULL; + gchar *scanner_feed_version = NULL; +#if OPENVASD + int ret = 0; + const char *update_socket = NULL; + + ret = nvts_feed_version_status_internal (update_socket, + &db_feed_version, + &scanner_feed_version); + if (ret == -1) + { + g_warning ("Failed to get scanner feed version."); + return -3; + } + + g_debug ("%s: db_feed_version: %s", __func__, db_feed_version); + + if (update == 0) + set_nvts_feed_version ("0"); + ret = update_nvt_cache_openvasd (SCANNER_UUID_OPENVASD_DEFAULT, + db_feed_version, + scanner_feed_version, 0); + if (ret != 0) + ret = -1; + + return ret; + +#else const char *osp_update_socket; - gchar *db_feed_version, *scanner_feed_version; osp_connection_t *connection; int ret; gchar *error; @@ -2621,7 +3236,7 @@ update_or_rebuild_nvts (int update) { return -1; } - +#endif return 0; }