diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 345f67dcef..2e00dbcbcb 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: - name: Install Deps run: | sudo apt-get update - sudo apt-get -y install lcov swig xsltproc rpm-common lua5.3 libyaml-dev libdbus-1-dev libdbus-glib-1-dev libcurl4-openssl-dev libgcrypt-dev libselinux1-dev libgconf2-dev libacl1-dev libblkid-dev libcap-dev libxml2-dev libxslt1-dev libxml-parser-perl libxml-xpath-perl libperl-dev librpm-dev librtmp-dev libxmlsec1-dev libxmlsec1-openssl python3-dbusmock + sudo apt-get -y install lcov swig xsltproc rpm-common lua5.3 libyaml-dev libdbus-1-dev libdbus-glib-1-dev libcurl4-openssl-dev libgcrypt-dev libselinux1-dev libglib2.0-dev libacl1-dev libblkid-dev libcap-dev libxml2-dev libxslt1-dev libxml-parser-perl libxml-xpath-perl libperl-dev librpm-dev librtmp-dev libxmlsec1-dev libxmlsec1-openssl python3-dbusmock sudo apt-get -y remove rpm # Initializes the CodeQL tools for scanning. diff --git a/AUTHORS b/AUTHORS index 863c670682..248dfaf1e5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,6 +18,7 @@ Dirk Müller Dmitry Teselkin DominiqueDevinci Ed Sealing +Edgar Aguilar Evgeni Golov Evgeny Kolesnikov Felix Wolfsteller @@ -29,6 +30,7 @@ Gary Gapinski Gautam Satish Greg Elin Hideki Yamane +Hugo Beauzée-Luyssen Ilya Okomin Jacob Varughese Jakub Jelen diff --git a/CMakeLists.txt b/CMakeLists.txt index d568d2cf0e..ed539cc7d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ endif() project("openscap") set(OPENSCAP_VERSION_MAJOR "1") set(OPENSCAP_VERSION_MINOR "3") -set(OPENSCAP_VERSION_PATCH "12") +set(OPENSCAP_VERSION_PATCH "13") if(OPENSCAP_VERSION_SUFFIX) set(OPENSCAP_VERSION "${OPENSCAP_VERSION_MAJOR}.${OPENSCAP_VERSION_MINOR}.${OPENSCAP_VERSION_PATCH}_${OPENSCAP_VERSION_SUFFIX}") @@ -26,7 +26,7 @@ endif() set(LT_CURRENT 32) ## increment any time the source changes; set 0 to if you increment CURRENT -set(LT_REVISION 1) +set(LT_REVISION 2) ## increment if any interfaces have been added; set to 0 ## if any interfaces have been changed or removed. removal has @@ -535,7 +535,7 @@ if (MSVC) endif() if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -W -Wall -Wnonnull -Wshadow -Wformat -Wundef -Wno-unused-parameter -Wmissing-prototypes -Wno-unknown-pragmas -Wno-int-conversion -Werror=implicit-function-declaration -D_GNU_SOURCE -std=c99") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -W -Wall -Wnonnull -Wshadow -Wformat -Wundef -Wno-unused-parameter -Wmissing-prototypes -Wno-unknown-pragmas -Wno-int-conversion -Werror=implicit-function-declaration -D_GNU_SOURCE -DRBT_IMPLICIT_LOCKING=1 -std=c99") add_link_options(-Wl,-z,now) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..d0dad8e311 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,2 @@ +/tests/ @jan-cerny @evgenyz @mab879 @matusmarhefka +/CODEOWNERS @jan-cerny @evgenyz @mab879 @matusmarhefka diff --git a/NEWS b/NEWS index 8073d6d175..0ed2fd29b3 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +openscap-1.3.12 07-04-2025 +- Maintenance, bug fix + - Fix thread synchronization bugs + - Fix textfilecontent54_probe behaviour for negative instance numbers + - Fix signature obtaining in rpm_info probe + openscap-1.3.11 2025-02-10 - New features - Introduce "oscap-im" - script that can be used in Containerfiles to build diff --git a/docs/manual/manual.adoc b/docs/manual/manual.adoc index 4d1e807293..484cd1179c 100644 --- a/docs/manual/manual.adoc +++ b/docs/manual/manual.adoc @@ -1655,11 +1655,13 @@ Also, OpenSCAP uses `libcurl` library which also can be configured using environ == Using external or remote resources -Some SCAP content references external resources. For example SCAP Security Guide -uses external OVAL file to check that the system is up to date and has no known +Some SCAP content references external resources. For example, older versions of SCAP Security Guide (prior to version 0.1.73) +used external OVAL file to check that the system is up to date and has no known security vulnerabilities. However, other content can use external resources for other purposes. +NOTE: Starting with version 0.1.73, SCAP Security Guide content doesn't use external resources anymore. + When you are evaluating SCAP content with external resources the `oscap` tool will warn you: @@ -1708,6 +1710,8 @@ $ wget -O ~/scap-files/security-data-oval-com.redhat.rhsa-RHEL8.xml https://www. $ oscap xccdf eval --local-files ~/scap-files --profile ospp ssg-rhel8-ds.xml ---- +NOTE: The `--local-files` option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. + == Practical Examples This section demonstrates practical usage of certain security content provided for Red Hat products. @@ -2297,4 +2301,5 @@ You can find the ID of the customized profile with `oscap info >. diff --git a/release_tools/versions.sh b/release_tools/versions.sh index 17775d843e..974170b2c3 100644 --- a/release_tools/versions.sh +++ b/release_tools/versions.sh @@ -1,4 +1,4 @@ -version=1.3.12 -previous_version=1.3.11 +version=1.3.13 +previous_version=1.3.12 version_major_minor="${version%.*}" diff --git a/src/DS/ds_sds_session.c b/src/DS/ds_sds_session.c index 3a720e8131..747166ed4f 100644 --- a/src/DS/ds_sds_session.c +++ b/src/DS/ds_sds_session.c @@ -343,6 +343,25 @@ void ds_sds_session_configure_remote_resources(struct ds_sds_session *session, b session->fetch_remote_resources = allowed; session->local_files = local_files; session->progress = (callback != NULL) ? callback : download_progress_empty_calllback; + if (local_files != NULL) { + struct ds_sds_index *idx = ds_sds_session_get_sds_idx(session); + struct ds_stream_index_iterator *streams = ds_sds_index_get_streams(idx); + while (ds_stream_index_iterator_has_more(streams)) { + struct ds_stream_index *stream = ds_stream_index_iterator_next(streams); + const char *version = ds_stream_index_get_version(stream); + if (strcmp(version, "1.3")) { + ds_sds_session_remote_resources_progress(session)( + true, + "WARNING: The '--local-files' option can be used only with " + "SCAP 1.3 source data streams, but the provided data stream " + "is version '%s'. No local files will be used.\n", + version); + break; + } + + } + ds_stream_index_iterator_free(streams); + } } void ds_sds_session_set_remote_resources(struct ds_sds_session *session, bool allowed, download_progress_calllback_t callback) diff --git a/src/OVAL/probes/SEAP/seap-command.c b/src/OVAL/probes/SEAP/seap-command.c index bf33a885c1..63783087d6 100644 --- a/src/OVAL/probes/SEAP/seap-command.c +++ b/src/OVAL/probes/SEAP/seap-command.c @@ -205,7 +205,7 @@ static SEXP_t *__SEAP_cmd_sync_handler (SEXP_t *res, void *arg) h->args = res; (void) pthread_mutex_lock (&h->mtx); h->signaled = 1; - (void) pthread_cond_signal (&h->cond); + (void) pthread_cond_broadcast (&h->cond); (void) pthread_mutex_unlock (&h->mtx); return (NULL); @@ -322,9 +322,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx, h.args = NULL; h.signaled = 0; - if (pthread_mutex_lock (&(h.mtx)) != 0) - abort (); - rec = SEAP_cmdrec_new (); rec->code = cmdptr->id; rec->func = &__SEAP_cmd_sync_handler; @@ -377,8 +374,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx, timeout.tv_nsec = 0; */ for (;;) { - pthread_mutex_unlock(&h.mtx); - if (SEAP_packet_recv(ctx, sd, &packet_rcv) != 0) { dD("FAIL: ctx=%p, sd=%d, errno=%u, %s.", ctx, sd, errno, strerror(errno)); SEAP_packet_free(packet); @@ -407,21 +402,23 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx, } /* Morbo: THIS IS NOT HOW SYCHNRONIZATION WORKS! */ - if (h.signaled) + if (h.signaled) { + h.signaled = 0; break; + } } } else { /* * Someone else does receiving of events for us. * Just wait for the condition to be signaled. */ - if (pthread_cond_wait(&h.cond, &h.mtx) != 0) { - /* - * Fatal error - don't know how to handle - * this so let's just call abort()... - */ - abort(); - } + pthread_mutex_lock(&h.mtx); + while (!h.signaled) { + pthread_cond_wait(&h.cond, &h.mtx); + } + // This might not be needed, but still + h.signaled = 0; + pthread_mutex_unlock(&h.mtx); } dD("cond return: h.args=%p", h.args); @@ -436,7 +433,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx, /* * SEAP_cmdtbl_del(dsc->cmd_w_table, rec); */ - pthread_mutex_unlock (&(h.mtx)); pthread_cond_destroy (&(h.cond)); pthread_mutex_destroy (&(h.mtx)); SEAP_packet_free(packet); diff --git a/src/OVAL/probes/SEAP/seap-packet.c b/src/OVAL/probes/SEAP/seap-packet.c index 6bb698b1ab..bf07131cab 100644 --- a/src/OVAL/probes/SEAP/seap-packet.c +++ b/src/OVAL/probes/SEAP/seap-packet.c @@ -206,9 +206,14 @@ static int SEAP_packet_sexp2msg (SEXP_t *sexp_msg, SEAP_msg_t *seap_msg) _A(attr_i >= (SEXP_list_length (sexp_msg) - 4)/2); seap_msg->attrs_cnt = attr_i; - void *new_attrs = realloc(seap_msg->attrs, sizeof(SEAP_attr_t) * seap_msg->attrs_cnt); - if (new_attrs != NULL || seap_msg->attrs_cnt == 0) + if (seap_msg->attrs_cnt == 0) { + free(seap_msg->attrs); + seap_msg->attrs = NULL; + } else { + void *new_attrs = realloc(seap_msg->attrs, sizeof(SEAP_attr_t) * seap_msg->attrs_cnt); seap_msg->attrs = new_attrs; + } + seap_msg->sexp = SEXP_list_last (sexp_msg); return (0); diff --git a/src/OVAL/probes/independent/textfilecontent54_probe.c b/src/OVAL/probes/independent/textfilecontent54_probe.c index 34199853fa..5fcc00f005 100644 --- a/src/OVAL/probes/independent/textfilecontent54_probe.c +++ b/src/OVAL/probes/independent/textfilecontent54_probe.c @@ -123,12 +123,15 @@ struct pfdata { static int process_file(const char *prefix, const char *path, const char *file, struct pfdata *pfd, oval_schema_version_t over, struct oscap_list *blocked_paths) { int ret = 0, path_len, file_len, cur_inst = 0, fd = -1, substr_cnt, - buf_size = 0, buf_used = 0, ofs = 0, buf_inc = 4096; + buf_size = 0, buf_used = 0, ofs = 0, buf_inc = 4096, instance_count = 0, + want_instance = 1, negative_instance_value = 0; char **substrs = NULL; char *whole_path = NULL, *whole_path_with_prefix = NULL, *buf = NULL; - SEXP_t *next_inst = NULL; + SEXP_t *next_inst = NULL, *items = SEXP_list_new(NULL), *instance_value_list = NULL, + *instance_value = NULL; struct stat st; + if (file == NULL) goto cleanup; @@ -210,16 +213,6 @@ static int process_file(const char *prefix, const char *path, const char *file, buf[buf_used++] = '\0'; do { - int want_instance; - - next_inst = SEXP_number_newi_32(cur_inst + 1); - - if (probe_entobj_cmp(pfd->instance_ent, next_inst) == OVAL_RESULT_TRUE) - want_instance = 1; - else - want_instance = 0; - - SEXP_free(next_inst); substr_cnt = oscap_pcre_get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs); if (substr_cnt < 0) { @@ -235,27 +228,49 @@ static int process_file(const char *prefix, const char *path, const char *file, } if (substr_cnt > 0) { - ++cur_inst; - - if (want_instance) { - int k; - SEXP_t *item; - - item = create_item(path, file, pfd->pattern, - cur_inst, substrs, substr_cnt, over); - - for (k = 0; k < substr_cnt; ++k) - free(substrs[k]); - free(substrs); - int pic_ret = probe_item_collect(pfd->ctx, item); - if (pic_ret == 2 || pic_ret == -1) { - ret = -4; - break; - } - } + int k; + instance_count++; + + SEXP_list_add(items, create_item(path, file, pfd->pattern, + instance_count, substrs, substr_cnt, over)); + + for (k = 0; k < substr_cnt; ++k) + free(substrs[k]); + free(substrs); } } while (substr_cnt > 0 && ofs < buf_used); + probe_ent_getvals(pfd->instance_ent, &instance_value_list); + instance_value = SEXP_list_first(instance_value_list); + negative_instance_value = SEXP_number_geti_64(instance_value) < 0; + SEXP_free(instance_value_list); + SEXP_free(instance_value); + + for(cur_inst = 0; cur_inst < instance_count; cur_inst++){ + if (negative_instance_value) + next_inst = SEXP_number_newi_32(cur_inst - instance_count); + + else + next_inst = SEXP_number_newi_32(cur_inst + 1); + + if (probe_entobj_cmp(pfd->instance_ent, next_inst) == OVAL_RESULT_TRUE) + want_instance = 1; + else + want_instance = 0; + + SEXP_free(next_inst); + + if (want_instance) { + int pic_ret = probe_item_collect(pfd->ctx, SEXP_list_nth(items, cur_inst + 1)); + if (pic_ret == 2 || pic_ret == -1) { + ret = -4; + break; + } + } + else + SEXP_free(SEXP_list_nth(items, cur_inst + 1)); + } + cleanup: if (fd != -1) close(fd); diff --git a/src/OVAL/probes/probe/icache.c b/src/OVAL/probes/probe/icache.c index 32e5adee07..ddaca69427 100644 --- a/src/OVAL/probes/probe/icache.c +++ b/src/OVAL/probes/probe/icache.c @@ -201,7 +201,7 @@ const char* thread_name = "icache_worker"; pair = &pair_mem; dD("icache worker ready"); - switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier))) + switch (errno = pthread_barrier_wait(cache->th_barrier)) { case 0: case PTHREAD_BARRIER_SERIAL_THREAD: @@ -309,7 +309,7 @@ const char* thread_name = "icache_worker"; return (NULL); } -probe_icache_t *probe_icache_new(void) +probe_icache_t *probe_icache_new(pthread_barrier_t *th_barrier) { probe_icache_t *cache = malloc(sizeof(probe_icache_t)); cache->tree = rbt_i64_new(); @@ -323,6 +323,7 @@ probe_icache_t *probe_icache_new(void) cache->queue_end = 0; cache->queue_cnt = 0; cache->queue_max = PROBE_IQUEUE_CAPACITY; + cache->th_barrier = th_barrier; if (pthread_cond_init(&cache->queue_notempty, NULL) != 0) { dE("Can't initialize icache queue condition variable (notempty): %u, %s", diff --git a/src/OVAL/probes/probe/icache.h b/src/OVAL/probes/probe/icache.h index ec91fc8fc8..351cd539ed 100644 --- a/src/OVAL/probes/probe/icache.h +++ b/src/OVAL/probes/probe/icache.h @@ -25,6 +25,7 @@ #include #include #include "../SEAP/generic/rbt/rbt.h" +#include "common/compat_pthread_barrier.h" #ifndef PROBE_IQUEUE_CAPACITY #define PROBE_IQUEUE_CAPACITY 1024 @@ -41,6 +42,7 @@ typedef struct { typedef struct { rbt_t *tree; /* XXX: rewrite to extensible or linear hashing */ pthread_t thid; + pthread_barrier_t *th_barrier; pthread_mutex_t queue_mutex; pthread_cond_t queue_notempty; @@ -58,7 +60,7 @@ typedef struct { uint16_t count; } probe_citem_t; -probe_icache_t *probe_icache_new(void); +probe_icache_t *probe_icache_new(pthread_barrier_t *th_barrier); int probe_icache_add(probe_icache_t *cache, SEXP_t *cobj, SEXP_t *item); int probe_icache_nop(probe_icache_t *cache); void probe_icache_free(probe_icache_t *cache); diff --git a/src/OVAL/probes/probe/input_handler.c b/src/OVAL/probes/probe/input_handler.c index 41691a288f..963ce4497e 100644 --- a/src/OVAL/probes/probe/input_handler.c +++ b/src/OVAL/probes/probe/input_handler.c @@ -85,7 +85,7 @@ void *probe_input_handler(void *arg) pthread_cleanup_push(pthread_attr_cleanup_handler, (void *)&pth_attr); - switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier))) + switch (errno = pthread_barrier_wait(probe->th_barrier)) { case 0: case PTHREAD_BARRIER_SERIAL_THREAD: diff --git a/src/OVAL/probes/probe/probe.h b/src/OVAL/probes/probe/probe.h index 3dde2a2eba..66e29935a0 100644 --- a/src/OVAL/probes/probe/probe.h +++ b/src/OVAL/probes/probe/probe.h @@ -66,6 +66,7 @@ typedef struct { pthread_t th_input; pthread_t th_signal; + pthread_barrier_t *th_barrier; rbt_t *workers; uint32_t max_threads; @@ -105,6 +106,4 @@ typedef enum { PROBE_OFFLINE_ALL = 0x0f } probe_offline_flags; -extern pthread_barrier_t OSCAP_GSYM(th_barrier); - #endif /* PROBE_H */ diff --git a/src/OVAL/probes/probe/probe_main.c b/src/OVAL/probes/probe/probe_main.c index 17bf7a0ac0..2ef3ee4d1c 100644 --- a/src/OVAL/probes/probe/probe_main.c +++ b/src/OVAL/probes/probe/probe_main.c @@ -71,8 +71,6 @@ bool OSCAP_GSYM(varref_handling) = true; char **OSCAP_GSYM(no_varref_ents) = NULL; size_t OSCAP_GSYM(no_varref_ents_cnt) = 0; -pthread_barrier_t OSCAP_GSYM(th_barrier); - extern probe_ncache_t *OSCAP_GSYM(ncache); static int probe_optecmp(char **a, char **b) @@ -191,8 +189,10 @@ void *probe_common_main(void *arg) dD("probe_common_main started"); + pthread_barrier_t barrier; + const unsigned thread_count = 2; // input and icache threads - if ((errno = pthread_barrier_init(&OSCAP_GSYM(th_barrier), NULL, thread_count)) != 0) { + if ((errno = pthread_barrier_init(&barrier, NULL, thread_count)) != 0) { fail(errno, "pthread_barrier_init", __LINE__ - 6); } @@ -218,9 +218,10 @@ void *probe_common_main(void *arg) * Initialize result & name caching */ probe.rcache = probe_rcache_new(); - probe.icache = probe_icache_new(); + probe.icache = probe_icache_new(&barrier); probe_ncache_clear(OSCAP_GSYM(ncache)); probe.ncache = OSCAP_GSYM(ncache); + probe.th_barrier = &barrier; /* * Initialize probe option handlers @@ -266,5 +267,7 @@ void *probe_common_main(void *arg) pthread_cleanup_pop(1); + pthread_barrier_destroy(&barrier); + return NULL; } diff --git a/src/OVAL/probes/probe/worker.c b/src/OVAL/probes/probe/worker.c index 660b9888a3..e0a07c31ec 100644 --- a/src/OVAL/probes/probe/worker.c +++ b/src/OVAL/probes/probe/worker.c @@ -72,6 +72,13 @@ static void preload_libraries_before_chroot() pthread_join(t, NULL); } +static void pthread_pair_cleanup_handler(void *arg) +{ + probe_pwpair_t *pair = (probe_pwpair_t *)arg; + dW("Probe worker thread finished unxpectedly, trying to avoid deadlock now..."); + SEAP_replyerr(pair->probe->SEAP_ctx, pair->probe->sd, pair->pth->msg, -100); +} + void *probe_worker_runfn(void *arg) { dD("probe_worker_runfn has started"); @@ -88,6 +95,8 @@ void *probe_worker_runfn(void *arg) # endif #endif dD("handling SEAP message ID %u", pair->pth->sid); + pthread_cleanup_push(pthread_pair_cleanup_handler, (void *)pair); + // probe_ret = -1; probe_res = pair->pth->msg_handler(pair->probe, pair->pth->msg, &probe_ret); @@ -172,6 +181,8 @@ void *probe_worker_runfn(void *arg) free(pair); pthread_detach(pthread_self()); + pthread_cleanup_pop(0); + dD("probe_worker_runfn has finished"); return (NULL); } @@ -974,7 +985,7 @@ static SEXP_t *probe_set_eval(probe_t *probe, SEXP_t *set, size_t depth) static void _add_blocked_paths(struct oscap_list *bpaths) { - char *envar = getenv("OSCAP_PROBE_IGNORE_PATHS"); + char *envar = oscap_strdup(getenv("OSCAP_PROBE_IGNORE_PATHS")); if (envar == NULL) { return; } @@ -985,6 +996,7 @@ static void _add_blocked_paths(struct oscap_list *bpaths) for (int i = 0; paths[i]; ++i) { oscap_list_add(bpaths, strdup(paths[i])); } + free(envar); free(paths); #endif } diff --git a/src/OVAL/probes/unix/linux/dpkginfo-helper.c b/src/OVAL/probes/unix/linux/dpkginfo-helper.c index fcbb8d150b..34f20b18d2 100644 --- a/src/OVAL/probes/unix/linux/dpkginfo-helper.c +++ b/src/OVAL/probes/unix/linux/dpkginfo-helper.c @@ -68,7 +68,7 @@ static int version(struct dpkginfo_reply_t *reply) struct dpkginfo_reply_t* dpkginfo_get_by_name(const char *name, int *err) { FILE *f; - char buf[DPKG_STATUS_BUFFER_SIZE], path[PATH_MAX], *root, *key, *value; + char buf[DPKG_STATUS_BUFFER_SIZE], path[PATH_MAX], *root, *key, *value, *p; struct dpkginfo_reply_t *reply; *err = 0; @@ -93,8 +93,14 @@ struct dpkginfo_reply_t* dpkginfo_get_by_name(const char *name, int *err) if (buf[0] == '\n') { // New package entry. if (reply != NULL) { - // Package found. - goto out; + if (reply->name != NULL) { + // Package found. + goto out; + } else { + // Package not found yet. + dpkginfo_free_reply(reply); + reply = NULL; + } } continue; } @@ -113,12 +119,12 @@ struct dpkginfo_reply_t* dpkginfo_get_by_name(const char *name, int *err) value = trimleft(value); // Package should be the first line. if (strcmp(key, "Package") == 0) { + if (reply != NULL) + continue; + reply = calloc(1, sizeof(*reply)); + if (reply == NULL) + goto err; if (strcmp(value, name) == 0) { - if (reply != NULL) - continue; - reply = calloc(1, sizeof(*reply)); - if (reply == NULL) - goto err; reply->name = strdup(value); if (reply->name == NULL) goto err; @@ -142,6 +148,23 @@ struct dpkginfo_reply_t* dpkginfo_get_by_name(const char *name, int *err) goto err; if (version(reply) < 0) goto err; + } else if (strcmp(key, "Provides") == 0) { + // Handle virtual packages. + char *s = strtok(value, ","); + while (s != NULL) { + s = trimleft(s); + // Ignore version. + p = strchr(s, ' '); + if (p != NULL) + *p++ = '\0'; + if (strcmp(s, name) == 0) { + reply->name = strdup(value); + if (reply->name == NULL) + goto err; + break; + } + s = strtok(NULL, ","); + } } } } diff --git a/src/XCCDF/result.c b/src/XCCDF/result.c index e317319fe0..83456f8133 100644 --- a/src/XCCDF/result.c +++ b/src/XCCDF/result.c @@ -91,7 +91,8 @@ // References containing STIG Rule IDs can be found by their href attribute, it must match the following url static const char *DISA_STIG_VIEWER_HREF[] = { "http://iase.disa.mil/stigs/Pages/stig-viewing-guidance.aspx", - "https://public.cyber.mil/stigs/srg-stig-tools/" }; + "https://public.cyber.mil/stigs/srg-stig-tools/", + "https://www.cyber.mil/stigs/srg-stig-tools/" }; // constants static const xccdf_numeric XCCDF_SCORE_MAX_DAFAULT = 100.0f; @@ -1278,7 +1279,8 @@ void xccdf_result_to_dom(struct xccdf_result *result, xmlNode *result_node, xmlD struct oscap_reference *ref = oscap_reference_iterator_next(references); const char *href = oscap_reference_get_href(ref); if (href && (strcmp(href, DISA_STIG_VIEWER_HREF[0]) == 0 || - strcmp(href, DISA_STIG_VIEWER_HREF[1]) == 0)) { + strcmp(href, DISA_STIG_VIEWER_HREF[1]) == 0 || + strcmp(href, DISA_STIG_VIEWER_HREF[2]) == 0)) { const char *stig_rule_id = oscap_reference_get_title(ref); xccdf_test_result_type_t other_res = (xccdf_test_result_type_t)oscap_htable_detach(nodes_by_rule_id, stig_rule_id); @@ -1487,7 +1489,8 @@ void xccdf_rule_result_to_dom(struct xccdf_rule_result *result, xmlDoc *doc, xml struct oscap_reference *ref = oscap_reference_iterator_next(references); const char *href = oscap_reference_get_href(ref); if (href && (strcmp(href, DISA_STIG_VIEWER_HREF[0]) == 0 || - strcmp(href, DISA_STIG_VIEWER_HREF[1]) == 0)) { + strcmp(href, DISA_STIG_VIEWER_HREF[1]) == 0 || + strcmp(href, DISA_STIG_VIEWER_HREF[2]) == 0)) { const char *stig_rule_id = oscap_reference_get_title(ref); xccdf_test_result_type_t expected_res = (xccdf_test_result_type_t)oscap_htable_get(nodes_by_rule_id, stig_rule_id); diff --git a/src/XCCDF_POLICY/xccdf_policy_remediate.c b/src/XCCDF_POLICY/xccdf_policy_remediate.c index 72b8bed34b..842ef2df9d 100644 --- a/src/XCCDF_POLICY/xccdf_policy_remediate.c +++ b/src/XCCDF_POLICY/xccdf_policy_remediate.c @@ -464,18 +464,8 @@ static inline int _xccdf_fix_execute(struct xccdf_rule_result *rr, struct xccdf_ NULL }; - char *oscap_bootc_build = getenv("OSCAP_BOOTC_BUILD"); - char *oscap_bootc_build_kvarg = NULL; - if (oscap_bootc_build != NULL) { - oscap_bootc_build_kvarg = oscap_sprintf("OSCAP_BOOTC_BUILD=%s", oscap_bootc_build); - } - char *const envp[3] = { - "PATH=/bin:/sbin:/usr/bin:/usr/sbin", - oscap_bootc_build_kvarg, - NULL - }; - - execve(interpret, argvp, envp); + // We are inheriting openscap environment + execve(interpret, argvp, environ); /* Wow, execve returned. In this special case, we failed to execute the fix * and we return 0 from function. At least the following error message will * indicate the problem in xccdf:message. */ diff --git a/src/common/oscap_pcre.c b/src/common/oscap_pcre.c index 65694c4403..81bee0a3ad 100644 --- a/src/common/oscap_pcre.c +++ b/src/common/oscap_pcre.c @@ -142,7 +142,6 @@ oscap_pcre_t *oscap_pcre_compile(const char *pattern, oscap_pcre_options_t optio int errno; PCRE2_SIZE erroffset2; res->re_ctx = NULL; - dD("pcre2_compile_8: patt=%s", pattern); res->re = pcre2_compile_8((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, _oscap_pcre_opts_to_pcre(options), &errno, &erroffset2, NULL); if (res->re == NULL) { PCRE2_UCHAR8 errmsg[PCRE2_ERR_BUF_SIZE]; @@ -206,13 +205,9 @@ int oscap_pcre_exec(const oscap_pcre_t *opcre, const char *subject, // The ovecsize is multiplied by 3 in the code for compatibility with PCRE1 int ovecsize2 = ovecsize/3; pcre2_match_data_8 *mdata = pcre2_match_data_create_8(ovecsize2, NULL); - dD("pcre2_match_8: subj=%s", subject); rc = pcre2_match_8(opcre->re, (PCRE2_SPTR8)subject, length, startoffset, _oscap_pcre_opts_to_pcre(options), mdata, opcre->re_ctx); - dD("pcre2_match_8: rc=%d, ", rc); if (rc > PCRE2_ERROR_NOMATCH) { PCRE2_SIZE *ovecp = pcre2_get_ovector_pointer_8(mdata); - uint32_t ovecp_count = pcre2_get_ovector_count_8(mdata); - dD("pcre2_match_8: pcre2_get_ovector_count_8=%d", ovecp_count); for (int i = 0; i < rc; i++) { if (i < ovecsize2) { ovector[i*2] = ovecp[i*2]; diff --git a/tests/API/OVAL/skip_paths/test_skip_paths.sh b/tests/API/OVAL/skip_paths/test_skip_paths.sh index 4b69c9aa33..26dc5b395a 100755 --- a/tests/API/OVAL/skip_paths/test_skip_paths.sh +++ b/tests/API/OVAL/skip_paths/test_skip_paths.sh @@ -15,8 +15,8 @@ cp "$srcdir/test.xml" "$root/b/" mkdir -p "$root/c" touch "$root/c/z" cp "$srcdir/test.xml" "$root/c/" -# oscap probes will skip directories "b" and "c" -export OSCAP_PROBE_IGNORE_PATHS="$root/b:$root/c" +# oscap probes will skip directories "$root/n", "$root/b" and "$root/c" +export OSCAP_PROBE_IGNORE_PATHS="$root/n:$root/c:$root/b" $OSCAP oval eval --results $result "$srcdir/test_skip_paths.xml" assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:1" and @result="true"]' assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:1" and @flag="complete"]' diff --git a/tests/API/OVAL/skip_paths/test_skip_paths.xml b/tests/API/OVAL/skip_paths/test_skip_paths.xml index a03196153b..57048f3ef7 100644 --- a/tests/API/OVAL/skip_paths/test_skip_paths.xml +++ b/tests/API/OVAL/skip_paths/test_skip_paths.xml @@ -90,12 +90,12 @@ /tmp/oscap_test_skip_paths/a/x ^.*$ - 1 + 1 /tmp/oscap_test_skip_paths/b/y ^.*$ - 1 + 1 /tmp/oscap_test_skip_paths/a/x diff --git a/tests/API/XCCDF/unittests/CMakeLists.txt b/tests/API/XCCDF/unittests/CMakeLists.txt index d8c5432e5f..ef835e3506 100644 --- a/tests/API/XCCDF/unittests/CMakeLists.txt +++ b/tests/API/XCCDF/unittests/CMakeLists.txt @@ -92,6 +92,7 @@ add_oscap_test("test_remediation_cdata.sh") add_oscap_test("test_remediation_subs_unresolved.sh") add_oscap_test("test_remediation_fix_without_system.sh") add_oscap_test("test_remediation_invalid_characters.sh") +add_oscap_test("test_remediation_environment.sh") add_oscap_test("test_remediate_simple.sh") add_oscap_test("test_remediate_perl.sh") add_oscap_test("test_report_check_with_empty_selector.sh") @@ -111,4 +112,3 @@ add_oscap_test("test_no_newline_between_select_elements.sh") add_oscap_test("test_single_line_tailoring.sh") add_oscap_test("test_reference.sh") add_oscap_test("test_remediation_bootc.sh") -add_oscap_test("test_oscap_bootc_pass_down.sh") diff --git a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml deleted file mode 100644 index 660575d55e..0000000000 --- a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.ds.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - 5.11.1 - 2009-01-12T10:41:00-05:00 - - - - - FAIL - fail - - - - - - - - - - - - - - oval:x:var:1 - - - - - 100 - - - - - - - accepted - 1.0 - - This rule always fails - - if [[ "$OSCAP_BOOTC_BUILD" == "YES" ]] ; then - printf "WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW" - fi - - - - - - - - diff --git a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh b/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh deleted file mode 100755 index 09783de1d3..0000000000 --- a/tests/API/XCCDF/unittests/test_oscap_bootc_pass_down.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -. $builddir/tests/test_common.sh - -set -e -o pipefail - -function test_pass_env_var_down() { - stdout=$(mktemp) - stderr=$(mktemp) - result=$(mktemp) - - OSCAP_BOOTC_BUILD=YES $OSCAP xccdf eval --remediate --results "$result" "$srcdir/test_oscap_bootc_pass_down.ds.xml" > "$stdout" 2> "$stderr" || ret=$? - assert_exists 1 '//rule-result/message[text()="WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW"]' - - rm -rf "$stdout" "$stderr" "$result" -} - -function test_no_env_var() { - stdout=$(mktemp) - stderr=$(mktemp) - result=$(mktemp) - - $OSCAP xccdf eval --remediate --results "$result" "$srcdir/test_oscap_bootc_pass_down.ds.xml" > "$stdout" 2> "$stderr" || ret=$? - assert_exists 0 '//rule-result/message[text()="WE ARE BUILDING BOOTABLE CONTAINER IMAGE NOW"]' - - rm -rf "$stdout" "$stderr" "$result" -} - - -test_pass_env_var_down -test_no_env_var diff --git a/tests/API/XCCDF/unittests/test_remediation_environment.sh b/tests/API/XCCDF/unittests/test_remediation_environment.sh new file mode 100755 index 0000000000..1f5fd0afbf --- /dev/null +++ b/tests/API/XCCDF/unittests/test_remediation_environment.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +. $builddir/tests/test_common.sh + +set -e +set -o pipefail + +name=$(basename $0 .sh) +result=$(mktemp -t ${name}.out.XXXXXX) + +rm -f remediation.env + +CANARY_EXPORTED="CANARY_EXPORTED_VALUE" +export CANARY_EXPORTED +CANARY_PROCESS="CANARY_PROCESS_VALUE" $OSCAP xccdf eval --remediate $srcdir/${name}.xccdf.xml || true + +grep -q "${PATH}" remediation.env || die "PATH not found" +grep -q "CANARY_EXPORTED_VALUE" remediation.env || die "CANARY_EXPORTED_VALUE not found" +grep -q "CANARY_PROCESS_VALUE" remediation.env || die "CANARY_PROCESS_VALUE not found" + +rm -f remediation.env +rm $result diff --git a/tests/API/XCCDF/unittests/test_remediation_environment.xccdf.xml b/tests/API/XCCDF/unittests/test_remediation_environment.xccdf.xml new file mode 100644 index 0000000000..0875b6c241 --- /dev/null +++ b/tests/API/XCCDF/unittests/test_remediation_environment.xccdf.xml @@ -0,0 +1,16 @@ + + + accepted + 1.0 + + Write some environment variables + + echo "PATH=${PATH}" > remediation.env + echo "CANARY_EXPORTED=${CANARY_EXPORTED}" >> remediation.env + echo "CANARY_PROCESS=${CANARY_PROCESS}" >> remediation.env + + + + + + diff --git a/tests/DS/test_ds_use_local_remote_resources.sh b/tests/DS/test_ds_use_local_remote_resources.sh index 2feb47da15..48245186ba 100755 --- a/tests/DS/test_ds_use_local_remote_resources.sh +++ b/tests/DS/test_ds_use_local_remote_resources.sh @@ -4,7 +4,6 @@ # Jan Černý set -e -o pipefail -set -x . $builddir/tests/test_common.sh @@ -81,3 +80,13 @@ assert_exists 1 '//rule-result[@idref="xccdf_com.example.www_rule_test-pass2"]/r popd rm -f "$result" "$stderr" rm -rf "$tmpdir1" "$tmpdir2" "$tmpdir3" + + +# test that a warning is shown when --local-files is provided with SCAP 1.2 DS +result=$(mktemp) +stderr=$(mktemp) +tmpdir=$(mktemp -d) +$OSCAP xccdf eval --local-files "$tmpdir" --profile "$PROFILE" --results "$result" "${srcdir}/ds_continue_without_remote_resources/remote_content_1.2.ds.xml" 2>"$stderr" || ret=$? +[ "$ret" = 2 ] +grep -q "WARNING: The '--local-files' option can be used only with SCAP 1.3 source data streams, but the provided data stream is version '1.2'. No local files will be used." "$stderr" +rm -rf "$result" "$stderr" "$tmpdir" diff --git a/tests/probes/textfilecontent54/CMakeLists.txt b/tests/probes/textfilecontent54/CMakeLists.txt index 9577016ba1..3f95ae8a20 100644 --- a/tests/probes/textfilecontent54/CMakeLists.txt +++ b/tests/probes/textfilecontent54/CMakeLists.txt @@ -6,4 +6,5 @@ if(ENABLE_PROBES_INDEPENDENT) add_oscap_test("test_recursion_limit.sh") add_oscap_test("test_symlinks.sh") add_oscap_test("test_validation_of_various_oval_versions.sh") + add_oscap_test("test_negative_instance.sh") endif() diff --git a/tests/probes/textfilecontent54/test_negative_instance.sh b/tests/probes/textfilecontent54/test_negative_instance.sh new file mode 100755 index 0000000000..960664fb15 --- /dev/null +++ b/tests/probes/textfilecontent54/test_negative_instance.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +. $builddir/tests/test_common.sh + +function test_negative_instance { + + probecheck "textfilecontent54" || return 255 + + local ret_val=0; + local DF="${srcdir}/test_negative_instance.xml" + local RF="results.xml" + + [ -f $RF ] && rm -f $RF + + local FILE_A="/tmp/test_negative_instance.tmp_file" + + touch "$FILE_A" + + echo "valid_key = valid_value" > "$FILE_A" + echo "valid_key = valid_value" >> "$FILE_A" + echo "valid_key = valid_value" >> "$FILE_A" + + $OSCAP oval eval --results $RF $DF + + if [ -f $RF ]; then + verify_results "tst" $DF $RF 13 && verify_results "def" $DF $RF 1 + ret_val=$? + else + ret_val=1 + fi + + rm -f $FILE_A $FILE_B $FILE_C + + return $ret_val +} + +test_negative_instance diff --git a/tests/probes/textfilecontent54/test_negative_instance.xml b/tests/probes/textfilecontent54/test_negative_instance.xml new file mode 100644 index 0000000000..bb227e7175 --- /dev/null +++ b/tests/probes/textfilecontent54/test_negative_instance.xml @@ -0,0 +1,180 @@ + + + + + 5.11.1 + 2025-03-24T00:00:00-00:00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + 1 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + 2 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + 3 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -1 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -2 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -3 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -1 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -2 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -3 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -1 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -2 + + + + /tmp + test_negative_instance.tmp_file + (\s)*valid_key(\s)*=(\s)*valid_value(\s)* + -3 + + + + + + diff --git a/utils/oscap-im b/utils/oscap-im index 4acb661716..7f416bb3a1 100755 --- a/utils/oscap-im +++ b/utils/oscap-im @@ -105,14 +105,24 @@ def add_eval_args(args, cmd): def pre_scan_fix(args): - with tempfile.NamedTemporaryFile(delete=False) as remediation_script: + with tempfile.NamedTemporaryFile() as remediation_script: gen_fix_cmd = [ "oscap", "xccdf", "generate", "fix", "--fix-type", "bootc", "--output", remediation_script.name] add_common_args(args, gen_fix_cmd) gen_fix_cmd.append(args.data_stream) - subprocess.run(gen_fix_cmd, check=True) - subprocess.run(["bash", remediation_script.name], check=True) + try: + subprocess.run(gen_fix_cmd, check=True, capture_output=True) + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"OpenSCAP generate fix failed with return code " + f"{e.returncode}.\nOutput: {e.stderr.decode()}") + try: + subprocess.run(["bash", remediation_script.name], check=True) + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Remediation script failed with return code " + f"{e.returncode}.") def scan_and_remediate(args): @@ -120,20 +130,25 @@ def scan_and_remediate(args): add_common_args(args, oscap_cmd) add_eval_args(args, oscap_cmd) oscap_cmd.append(args.data_stream) - env = {"OSCAP_PREFERRED_ENGINE": "SCE", "OSCAP_BOOTC_BUILD": "YES"} + env = {"OSCAP_PREFERRED_ENGINE": "SCE"} try: subprocess.run(oscap_cmd, env=env, check=True) except subprocess.CalledProcessError as e: if e.returncode not in [0, 2]: - print(e, file=sys.stderr) + raise RuntimeError( + f"OpenSCAP scan failed with return code {e.returncode}.\n") def main(): args = parse_args() verify_bootc_build_env() install_sce_dependencies() - pre_scan_fix(args) - scan_and_remediate(args) + try: + pre_scan_fix(args) + scan_and_remediate(args) + except RuntimeError as e: + print(e, file=sys.stderr) + sys.exit(1) if __name__ == "__main__": diff --git a/utils/oscap-xccdf.c b/utils/oscap-xccdf.c index 54680b3595..e727662ae4 100644 --- a/utils/oscap-xccdf.c +++ b/utils/oscap-xccdf.c @@ -586,6 +586,49 @@ int xccdf_set_profile_or_report_bad_id(struct xccdf_session *session, const char return return_code; } + +static bool _system_is_in_bootc_mode(void) +{ +#ifdef OS_WINDOWS + return false; +#else + #define BOOTC_PATH "/usr/bin/bootc" + #define CHUNK_SIZE 1024 + struct stat statbuf; + if (stat(BOOTC_PATH, &statbuf) == -1) { + return false; + } + FILE *output = popen(BOOTC_PATH " status --format json 2>/dev/null", "r"); + if (output == NULL) { + return false; + } + size_t buf_size = CHUNK_SIZE; + char *buf = calloc(buf_size, sizeof(char)); + if (buf == NULL) { + pclose(output); + return false; + } + int c; + size_t i = 0; + while ((c = fgetc(output)) != EOF) { + if (i >= buf_size) { + buf_size += CHUNK_SIZE; + char *new_buf = realloc(buf, buf_size); + if (new_buf == NULL) { + pclose(output); + return false; + } + buf = new_buf; + } + buf[i++] = c; + } + pclose(output); + bool result = (*buf != '\0' && strstr(buf, "\"booted\":null") == NULL); + free(buf); + return result; +#endif +} + /** * XCCDF Processing fucntion * @param action OSCAP Action structure @@ -596,6 +639,16 @@ int app_evaluate_xccdf(const struct oscap_action *action) struct xccdf_session *session = NULL; int result = OSCAP_ERROR; + + if (action->remediate && _system_is_in_bootc_mode()) { + fprintf(stderr, + "Detected running Image Mode operating system. OpenSCAP can't " + "perform remediation of this system because majority of the " + "system is read-only. Please apply remediation during bootable " + "container image build using 'oscap-im' instead.\n"); + return result; + } + #if defined(HAVE_SYSLOG_H) int priority = LOG_NOTICE; @@ -797,6 +850,14 @@ int app_xccdf_remediate(const struct oscap_action *action) { struct xccdf_session *session = NULL; int result = OSCAP_ERROR; + if (_system_is_in_bootc_mode()) { + fprintf(stderr, + "Detected running Image Mode operating system. OpenSCAP can't " + "perform remediation of this system because majority of the " + "system is read-only. Please apply remediation during bootable " + "container image build using 'oscap-im' instead.\n"); + return result; + } session = xccdf_session_new(action->f_xccdf); if (session == NULL) goto cleanup; diff --git a/utils/oscap.8 b/utils/oscap.8 index 23c6c80cca..339079ffa9 100644 --- a/utils/oscap.8 +++ b/utils/oscap.8 @@ -75,6 +75,7 @@ Allow download of remote components referenced from data stream. \fB\-\-local-files DIRECTORY\fR .RS Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP \fB\-\-profile PROFILE\fR @@ -225,6 +226,7 @@ Allow download of remote OVAL content referenced from XCCDF by check-content-ref \fB\-\-local-files DIRECTORY\fR .RS Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP \fB\-\-remediate\fR @@ -255,6 +257,7 @@ Allow download of remote OVAL content referenced from XCCDF by check-content-ref \fB\-\-local-files DIRECTORY\fR .RS Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP \fB\-\-cpe CPE_FILE\fR @@ -342,6 +345,7 @@ Allow download of remote OVAL content referenced from XCCDF by check-content-ref \fB\-\-local-files DIRECTORY\fR .RS Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP \fB\-\-skip-valid\fR, \fB\-\-skip-validation\fR @@ -518,6 +522,7 @@ Allow download of remote components referenced from data stream. .TP \fB\-\-local-files DIRECTORY\fR Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP @@ -682,6 +687,7 @@ Allow download of remote components referenced from data stream. .TP \fB\-\-local-files DIRECTORY\fR Instead of downloading remote data stream components from the network, use data stream components stored locally as files in the given directory. In place of the remote data stream component OpenSCAP will attempt to use a file whose file name is equal to @name attribute of the uri element within the catalog element within the component-ref element in the data stream if such file exists. +This option works only with SCAP 1.3 source data streams. It can't be used with SCAP 1.2 source data streams. .RE .TP .B \fBsds-validate\fR SOURCE_DS diff --git a/xsl/xccdf-references.xsl b/xsl/xccdf-references.xsl index 47d59cac46..c91f033123 100644 --- a/xsl/xccdf-references.xsl +++ b/xsl/xccdf-references.xsl @@ -82,7 +82,9 @@ Authors: ISO 27001-2013 - + STIG Viewer diff --git a/xsl/xccdf-report-oval-details.xsl b/xsl/xccdf-report-oval-details.xsl index 20cf418cd5..26af7ce518 100644 --- a/xsl/xccdf-report-oval-details.xsl +++ b/xsl/xccdf-report-oval-details.xsl @@ -146,23 +146,10 @@ Authors: - - - - - - - -
-
- - - -
- - -
- + + + + @@ -188,13 +175,32 @@ Authors: + + + - no value - - - - - + + + + + + + + +
+
+ + + +
+ +
+ + + + +
+