diff --git a/docs/developer/developer.adoc b/docs/developer/developer.adoc index 08273e24d..823a1504e 100644 --- a/docs/developer/developer.adoc +++ b/docs/developer/developer.adoc @@ -317,6 +317,8 @@ behaviour. * *OSCAP_FULL_VALIDATION=1* - validate all exported documents (slower) * *SEXP_VALIDATE_DISABLE=1* - do not validate SEXP expressions (faster) +* *OSCAP_PCRE_EXEC_RECURSION_LIMIT* - override default recursion limit + for match in pcre_exec call in textfilecontent(54) probes. diff --git a/src/OVAL/probes/independent/textfilecontent54_probe.c b/src/OVAL/probes/independent/textfilecontent54_probe.c index 1c449833f..3053f5d95 100644 --- a/src/OVAL/probes/independent/textfilecontent54_probe.c +++ b/src/OVAL/probes/independent/textfilecontent54_probe.c @@ -52,68 +52,11 @@ #include #include #include "common/debug_priv.h" +#include "common/util.h" #include "textfilecontent54_probe.h" #define FILE_SEPARATOR '/' -static int get_substrings(char *str, int *ofs, pcre *re, int want_substrs, char ***substrings) { - int i, ret, rc; - int ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]); - char **substrs; - - // todo: max match count check - - for (i = 0; i < ovector_len; ++i) - ovector[i] = -1; - -#if defined(OS_SOLARIS) - rc = pcre_exec(re, NULL, str, strlen(str), *ofs, PCRE_NO_UTF8_CHECK, ovector, ovector_len); -#else - rc = pcre_exec(re, NULL, str, strlen(str), *ofs, 0, ovector, ovector_len); -#endif - - if (rc < -1) { - dE("Function pcre_exec() failed to match a regular expression with return code %d on string '%s'.", rc, str); - return rc; - } else if (rc == -1) { - /* no match */ - return 0; - } - - *ofs = (*ofs == ovector[1]) ? ovector[1] + 1 : ovector[1]; - - if (!want_substrs) { - /* just report successful match */ - return 1; - } - - ret = 0; - if (rc == 0) { - /* vector too small */ - // todo: report partial results - rc = ovector_len / 3; - } - - substrs = malloc(rc * sizeof (char *)); - for (i = 0; i < rc; ++i) { - int len; - char *buf; - - if (ovector[2 * i] == -1) - continue; - len = ovector[2 * i + 1] - ovector[2 * i]; - buf = malloc(len + 1); - memcpy(buf, str + ovector[2 * i], len); - buf[len] = '\0'; - substrs[ret] = buf; - ++ret; - } - - *substrings = substrs; - - return ret; -} - static SEXP_t *create_item(const char *path, const char *filename, char *pattern, int instance, char **substrs, int substr_cnt, oval_schema_version_t over) { @@ -260,7 +203,7 @@ static int process_file(const char *prefix, const char *path, const char *file, want_instance = 0; SEXP_free(next_inst); - substr_cnt = get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs); + substr_cnt = oscap_get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs); if (substr_cnt < 0) { SEXP_t *msg; diff --git a/src/OVAL/probes/independent/textfilecontent_probe.c b/src/OVAL/probes/independent/textfilecontent_probe.c index 9abf8fcc3..988a6471d 100644 --- a/src/OVAL/probes/independent/textfilecontent_probe.c +++ b/src/OVAL/probes/independent/textfilecontent_probe.c @@ -71,63 +71,11 @@ #include #include #include "common/debug_priv.h" +#include "common/util.h" #include "textfilecontent_probe.h" #define FILE_SEPARATOR '/' -static int get_substrings(char *str, pcre *re, int want_substrs, char ***substrings) { - int i, ret, rc; - int ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]); - - // todo: max match count check - - for (i = 0; i < ovector_len; ++i) - ovector[i] = -1; - - rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, - ovector, ovector_len); - - if (rc < -1) { - return -1; - } else if (rc == -1) { - /* no match */ - return 0; - } else if(!want_substrs) { - /* just report successful match */ - return 1; - } - - char **substrs; - - ret = 0; - if (rc == 0) { - /* vector too small */ - rc = ovector_len / 3; - } - - substrs = malloc(rc * sizeof (char *)); - for (i = 0; i < rc; ++i) { - int len; - char *buf; - - if (ovector[2 * i] == -1) - continue; - len = ovector[2 * i + 1] - ovector[2 * i]; - buf = malloc(len + 1); - memcpy(buf, str + ovector[2 * i], len); - buf[len] = '\0'; - substrs[ret] = buf; - ++ret; - } - /* - if (ret < rc) - substrs = realloc(substrs, ret * sizeof (char *)); - */ - *substrings = substrs; - - return ret; -} - static SEXP_t *create_item(const char *path, const char *filename, char *pattern, int instance, char **substrs, int substr_cnt, oval_schema_version_t over) { @@ -244,9 +192,10 @@ static int process_file(const char *prefix, const char *path, const char *filena int cur_inst = 0; char line[4096]; + int ofs = 0; while (fgets(line, sizeof(line), fp) != NULL) { - substr_cnt = get_substrings(line, re, 1, &substrs); + substr_cnt = oscap_get_substrings(line, &ofs, re, 1, &substrs); if (substr_cnt > 0) { int k; SEXP_t *item; diff --git a/src/common/util.c b/src/common/util.c index 146b7bc39..8f130c50e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -30,11 +30,13 @@ #include #include #include +#include #include "util.h" #include "_error.h" #include "oscap.h" #include "oscap_helpers.h" +#include "debug_priv.h" #ifdef OS_WINDOWS #include @@ -45,6 +47,7 @@ #endif #define PATH_SEPARATOR '/' +#define OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT 5000 int oscap_string_to_enum(const struct oscap_string_map *map, const char *str) { @@ -353,6 +356,76 @@ char *oscap_path_join(const char *path1, const char *path2) return joined_path; } +int oscap_get_substrings(char *str, int *ofs, pcre *re, int want_substrs, char ***substrings) { + int i, ret, rc; + int ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]); + char **substrs; + + // todo: max match count check + + for (i = 0; i < ovector_len; ++i) { + ovector[i] = -1; + } + + struct pcre_extra extra; + extra.match_limit_recursion = OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT; + char *limit_str = getenv("OSCAP_PCRE_EXEC_RECURSION_LIMIT"); + if (limit_str != NULL) { + unsigned long limit; + if (sscanf(limit_str, "%lu", &limit) == 1) { + extra.match_limit_recursion = limit; + } + } + extra.flags = PCRE_EXTRA_MATCH_LIMIT_RECURSION; +#if defined(OS_SOLARIS) + rc = pcre_exec(re, &extra, str, strlen(str), *ofs, PCRE_NO_UTF8_CHECK, ovector, ovector_len); +#else + rc = pcre_exec(re, &extra, str, strlen(str), *ofs, 0, ovector, ovector_len); +#endif + + if (rc < -1) { + dE("Function pcre_exec() failed to match a regular expression with return code %d on string '%s'.", rc, str); + return rc; + } else if (rc == -1) { + /* no match */ + return 0; + } + + *ofs = (*ofs == ovector[1]) ? ovector[1] + 1 : ovector[1]; + + if (!want_substrs) { + /* just report successful match */ + return 1; + } + + ret = 0; + if (rc == 0) { + /* vector too small */ + // todo: report partial results + rc = ovector_len / 3; + } + + substrs = malloc(rc * sizeof (char *)); + for (i = 0; i < rc; ++i) { + int len; + char *buf; + + if (ovector[2 * i] == -1) { + continue; + } + len = ovector[2 * i + 1] - ovector[2 * i]; + buf = malloc(len + 1); + memcpy(buf, str + ovector[2 * i], len); + buf[len] = '\0'; + substrs[ret] = buf; + ++ret; + } + + *substrings = substrs; + + return ret; +} + #ifdef OS_WINDOWS char *oscap_windows_wstr_to_str(const wchar_t *wstr) { diff --git a/src/common/util.h b/src/common/util.h index 50a1c746f..2592f3962 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -31,6 +31,7 @@ #include "public/oscap.h" #include #include +#include #include "oscap_export.h" #ifndef __attribute__nonnull__ @@ -467,6 +468,19 @@ int oscap_strncasecmp(const char *s1, const char *s2, size_t n); */ char *oscap_strerror_r(int errnum, char *buf, size_t buflen); +/** + * Match a regular expression and return substrings. + * Caller is responsible for freeing the returned array. + * @param str subject string + * @param ofs starting offset in str + * @param re compiled regular expression + * @param want_substrs if non-zero, substrings will be returned + * @param substrings contains returned substrings + * @return count of matched substrings, 0 if no match + * negative value on failure + */ +int oscap_get_substrings(char *str, int *ofs, pcre *re, int want_substrs, char ***substrings); + #ifdef OS_WINDOWS /** * Convert wide character string to a C string (UTF-16 to UTF-8) diff --git a/tests/probes/textfilecontent54/30-ospp-v42.rules b/tests/probes/textfilecontent54/30-ospp-v42.rules new file mode 100644 index 000000000..7ad0c254d --- /dev/null +++ b/tests/probes/textfilecontent54/30-ospp-v42.rules @@ -0,0 +1,113 @@ +## The purpose of these rules is to meet the requirements for Operating +## System Protection Profile (OSPP)v4.2. These rules depends on having +## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed. + +## Unsuccessful file creation (open with O_CREAT) +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b32 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S open -F a1&0100 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create +-a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-create + +## Unsuccessful file modifications (open for write or truncate) +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b32 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S open -F a1&01003 -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification +-a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification + +## Unsuccessful file access (any other opens) This has to go last. +-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access +-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access +-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access +-a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-access + +## Unsuccessful file delete +-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-delete +-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-delete +-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-delete +-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-delete + +## Unsuccessful permission change +-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat,setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat,setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat,setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat,setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change + +## Unsuccessful ownership change +-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b64 -S lchown,fchown,chown,fchownat -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change +-a always,exit -F arch=b64 -S lchown,fchown,chown,fchownat -F exit=-EPERM -F auid>=1000 -F auid!=unset -F key=unsuccesful-perm-change + +## User add delete modify. This is covered by pam. However, someone could +## open a file and directly create or modify a user, so we'll watch passwd and +## shadow for writes +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&03 -F path=/etc/passwd -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&03 -F path=/etc/passwd -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b32 -S open -F a1&03 -F path=/etc/passwd -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b64 -S open -F a1&03 -F path=/etc/passwd -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&03 -F path=/etc/shadow -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&03 -F path=/etc/shadow -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b32 -S open -F a1&03 -F path=/etc/shadow -F auid>=1000 -F auid!=unset -F key=user-modify +-a always,exit -F arch=b64 -S open -F a1&03 -F path=/etc/shadow -F auid>=1000 -F auid!=unset -F key=user-modify + +## User enable and disable. This is entirely handled by pam. + +## Group add delete modify. This is covered by pam. However, someone could +## open a file and directly create or modify a user, so we'll watch group and +## gshadow for writes +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&03 -F path=/etc/group -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&03 -F path=/etc/group -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b32 -S open -F a1&03 -F path=/etc/group -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b64 -S open -F a1&03 -F path=/etc/group -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&03 -F path=/etc/gshadow -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&03 -F path=/etc/gshadow -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b32 -S open -F a1&03 -F path=/etc/gshadow -F auid>=1000 -F auid!=unset -F key=group-modify +-a always,exit -F arch=b64 -S open -F a1&03 -F path=/etc/gshadow -F auid>=1000 -F auid!=unset -F key=group-modify + +## Use of special rights for config changes. This would be use of setuid +## programs that relate to user accts. This is not all setuid apps because +## requirements are only for ones that affect system configuration. +-a always,exit -F path=/usr/sbin/usernetctl -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/sbin/seunshare -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/mount -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/newuidmap -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/gpasswd -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/newgidmap -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/umount -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes +-a always,exit -F path=/usr/bin/at -F perm=x -F auid>=1000 -F auid!=unset -F key=special-config-changes + +## Privilege escalation via su or sudo. This is entirely handled by pam. + +## Audit log access +-a always,exit -F dir=/var/log/audit/ -F perm=r -F auid>=1000 -F auid!=unset -F key=access-audit-trail + +## Software updates. This is entirely handled by rpm. + +## System start and shutdown. This is entirely handled by systemd + +## Kernel Module loading. This is handled in 43-module-load.rules + +## Application invocation. The requirements list an optional requirement +## FPT_SRP_EXT.1 Software Restriction Policies. This event is intended to +## state results from that policy. This would be handled entirely by +## that daemon. + diff --git a/tests/probes/textfilecontent54/CMakeLists.txt b/tests/probes/textfilecontent54/CMakeLists.txt index 87c6e215d..48bbde0e6 100644 --- a/tests/probes/textfilecontent54/CMakeLists.txt +++ b/tests/probes/textfilecontent54/CMakeLists.txt @@ -1,4 +1,5 @@ if(ENABLE_PROBES_INDEPENDENT) add_oscap_test("all.sh") add_oscap_test("test_filecontent_non_utf.sh") + add_oscap_test("test_recursion_limit.sh") endif() diff --git a/tests/probes/textfilecontent54/test_recursion_limit.oval.xml b/tests/probes/textfilecontent54/test_recursion_limit.oval.xml new file mode 100644 index 000000000..6f6a5ba14 --- /dev/null +++ b/tests/probes/textfilecontent54/test_recursion_limit.oval.xml @@ -0,0 +1,38 @@ + + + + 5.11.1 + 0001-01-01T00:00:00+00:00 + + + + + + The regular expression and the provided file should exceed recursion limits within pcre_exec used in the probe and cause a segfault. + x + + x + + + + + + + + + + + + + + + + + /tmp + 30-ospp-v42.rules + -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&0100 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-create(?:[^.]|\.\s)*-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&01003 -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-modification(?:[^.]|\.\s)*-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid>=1000 -F auid!=unset -F key=unsuccesful-access + 1 + + + + diff --git a/tests/probes/textfilecontent54/test_recursion_limit.sh b/tests/probes/textfilecontent54/test_recursion_limit.sh new file mode 100755 index 000000000..2619dafdd --- /dev/null +++ b/tests/probes/textfilecontent54/test_recursion_limit.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e -o pipefail + +. $builddir/tests/test_common.sh + +probecheck "textfilecontent54" || exit 255 + +cp $srcdir/30-ospp-v42.rules /tmp + +name=$(basename $0 .sh) +input=$srcdir/$name.oval.xml +result=$(mktemp) +stdout=$(mktemp) +stderr=$(mktemp) + +$OSCAP oval eval --results $result $input > $stdout 2> $stderr + +grep -q "Function pcre_exec() failed to match a regular expression with return code -21" $stderr + +assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:1" and @result="error"]' + +co='/oval_results/results/system/oval_system_characteristics/collected_objects' +assert_exists 1 $co'/object[@flag="error"]' +assert_exists 1 $co'/object/message[@level="error"]' +assert_exists 1 $co'/object/message[text()="Regular expression pattern match failed in file /tmp/30-ospp-v42.rules with error -21."]' + +rm -f /tmp/30-ospp-v42.rules +rm -f $result +rm -f $stdout +rm -f $stderr