diff --git a/docs/manual/manual.adoc b/docs/manual/manual.adoc index ab069a3708..2c534d8aa7 100644 --- a/docs/manual/manual.adoc +++ b/docs/manual/manual.adoc @@ -1619,6 +1619,7 @@ not considered local by the scanner: * `SOURCE_DATE_EPOCH` - Timestamp in seconds since epoch. This timestamp will be used instead of the current time to populate `timestamp` attributes in SCAP source data streams created by `oscap ds sds-compose` sub-module. This is used for reproducible builds of data streams. * `OSCAP_PROBE_MEMORY_USAGE_RATIO` - maximum memory usage ratio (used/total) for OpenSCAP probes, default: 0.1 * `OSCAP_PROBE_MAX_COLLECTED_ITEMS` - maximal count of collected items by OpenSCAP probe for a single OVAL object evaluation +* `OSCAP_PROBE_IGNORE_PATHS` - Skip given paths during evaluation. If multiple paths should be skipped they need to be separated by a colon. The paths should be absolute canonical paths. Also, OpenSCAP uses `libcurl` library which also can be configured using environment variables. See https://curl.se/libcurl/c/libcurl-env.html[the list of libcurl environment variables]. diff --git a/src/OVAL/probes/independent/filehash58_probe.c b/src/OVAL/probes/independent/filehash58_probe.c index 55fbbf9b2e..e7facd4b3c 100644 --- a/src/OVAL/probes/independent/filehash58_probe.c +++ b/src/OVAL/probes/independent/filehash58_probe.c @@ -152,6 +152,10 @@ static int filehash58_cb(const char *prefix, const char *p, const char *f, const memcpy (pbuf + plen, f, sizeof (char) * flen); pbuf[plen+flen] = '\0'; + if (probe_path_is_blocked(pbuf, ctx->blocked_paths)) { + return 0; + } + /* * Open the file */ diff --git a/src/OVAL/probes/independent/filehash_probe.c b/src/OVAL/probes/independent/filehash_probe.c index 6d8780dc95..014b486abc 100644 --- a/src/OVAL/probes/independent/filehash_probe.c +++ b/src/OVAL/probes/independent/filehash_probe.c @@ -105,6 +105,10 @@ static int filehash_cb (const char *prefix, const char *p, const char *f, probe_ pbuf[plen+flen] = '\0'; include_filepath = oval_schema_version_cmp(over, OVAL_SCHEMA_VERSION(5.6)) >= 0; + if (probe_path_is_blocked(pbuf, ctx->blocked_paths)) { + return 0; + } + /* * Open the file */ diff --git a/src/OVAL/probes/independent/textfilecontent54_probe.c b/src/OVAL/probes/independent/textfilecontent54_probe.c index 4c6c9a1fa1..34199853fa 100644 --- a/src/OVAL/probes/independent/textfilecontent54_probe.c +++ b/src/OVAL/probes/independent/textfilecontent54_probe.c @@ -53,6 +53,8 @@ #include "common/debug_priv.h" #include "common/util.h" #include "common/oscap_pcre.h" +#include "common/list.h" + #include "textfilecontent54_probe.h" #define FILE_SEPARATOR '/' @@ -118,9 +120,8 @@ struct pfdata { oscap_pcre_t *compiled_regex; }; -static int process_file(const char *prefix, const char *path, const char *file, void *arg, oval_schema_version_t over) +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) { - struct pfdata *pfd = (struct pfdata *) arg; 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; char **substrs = NULL; @@ -144,6 +145,9 @@ static int process_file(const char *prefix, const char *path, const char *file, memcpy(whole_path + path_len, file, file_len + 1); + if (probe_path_is_blocked(whole_path, blocked_paths)) { + goto cleanup; + } /* * If stat() fails, don't report an error and just skip the file. * This is an expected situation, because the fts_*() functions @@ -361,7 +365,7 @@ int textfilecontent54_probe_main(probe_ctx *ctx, void *arg) if (ofts_ent->fts_info == FTS_F || ofts_ent->fts_info == FTS_SL) { // todo: handle return code - process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd, over); + process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd, over, ctx->blocked_paths); } oval_ftsent_free(ofts_ent); } diff --git a/src/OVAL/probes/independent/textfilecontent_probe.c b/src/OVAL/probes/independent/textfilecontent_probe.c index 1f2f9bf2ea..54c9ab1be1 100644 --- a/src/OVAL/probes/independent/textfilecontent_probe.c +++ b/src/OVAL/probes/independent/textfilecontent_probe.c @@ -136,7 +136,7 @@ struct pfdata { probe_ctx *ctx; }; -static int process_file(const char *prefix, const char *path, const char *filename, void *arg, oval_schema_version_t over) +static int process_file(const char *prefix, const char *path, const char *filename, void *arg, oval_schema_version_t over, struct oscap_list *blocked_paths) { struct pfdata *pfd = (struct pfdata *) arg; int ret = 0, path_len, filename_len; @@ -170,6 +170,10 @@ static int process_file(const char *prefix, const char *path, const char *filena } memcpy(whole_path + path_len, filename, filename_len + 1); + if (probe_path_is_blocked(whole_path, blocked_paths)) { + goto cleanup; + } + /* * If stat() fails, don't report an error and just skip the file. * This is an expected situation, because the fts_*() functions @@ -294,7 +298,7 @@ int textfilecontent_probe_main(probe_ctx *ctx, void *arg) if (ofts_ent->fts_info == FTS_F || ofts_ent->fts_info == FTS_SL) { // todo: handle return code - process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd, over); + process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd, over, ctx->blocked_paths); } oval_ftsent_free(ofts_ent); } diff --git a/src/OVAL/probes/independent/xmlfilecontent_probe.c b/src/OVAL/probes/independent/xmlfilecontent_probe.c index da74cb94e8..6de5a62e30 100644 --- a/src/OVAL/probes/independent/xmlfilecontent_probe.c +++ b/src/OVAL/probes/independent/xmlfilecontent_probe.c @@ -142,9 +142,8 @@ static xmlDocPtr strip_ns(xmlDocPtr doc) return result; } -static int process_file(const char *prefix, const char *path, const char *filename, void *arg) +static int process_file(const char *prefix, const char *path, const char *filename, struct pfdata *pfd, struct oscap_list *blocked_paths) { - struct pfdata *pfd = (struct pfdata *) arg; int ret = 0, path_len, filename_len; char *whole_path = NULL; xmlDoc *doc = NULL; @@ -171,6 +170,10 @@ static int process_file(const char *prefix, const char *path, const char *filena memcpy(whole_path + path_len, filename, filename_len + 1); + if (probe_path_is_blocked(whole_path, blocked_paths)) { + goto cleanup; + } + if (prefix == NULL) { doc = xmlParseFile(whole_path); } else { @@ -393,7 +396,7 @@ int xmlfilecontent_probe_main(probe_ctx *ctx, void *arg) if ((ofts = oval_fts_open_prefixed(prefix, path_ent, filename_ent, filepath_ent, behaviors_ent, probe_ctx_getresult(ctx))) != NULL) { while ((ofts_ent = oval_fts_read(ofts)) != NULL) { - process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd); + process_file(prefix, ofts_ent->path, ofts_ent->file, &pfd, ctx->blocked_paths); oval_ftsent_free(ofts_ent); } diff --git a/src/OVAL/probes/independent/yamlfilecontent_probe.c b/src/OVAL/probes/independent/yamlfilecontent_probe.c index f4698ff4d5..5e9417e789 100644 --- a/src/OVAL/probes/independent/yamlfilecontent_probe.c +++ b/src/OVAL/probes/independent/yamlfilecontent_probe.c @@ -396,6 +396,9 @@ static int process_yaml_file(const char *prefix, const char *path, const char *f yaml_parser_initialize(&parser); char *filepath = oscap_path_join(path, filename); + if (probe_path_is_blocked(filepath, ctx->blocked_paths)) { + goto cleanup; + } char *filepath_with_prefix = oscap_path_join(prefix, filepath); FILE *yaml_file = fopen(filepath_with_prefix, "r"); diff --git a/src/OVAL/probes/probe-api.c b/src/OVAL/probes/probe-api.c index 462494cf3b..d5f0ebeb28 100644 --- a/src/OVAL/probes/probe-api.c +++ b/src/OVAL/probes/probe-api.c @@ -1794,4 +1794,20 @@ SEXP_t *probe_obj_getmask(SEXP_t *obj) SEXP_free(objents); return (mask); } + +bool probe_path_is_blocked(const char *path, struct oscap_list *blocked_paths) +{ + bool res = false; + struct oscap_iterator *it = oscap_iterator_new(blocked_paths); + while (oscap_iterator_has_more(it)) { + const char *item = oscap_iterator_next(it); + if (oscap_path_startswith(path, item)) { + res = true; + break; + } + } + oscap_iterator_free(it); + return res; +} + /// @} diff --git a/src/OVAL/probes/probe/probe.h b/src/OVAL/probes/probe/probe.h index 20244fab27..e7b00ae6ad 100644 --- a/src/OVAL/probes/probe/probe.h +++ b/src/OVAL/probes/probe/probe.h @@ -94,6 +94,7 @@ struct probe_ctx { int offline_mode; double max_mem_ratio; size_t max_collected_items; + struct oscap_list *blocked_paths; }; typedef enum { diff --git a/src/OVAL/probes/probe/worker.c b/src/OVAL/probes/probe/worker.c index 526bbbe78e..53ebf26639 100644 --- a/src/OVAL/probes/probe/worker.c +++ b/src/OVAL/probes/probe/worker.c @@ -972,6 +972,23 @@ static SEXP_t *probe_set_eval(probe_t *probe, SEXP_t *set, size_t depth) return result; } +static void _add_blocked_paths(struct oscap_list *bpaths) +{ + char *envar = getenv("OSCAP_PROBE_IGNORE_PATHS"); + if (envar == NULL) { + return; + } +#ifdef OS_WINDOWS + dW("OSCAP_PROBE_IGNORE_PATHS isn't effective on Windows."); +#else + char **paths = oscap_split(envar, ":"); + for (int i = 0; paths[i]; ++i) { + oscap_list_add(bpaths, strdup(paths[i])); + } + free(paths); +#endif +} + /** * Worker thread function. This functions handles the evalution of objects and sets. * @param msg_in SEAP message with the request which contains the object to be evaluated @@ -1083,6 +1100,9 @@ SEXP_t *probe_worker(probe_t *probe, SEAP_msg_t *msg_in, int *ret) } } + pctx.blocked_paths = oscap_list_new(); + _add_blocked_paths(pctx.blocked_paths); + /* simple object */ pctx.icache = probe->icache; pctx.filters = probe_prepare_filters(probe, probe_in); @@ -1142,6 +1162,7 @@ SEXP_t *probe_worker(probe_t *probe, SEAP_msg_t *msg_in, int *ret) SEXP_free(pctx.filters); SEXP_free(probe_in); SEXP_free(mask); + oscap_list_free(pctx.blocked_paths, free); *ret = PROBE_EUNKNOWN; return (NULL); } @@ -1181,6 +1202,7 @@ SEXP_t *probe_worker(probe_t *probe, SEAP_msg_t *msg_in, int *ret) } SEXP_free(pctx.filters); + oscap_list_free(pctx.blocked_paths, free); } SEXP_free(probe_in); diff --git a/src/OVAL/probes/public/probe-api.h b/src/OVAL/probes/public/probe-api.h index c1178956f2..fbce8d27d2 100644 --- a/src/OVAL/probes/public/probe-api.h +++ b/src/OVAL/probes/public/probe-api.h @@ -68,6 +68,7 @@ #include #include "sexp-types.h" #include "oscap_export.h" +#include "list.h" /* * items @@ -538,4 +539,11 @@ OSCAP_API oval_schema_version_t probe_obj_get_platform_schema_version(const SEXP */ OSCAP_API SEXP_t *probe_obj_getmask(SEXP_t *obj); +/** + * Check if the given path matches any of the paths in the blocked paths list + * @param path path to be examined + * @param blocked_paths list of blocked paths + */ +OSCAP_API bool probe_path_is_blocked(const char *path, struct oscap_list *blocked_paths); + /// @} diff --git a/src/OVAL/probes/unix/file_probe.c b/src/OVAL/probes/unix/file_probe.c index 07f86aee4f..f3adfcd661 100644 --- a/src/OVAL/probes/unix/file_probe.c +++ b/src/OVAL/probes/unix/file_probe.c @@ -304,7 +304,7 @@ static SEXP_t *has_extended_acl(const char *path) #endif } -static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, oval_schema_version_t over, struct ID_cache *cache, struct gr_sexps *grs, SEXP_t *gr_lastpath) +static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, oval_schema_version_t over, struct ID_cache *cache, struct gr_sexps *grs, SEXP_t *gr_lastpath, struct oscap_list *blocked_paths) { char path_buffer[PATH_MAX]; SEXP_t *item; @@ -325,6 +325,10 @@ static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, st_path = path_buffer; } + if (probe_path_is_blocked(st_path, blocked_paths)) { + return 0; + } + char *st_path_with_prefix = oscap_path_join(prefix, st_path); if (lstat(st_path_with_prefix, &st) == -1) { dD("lstat failed when processing %s: errno=%u, %s.", st_path, errno, strerror (errno)); @@ -509,7 +513,7 @@ int file_probe_main(probe_ctx *ctx, void *mutex) if ((ofts = oval_fts_open_prefixed(prefix, path, filename, filepath, behaviors, probe_ctx_getresult(ctx))) != NULL) { while ((ofts_ent = oval_fts_read(ofts)) != NULL) { - if (file_cb(prefix, ofts_ent->path, ofts_ent->file, &cbargs, over, cache, grs, &gr_lastpath) != 0) { + if (file_cb(prefix, ofts_ent->path, ofts_ent->file, &cbargs, over, cache, grs, &gr_lastpath, ctx->blocked_paths) != 0) { oval_ftsent_free(ofts_ent); break; } diff --git a/src/OVAL/probes/unix/fileextendedattribute_probe.c b/src/OVAL/probes/unix/fileextendedattribute_probe.c index ee853886a8..ba92a150ed 100644 --- a/src/OVAL/probes/unix/fileextendedattribute_probe.c +++ b/src/OVAL/probes/unix/fileextendedattribute_probe.c @@ -77,7 +77,7 @@ struct cbargs { }; #if defined(OS_FREEBSD) -static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, SEXP_t *gr_lastpath) +static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, SEXP_t *gr_lastpath, struct oscap_list *blocked_paths) { char path_buffer[PATH_MAX]; SEXP_t *item; @@ -110,6 +110,10 @@ static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, st_path = path_buffer; } + if (probe_path_is_blocked(st_path, blocked_paths)) { + return 0; + } + char *st_path_with_prefix = oscap_path_join(prefix, st_path); /* update lastpath if needed */ @@ -205,7 +209,7 @@ static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, } #else -static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, SEXP_t *gr_lastpath) +static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, SEXP_t *gr_lastpath, struct oscap_list *blocked_paths) { char path_buffer[PATH_MAX]; SEXP_t *item, xattr_name; @@ -231,6 +235,10 @@ static int file_cb(const char *prefix, const char *p, const char *f, void *ptr, SEXP_init(&xattr_name); + if (probe_path_is_blocked(st_path, blocked_paths)) { + return 0; + } + char *st_path_with_prefix = oscap_path_join(prefix, st_path); do { /* estimate the size of the buffer */ @@ -441,7 +449,7 @@ int fileextendedattribute_probe_main(probe_ctx *ctx, void *mutex) if ((ofts = oval_fts_open_prefixed(prefix, path, filename, filepath, behaviors, probe_ctx_getresult(ctx))) != NULL) { while ((ofts_ent = oval_fts_read(ofts)) != NULL) { - file_cb(prefix, ofts_ent->path, ofts_ent->file, &cbargs, &gr_lastpath); + file_cb(prefix, ofts_ent->path, ofts_ent->file, &cbargs, &gr_lastpath, ctx->blocked_paths); oval_ftsent_free(ofts_ent); } oval_fts_close(ofts); diff --git a/src/OVAL/probes/unix/symlink_probe.c b/src/OVAL/probes/unix/symlink_probe.c index 1f0b13a06e..b3d5641e90 100644 --- a/src/OVAL/probes/unix/symlink_probe.c +++ b/src/OVAL/probes/unix/symlink_probe.c @@ -58,6 +58,10 @@ static int collect_symlink(SEXP_t *ent, probe_ctx *ctx) if (pathname == NULL) { return PROBE_EINVAL; } + if (probe_path_is_blocked(pathname, ctx->blocked_paths)) { + free(pathname); + return 0; + } if (lstat(pathname, &sb) == -1) { if (errno == ENOENT) { diff --git a/src/common/util.c b/src/common/util.c index 8bce0d6a03..a8b4a34dda 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -442,3 +442,35 @@ int oscap_open_writable(const char *filename) } return fd; } + +bool oscap_path_startswith(const char *path, const char *prefix) +{ + bool res = true; + const char *del = "/"; + char *path_dup = oscap_strdup(path); + char **path_split = oscap_split(path_dup, del); + char *prefix_dup = oscap_strdup(prefix); + char **prefix_split = oscap_split(prefix_dup, del); + int i = 0, j = 0; + while (prefix_split[i] && path_split[j]) { + if (!strcmp(prefix_split[i], "")) { + ++i; + continue; + } + if (!strcmp(path_split[j], "")) { + ++j; + continue; + } + if (strcmp(prefix_split[i], path_split[j])) { + res = false; + break; + } + ++i; + ++j; + } + free(path_dup); + free(path_split); + free(prefix_dup); + free(prefix_split); + return res; +} diff --git a/src/common/util.h b/src/common/util.h index 0811a7698c..8abe68d479 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -540,4 +540,12 @@ char *oscap_windows_error_message(unsigned long error_code); */ int oscap_open_writable(const char *filename); +/** + * Check if a path starts with the given prefix + * @param path file system path + * @param prefix file system path that will be tested if it's a prefix of the path parameter + * @return true or false + */ +bool oscap_path_startswith(const char *path, const char *prefix); + #endif /* OSCAP_UTIL_H_ */ diff --git a/tests/API/OVAL/CMakeLists.txt b/tests/API/OVAL/CMakeLists.txt index a653f593f5..5eca0c3ad3 100644 --- a/tests/API/OVAL/CMakeLists.txt +++ b/tests/API/OVAL/CMakeLists.txt @@ -8,5 +8,6 @@ add_oscap_test("test_api_oval.sh") add_subdirectory("glob_to_regex") add_subdirectory("report_variable_values") add_subdirectory("schema_version") +add_subdirectory("skip_paths") add_subdirectory("unittests") add_subdirectory("validate") diff --git a/tests/API/OVAL/skip_paths/CMakeLists.txt b/tests/API/OVAL/skip_paths/CMakeLists.txt new file mode 100644 index 0000000000..7381a1cb59 --- /dev/null +++ b/tests/API/OVAL/skip_paths/CMakeLists.txt @@ -0,0 +1,2 @@ +add_oscap_test("test_skip_paths.sh") +add_oscap_test("test_skip_paths_offline.sh") diff --git a/tests/API/OVAL/skip_paths/test.xml b/tests/API/OVAL/skip_paths/test.xml new file mode 100644 index 0000000000..cc0d933286 --- /dev/null +++ b/tests/API/OVAL/skip_paths/test.xml @@ -0,0 +1,3 @@ + + text + diff --git a/tests/API/OVAL/skip_paths/test_skip_paths.sh b/tests/API/OVAL/skip_paths/test_skip_paths.sh new file mode 100755 index 0000000000..4b69c9aa33 --- /dev/null +++ b/tests/API/OVAL/skip_paths/test_skip_paths.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +. $builddir/tests/test_common.sh + +set -e -o pipefail + +result=$(mktemp) +root="/tmp/oscap_test_skip_paths" +mkdir -p "$root/a" +touch "$root/a/x" +cp "$srcdir/test.xml" "$root/a/" +mkdir -p "$root/b" +touch "$root/b/y" +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 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"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:2" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:2" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:3" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:3" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:4" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:4" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:5" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:5" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:6" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:6" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:7" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:7" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/test.xml"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:8" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:8" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/test.xml"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/test.xml"]' +rm -f $result +rm -rf "$root" diff --git a/tests/API/OVAL/skip_paths/test_skip_paths.xml b/tests/API/OVAL/skip_paths/test_skip_paths.xml new file mode 100644 index 0000000000..a03196153b --- /dev/null +++ b/tests/API/OVAL/skip_paths/test_skip_paths.xml @@ -0,0 +1,117 @@ + + + + 5.11.1 + 2009-05-21T11:46:00-04:00 + + + + <description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:1"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:2"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:2"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:3"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:3"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:4"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:4"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:5"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:5"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:6"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:6"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:7"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:7"/> + </criteria> + </definition> + <definition class="compliance" version="1" id="oval:x:def:8"> + <metadata><title/><description/></metadata> + <criteria operator="AND"> + <criterion test_ref="oval:x:tst:8"/> + </criteria> + </definition> + </definitions> + <tests> + <file_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix" check_existence="at_least_one_exists" version="1" id="oval:x:tst:1" check="all" comment="read file from directory 'a' - should be read"> + <object object_ref="oval:x:obj:1"/> + </file_test> + <file_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix" check_existence="none_exist" version="1" id="oval:x:tst:2" check="all" comment="read file from directory 'b' - should be skip"> + <object object_ref="oval:x:obj:2"/> + </file_test> + <textfilecontent54_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="at_least_one_exists" version="1" id="oval:x:tst:3" check="all" comment="read file from directory 'a' - should be read"> + <object object_ref="oval:x:obj:3"/> + </textfilecontent54_test> + <textfilecontent54_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="none_exist" version="1" id="oval:x:tst:4" check="all" comment="read file from directory 'b' - should be skip"> + <object object_ref="oval:x:obj:4"/> + </textfilecontent54_test> + <filehash58_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="at_least_one_exists" version="1" id="oval:x:tst:5" check="all" comment="read file from directory 'a' - should be read"> + <object object_ref="oval:x:obj:5"/> + </filehash58_test> + <filehash58_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="none_exist" version="1" id="oval:x:tst:6" check="all" comment="read file from directory 'b' - should be skip"> + <object object_ref="oval:x:obj:6"/> + </filehash58_test> + <xmlfilecontent_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="at_least_one_exists" version="1" id="oval:x:tst:7" check="all" comment="read file from directory 'a' - should be read"> + <object object_ref="oval:x:obj:7"/> + </xmlfilecontent_test> + <xmlfilecontent_test xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" check_existence="none_exist" version="1" id="oval:x:tst:8" check="all" comment="read file from directory 'b' - should be skip"> + <object object_ref="oval:x:obj:8"/> + </xmlfilecontent_test> + </tests> + <objects> + <file_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix" version="1" id="oval:x:obj:1"> + <filepath>/tmp/oscap_test_skip_paths/a/x</filepath> + </file_object> + <file_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix" version="1" id="oval:x:obj:2"> + <filepath>/tmp/oscap_test_skip_paths/b/y</filepath> + </file_object> + <textfilecontent54_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:3"> + <filepath>/tmp/oscap_test_skip_paths/a/x</filepath> + <pattern>^.*$</pattern> + <instance datatype="int" operation="greater than or equal">1</instance> + </textfilecontent54_object> + <textfilecontent54_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:4"> + <filepath>/tmp/oscap_test_skip_paths/b/y</filepath> + <pattern>^.*$</pattern> + <instance datatype="int" operation="greater than or equal">1</instance> + </textfilecontent54_object> + <filehash58_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:5"> + <filepath>/tmp/oscap_test_skip_paths/a/x</filepath> + <hash_type>SHA-512</hash_type> + </filehash58_object> + <filehash58_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:6"> + <filepath>/tmp/oscap_test_skip_paths/b/y</filepath> + <hash_type>SHA-512</hash_type> + </filehash58_object> + <xmlfilecontent_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:7"> + <filepath>/tmp/oscap_test_skip_paths/a/test.xml</filepath> + <xpath>/parent</xpath> + </xmlfilecontent_object> + <xmlfilecontent_object xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" version="1" id="oval:x:obj:8"> + <filepath>/tmp/oscap_test_skip_paths/b/test.xml</filepath> + <xpath>/parent</xpath> + </xmlfilecontent_object> + </objects> +</oval_definitions> diff --git a/tests/API/OVAL/skip_paths/test_skip_paths_offline.sh b/tests/API/OVAL/skip_paths/test_skip_paths_offline.sh new file mode 100755 index 0000000000..393489f193 --- /dev/null +++ b/tests/API/OVAL/skip_paths/test_skip_paths_offline.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +. $builddir/tests/test_common.sh + +set -e -o pipefail + +result=$(mktemp) + +guest="/tmp/guest" +mkdir -p "$guest" +test_data_dir="/tmp/oscap_test_skip_paths" +mkdir -p "$guest/$test_data_dir/a" +touch "$guest/$test_data_dir/a/x" +cp "$srcdir/test.xml" "$guest/$test_data_dir/a/" +mkdir -p "$guest/$test_data_dir/b" +touch "$guest/$test_data_dir/b/y" +cp "$srcdir/test.xml" "$guest/$test_data_dir/b/" +mkdir -p "$guest/$test_data_dir/c" +touch "$guest/$test_data_dir/c/z" +cp "$srcdir/test.xml" "$guest/$test_data_dir/c/" +# oscap probes will skip directories "b" and "c" +export OSCAP_PROBE_IGNORE_PATHS="$test_data_dir/b:$test_data_dir/c" +set_chroot_offline_test_mode "$guest" +$OSCAP oval eval --results $result "$srcdir/test_skip_paths.xml" +unset_chroot_offline_test_mode +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"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:2" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:2" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/unix-sys:file_item/unix-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:3" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:3" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:4" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:4" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:textfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:5" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:5" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/x"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:6" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:6" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/y"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:filehash58_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/z"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:7" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:7" and @flag="complete"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/a/test.xml"]' +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:8" and @result="true"]' +assert_exists 1 '/oval_results/results/system/oval_system_characteristics/collected_objects/object[@id="oval:x:obj:8" and @flag="does not exist"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/b/test.xml"]' +assert_exists 0 '/oval_results/results/system/oval_system_characteristics/system_data/ind-sys:xmlfilecontent_item/ind-sys:filepath[text()="/tmp/oscap_test_skip_paths/c/test.xml"]' +rm -f $result +rm -rf "$guest" diff --git a/tests/common/CMakeLists.txt b/tests/common/CMakeLists.txt index 4beb0323f6..4281500466 100644 --- a/tests/common/CMakeLists.txt +++ b/tests/common/CMakeLists.txt @@ -1,5 +1,8 @@ add_oscap_test_executable(test_oscap_util "test_oscap_util.c" + ${CMAKE_SOURCE_DIR}/src/common/util.c + ${CMAKE_SOURCE_DIR}/src/common/error.c + ${CMAKE_SOURCE_DIR}/src/common/err_queue.c ) add_oscap_test("test_oscap_util.sh") diff --git a/tests/common/test_oscap_util.c b/tests/common/test_oscap_util.c index 22559966bc..88f4497b6a 100644 --- a/tests/common/test_oscap_util.c +++ b/tests/common/test_oscap_util.c @@ -29,8 +29,44 @@ #include <string.h> #include "common/util.h" +int test_oscap_path_startswith(void); int test_oscap_strrm(void); +int test_oscap_path_startswith() +{ + if (!oscap_path_startswith("/", "/")) + return 1; + if (!oscap_path_startswith("/aaa", "/")) + return 2; + if (!oscap_path_startswith("/aaa", "/aaa")) + return 3; + if (!oscap_path_startswith("/aaa/bbb", "/aaa")) + return 4; + if (!oscap_path_startswith("/aaa/bbb/ccc", "/aaa")) + return 5; + if (!oscap_path_startswith("/aaa/bbb/ccc/", "/aaa/")) + return 6; + if (!oscap_path_startswith("/aaa/bbb/ccc", "/aaa/bbb/ccc")) + return 7; + if (!oscap_path_startswith("/aaa/bbb/ccc", "")) + return 8; + if (!oscap_path_startswith("", "")) + return 9; + if (!oscap_path_startswith("", "/")) + return 10; + + if (oscap_path_startswith("/bbb", "/aaa")) + return 101; + if (oscap_path_startswith("/bbb/aaa", "/aaa")) + return 102; + if (oscap_path_startswith("/bbb/aaa/", "/aaa")) + return 103; + if (oscap_path_startswith("/bbb/aaa/", "/aaa/")) + return 104; + + return 0; +} + int test_oscap_strrm() { char str[] = "abcdef12345678def90"; @@ -59,6 +95,8 @@ int main (int argc, char *argv[]) { int retval = 0; + if ((retval = test_oscap_path_startswith()) != 0) + return retval; if ((retval = test_oscap_strrm()) != 0) return retval;