diff --git a/.docker/prod.Dockerfile b/.docker/prod.Dockerfile index 98bd6b9e5..204d14036 100644 --- a/.docker/prod.Dockerfile +++ b/.docker/prod.Dockerfile @@ -2,8 +2,14 @@ ARG VERSION=edge ARG GVM_LIBS_VERSION=oldstable ARG DEBIAN_FRONTEND=noninteractive ARG IMAGE_REGISTRY=ghcr.io +# when set it will added to the cmake command +# As an example: +# FEATURE_TOGGLES="-DOPENVASD=1" +# enables openvasd feature toggle. +ARG FEATURE_TOGGLE="" FROM ${IMAGE_REGISTRY}/greenbone/gvmd-build:${VERSION} as builder +ARG FEATURE_TOGGLE COPY . /source WORKDIR /source @@ -11,7 +17,7 @@ WORKDIR /source RUN mkdir /build && \ mkdir /install && \ cd /build && \ - cmake -DCMAKE_BUILD_TYPE=Release /source && \ + cmake -DCMAKE_BUILD_TYPE=Release $FEATURE_TOGGLE /source && \ make DESTDIR=/install install FROM greenbone/gvm-libs:${GVM_LIBS_VERSION} diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 7b534424d..88aa3ef3e 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -14,6 +14,11 @@ jobs: images: name: Production Images runs-on: ubuntu-latest + strategy: + matrix: + build: + - default + - openvasd steps: - name: Checkout repository uses: actions/checkout@v4 @@ -41,8 +46,9 @@ jobs: type=ref,event=pr # when a new git tag is created set stable and a latest tags - type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} - type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' && matrix.build == 'default'}} + type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' && matrix.build == 'default'}} + type=raw,value=edge-openvasd,enable=${{ steps.latest.outputs.is-latest-tag == 'false' && matrix.build == 'openvasd' }} - name: Set container build options id: container-opts run: | @@ -53,6 +59,11 @@ jobs: echo "version=edge" >> $GITHUB_OUTPUT echo "gvm-libs-version=oldstable-edge" >> $GITHUB_OUTPUT fi + if [[ "${{ matrix.build }}" = 'openvasd' ]]; then + echo 'ft=-DOPENVASD=1' >> $GITHUB_OUTPUT + else + echo 'ft=-DOPENVASD=0' >> $GITHUB_OUTPUT + fi - name: Login to Docker Registry if: github.event_name != 'pull_request' uses: docker/login-action@v3 @@ -71,6 +82,7 @@ jobs: build-args: | VERSION=${{ steps.container-opts.outputs.version }} GVM_LIBS_VERSION=${{ steps.container-opts.outputs.gvm-libs-version }} + FEATURE_TOGGLE=${{ steps.container-opts.outputs.ft }} IMAGE_REGISTRY=${{ vars.IMAGE_REGISTRY }} file: .docker/prod.Dockerfile platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 000000000..83f64cfcf --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,58 @@ +name: Build and Push to Greenbone Registry + +on: + push: + branches: [ main ] + tags: ["v*"] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + building: + runs-on: self-hosted-generic + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: greenbone/actions/is-latest-tag@v3 + id: latest + + - name: Set container build options + id: container-opts + run: | + if [[ "${{ github.ref_type }}" = 'tag' ]]; then + echo "version=stable" >> $GITHUB_OUTPUT + echo "gvm-libs-version=oldstable" >> $GITHUB_OUTPUT + else + echo "version=edge" >> $GITHUB_OUTPUT + echo "gvm-libs-version=oldstable-edge" >> $GITHUB_OUTPUT + fi + + - name: Build and Push Container + id: build-and-push + uses: greenbone/actions/container-build-push-generic@v3 + with: + build-docker-file: .docker/prod.Dockerfile + build-args: | + VERSION=${{ steps.container-opts.outputs.version }} + GVM_LIBS_VERSION=${{ steps.container-opts.outputs.gvm-libs-version }} + IMAGE_REGISTRY=${{ vars.IMAGE_REGISTRY }} + cosign-key: ${{ secrets.COSIGN_KEY_OPENSIGHT }} + cosign-key-password: ${{ secrets.COSIGN_KEY_PASSWORD_OPENSIGHT }} + cosign-tlog-upload: "false" + image-url: community/gvmd + image-labels: | + org.opencontainers.image.vendor=Greenbone + org.opencontainers.image.base.name=greenbone/gvm-libs + image-tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=edge + type=ref,event=pr + type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + registry: ${{ secrets.GREENBONE_REGISTRY }} + registry-username: ${{ secrets.GREENBONE_REGISTRY_USER }} + registry-password: ${{ secrets.GREENBONE_REGISTRY_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 772712ac4..8af58ee08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ include (CPack) ## Variables -set (GVMD_DATABASE_VERSION 255) +set (GVMD_DATABASE_VERSION 256) set (GVMD_SCAP_DATABASE_VERSION 21) @@ -235,6 +235,11 @@ if (NOT GVM_DEFAULT_DROP_USER) set (GVM_DEFAULT_DROP_USER "") endif (NOT GVM_DEFAULT_DROP_USER) + +if (NOT OPENVASD) + set (OPENVASD 0) +endif (NOT OPENVASD) + message ("-- Install prefix: ${CMAKE_INSTALL_PREFIX}") ## Version @@ -275,7 +280,7 @@ set (HARDENING_FLAGS "-Wformat -Wformat-security -D_FORTIFY_SOURCE=2 set (LINKER_HARDENING_FLAGS "-Wl,-z,relro -Wl,-z,now") # To find unused functions, add: -flto -fwhole-program -ffunction-sections -Wl,--gc-sections -Wl,--print-gc-sections -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -D_BSD_SOURCE -D_ISOC99_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_FILE_OFFSET_BITS=64") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -D_BSD_SOURCE -D_ISOC99_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_FILE_OFFSET_BITS=64 -DOPENVASD=${OPENVASD}") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -Wshadow ${COVERAGE_FLAGS} ${DEBUG_FUNCTION_NAMES_FLAGS}") set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${HARDENING_FLAGS} ${COVERAGE_FLAGS}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 993824040..c075bdbdb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,10 +27,10 @@ find_package (Threads) ## might occur. pkg_check_modules (CJSON REQUIRED libcjson>=1.7.14) -pkg_check_modules (LIBGVM_BASE REQUIRED libgvm_base>=22.9) -pkg_check_modules (LIBGVM_UTIL REQUIRED libgvm_util>=22.9) -pkg_check_modules (LIBGVM_OSP REQUIRED libgvm_osp>=22.9) -pkg_check_modules (LIBGVM_GMP REQUIRED libgvm_gmp>=22.9) +pkg_check_modules (LIBGVM_BASE REQUIRED libgvm_base>=22.10) +pkg_check_modules (LIBGVM_UTIL REQUIRED libgvm_util>=22.10) +pkg_check_modules (LIBGVM_OSP REQUIRED libgvm_osp>=22.10) +pkg_check_modules (LIBGVM_GMP REQUIRED libgvm_gmp>=22.10) 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) diff --git a/src/gmp.c b/src/gmp.c index ce9bee5a4..8ca2162ff 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -12255,7 +12255,7 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) SEND_GET_START("credential"); while (1) { - const char *private_key, *public_key, *login, *type, *cert; + const char *login, *type, *cert; gchar *formats_xml; ret = get_next (&credentials, &get_credentials_data->get, @@ -12269,8 +12269,6 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) } SEND_GET_COMMON (credential, &get_credentials_data->get, &credentials); - private_key = credential_iterator_private_key (&credentials); - public_key = credential_iterator_public_key (&credentials); login = credential_iterator_login (&credentials); type = credential_iterator_type (&credentials); cert = credential_iterator_certificate (&credentials); @@ -12349,6 +12347,10 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) case CREDENTIAL_FORMAT_KEY: { + const char *public_key; + + public_key = credential_iterator_public_key (&credentials); + if (public_key && strcmp (public_key, "")) { SENDF_TO_CLIENT_OR_FAIL @@ -12357,8 +12359,9 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) else { char *pub; - const char *pass; + const char *pass, *private_key; + private_key = credential_iterator_private_key (&credentials); pass = credential_iterator_password (&credentials); pub = gvm_ssh_public_from_private (private_key, pass); SENDF_TO_CLIENT_OR_FAIL @@ -18582,9 +18585,13 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) auto_delete ? auto_delete : "0", auto_delete_data ? auto_delete_data : "0"); + g_free (assets_apply_overrides); + g_free (assets_min_qod); g_free (in_assets); g_free (max_checks); g_free (max_hosts); + g_free (auto_delete); + g_free (auto_delete_data); } count++; @@ -23419,6 +23426,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, log_event_fail ("user", "User", NULL, "created"); break; case -3: + case -4: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("create_user", "Error in SOURCE")); log_event_fail ("user", "User", NULL, "created"); @@ -26021,6 +26029,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context, ("modify_user", "Unknown role")); break; case -3: + case -4: SEND_TO_CLIENT_OR_FAIL (XML_ERROR_SYNTAX ("modify_user", "Error in SOURCES")); break; diff --git a/src/gmp_get.h b/src/gmp_get.h index e73019d0b..f6001736b 100644 --- a/src/gmp_get.h +++ b/src/gmp_get.h @@ -66,7 +66,6 @@ send_get_start (const char *, int (*) (const char *, void *), void *); * @brief Send start of GET response to client, returning on fail. * * @param[in] type Type of resource. - * @param[in] get GET data. */ #define SEND_GET_START(type) \ do \ diff --git a/src/gvmd.c b/src/gvmd.c index 34a720efd..d2492c407 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -2300,6 +2300,9 @@ gvmd (int argc, char** argv, char *env[]) else printf ("Sentry support disabled\n"); } +#if OPENVASD == 1 + printf ("OpenVASD is enabled\n"); +#endif printf ("Copyright (C) 2009-2021 Greenbone AG\n"); printf ("License: AGPL-3.0-or-later\n"); printf @@ -2401,6 +2404,9 @@ gvmd (int argc, char** argv, char *env[]) gvm_close_sentry (); exit (EXIT_FAILURE); } + else + set_log_tz ("utc 0"); + tzset (); /* Set umask to hoard created files, including the database. */ @@ -2484,6 +2490,7 @@ gvmd (int argc, char** argv, char *env[]) /** * LDAP debugging */ + if (ldap_debug) { if (ldap_enable_debug () == 0) diff --git a/src/lsc_crypt.c b/src/lsc_crypt.c index d4e1a0b8a..e64adad0b 100644 --- a/src/lsc_crypt.c +++ b/src/lsc_crypt.c @@ -581,6 +581,7 @@ lsc_crypt_release (lsc_crypt_ctx_t ctx) lsc_crypt_flush (ctx); if (ctx->encctx) /* Check required for gpgme < 1.3.1 */ gpgme_release (ctx->encctx); + g_free (ctx->enckey_uid); g_free (ctx); } diff --git a/src/manage.c b/src/manage.c index 12ae1c6a0..0af8a5486 100644 --- a/src/manage.c +++ b/src/manage.c @@ -5085,6 +5085,8 @@ manage_sync (sigset_t *sigmask_current, wait_for_pid (scap_pid, "SCAP sync"); wait_for_pid (cert_pid, "CERT sync"); + update_scap_extra (); + lockfile_unlock (&lockfile); } } @@ -5977,6 +5979,54 @@ get_nvt_xml (iterator_t *nvts, int details, int pref_count, free (default_timeout); } + if (nvt_iterator_epss_cve (nvts)) + { + buffer_xml_append_printf + (buffer, + "" + "" + "%0.5f" + "%0.5f" + "", + nvt_iterator_epss_score (nvts), + nvt_iterator_epss_percentile (nvts), + nvt_iterator_epss_cve (nvts)); + + if (nvt_iterator_has_epss_severity (nvts)) + { + buffer_xml_append_printf + (buffer, + "%0.1f", + nvt_iterator_epss_severity (nvts)); + } + + buffer_xml_append_printf + (buffer, + "" + "" + "" + "%0.5f" + "%0.5f" + "", + nvt_iterator_max_epss_score (nvts), + nvt_iterator_max_epss_percentile (nvts), + nvt_iterator_max_epss_cve (nvts)); + + if (nvt_iterator_has_max_epss_severity (nvts)) + { + buffer_xml_append_printf + (buffer, + "%0.1f", + nvt_iterator_max_epss_severity (nvts)); + } + + buffer_xml_append_printf + (buffer, + "" + "" + ""); + } + xml_string_append (buffer, close_tag ? "" : ""); msg = g_string_free (buffer, FALSE); } diff --git a/src/manage.h b/src/manage.h index abcbb0023..a272cb20d 100644 --- a/src/manage.h +++ b/src/manage.h @@ -1171,9 +1171,6 @@ result_detection_reference (result_t, report_t, const char *, const char *, /* Reports. */ -/** @todo How is this documented? */ -#define OVAS_MANAGE_REPORT_ID_LENGTH UUID_LEN_STR - /** * @brief Default apply_overrides setting */ @@ -1985,6 +1982,36 @@ nvt_iterator_solution_type (iterator_t*); const char* nvt_iterator_solution_method (iterator_t*); +double +nvt_iterator_epss_score (iterator_t*); + +double +nvt_iterator_epss_percentile (iterator_t*); + +const char* +nvt_iterator_epss_cve (iterator_t*); + +double +nvt_iterator_epss_severity (iterator_t*); + +gboolean +nvt_iterator_has_epss_severity (iterator_t*); + +double +nvt_iterator_max_epss_score (iterator_t*); + +double +nvt_iterator_max_epss_percentile (iterator_t*); + +const char* +nvt_iterator_max_epss_cve (iterator_t*); + +double +nvt_iterator_max_epss_severity (iterator_t*); + +gboolean +nvt_iterator_has_max_epss_severity (iterator_t*); + char* nvt_default_timeout (const char *); diff --git a/src/manage_acl.c b/src/manage_acl.c index 18996e780..e2953d8f1 100644 --- a/src/manage_acl.c +++ b/src/manage_acl.c @@ -1078,6 +1078,7 @@ acl_where_owned_user (const char *user_id, const char *user_sql, if (permissions == NULL || permissions->len == 0) { /* Treat filters with no permissions keyword as "any". */ + g_string_free (permission_or, TRUE); permission_or = g_string_new ("t ()"); index = 1; } diff --git a/src/manage_configs.c b/src/manage_configs.c index e88f7b023..d7de250af 100644 --- a/src/manage_configs.c +++ b/src/manage_configs.c @@ -620,7 +620,11 @@ should_sync_configs () && strlen (config_path) >= (36 /* UUID */ + strlen (".xml")) && g_str_has_suffix (config_path, ".xml") && should_sync_config_from_path (config_path, FALSE, &config)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_migrators.c b/src/manage_migrators.c index 9d5436716..3053fd2fe 100644 --- a/src/manage_migrators.c +++ b/src/manage_migrators.c @@ -3176,6 +3176,46 @@ migrate_254_to_255 () return 0; } +/** + * @brief Migrate the database from version 255 to version 256. + * + * @return 0 success, -1 error. + */ +int +migrate_255_to_256 () +{ + sql_begin_immediate (); + + /* Ensure that the database is currently version 255. */ + + if (manage_db_version () != 255) + { + sql_rollback (); + return -1; + } + + /* Update the database. */ + + // Add new columns + + sql ("ALTER TABLE nvts ADD COLUMN epss_cve TEXT;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_score DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_percentile DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_severity DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_cve TEXT;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_score DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_percentile DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_severity DOUBLE PRECISION;"); + + /* Set the database version to 256. */ + + set_db_version (256); + + sql_commit (); + + return 0; +} + #undef UPDATE_DASHBOARD_SETTINGS /** @@ -3237,6 +3277,7 @@ static migrator_t database_migrators[] = { {253, migrate_252_to_253}, {254, migrate_253_to_254}, {255, migrate_254_to_255}, + {256, migrate_255_to_256}, /* End marker. */ {-1, NULL}}; diff --git a/src/manage_pg.c b/src/manage_pg.c index 851769370..19d3463f7 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -1868,7 +1868,16 @@ create_tables_nvt (const gchar *suffix) " solution_method text," " detection text," " qod integer," - " qod_type text);", + " qod_type text," + " epss_cve TEXT," + " epss_score DOUBLE PRECISION," + " epss_percentile DOUBLE PRECISION," + " epss_severity DOUBLE PRECISION," + " max_epss_cve TEXT," + " max_epss_score DOUBLE PRECISION," + " max_epss_percentile DOUBLE PRECISION," + " max_epss_severity DOUBLE PRECISION" + ");", suffix); } diff --git a/src/manage_port_lists.c b/src/manage_port_lists.c index 39f2d1775..26f7c8cc5 100644 --- a/src/manage_port_lists.c +++ b/src/manage_port_lists.c @@ -537,7 +537,11 @@ should_sync_port_lists () && strlen (port_list_path) >= (36 /* UUID */ + strlen (".xml")) && g_str_has_suffix (port_list_path, ".xml") && should_sync_port_list_from_path (port_list_path, FALSE, &port_list)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_report_formats.c b/src/manage_report_formats.c index efc471633..8cc94feb0 100644 --- a/src/manage_report_formats.c +++ b/src/manage_report_formats.c @@ -905,7 +905,11 @@ should_sync_report_formats () && should_sync_report_format_from_path (report_format_path, FALSE, &report_format)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_sql.c b/src/manage_sql.c index d305986dc..1598be76c 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -262,10 +262,10 @@ static gchar* vulns_extra_where (int); static gchar* -vuln_iterator_opts_from_filter (const char*); +vuln_iterator_opts_from_filter (const gchar *); static gchar* -vuln_iterator_extra_with_from_filter (); +vuln_iterator_extra_with_from_filter (const gchar *); static int task_last_report_any_status (task_t, report_t *); @@ -22340,6 +22340,9 @@ where_qod (int min_qod) { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } +/** + * @brief SQL for result iterator column. + */ #define RESULT_HOSTNAME_SQL(hostname_col, host_col, report_col) \ "(CASE WHEN (" hostname_col " IS NULL) " \ " OR (" hostname_col " = '')" \ @@ -53652,7 +53655,8 @@ find_user_by_name (const char* name, user_t *user) * * @return 0 if the user has been added successfully, 1 failed to find group, * 2 failed to find role, 3 syntax error in hosts, 99 permission denied, - * -1 on error, -2 if user exists already. + * -1 on error, -2 if user exists already, -3 if wrong number of methods, + * -4 error in method. */ int create_user (const gchar * name, const gchar * password, const gchar *comment, @@ -53681,7 +53685,10 @@ create_user (const gchar * name, const gchar * password, const gchar *comment, if (allowed_methods && (allowed_methods->len == 0)) allowed_methods = NULL; - // TODO validate methods single source, one of ldap, ... + if (allowed_methods + && (auth_method_name_valid (g_ptr_array_index (allowed_methods, 0)) + == 0)) + return -4; if (validate_username (name) != 0) { @@ -54713,7 +54720,8 @@ delete_user (const char *user_id_arg, const char *name_arg, int ultimate, * 2 failed to find user, 3 success and user gained admin, 4 success * and user lost admin, 5 failed to find role, 6 syntax error in hosts, * 7 syntax error in new name, 99 permission denied, -1 on error, - * -2 for an unknown role, -3 if wrong number of methods. + * -2 for an unknown role, -3 if wrong number of methods, -4 error in + * method. */ int modify_user (const gchar * user_id, gchar **name, const gchar *new_name, @@ -54745,7 +54753,10 @@ modify_user (const gchar * user_id, gchar **name, const gchar *new_name, || (strlen (g_ptr_array_index (allowed_methods, 0)) == 0))) allowed_methods = NULL; - // TODO Validate methods: single source, one of "", "ldap", ... + if (allowed_methods + && (auth_method_name_valid (g_ptr_array_index (allowed_methods, 0)) + == 0)) + return -4; sql_begin_immediate (); @@ -55551,7 +55562,6 @@ user_resources_in_use (user_t user, * @param[in] task_id UUID of the task to limit vulns to. * @param[in] report_id UUID of the report to limit vulns to. * @param[in] host IP address of the task to limit vulns to. - * @param[in] min_qod Minimum QoD. * * @return Newly allocated string with the extra_with clause. */ @@ -55948,6 +55958,8 @@ vuln_count (const get_data_t *get) /** * @brief Extra WHERE clause for vulns. * + * @param[in] min_qod Min QOD. + * * @return WHERE clause. */ static gchar* @@ -57795,6 +57807,8 @@ type_opts_table (const char *type, const char *filter) { if (type == NULL) return NULL; + if (strcasecmp (type, "CVE") == 0) + return g_strdup (" LEFT JOIN scap.epss_scores ON cve = cves.uuid"); if (strcasecmp (type, "TASK") == 0) return task_iterator_opts_table (filter_term_apply_overrides (filter), filter_term_min_qod (filter), 0); @@ -57954,7 +57968,8 @@ type_extra_where (const char *type, int trash, const char *filter, /** * @brief Get the extra WITH clauses for a resource type. * - * @param[in] type The resource type. + * @param[in] type The resource type. + * @param[in] filter Filter term. * * @return The extra WITH clauses. */ @@ -57963,7 +57978,7 @@ type_extra_with (const char *type, const char *filter) { if (strcasecmp (type, "VULN") == 0) { - return vuln_iterator_extra_with_from_filter(filter); + return vuln_iterator_extra_with_from_filter (filter); } return NULL; } diff --git a/src/manage_sql_configs.c b/src/manage_sql_configs.c index bdda274b2..039cc3f98 100644 --- a/src/manage_sql_configs.c +++ b/src/manage_sql_configs.c @@ -2351,7 +2351,6 @@ config_insert_preferences (config_t config, else if (preference->type) { gchar *quoted_type, *quoted_nvt_oid, *quoted_preference_name; - gchar *quoted_default; gchar *quoted_preference_id; /* Presume NVT or OSP preference. */ @@ -2375,9 +2374,6 @@ config_insert_preferences (config_t config, : sql_quote (preference->type); quoted_value = sql_quote (value->str); g_string_free (value, TRUE); - quoted_default = preference->default_value - ? sql_quote (preference->default_value) - : NULL; /* NVT preference */ /* OID:PrefID:PrefType:PrefName value */ @@ -2401,7 +2397,6 @@ config_insert_preferences (config_t config, g_free (quoted_preference_name); g_free (quoted_type); g_free (quoted_value); - g_free (quoted_default); g_free (quoted_preference_id); } else diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 95714193d..ccebce74f 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -41,6 +41,7 @@ #include "manage_preferences.h" #include "manage_sql.h" #include "manage_sql_configs.h" +#include "manage_sql_secinfo.h" #include "sql.h" #include "utils.h" @@ -1214,6 +1215,153 @@ DEF_ACCESS (nvt_iterator_detection, GET_ITERATOR_COLUMN_COUNT + 19); */ DEF_ACCESS (nvt_iterator_solution_method, GET_ITERATOR_COLUMN_COUNT + 20); +/** + * @brief Get the EPSS score selected by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The EPSS score. + */ +double +nvt_iterator_epss_score (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 21); + return ret; +} + +/** + * @brief Get the EPSS percentile selected by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The EPSS percentile. + */ +double +nvt_iterator_epss_percentile (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 22); + return ret; +} + +/** + * @brief Get the CVE of the EPSS score by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return CVE-ID of the EPSS score, or NULL if iteration is complete. + * Freed by cleanup_iterator. + */ +DEF_ACCESS (nvt_iterator_epss_cve, GET_ITERATOR_COLUMN_COUNT + 23); + +/** + * @brief Get the maximum severity of CVEs with EPSS info from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The severity score. + */ +double +nvt_iterator_epss_severity (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 24); + return ret; +} + +/** + * @brief Get whether the NVT has a severity for the max severity EPSS score. + * + * @param[in] iterator Iterator. + * + * @return Whether the severity exists. + */ +gboolean +nvt_iterator_has_epss_severity (iterator_t* iterator) +{ + gboolean ret; + if (iterator->done) return -1; + ret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 24) != NULL; + return ret; +} + +/** + * @brief Get the maximum EPSS score from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The maximum EPSS score. + */ +double +nvt_iterator_max_epss_score (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 25); + return ret; +} + +/** + * @brief Get the maximum EPSS percentile from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The maximum EPSS percentile. + */ +double +nvt_iterator_max_epss_percentile (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 26); + return ret; +} + +/** + * @brief Get the CVE of the maximum EPSS score from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return CVE-ID of the maximum EPSS score, or NULL if iteration is complete. + * Freed by cleanup_iterator. + */ +DEF_ACCESS (nvt_iterator_max_epss_cve, GET_ITERATOR_COLUMN_COUNT + 27); + +/** + * @brief Get the severity of the maximum EPSS score from an NVT iterator. + * @param[in] iterator Iterator. + * + * @return The severity score. + */ +double +nvt_iterator_max_epss_severity (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 28); + return ret; +} + +/** + * @brief Get whether the NVT has a severity for the max EPSS score. + * + * @param[in] iterator Iterator. + * + * @return Whether the severity exists. + */ +gboolean +nvt_iterator_has_max_epss_severity (iterator_t* iterator) +{ + gboolean ret; + if (iterator->done) return -1; + ret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 28) != NULL; + return ret; +} + /** * @brief Get the default timeout of an NVT. * @@ -2314,8 +2462,10 @@ nvts_feed_version_status_internal (const gchar *update_socket, scanner_feed_version = osp_scanner_feed_version (update_socket); g_debug ("%s: scanner_feed_version: %s", __func__, scanner_feed_version); - if (scanner_feed_version == NULL) + 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); @@ -2327,6 +2477,8 @@ nvts_feed_version_status_internal (const gchar *update_socket, return 1; } + g_free (db_feed_version); + g_free (scanner_feed_version); return 0; } @@ -2532,6 +2684,9 @@ manage_rebuild (GSList *log_config, const db_conn_info_t *database) break; } + if (ret == 0) + update_scap_extra (); + feed_lockfile_unlock (&lockfile); manage_option_cleanup (); diff --git a/src/manage_sql_nvts.h b/src/manage_sql_nvts.h index e9db88fad..bbe4d39a6 100644 --- a/src/manage_sql_nvts.h +++ b/src/manage_sql_nvts.h @@ -31,7 +31,9 @@ { GET_ITERATOR_FILTER_COLUMNS, "version", "cve", \ "family", "cvss_base", "severity", "cvss", "script_tags", "qod", \ "qod_type", "solution_type", "solution", "summary", "insight", \ - "affected", "impact", "detection", "solution_method", NULL } + "affected", "impact", "detection", "solution_method", "epss_score", \ + "epss_percentile", "max_epss_score", "max_epss_percentile", \ + NULL } /** * @brief NVT iterator columns. @@ -62,6 +64,18 @@ { "impact", NULL, KEYWORD_TYPE_STRING }, \ { "detection", NULL, KEYWORD_TYPE_STRING }, \ { "solution_method", NULL, KEYWORD_TYPE_STRING }, \ + { "coalesce (epss_score, 0.0)", "epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (epss_percentile, 0.0)", "epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_score, 0.0)", "max_epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_percentile, 0.0)", "max_epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "max_epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "max_epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -94,6 +108,18 @@ { "impact", NULL, KEYWORD_TYPE_STRING }, \ { "detection", NULL, KEYWORD_TYPE_STRING }, \ { "solution_method", NULL, KEYWORD_TYPE_STRING }, \ + { "coalesce (epss_score, 0.0)", "epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (epss_percentile, 0.0)", "epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_score, 0.0)", "max_epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_percentile, 0.0)", "max_epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "max_epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "max_epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } diff --git a/src/manage_sql_report_configs.h b/src/manage_sql_report_configs.h index 065d4a8c1..d5fe578a7 100644 --- a/src/manage_sql_report_configs.h +++ b/src/manage_sql_report_configs.h @@ -44,9 +44,4 @@ restore_report_config (const char *); void delete_report_configs_user (user_t); -gboolean -inherit_report_configs (user_t, user_t); - - - #endif /* not _GVMD_MANAGE_SQL_REPORT_CONFIGS_H */ diff --git a/src/manage_sql_report_formats.c b/src/manage_sql_report_formats.c index 6a901aaf8..1579b3a71 100644 --- a/src/manage_sql_report_formats.c +++ b/src/manage_sql_report_formats.c @@ -3087,7 +3087,7 @@ report_format_alert_iterator_readable (iterator_t* iterator) * Iterates over all report configs that use the Report Format. * * @param[in] iterator Iterator. - * @param[in] report_format Report Format. + * @param[in] report_format_id Report Format. */ void init_report_format_report_config_iterator (iterator_t* iterator, diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 342c836f1..fdf76db8c 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -196,6 +196,8 @@ increment_transaction_size (int* current_size) /** * @brief Get the SQL buffer size threshold converted from MiB to bytes. + * + * @return Number of bytes. */ int setting_secinfo_sql_buffer_threshold_bytes () @@ -471,7 +473,6 @@ init_cpe_info_iterator (iterator_t* iterator, get_data_t *get, const char *name) * * @param[in] iterator Iterator. * @param[in] get GET data. - * @param[in] name Name of the info * * @return 0 success, 1 failed to find target, 2 failed to find filter, * -1 error. @@ -716,7 +717,6 @@ init_cve_info_iterator (iterator_t* iterator, get_data_t *get, const char *name) * * @param[in] iterator Iterator. * @param[in] get GET data. - * @param[in] name Name of the info * * @return 0 success, 1 failed to find target, 2 failed to find filter, * -1 error. @@ -2491,7 +2491,6 @@ static int insert_cve_from_entry (element_t entry, element_t last_modified, GHashTable *hashed_cpes, int *transaction_size) { - gboolean cvss_is_v3; element_t published, summary, cvss, score, base_metrics, cvss_vector, list; double severity_dbl; gchar *quoted_id, *quoted_summary, *quoted_cvss_vector; @@ -2518,21 +2517,36 @@ insert_cve_from_entry (element_t entry, element_t last_modified, return -1; } - cvss = element_child (entry, "vuln:cvss3"); + gchar *base_metrics_element = "cvss:base_metrics"; + gchar *score_element = "cvss:score"; + gchar *cvss_vector_element = "cvss:vector-string"; + + cvss = element_child (entry, "vuln:cvss4"); if (cvss == NULL) { - cvss = element_child (entry, "vuln:cvss"); - cvss_is_v3 = FALSE; + cvss = element_child (entry, "vuln:cvss3"); + if (cvss == NULL) + { + cvss = element_child (entry, "vuln:cvss"); + } + else + { + base_metrics_element = "cvss3:base_metrics"; + score_element = "cvss3:base-score"; + cvss_vector_element = "cvss3:vector-string"; + } } else - cvss_is_v3 = TRUE; + { + base_metrics_element = "cvss4:base_metrics"; + score_element = "cvss4:base-score"; + cvss_vector_element = "cvss4:vector-string"; + } if (cvss == NULL) base_metrics = NULL; else - base_metrics = element_child (cvss, - cvss_is_v3 ? "cvss3:base_metrics" - : "cvss:base_metrics"); + base_metrics = element_child (cvss, base_metrics_element); if (base_metrics == NULL) { @@ -2541,8 +2555,8 @@ insert_cve_from_entry (element_t entry, element_t last_modified, } else { - score = element_child (base_metrics, - cvss_is_v3 ? "cvss3:base-score" : "cvss:score"); + score = element_child (base_metrics, score_element); + if (score == NULL) { g_warning ("%s: cvss:score missing for %s", __func__, id); @@ -2550,9 +2564,8 @@ insert_cve_from_entry (element_t entry, element_t last_modified, return -1; } - cvss_vector = element_child (base_metrics, - cvss_is_v3 ? "cvss3:vector-string" - : "cvss:vector-string"); + cvss_vector = element_child (base_metrics, cvss_vector_element); + if (cvss_vector == NULL) { g_warning ("%s: cvss:access-vector missing for %s", __func__, id); @@ -3209,8 +3222,6 @@ check_cert_db_version () /** * @brief Update timestamp in CERT db from feed timestamp. - * - * @return 0 success, -1 error. */ static void update_cert_timestamp () @@ -3482,8 +3493,6 @@ check_scap_db_version () /** * @brief Update timestamp in SCAP db from feed timestamp. - * - * @return 0 success, -1 error. */ static void update_scap_timestamp () @@ -3575,6 +3584,65 @@ update_scap_placeholders () " WHERE cpe=cpes.id))" " WHERE cpes.title IS NULL;"); } + +/** + * @brief Update extra data for VTs based on SCAP and SCAP supplement data. + */ +static void +update_vt_scap_extra_data () +{ + g_info ("Assigning EPSS scores to VTs"); + + sql ("UPDATE nvts" + " SET epss_cve = NULL," + " epss_score = NULL," + " epss_percentile = NULL," + " epss_severity = NULL," + " max_epss_cve = NULL," + " max_epss_score = NULL," + " max_epss_percentile = NULL," + " max_epss_severity = NULL;"); + + sql ("WITH epss_candidates AS (" + " SELECT vt_oid, cve, severity, epss, percentile," + " rank() OVER (PARTITION BY vt_oid" + " ORDER BY severity DESC," + " epss DESC," + " scap.cves.modification_time DESC) AS rank" + " FROM (SELECT * FROM vt_refs WHERE type='cve') AS vt_cves" + " JOIN scap.epss_scores ON ref_id = cve" + " LEFT JOIN scap.cves ON scap.cves.name = cve" + " ORDER BY vt_oid" + ") " + "UPDATE nvts" + " SET epss_cve = epss_candidates.cve," + " epss_score = epss_candidates.epss," + " epss_percentile = epss_candidates.percentile," + " epss_severity = epss_candidates.severity" + " FROM epss_candidates" + " WHERE epss_candidates.vt_oid = nvts.oid" + " AND epss_candidates.rank = 1;"); + + sql ("WITH epss_candidates AS (" + " SELECT vt_oid, cve, severity, epss, percentile," + " rank() OVER (PARTITION BY vt_oid" + " ORDER BY epss DESC," + " severity DESC," + " scap.cves.modification_time DESC) AS rank" + " FROM (SELECT * FROM vt_refs WHERE type='cve') AS vt_cves" + " JOIN scap.epss_scores ON ref_id = cve" + " LEFT JOIN scap.cves ON scap.cves.name = cve" + " ORDER BY vt_oid" + ") " + "UPDATE nvts" + " SET max_epss_cve = epss_candidates.cve," + " max_epss_score = epss_candidates.epss," + " max_epss_percentile = epss_candidates.percentile," + " max_epss_severity = epss_candidates.severity" + " FROM epss_candidates" + " WHERE epss_candidates.vt_oid = nvts.oid" + " AND epss_candidates.rank = 1;"); +} /** * @brief Update CERT data that depends on SCAP. @@ -3910,6 +3978,25 @@ update_scap (gboolean reset_scap_db) return 0; } +/** + * @brief Update extra data in the SCAP DB that depends on other feeds. + */ +void +update_scap_extra () +{ + if (manage_scap_loaded () == 0) + { + g_info ("%s: SCAP database missing, skipping extra data update", + __func__); + return; + } + + g_debug ("%s: update SCAP extra data of VTs", __func__); + setproctitle ("Syncing SCAP: Updating VT extra data"); + + update_vt_scap_extra_data (); +} + /** * @brief Sync the SCAP DB. * @@ -3954,8 +4041,9 @@ rebuild_scap () return -1; ret = update_scap (TRUE); - if (ret == 1) - ret = 2; + + if (ret == 0) + update_scap_extra (); if (feed_lockfile_unlock (&lockfile)) { diff --git a/src/manage_sql_secinfo.h b/src/manage_sql_secinfo.h index 7e7a83ed6..5e8ad4761 100644 --- a/src/manage_sql_secinfo.h +++ b/src/manage_sql_secinfo.h @@ -195,4 +195,7 @@ get_secinfo_commit_size (); void set_secinfo_commit_size (int); +void +update_scap_extra (); + #endif /* not _GVMD_MANAGE_SQL_SECINFO_H */ diff --git a/src/schema_formats/HTML/HTML.xsl b/src/schema_formats/HTML/HTML.xsl index bd8a9d7da..88b58b7f2 100644 --- a/src/schema_formats/HTML/HTML.xsl +++ b/src/schema_formats/HTML/HTML.xsl @@ -342,7 +342,7 @@ along with this program. If not, see . -
+
@@ -427,7 +427,7 @@ along with this program. If not, see . -
    +
    • @@ -656,11 +656,14 @@ along with this program. If not, see . -
        +
          Empty single element. + + + @@ -693,11 +696,11 @@ along with this program. If not, see .
          • - Command +
            Command
          • - Response +
            Response
            diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 5dd097f66..e6a362607 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -582,6 +582,7 @@ along with this program. If not, see . timeout default_timeout solution + epss preferences @@ -680,6 +681,112 @@ along with this program. If not, see . + + epss + Exploit Prediction Scoring System (EPSS) info if available + + max_severity + max_epss + + + max_severity + + EPSS info of the referenced CVE with the highest severity + + + In case there are multiple CVEs referenced by the NVT tied for the + highest severity, they are also sorted by EPSS score and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + + max_epss + + EPSS info of the referenced CVE with the highest EPSS score + + + In case there are multiple CVEs referenced by the NVT tied for the + highest EPSS score, they are also sorted by severity and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + preferences The list of preferences @@ -3624,7 +3731,6 @@ along with this program. If not, see . copy get_configs - scanner name usage_type @@ -3643,13 +3749,6 @@ along with this program. If not, see . uuid - - scanner - The UUID of an OSP scanner to get config data from - - uuid - - name A name for the config @@ -3716,20 +3815,6 @@ along with this program. If not, see . - - Create an OSP config from a scanner - - - Full - daba56c8-73ec-11df-a475-002264764cea - - - - - - - create_credential @@ -3883,6 +3968,15 @@ along with this program. If not, see . type The type of credential to create + +

            cc: Client certificate

            +

            pgp: PGP encryption key

            +

            pw: Password only

            +

            smime: S/MIME certificate

            +

            snmp: SNMP

            +

            up: User name + password

            +

            usk: User name + SSH key

            +
            cc @@ -6107,6 +6201,7 @@ END:VCALENDAR hosts password role + sources name @@ -6153,6 +6248,32 @@ END:VCALENDAR + + sources + Authentication source for this user (if omitted then 'file') + +

            + 'file' means to store the user in the database. +

            +

            + The element is called SOURCES for historic reasons. Only one SOURCE is allowed. +

            +
            + + source + + + source + Authentication source + + + file + ldap_connect + radius_connect + + + +
            @@ -10609,6 +10730,15 @@ END:VCALENDAR type The type of the credential + +

            cc: Client certificate

            +

            pgp: PGP encryption key

            +

            pw: Password only

            +

            smime: S/MIME certificate

            +

            snmp: SNMP

            +

            up: User name + password

            +

            usk: User name + SSH key

            +
            cc @@ -12175,6 +12305,34 @@ END:VCALENDAR integer Version of the NVT (deprected) + + epss_score + decimal + + EPSS score of highest severity CVE (see epss/max_severity) + + + + epss_percentile + decimal + + EPSS percentile of highest severity CVE (see epss/max_severity) + + + + max_epss_score + decimal + + Highest EPSS score of referenced CVEs (see epss/max_epss) + + + + max_epss_percentile + decimal + + Highest EPSS percentile of referenced CVEs (see epss/max_epss) + + type is "cve" @@ -12198,6 +12356,16 @@ END:VCALENDAR iso_time Time the CVE was published, alias for created + + epss_score + decimal + EPSS score the CVE + + + epss_percentile + decimal + EPSS percentile of the CVE + type is "cpe" @@ -13769,6 +13937,7 @@ END:VCALENDAR timeout default_timeout solution + epss preferences @@ -13945,6 +14114,112 @@ END:VCALENDAR text
            + + epss + Exploit Prediction Scoring System (EPSS) info if available + + max_severity + max_epss + + + max_severity + + EPSS info of the referenced CVE with the highest severity + + + In case there are multiple CVEs referenced by the NVT tied for the + highest severity, they are also sorted by EPSS score and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + + max_epss + + EPSS info of the referenced CVE with the highest EPSS score + + + In case there are multiple CVEs referenced by the NVT tied for the + highest EPSS score, they are also sorted by severity and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + preferences List of preferences of the NVT @@ -25655,7 +25930,6 @@ END:VCALENDAR
            >name comment - scanner preference family_selection nvt_selection @@ -25670,11 +25944,6 @@ END:VCALENDAR New comment for the config text
            - - scanner - New scanner's UUID for the config - text - preference @@ -27869,9 +28138,17 @@ END:VCALENDAR sources - List of authentication sources for this user (if omitted, no changes) + Authentication source for this user (if omitted, no changes) + +

            + 'file' means to store the user in the database. +

            +

            + The element is called SOURCES for historic reasons. Only one SOURCE is allowed. +

            +
            - source + source source