diff --git a/src/OVAL/_oval_probe_session.h b/src/OVAL/_oval_probe_session.h index 2d4c5c26a4..d6e96ba2aa 100644 --- a/src/OVAL/_oval_probe_session.h +++ b/src/OVAL/_oval_probe_session.h @@ -45,6 +45,7 @@ struct oval_probe_session { struct oval_syschar_model *sys_model; /**< system characteristics model */ char *dir; /**< probe session directory */ uint32_t flg; /**< probe session flags */ + struct oscap_stringlist *blocked_paths; /**< list of blocked paths */ }; #endif /* _OVAL_PROBE_SESSION */ diff --git a/src/OVAL/oval_agent.c b/src/OVAL/oval_agent.c index 4e31158704..1e190ecf4d 100644 --- a/src/OVAL/oval_agent.c +++ b/src/OVAL/oval_agent.c @@ -140,6 +140,11 @@ oval_agent_session_t * oval_agent_new_session(struct oval_definition_model *mode return ag_sess; } +void oval_agent_set_blocked_paths(oval_agent_session_t *ag_sess, struct oscap_stringlist *blocked_paths) +{ + oval_probe_session_set_blocked_paths(ag_sess->psess, blocked_paths); +} + struct oval_definition_model* oval_agent_get_definition_model(oval_agent_session_t* ag_sess) { return ag_sess->def_model; diff --git a/src/OVAL/oval_probe_ext.c b/src/OVAL/oval_probe_ext.c index 32328b36aa..343369b9ee 100644 --- a/src/OVAL/oval_probe_ext.c +++ b/src/OVAL/oval_probe_ext.c @@ -970,6 +970,7 @@ int oval_probe_ext_eval(SEAP_CTX_t *ctx, oval_pd_t *pd, oval_pext_t *pext, struc oscap_seterr(OSCAP_EFAMILY_OVAL, "Internal error: syschar == NULL"); return (-1); } + ctx->blocked_paths = oval_probe_session_get_blocked_paths(pext->sess_ptr); object = oval_syschar_get_object(syschar); ret = oval_object_to_sexp(pext->sess_ptr, oval_subtype_to_str(oval_object_get_subtype(object)), syschar, &s_obj); diff --git a/src/OVAL/oval_probe_session.c b/src/OVAL/oval_probe_session.c index 6d4fda6ced..19da074090 100644 --- a/src/OVAL/oval_probe_session.c +++ b/src/OVAL/oval_probe_session.c @@ -133,6 +133,7 @@ static void oval_probe_session_init(oval_probe_session_t *sess, struct oval_sysc sess->pext = oval_pext_new(); sess->pext->model = &sess->sys_model; sess->pext->sess_ptr = sess; + sess->blocked_paths = NULL; __init_once(); @@ -222,4 +223,15 @@ struct oval_syschar_model *oval_probe_session_getmodel(oval_probe_session_t *ses return (sess->sys_model); } +void oval_probe_session_set_blocked_paths(oval_probe_session_t *sess, struct oscap_stringlist *blocked_paths) +{ + sess->blocked_paths = blocked_paths; +} + +struct oscap_stringlist *oval_probe_session_get_blocked_paths(oval_probe_session_t *sess) +{ + return sess->blocked_paths; +} + + /// @} diff --git a/src/OVAL/oval_session.c b/src/OVAL/oval_session.c index bb73543ed8..0d4bbdf14d 100644 --- a/src/OVAL/oval_session.c +++ b/src/OVAL/oval_session.c @@ -85,6 +85,7 @@ struct oval_session { bool fetch_remote_resources; download_progress_calllback_t progress; const char *local_files; + struct oscap_stringlist *blocked_paths; }; struct oval_session *oval_session_new(const char *filename) @@ -324,6 +325,7 @@ static int oval_session_setup_agent(struct oval_session *session) char *base_name = oscap_basename(path_clone); session->sess = oval_agent_new_session(session->def_model, base_name); + oval_agent_set_blocked_paths(session->sess, session->blocked_paths); free(base_name); if (session->sess == NULL) { oscap_seterr(OSCAP_EFAMILY_OVAL, "Failed to create a new agent session."); diff --git a/src/OVAL/probes/SEAP/_seap-types.h b/src/OVAL/probes/SEAP/_seap-types.h index f8cb92aa7e..2a521a1a32 100644 --- a/src/OVAL/probes/SEAP/_seap-types.h +++ b/src/OVAL/probes/SEAP/_seap-types.h @@ -58,6 +58,7 @@ struct SEAP_CTX { uint16_t recv_timeout; uint16_t send_timeout; oval_subtype_t subtype; + struct oscap_stringlist *blocked_paths; }; typedef struct SEAP_CTX SEAP_CTX_t; diff --git a/src/OVAL/probes/SEAP/sch_queue.c b/src/OVAL/probes/SEAP/sch_queue.c index 3b13f29f74..f2c965ebc6 100644 --- a/src/OVAL/probes/SEAP/sch_queue.c +++ b/src/OVAL/probes/SEAP/sch_queue.c @@ -54,6 +54,7 @@ int sch_queue_connect(SEAP_desc_t *desc) struct probe_common_main_argument *arg = malloc(sizeof(struct probe_common_main_argument)); arg->subtype = desc->subtype; arg->queuedata = data; + arg->blocked_paths = desc->blocked_paths; desc->arg = arg; pthread_attr_t attr; diff --git a/src/OVAL/probes/SEAP/seap-descriptor.h b/src/OVAL/probes/SEAP/seap-descriptor.h index 08336fda94..d6ebca2ca0 100644 --- a/src/OVAL/probes/SEAP/seap-descriptor.h +++ b/src/OVAL/probes/SEAP/seap-descriptor.h @@ -60,6 +60,7 @@ typedef struct { SEAP_cmdtbl_t *cmd_w_table; /* Waiting SEAP commands */ oval_subtype_t subtype; struct probe_common_main_argument *arg; + struct oscap_stringlist *blocked_paths; } SEAP_desc_t; #define SEAP_DESC_FDIN 0x00000001 diff --git a/src/OVAL/probes/SEAP/seap.c b/src/OVAL/probes/SEAP/seap.c index b5a152be51..dec1ed22ca 100644 --- a/src/OVAL/probes/SEAP/seap.c +++ b/src/OVAL/probes/SEAP/seap.c @@ -112,6 +112,7 @@ int SEAP_connect(SEAP_CTX_t *ctx) return(-1); } dsc->subtype = ctx->subtype; + dsc->blocked_paths = ctx->blocked_paths; if (sch_queue_connect(dsc) != 0) { dD("FAIL: errno=%u, %s.", errno, strerror (errno)); diff --git a/src/OVAL/probes/independent/textfilecontent54_probe.c b/src/OVAL/probes/independent/textfilecontent54_probe.c index db404e3bc2..6d789881c9 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,7 +120,7 @@ struct pfdata { oscap_pcre_t *compiled_regex; }; -static int process_file(const char *prefix, const char *path, const char *file, struct pfdata *pfd, 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_stringlist *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; @@ -143,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 @@ -357,7 +362,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/probe-api.c b/src/OVAL/probes/probe-api.c index 462494cf3b..8e1b0a43c7 100644 --- a/src/OVAL/probes/probe-api.c +++ b/src/OVAL/probes/probe-api.c @@ -1794,4 +1794,54 @@ SEXP_t *probe_obj_getmask(SEXP_t *obj) SEXP_free(objents); return (mask); } + +static bool 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; +} + +bool probe_path_is_blocked(const char *path, struct oscap_stringlist *blocked_paths) +{ + bool res = false; + printf("calling probe_path_is_blocked('%s')\n", path); + struct oscap_iterator *it = oscap_iterator_new(blocked_paths); + while (oscap_iterator_has_more(it)) { + const char *item = oscap_iterator_next(it); + if (path_startswith(path, item)) { + printf("Skipping '%s'\n", path); + 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 d3a488c4d5..eef822b1d5 100644 --- a/src/OVAL/probes/probe/probe.h +++ b/src/OVAL/probes/probe/probe.h @@ -75,6 +75,7 @@ typedef struct { int real_root_fd; int real_cwd_fd; + struct oscap_stringlist *blocked_paths; } probe_t; struct probe_ctx { @@ -84,6 +85,7 @@ struct probe_ctx { probe_icache_t *icache; /**< item cache */ int offline_mode; double max_mem_ratio; + struct oscap_stringlist *blocked_paths; }; typedef enum { diff --git a/src/OVAL/probes/probe/probe_main.c b/src/OVAL/probes/probe/probe_main.c index 17bf7a0ac0..fecb24350d 100644 --- a/src/OVAL/probes/probe/probe_main.c +++ b/src/OVAL/probes/probe/probe_main.c @@ -180,6 +180,7 @@ void *probe_common_main(void *arg) probe.subtype = subtype; probe.real_root_fd = -1; probe.real_cwd_fd = -1; + probe.blocked_paths = probe_argument->blocked_paths; #if defined(HAVE_PTHREAD_SETNAME_NP) # if defined(OS_APPLE) diff --git a/src/OVAL/probes/probe/probe_main.h b/src/OVAL/probes/probe/probe_main.h index 5f34548fcd..18df9192d4 100644 --- a/src/OVAL/probes/probe/probe_main.h +++ b/src/OVAL/probes/probe/probe_main.h @@ -26,6 +26,7 @@ struct probe_common_main_argument { oval_subtype_t subtype; sch_queuedata_t *queuedata; + struct oscap_stringlist *blocked_paths; }; void *probe_common_main(void *); diff --git a/src/OVAL/probes/probe/worker.c b/src/OVAL/probes/probe/worker.c index fddc1b3965..586ed38bc1 100644 --- a/src/OVAL/probes/probe/worker.c +++ b/src/OVAL/probes/probe/worker.c @@ -1078,6 +1078,7 @@ SEXP_t *probe_worker(probe_t *probe, SEAP_msg_t *msg_in, int *ret) if (max_ratio > 0) pctx.max_mem_ratio = max_ratio; } + pctx.blocked_paths = probe->blocked_paths; /* simple object */ pctx.icache = probe->icache; diff --git a/src/OVAL/probes/public/probe-api.h b/src/OVAL/probes/public/probe-api.h index c1178956f2..265566e66b 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_stringlist *blocked_paths); + /// @} diff --git a/src/OVAL/probes/unix/file_probe.c b/src/OVAL/probes/unix/file_probe.c index 07f86aee4f..8230994ef0 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_stringlist *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/public/oval_agent_api.h b/src/OVAL/public/oval_agent_api.h index 9e6236f3c4..f75db606be 100644 --- a/src/OVAL/public/oval_agent_api.h +++ b/src/OVAL/public/oval_agent_api.h @@ -42,6 +42,7 @@ #include "oval_results.h" #include "oval_variables.h" #include "oscap_export.h" +#include "list.h" //#include "oval_probe.h" struct oval_agent_session; @@ -73,6 +74,13 @@ OSCAP_API struct oval_definition_model* oval_agent_get_definition_model(oval_age */ OSCAP_API void oval_agent_set_product_name(oval_agent_session_t *, char *); +/** + * Block certain paths during content evaluation + * @param ag_sess OVAL agent session + * @param blocked_paths a list of filesystem paths that will be skipped + */ +OSCAP_API void oval_agent_set_blocked_paths(oval_agent_session_t *, struct oscap_stringlist *); + /** * Probe the system and evaluate specified definition * @return 0 on success; -1 error; 1 warning diff --git a/src/OVAL/public/oval_probe_session.h b/src/OVAL/public/oval_probe_session.h index 0fe0904997..163c5ec18d 100644 --- a/src/OVAL/public/oval_probe_session.h +++ b/src/OVAL/public/oval_probe_session.h @@ -34,6 +34,7 @@ typedef struct oval_probe_session oval_probe_session_t; #include "oval_system_characteristics.h" #include "oscap_export.h" +#include "list.h" /** * Create and initialize a new probe session @@ -74,5 +75,18 @@ OSCAP_API int oval_probe_session_abort(oval_probe_session_t *sess); */ OSCAP_API struct oval_syschar_model *oval_probe_session_getmodel(oval_probe_session_t *sess); +/** + * Block certain paths during content evaluation + * @param sess pointer to the probe session structure + * @param blocked_paths a list of filesystem paths that will be skipped + */ +OSCAP_API void oval_probe_session_set_blocked_paths(oval_probe_session_t *sess, struct oscap_stringlist *blocked_paths); + +/** + * Retrieve a list of filesystem paths that will be skipped during content evaluation + * @param sess pointer to the probe session structure + */ +OSCAP_API struct oscap_stringlist *oval_probe_session_get_blocked_paths(oval_probe_session_t *sess); + #endif /* OVAL_PROBE_SESSION */ /// @} diff --git a/src/XCCDF/public/xccdf_session.h b/src/XCCDF/public/xccdf_session.h index 8efa1d16d7..f35a72e68f 100644 --- a/src/XCCDF/public/xccdf_session.h +++ b/src/XCCDF/public/xccdf_session.h @@ -35,6 +35,7 @@ #include "xccdf_policy.h" #include "oscap_download_cb.h" #include "oscap_export.h" +#include "list.h" /** * @struct xccdf_session @@ -644,6 +645,13 @@ OSCAP_API int xccdf_session_generate_guide(struct xccdf_session *session, const */ OSCAP_API int xccdf_session_export_all(struct xccdf_session *session); +/** + * Block certain paths during content evaluation + * @param session pointer to XCCDF session + * @param blocked_paths a list of filesystem paths that will be skipped + */ +OSCAP_API void xccdf_session_set_blocked_paths(struct xccdf_session *session, struct oscap_stringlist *blocked_paths); + /// @} /// @} #endif diff --git a/src/XCCDF/xccdf_session.c b/src/XCCDF/xccdf_session.c index c5bc6d6947..40d4102173 100644 --- a/src/XCCDF/xccdf_session.c +++ b/src/XCCDF/xccdf_session.c @@ -99,6 +99,7 @@ struct xccdf_session { struct oscap_htable *result_sources; ///< mapping 'filepath' to oscap_source for OVAL results struct oscap_htable *results_mapping; ///< mapping OVAL filename to filepath for OVAL results struct oscap_htable *arf_report_mapping; ///< mapping OVAL filename to ARF report ID for OVAL results + struct oscap_stringlist *blocked_paths; ///< a list of filesystem paths that will be skipped during content evaluation } oval; struct { char *arf_file; ///< Path to ARF file to export @@ -1210,6 +1211,7 @@ int xccdf_session_load_oval(struct xccdf_session *session) /* def_model -> session */ struct oval_agent_session *tmp_sess = oval_agent_new_session(tmp_def_model, contents[idx]->href); + oval_agent_set_blocked_paths(tmp_sess, session->oval.blocked_paths); if (tmp_sess == NULL) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Failed to create new OVAL agent session for: '%s'.", contents[idx]->href); oval_definition_model_free(tmp_def_model); @@ -2059,3 +2061,8 @@ int xccdf_session_export_all(struct xccdf_session *session) oscap_source_free(arf_source); return ret; } + +void xccdf_session_set_blocked_paths(struct xccdf_session *session, struct oscap_stringlist *blocked_paths) +{ + session->oval.blocked_paths = blocked_paths; +} diff --git a/utils/oscap-tool.c b/utils/oscap-tool.c index b91866ed14..c0c8dfd488 100644 --- a/utils/oscap-tool.c +++ b/utils/oscap-tool.c @@ -62,6 +62,7 @@ static void oscap_action_init(struct oscap_action *action) action->validate_signature = 1; action->rules = oscap_stringlist_new(); action->skip_rules = oscap_stringlist_new(); + action->blocked_paths = oscap_stringlist_new(); } static void oscap_action_release(struct oscap_action *action) diff --git a/utils/oscap-tool.h b/utils/oscap-tool.h index c0f11e45d3..3bdb24e8e8 100644 --- a/utils/oscap-tool.h +++ b/utils/oscap-tool.h @@ -176,6 +176,7 @@ struct oscap_action { char *verbosity_level; char *fix_type; char *local_files; + struct oscap_stringlist *blocked_paths; }; int app_xslt(const char *infile, const char *xsltfile, const char *outfile, const char **params); diff --git a/utils/oscap-xccdf.c b/utils/oscap-xccdf.c index 746a3dfbec..cae346a0c7 100644 --- a/utils/oscap-xccdf.c +++ b/utils/oscap-xccdf.c @@ -186,7 +186,9 @@ static struct oscap_module XCCDF_EVAL = { " (only applicable for source data streams)\n" " (only applicable when datastream-id AND xccdf-id are not specified)\n" " --remediate - Automatically execute XCCDF fix elements for failed rules.\n" - " Use of this option is always at your own risk.\n", + " Use of this option is always at your own risk.\n" + " --block-path - Specify file system paths that will not be scanned during SCAP content evaluation.\n" + " This option can be used multiple times to block multiple paths.", .opt_parser = getopt_xccdf, .func = app_evaluate_xccdf }; @@ -616,6 +618,7 @@ int app_evaluate_xccdf(const struct oscap_action *action) xccdf_session_set_component_id(session, action->f_xccdf_id); xccdf_session_set_benchmark_id(session, action->f_benchmark_id); } + xccdf_session_set_blocked_paths(session, action->blocked_paths); xccdf_session_set_user_cpe(session, action->cpe); // The tailoring_file may be NULL but the tailoring file may have been // autonegotiated from the input file, we don't want to lose that. @@ -1186,6 +1189,7 @@ enum oval_opt { XCCDF_OPT_PROFILE, XCCDF_OPT_RULE, XCCDF_OPT_SKIP_RULE, + XCCDF_OPT_BLOCK_PATH, XCCDF_OPT_REPORT_FILE, XCCDF_OPT_TEMPLATE, XCCDF_OPT_FORMAT, @@ -1234,6 +1238,7 @@ bool getopt_xccdf(int argc, char **argv, struct oscap_action *action) {"sce-template", required_argument, NULL, XCCDF_OPT_SCE_TEMPLATE}, {"fix-type", required_argument, NULL, XCCDF_OPT_FIX_TYPE}, {"local-files", required_argument, NULL, XCCDF_OPT_LOCAL_FILES}, + {"block-path", required_argument, NULL, XCCDF_OPT_BLOCK_PATH}, // flags {"force", no_argument, &action->force, 1}, {"oval-results", no_argument, &action->oval_results, 1}, @@ -1275,6 +1280,9 @@ bool getopt_xccdf(int argc, char **argv, struct oscap_action *action) case XCCDF_OPT_SKIP_RULE: oscap_stringlist_add_string(action->skip_rules, optarg); break; + case XCCDF_OPT_BLOCK_PATH: + oscap_stringlist_add_string(action->blocked_paths, optarg); + break; case XCCDF_OPT_RESULT_ID: action->id = optarg; break; case XCCDF_OPT_REPORT_FILE: action->f_report = optarg; break; case XCCDF_OPT_TEMPLATE: action->tmpl = optarg; break;