Skip to content

Commit

Permalink
Merge pull request OpenSCAP#2015 from evgenyz/pcre2
Browse files Browse the repository at this point in the history
PCRE2
  • Loading branch information
jan-cerny authored Sep 5, 2023
2 parents ed91feb + f239fd8 commit 4704813
Show file tree
Hide file tree
Showing 35 changed files with 699 additions and 397 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ jobs:
- name: Install Deps
run: |
sudo apt-get update
sudo apt-get -y install lcov swig xsltproc rpm-common lua5.3 libyaml-dev libapt-pkg-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 libpcre2-dev libyaml-dev libapt-pkg-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 remove rpm
# Runs a set of commands using the runners shell
- name: Build
working-directory: ./build
run: |
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ../
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_PCRE2=True ../
make all
- name: Test
Expand All @@ -57,15 +57,15 @@ jobs:
image: fedora:latest
steps:
- name: Install Deps
run: dnf install -y cmake git dbus-devel GConf2-devel libacl-devel libblkid-devel libcap-devel libcurl-devel libgcrypt-devel libselinux-devel libxml2-devel libxslt-devel libattr-devel make openldap-devel pcre-devel perl-XML-Parser perl-XML-XPath perl-devel python3-devel python3-dbusmock rpm-devel swig bzip2-devel gcc-c++ libyaml-devel xmlsec1-devel xmlsec1-openssl-devel hostname bzip2 lua rpm-build which strace apt-devel
run: dnf install -y cmake git dbus-devel GConf2-devel libacl-devel libblkid-devel libcap-devel libcurl-devel libgcrypt-devel libselinux-devel libxml2-devel libxslt-devel libattr-devel make openldap-devel pcre2-devel perl-XML-Parser perl-XML-XPath perl-devel python3-devel python3-dbusmock rpm-devel swig bzip2-devel gcc-c++ libyaml-devel xmlsec1-devel xmlsec1-openssl-devel hostname bzip2 lua rpm-build which strace apt-devel
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build
working-directory: ./build
run: |
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ../
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_PCRE2=True ../
make all
- name: Test
working-directory: ./build
Expand Down Expand Up @@ -97,13 +97,13 @@ jobs:
brew install swig
brew install libxmlsec1
brew install openssl
brew install pcre
brew install pcre2
# Runs a set of commands using the runners shell
- name: Build
run: |
cd $GITHUB_WORKSPACE/build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_PROBES=false ../
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_PCRE2=True -DENABLE_PROBES=False ../
make all
- name: Test
Expand Down
17 changes: 16 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ find_package(Doxygen)
find_package(GConf)
find_package(Ldap)
find_package(OpenDbx)
find_package(PCRE REQUIRED)
if(WITH_PCRE2)
find_package(PCRE2 REQUIRED)
else()
find_package(PCRE REQUIRED)
endif()
find_package(PerlLibs)
find_package(Popt)
find_package(Systemd)
Expand Down Expand Up @@ -193,6 +197,13 @@ else()
set(YAML_FILTER_FOUND FALSE)
endif()

if(PCRE2_FOUND)
set(HAVE_PCRE2 1)
message("-- Using PCRE2")
elseif(PCRE_FOUND)
message("-- Using PCRE")
endif()

check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)
check_function_exists(memalign HAVE_MEMALIGN)
Expand Down Expand Up @@ -330,6 +341,8 @@ cmake_dependent_option(ENABLE_OSCAP_UTIL_CHROOT "enables the oscap-chroot utilit
option(ENABLE_OSCAP_UTIL_AUTOTAILOR "enables the autotailor utility that is able to perform command-line tailoring" TRUE)
option(ENABLE_OSCAP_REMEDIATE_SERVICE "enables the oscap-remediate service" FALSE)

option(WITH_PCRE2 "use PCRE2 library" FALSE)

# ---------- TEST-SUITE SWITCHES

# Tests will be turned off on Windows, because the test suite uses bash
Expand Down Expand Up @@ -517,6 +530,7 @@ 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")
add_link_options(-Wl,-z,now)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
add_link_options(-lkvm -lm -lprocstat)
Expand Down Expand Up @@ -563,6 +577,7 @@ include_directories(
${XMLSEC_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
${PCRE_INCLUDE_DIRS}
${PCRE2_INCLUDE_DIRS}
)

# Honor visibility properties for all target types
Expand Down
27 changes: 27 additions & 0 deletions cmake/FindPCRE2.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# - Find pcre
# Find the native PCRE2 headers and libraries.
#
# PCRE2_INCLUDE_DIRS - where to find pcre2.h, etc.
# PCRE2_LIBRARIES - List of libraries when using pcre.
# PCRE2_FOUND - True if pcre found.

# Look for the header file.
FIND_PATH(PCRE2_INCLUDE_DIR pcre2.h)

# Look for the library.
FIND_LIBRARY(PCRE2_LIBRARY NAMES libpcre2.a pcre2-8)

# Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE.
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR)

# Copy the results to the output variables.
IF(PCRE2_FOUND)
SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
ELSE(PCRE2_FOUND)
SET(PCRE_LIBRARIES)
SET(PCRE_INCLUDE_DIRS)
ENDIF(PCRE2_FOUND)

MARK_AS_ADVANCED(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES)
2 changes: 2 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define OSCAP_DEFAULT_CPE_PATH "@OSCAP_DEFAULT_CPE_PATH@"
#define OSCAP_TEMP_DIR "@OSCAP_TEMP_DIR@"

#cmakedefine HAVE_PCRE2

#cmakedefine HAVE_ATOMIC_BUILTINS

#cmakedefine HAVE_ACL_EXTENDED_FILE
Expand Down
8 changes: 7 additions & 1 deletion docs/developer/developer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ libxml-xpath-perl libperl-dev libbz2-dev librpm-dev g++ libapt-pkg-dev libyaml-d
libxmlsec1-dev libxmlsec1-openssl
----

Since version 1.3.9 OpenSCAP can use either PCRE or PCRE2 library to handle regular
expressions. The default behaviour for 1.3.x line of versions is to try and link
with PCRE. In order to switxh the build system to PCRE2 one must configure
CMake with '-DWITH_PCRE2=True' parameter. Dependencies: Debian/Ubuntu — pcre2-dev,
Fedora/RHEL — pcre2-devel.

When you have all the build dependencies installed you can build the library.
--

Expand Down Expand Up @@ -319,7 +325,7 @@ 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.
for match in pcre_exec/pcre2_match calls in textfilecontent(54) probes.



Expand Down
2 changes: 1 addition & 1 deletion docs/manual/manual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1613,7 +1613,7 @@ not considered local by the scanner:
* `OSCAP_EVALUATION_TARGET` - Change value of target facts `urn:xccdf:fact:identifier` and `urn:xccdf:fact:asset:identifier:ein` in XCCDF results. Used during offline scanning to pass the name of the target system.
* `OSCAP_FULL_VALIDATION` - If set, XML schema validation will be performed in every step of SCAP content processing.
* `OSCAP_OVAL_COMMAND_OPTIONS` - Additional command line options for `oscap oval` module. The value of this environment variable is appended to the actual command line options of `oscap` command.
* `OSCAP_PCRE_EXEC_RECURSION_LIMIT` - Set recursion limit of regular expression matching using `pcre_exec` function.
* `OSCAP_PCRE_EXEC_RECURSION_LIMIT` - Set recursion limit of regular expression matching using `pcre_exec`/`pcre2_match` functions.
* `OSCAP_PROBE_ROOT` - Path to a directory which contains mounted filesystem to be evaluated. Used for offline scanning.
* `SEXP_VALIDATE_DISABLE` - If set, `oscap` will not validate SEXP expressions during its execution.
* `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.
Expand Down
7 changes: 7 additions & 0 deletions openscap.spec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ BuildRequires: apt-devel
%endif
BuildRequires: rpm-devel
BuildRequires: libgcrypt-devel
%if 0%{?fedora}
BuildRequires: pcre2-devel
%else
BuildRequires: pcre-devel
%endif
BuildRequires: libacl-devel
BuildRequires: libselinux-devel
BuildRequires: libcap-devel
Expand Down Expand Up @@ -136,6 +140,9 @@ Tool for scanning Atomic containers.
# gconf is a legacy system not used any more, and it blocks testing of oscap-anaconda-addon
# as gconf is no longer part of the installation medium
%cmake \
%if 0%{?fedora}
-DWITH_PCRE2=ON \
%endif
-DENABLE_PERL=OFF \
-DENABLE_DOCS=ON \
-DOPENSCAP_PROBE_UNIX_GCONF=OFF \
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ set_target_properties(openscap PROPERTIES
C_VISIBILITY_PRESET hidden
)

target_link_libraries(openscap ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${XMLSEC_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBXSLT_EXSLT_LIBRARIES} ${PCRE_LIBRARIES} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(openscap ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${XMLSEC_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBXSLT_EXSLT_LIBRARIES} ${PCRE_LIBRARIES} ${PCRE2_LIBRARIES} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if (BZIP2_FOUND)
target_link_libraries(openscap ${BZIP2_LIBRARIES})
endif()
Expand Down
36 changes: 24 additions & 12 deletions src/CPE/cpename.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <string.h>
#include <stdio.h>
#include <pcre.h>
#include <ctype.h>

#include "cpe_name.h"
#include "common/util.h"
#include "common/oscap_pcre.h"
#include "oscap_helpers.h"

#define CPE_URI_SUPPORTED "2.3"
Expand Down Expand Up @@ -549,8 +549,8 @@ cpe_format_t cpe_name_get_format_of_str(const char *str)
if (str == NULL)
return CPE_FORMAT_UNKNOWN;

pcre *re;
const char *error;
oscap_pcre_t *re;
char *error;
int erroffset;
int rc;
int ovector[30];
Expand All @@ -559,26 +559,38 @@ cpe_format_t cpe_name_get_format_of_str(const char *str)
// http://scap.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd
// [c] was replaced with [cC] here and in the schemas

re = pcre_compile("^[cC][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6}$", 0, &error, &erroffset, NULL);
rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, ovector, 30);
pcre_free(re);
re = oscap_pcre_compile("^[cC][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6}$", 0, &error, &erroffset);
if (re == NULL) {
oscap_pcre_err_free(error);
return CPE_FORMAT_UNKNOWN;
}
rc = oscap_pcre_exec(re, str, strlen(str), 0, 0, ovector, 30);
oscap_pcre_free(re);

if (rc >= 0)
return CPE_FORMAT_URI;

// The regex was taken from the official XSD at
// http://scap.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd
re = pcre_compile("^cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){4}$", 0, &error, &erroffset, NULL);
rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, ovector, 30);
pcre_free(re);
re = oscap_pcre_compile("^cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){4}$", 0, &error, &erroffset);
if (re == NULL) {
oscap_pcre_err_free(error);
return CPE_FORMAT_UNKNOWN;
}
rc = oscap_pcre_exec(re, str, strlen(str), 0, 0, ovector, 30);
oscap_pcre_free(re);

if (rc >= 0)
return CPE_FORMAT_STRING;

// FIXME: This should be way more strict
re = pcre_compile("^wfn:\\[.+\\]$", PCRE_CASELESS, &error, &erroffset, NULL);
rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, ovector, 30);
pcre_free(re);
re = oscap_pcre_compile("^wfn:\\[.+\\]$", OSCAP_PCRE_OPTS_CASELESS, &error, &erroffset);
if (re == NULL) {
oscap_pcre_err_free(error);
return CPE_FORMAT_UNKNOWN;
}
rc = oscap_pcre_exec(re, str, strlen(str), 0, 0, ovector, 30);
oscap_pcre_free(re);

if (rc >= 0)
return CPE_FORMAT_WFN;
Expand Down
31 changes: 18 additions & 13 deletions src/OVAL/oval_component.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
#include "common/debug_priv.h"
#include "common/_error.h"
#include "common/oscap_string.h"
#include "common/oscap_pcre.h"
#include "oval_glob_to_regex.h"
#include <pcre.h>

#if !defined(OVAL_PROBES_ENABLED)
const char *oval_subtype_to_str(oval_subtype_t subtype);
Expand Down Expand Up @@ -1980,12 +1980,16 @@ static long unsigned int _parse_fmt_sse(char *dt)
static bool _match(const char *pattern, const char *string)
{
bool match = false;
pcre *re;
const char *error;
oscap_pcre_t *re;
char *error;
int erroffset = -1, ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]);
re = pcre_compile(pattern, PCRE_UTF8, &error, &erroffset, NULL);
match = (pcre_exec(re, NULL, string, strlen(string), 0, 0, ovector, ovector_len) >= 0);
pcre_free(re);
re = oscap_pcre_compile(pattern, OSCAP_PCRE_OPTS_UTF8, &error, &erroffset);
if (re == NULL) {
oscap_pcre_err_free(error);
return false;
}
match = (oscap_pcre_exec(re, string, strlen(string), 0, 0, ovector, ovector_len) >= 0);
oscap_pcre_free(re);
return match;
}

Expand Down Expand Up @@ -2208,13 +2212,14 @@ static oval_syschar_collection_flag_t _oval_component_evaluate_REGEX_CAPTURE(ova
int rc;
char *pattern;
int erroffset = -1;
pcre *re = NULL;
const char *error;
oscap_pcre_t *re = NULL;
char *error;

pattern = oval_component_get_regex_pattern(component);
re = pcre_compile(pattern, PCRE_UTF8, &error, &erroffset, NULL);
re = oscap_pcre_compile(pattern, OSCAP_PCRE_OPTS_UTF8, &error, &erroffset);
if (re == NULL) {
dE("pcre_compile() failed: \"%s\".", error);
dE("oscap_pcre_compile() failed: \"%s\".", error);
oscap_pcre_err_free(error);
return SYSCHAR_FLAG_ERROR;
}

Expand All @@ -2233,9 +2238,9 @@ static oval_syschar_collection_flag_t _oval_component_evaluate_REGEX_CAPTURE(ova
for (i = 0; i < ovector_len; ++i)
ovector[i] = -1;

rc = pcre_exec(re, NULL, text, strlen(text), 0, 0, ovector, ovector_len);
rc = oscap_pcre_exec(re, text, strlen(text), 0, 0, ovector, ovector_len);
if (rc < -1) {
dE("pcre_exec() failed: %d.", rc);
dE("oscap_pcre_exec() failed: %d.", rc);
flag = SYSCHAR_FLAG_ERROR;
break;
}
Expand Down Expand Up @@ -2263,7 +2268,7 @@ static oval_syschar_collection_flag_t _oval_component_evaluate_REGEX_CAPTURE(ova
oval_collection_free_items(subcoll, (oscap_destruct_func) oval_value_free);
}
oval_component_iterator_free(subcomps);
pcre_free(re);
oscap_pcre_free(re);
return flag;
}

Expand Down
14 changes: 7 additions & 7 deletions src/OVAL/oval_schema_version.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@
#include <string.h>
#include <sys/types.h>
#include "common/util.h"
#include "common/oscap_pcre.h"
#include "common/debug_priv.h"
#include "public/oval_schema_version.h"

#include <pcre.h>

#define OVECTOR_LEN 30 // must be a multiple of 30
#define OVECTOR_LEN 60 // must be a multiple of 30

static int _parse_int(const char *substring, size_t substring_length)
{
Expand All @@ -55,16 +54,17 @@ oval_schema_version_t oval_schema_version_from_cstr(const char *ver_str)
return version;
}
const char *pattern = "([0-9]+)\\.([0-9]+)(?:\\.([0-9]+))?(?::([0-9]+)\\.([0-9]+)(?:\\.([0-9]+))?)?";
const char *error;
char *error;
int erroffset;
pcre *re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
oscap_pcre_t *re = oscap_pcre_compile(pattern, 0, &error, &erroffset);
if (re == NULL) {
dE("Regular expression compilation failed with %s", pattern);
oscap_pcre_err_free(error);
return version;
}
int ovector[OVECTOR_LEN];
int rc = pcre_exec(re, NULL, ver_str, strlen(ver_str), 0, 0, ovector, OVECTOR_LEN);
pcre_free(re);
int rc = oscap_pcre_exec(re, ver_str, strlen(ver_str), 0, 0, ovector, OVECTOR_LEN);
oscap_pcre_free(re);
if (rc < 0) {
dE("Regular expression %s did not match string %s", pattern, ver_str);
return version;
Expand Down
Loading

0 comments on commit 4704813

Please sign in to comment.