diff --git a/SOURCES/openscap-1.2.18-oscap-ssh-sudo.patch b/SOURCES/openscap-1.2.18-oscap-ssh-sudo.patch
new file mode 100644
index 0000000..064bbdb
--- /dev/null
+++ b/SOURCES/openscap-1.2.18-oscap-ssh-sudo.patch
@@ -0,0 +1,52 @@
+From f2d9ec9883a344daa67a80ad54e6652185346395 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
+Date: Fri, 14 Feb 2020 14:57:33 +0100
+Subject: [PATCH] Fixed oscap-ssh failing to retrieve the result files when
+ executing with --sudo
+
+Depending on the umask configuration of the target system, "sudo oscap"
+may create the result files in temporary directory with 600 permissions,
+which makes retrieving the log (as the regular user that ssh'ed to the
+system) impossible:
+
+~~~
+$ oscap-ssh --sudo user@system 22 xccdf eval ...
+[...]
+oscap exit code: 0
+Copying back requested files...
+scp: /tmp/tmp.0kfbPWEy6u/report.html: Permission denied
+Failed to copy the HTML report back to local machine!
+~~~
+
+Scenario to reproduce the failure: set a default umask in /etc/sudoers:
+
+~~~
+Defaults	umask = 0077
+~~~
+
+The fix consists in changing the result files' ownership from "root" to
+user's back, all while in the single sudo (using two sudo commands
+wouldn't be nice since the user may get the password prompt twice,
+depending on the sudo's configuration).
+---
+ utils/oscap-ssh | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/utils/oscap-ssh b/utils/oscap-ssh
+index 658cc2ee4..bd2e209c4 100755
+--- a/utils/oscap-ssh
++++ b/utils/oscap-ssh
+@@ -280,7 +280,12 @@ echo "Starting the evaluation..."
+ # changing directory because of --oval-results support. oval results files are
+ # dumped into PWD, and we can't be sure by the file names - we need controlled
+ # environment
+-ssh_execute_with_command_and_options "cd $REMOTE_TEMP_DIR; $OSCAP_SUDO oscap $(command_array_to_string oscap_args)" "$SSH_TTY_ALLOCATION_OPTION"
++if [ -z "$OSCAP_SUDO" ]; then
++    ssh_execute_with_command_and_options "cd $REMOTE_TEMP_DIR; oscap $(command_array_to_string oscap_args)" "$SSH_TTY_ALLOCATION_OPTION"
++else
++    OSCAP_CMD="oscap $(command_array_to_string oscap_args); rc=\$?; chown \$SUDO_USER $REMOTE_TEMP_DIR/*; exit \$rc"
++    ssh_execute_with_command_and_options "cd $REMOTE_TEMP_DIR; $OSCAP_SUDO sh -c '$OSCAP_CMD'" "$SSH_TTY_ALLOCATION_OPTION"
++fi
+ OSCAP_EXIT_CODE=$?
+ echo "oscap exit code: $OSCAP_EXIT_CODE"
+ 
diff --git a/SOURCES/openscap-1.3.3-ansible-newlines.patch b/SOURCES/openscap-1.3.3-ansible-newlines.patch
new file mode 100644
index 0000000..7e6b509
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-ansible-newlines.patch
@@ -0,0 +1,156 @@
+diff --git a/src/XCCDF_POLICY/xccdf_policy_remediate.c b/src/XCCDF_POLICY/xccdf_policy_remediate.c
+index f59737727..19bb59f2e 100644
+--- a/src/XCCDF_POLICY/xccdf_policy_remediate.c
++++ b/src/XCCDF_POLICY/xccdf_policy_remediate.c
+@@ -139,11 +139,10 @@ static int _write_remediation_to_fd_and_free(int output_fd, const char* template
+ 					free(text);
+ 					return 1;
+ 				}
+-
+-				if (_write_text_to_fd(output_fd, "\n") != 0) {
+-					free(text);
+-					return 1;
+-				}
++			}
++			if (_write_text_to_fd(output_fd, "\n") != 0) {
++				free(text);
++				return 1;
+ 			}
+ 
+ 			if (next_delim != NULL) {
+diff --git a/tests/API/XCCDF/unittests/CMakeLists.txt b/tests/API/XCCDF/unittests/CMakeLists.txt
+index 2a56d3cdc..05ddea219 100644
+--- a/tests/API/XCCDF/unittests/CMakeLists.txt
++++ b/tests/API/XCCDF/unittests/CMakeLists.txt
+@@ -18,6 +18,7 @@ if(PYTHONINTERP_FOUND)
+ 	add_oscap_test("all_python.sh")
+ endif()
+ 
++add_oscap_test("test_ansible_yaml_block_scalar.sh")
+ add_oscap_test("test_xccdf_shall_pass1.sh")
+ add_oscap_test("test_xccdf_shall_pass2.sh")
+ add_oscap_test("test_xccdf_shall_pass3.sh")
+diff --git a/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.playbook.yml b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.playbook.yml
+new file mode 100644
+index 000000000..dd0276739
+--- /dev/null
++++ b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.playbook.yml
+@@ -0,0 +1,37 @@
++---
++
++
++- hosts: all
++  vars:
++  tasks:
++    - name: Make sure contents of /etc/audit/rules.d/10-base-config.rules are as expected
++      copy:
++        dest: /etc/audit/rules.d/10-base-config.rules
++        content: |+
++          ## First rule - delete all
++          -D
++
++          ## Increase the buffers to survive stress events.
++          ## Make this bigger for busy systems
++          -b 8192
++
++          ## This determine how long to wait in burst of events
++          --backlog_wait_time 60000
++
++          ## Set failure mode to syslog
++          -f 1
++
++
++        force: true
++      when: ansible_virtualization_role != "guest" or ansible_virtualization_type != "docker"
++      tags:
++        - audit_basic_configuration
++        - medium_severity
++        - restrict_strategy
++        - low_complexity
++        - low_disruption
++        - no_reboot_needed
++        - CCE-82462-3
++        - NIST-800-53-AU-2(a)
++
++
+diff --git a/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.sh b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.sh
+new file mode 100755
+index 000000000..4ca5b3be5
+--- /dev/null
++++ b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.sh
+@@ -0,0 +1,21 @@
++#!/bin/bash
++. $builddir/tests/test_common.sh
++
++set -e
++set -o pipefail
++
++profile="xccdf_moc.elpmaxe.www_profile_standard"
++
++name=$(basename $0 .sh)
++stderr=$(mktemp -t ${name}.err.XXXXXX)
++playbook=$(mktemp -t ${name}.yml.XXXXXX)
++playbook_without_header=$(mktemp -t ${name}.yml.XXXXXX)
++
++# Generate an Ansible playbook from a profile in SDS file
++$OSCAP xccdf generate fix --profile $profile --fix-type ansible "$srcdir/$name.xccdf.xml"  >$playbook 2>$stderr
++sed '/^#/d' $playbook > $playbook_without_header
++diff -u $playbook_without_header $srcdir/$name.playbook.yml
++[ -f $stderr ]; [ ! -s $stderr ]; rm $stderr
++
++rm $playbook
++rm $playbook_without_header
+diff --git a/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.xccdf.xml b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.xccdf.xml
+new file mode 100644
+index 000000000..81b2adfd4
+--- /dev/null
++++ b/tests/API/XCCDF/unittests/test_ansible_yaml_block_scalar.xccdf.xml
+@@ -0,0 +1,48 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<Benchmark xmlns="http://checklists.nist.gov/xccdf/1.2" id="xccdf_moc.elpmaxe.www_benchmark_test">
++  <status>incomplete</status>
++  <title>Security Benchmark</title>
++  <description xml:lang="en-US">A sample benchmark</description>
++  <version>1.0</version>
++  <Profile id="xccdf_moc.elpmaxe.www_profile_standard">
++    <title xml:lang="en-US">Standard System Security Profile</title>
++    <description xml:lang="en-US">This profile contains rules to ensure standard security baseline of your system.</description>
++    <select idref="xccdf_moc.elpmaxe.www_rule_1" selected="true"/>
++  </Profile>
++  <Rule selected="false" id="xccdf_moc.elpmaxe.www_rule_1">
++    <title>Passing rule</title>
++    <fix id="ansible_fix_for_passing_rule" system="urn:xccdf:fix:script:ansible">- name: Make sure contents of /etc/audit/rules.d/10-base-config.rules are as expected
++  copy:
++    dest: /etc/audit/rules.d/10-base-config.rules
++    content: |+
++      ## First rule - delete all
++      -D
++
++      ## Increase the buffers to survive stress events.
++      ## Make this bigger for busy systems
++      -b 8192
++
++      ## This determine how long to wait in burst of events
++      --backlog_wait_time 60000
++
++      ## Set failure mode to syslog
++      -f 1
++
++
++    force: true
++  when: ansible_virtualization_role != "guest" or ansible_virtualization_type != "docker"
++  tags:
++    - audit_basic_configuration
++    - medium_severity
++    - restrict_strategy
++    - low_complexity
++    - low_disruption
++    - no_reboot_needed
++    - CCE-82462-3
++    - NIST-800-53-AU-2(a)
++</fix>
++    <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
++        <check-content-ref href="oval/pass/oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
++    </check>
++  </Rule>
++</Benchmark>
diff --git a/SOURCES/openscap-1.3.3-generate-guide-tailoring.patch b/SOURCES/openscap-1.3.3-generate-guide-tailoring.patch
new file mode 100644
index 0000000..6c234cd
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-generate-guide-tailoring.patch
@@ -0,0 +1,249 @@
+diff --git a/src/XCCDF/benchmark.c b/src/XCCDF/benchmark.c
+index f561736d4..d6560b7c9 100644
+--- a/src/XCCDF/benchmark.c
++++ b/src/XCCDF/benchmark.c
+@@ -866,6 +866,19 @@ xccdf_benchmark_find_target_htable(const struct xccdf_benchmark *benchmark, xccd
+ 	return XITEM(benchmark)->sub.benchmark.items_dict;
+ }
+ 
++int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark)
++{
++	struct oscap_list *profiles = XITEM(benchmark)->sub.benchmark.profiles;
++	struct oscap_htable_iterator *it = oscap_htable_iterator_new(XITEM(benchmark)->sub.benchmark.profiles_dict);
++	while(oscap_htable_iterator_has_more(it)) {
++		struct xccdf_profile *profile = oscap_htable_iterator_next_value(it);
++		if (xccdf_profile_get_tailoring(profile)) {
++			oscap_list_add(profiles, xccdf_profile_clone(profile));
++		}
++	}
++	oscap_htable_iterator_free(it);
++	return 0;
++}
+ 
+ struct xccdf_plain_text *xccdf_plain_text_new(void)
+ {
+diff --git a/src/XCCDF/item.h b/src/XCCDF/item.h
+index 35204744f..da76f854d 100644
+--- a/src/XCCDF/item.h
++++ b/src/XCCDF/item.h
+@@ -437,6 +437,7 @@ void xccdf_item_dump(struct xccdf_item *item, int depth);
+ struct xccdf_item* xccdf_item_get_benchmark_internal(struct xccdf_item* item);
+ bool xccdf_benchmark_parse(struct xccdf_item *benchmark, xmlTextReaderPtr reader);
+ void xccdf_benchmark_dump(struct xccdf_benchmark *benchmark);
++int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark);
+ struct oscap_htable_iterator *xccdf_benchmark_get_cluster_items(struct xccdf_benchmark *benchmark, const char *cluster_id);
+ bool xccdf_benchmark_register_item(struct xccdf_benchmark *benchmark, struct xccdf_item *item);
+ bool xccdf_benchmark_unregister_item(struct xccdf_item *item);
+diff --git a/src/XCCDF/public/xccdf_session.h b/src/XCCDF/public/xccdf_session.h
+index ac96e2036..026432693 100644
+--- a/src/XCCDF/public/xccdf_session.h
++++ b/src/XCCDF/public/xccdf_session.h
+@@ -558,6 +558,14 @@ OSCAP_API int xccdf_session_build_policy_from_testresult(struct xccdf_session *s
+  */
+ OSCAP_API int xccdf_session_add_report_from_source(struct xccdf_session *session, struct oscap_source *report_source);
+ 
++/**
++ * Generate HTML guide form a loaded XCCDF session
++ * @param session XCCDF Session
++ * @param outfile path to the output file
++ * @returns zero on success
++ */
++OSCAP_API int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile);
++
+ /// @}
+ /// @}
+ #endif
+diff --git a/src/XCCDF/xccdf_session.c b/src/XCCDF/xccdf_session.c
+index 1005a030a..d38905f77 100644
+--- a/src/XCCDF/xccdf_session.c
++++ b/src/XCCDF/xccdf_session.c
+@@ -1746,3 +1746,44 @@ int xccdf_session_add_report_from_source(struct xccdf_session *session, struct o
+ 	session->xccdf.result = result;
+ 	return 0;
+ }
++
++int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile)
++{
++	struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
++	if (policy == NULL) {
++		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy.");
++		return 1;
++	}
++	struct xccdf_policy_model *model = xccdf_policy_get_model(policy);
++	if (model == NULL) {
++		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy model.");
++		return 1;
++	}
++	struct xccdf_benchmark *benchmark = xccdf_policy_model_get_benchmark(model);
++	if (benchmark == NULL) {
++		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF benchmark.");
++		return 1;
++	}
++	xccdf_benchmark_include_tailored_profiles(benchmark);
++	const char *params[] = {
++		"oscap-version",     oscap_get_version(),
++		"benchmark_id",      xccdf_benchmark_get_id(benchmark),
++		"profile_id",        xccdf_session_get_profile_id(session),
++		NULL
++	};
++	struct oscap_source *benchmark_source = xccdf_benchmark_export_source(benchmark, NULL);
++	if (benchmark_source == NULL) {
++		oscap_seterr(OSCAP_EFAMILY_OSCAP,
++			"Failed to export source from XCCDF benchmark %s.",
++			xccdf_benchmark_get_id(benchmark));
++		return 1;
++	}
++	int ret = oscap_source_apply_xslt_path(benchmark_source,
++		"xccdf-guide.xsl", outfile, params, oscap_path_to_xslt());
++	oscap_source_free(benchmark_source);
++	if (ret < 0) {
++		oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not apply XSLT.");
++		return 1;
++	}
++	return 0;
++}
+\ No newline at end of file
+diff --git a/tests/API/XCCDF/tailoring/all.sh b/tests/API/XCCDF/tailoring/all.sh
+index dbed97a87..fc2ccd743 100755
+--- a/tests/API/XCCDF/tailoring/all.sh
++++ b/tests/API/XCCDF/tailoring/all.sh
+@@ -134,6 +134,21 @@ function test_api_xccdf_tailoring_profile_generate_fix {
+     rm -f $tailoring_result $fix_result
+ }
+ 
++function test_api_xccdf_tailoring_profile_generate_guide {
++    local INPUT=$srcdir/$1
++    local TAILORING=$srcdir/$2
++
++    guide=`mktemp`
++    # tailoring profile only with "always fail" rule and generate HTML guide
++    $OSCAP xccdf generate guide --tailoring-file $TAILORING --profile "xccdf_com.example.www_profile_customized" --output $guide $INPUT
++
++    grep -q "Baseline Testing Profile 1 \[CUSTOMIZED\]" $guide
++    # profile 'customized' selects first rule and deselects the second
++    grep -q "xccdf_com.example.www_rule_first" $guide
++    grep -v "xccdf_com.example.www_rule_second" $guide
++    rm -f $guide
++}
++
+ # Testing.
+ 
+ test_init "test_api_xccdf_tailoring.log"
+@@ -154,6 +169,7 @@ test_run "test_api_xccdf_tailoring_autonegotiation" test_api_xccdf_tailoring_aut
+ test_run "test_api_xccdf_tailoring_simple_include_in_arf" test_api_xccdf_tailoring_simple_include_in_arf simple-xccdf.xml simple-tailoring.xml
+ test_run "test_api_xccdf_tailoring_profile_include_in_arf" test_api_xccdf_tailoring_profile_include_in_arf baseline.xccdf.xml baseline.tailoring.xml
+ test_run "test_api_xccdf_tailoring_profile_generate_fix" test_api_xccdf_tailoring_profile_generate_fix baseline.xccdf.xml baseline.tailoring.xml
++test_run "test_api_xccdf_tailoring_profile_generate_guide" test_api_xccdf_tailoring_profile_generate_guide baseline.xccdf.xml baseline.tailoring.xml
+ 
+ 
+ test_exit
+diff --git a/utils/oscap-xccdf.c b/utils/oscap-xccdf.c
+index 472a2cc6f..87a0c7ad1 100644
+--- a/utils/oscap-xccdf.c
++++ b/utils/oscap-xccdf.c
+@@ -77,6 +77,7 @@ static bool getopt_xccdf(int argc, char **argv, struct oscap_action *action);
+ static bool getopt_generate(int argc, char **argv, struct oscap_action *action);
+ static int app_xccdf_xslt(const struct oscap_action *action);
+ static int app_generate_fix(const struct oscap_action *action);
++static int app_generate_guide(const struct oscap_action *action);
+ 
+ #define XCCDF_SUBMODULES_NUM		7
+ #define XCCDF_GEN_SUBMODULES_NUM	5 /* See actual arrays
+@@ -244,12 +245,18 @@ static struct oscap_module XCCDF_GEN_GUIDE = {
+     .help = GEN_OPTS
+ 		"\nGuide Options:\n"
+ 		"   --output <file>               - Write the document into file.\n"
+-		"   --hide-profile-info           - Do not output additional information about selected profile.\n"
++		"   --hide-profile-info           - This option has no effect.\n"
+ 		"   --benchmark-id <id>           - ID of XCCDF Benchmark in some component in the datastream that should be used.\n"
++		"                                   (only applicable for source datastreams)\n"
++		"   --xccdf-id <id>               - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
++		"                                   (only applicable for source datastreams)\n"
++		"   --tailoring-file <file>       - Use given XCCDF Tailoring file.\n"
++		"                                   (only applicable for source datastreams)\n"
++		"   --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
+ 		"                                   (only applicable for source datastreams)\n",
+     .opt_parser = getopt_xccdf,
+-    .user = "xccdf-guide.xsl",
+-    .func = app_xccdf_xslt
++    .user = NULL,
++    .func = app_generate_guide
+ };
+ 
+ static struct oscap_module XCCDF_GEN_FIX = {
+@@ -973,6 +980,50 @@ int app_generate_fix(const struct oscap_action *action)
+ 	return ret;
+ }
+ 
++int app_generate_guide(const struct oscap_action *action)
++{
++	int ret = OSCAP_ERROR;
++
++	struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
++	struct xccdf_session *session = xccdf_session_new_from_source(source);
++	if (session == NULL) {
++		goto cleanup;
++	}
++
++	xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
++	xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
++	xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
++	xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
++	if (xccdf_session_is_sds(session)) {
++		xccdf_session_set_component_id(session, action->f_xccdf_id);
++		xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
++	}
++	xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
++
++	if (xccdf_session_load(session) != 0) {
++		goto cleanup;
++	}
++
++	if (!xccdf_session_set_profile_id(session, action->profile)) {
++		if (action->profile != NULL) {
++			if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
++				goto cleanup;
++		} else {
++			fprintf(stderr, "No Policy was found for default profile.\n");
++			goto cleanup;
++		}
++	}
++
++	if (xccdf_session_generate_guide(session, action->f_results) == 0) {
++		ret = OSCAP_OK;
++	}
++
++cleanup:
++	xccdf_session_free(session);
++	oscap_print_error();
++	return ret;
++}
++
+ int app_xccdf_xslt(const struct oscap_action *action)
+ {
+ 	const char *oval_template = action->oval_template;
+diff --git a/utils/oscap.8 b/utils/oscap.8
+index 1b05f8c9e..3a50d1df5 100644
+--- a/utils/oscap.8
++++ b/utils/oscap.8
+@@ -331,10 +331,19 @@ Generate a HTML document containing a security guide from an XCCDF Benchmark. Un
+ Write the guide to this file instead of standard output.
+ .TP
+ \fB\-\-hide-profile-info\fR
+-Information on chosen profile (e.g. rules selected by the profile) will be excluded from the document.
++This option has no effect and is kept only for backward compatibility purposes.
+ .TP
+ \fB\-\-benchmark-id ID\fR
+ Selects a component ref from any datastream that references a component with XCCDF Benchmark such that its @id attribute matches given string exactly.
++.TP
++\fB\-\-xccdf-id ID\fR
++Takes component ref with given ID from checklists. This allows to select a particular XCCDF component even in cases where there are 2 XCCDFs in one datastream. If none is given, the first component from the checklists element is used.
++.TP
++\fB\-\-tailoring-file TAILORING_FILE\fR
++Use given file for XCCDF tailoring. Select profile from tailoring file to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
++.TP
++\fB\-\-tailoring-id COMPONENT_REF_ID\fR
++Use tailoring component in input source datastream for XCCDF tailoring. The tailoring component must be specified by its Ref-ID (value of component-ref/@id attribute in input source datastream). Select profile from tailoring component to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
+ .RE
+ .TP
+ .B \fBreport\fR  [\fIoptions\fR] xccdf-file
diff --git a/SOURCES/openscap-1.3.3-remove-useless-warnings-tests.patch b/SOURCES/openscap-1.3.3-remove-useless-warnings-tests.patch
new file mode 100644
index 0000000..97a9420
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-remove-useless-warnings-tests.patch
@@ -0,0 +1,44 @@
+From b2b00e2316439d6517c8b763f542db637ebcf0b0 Mon Sep 17 00:00:00 2001
+From: Matus Marhefka <mmarhefk@redhat.com>
+Date: Tue, 3 Mar 2020 14:12:39 +0100
+Subject: [PATCH] tests/probes/environmentvariable58: add test to cover
+ 7c78b84dd
+
+---
+ .../test_probes_environmentvariable58.sh               | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/tests/probes/environmentvariable58/test_probes_environmentvariable58.sh b/tests/probes/environmentvariable58/test_probes_environmentvariable58.sh
+index 786ea528a..7679c3495 100755
+--- a/tests/probes/environmentvariable58/test_probes_environmentvariable58.sh
++++ b/tests/probes/environmentvariable58/test_probes_environmentvariable58.sh
+@@ -24,13 +24,16 @@ function test_probes_environmentvariable58 {
+     local ret_val=0;
+     local DF="$1.xml"
+     local RF="$1.results.xml"
++    echo "result file: $RF"
++    local stderr=$(mktemp $1.err.XXXXXX)
++    echo "stderr file: $stderr"
+ 
+     [ -f $RF ] && rm -f $RF
+ 
+     bash ${srcdir}/$1.xml.sh > $DF
+     LINES=$?
+ 
+-    $OSCAP oval eval --results $RF $DF
++    $OSCAP oval eval --results $RF $DF 2> $stderr
+ 
+     if [ -f $RF ]; then
+ 	verify_results "def" $DF $RF 1 && verify_results "tst" $DF $RF $LINES
+@@ -39,6 +42,11 @@ function test_probes_environmentvariable58 {
+ 	ret_val=1
+     fi
+ 
++    # Test fails if there are any warnings or "Entity has no value" on stderr.
++    echo "Verify that there are no warnings on stderr"
++    grep -Ei "(W:|Entity has no value)" $stderr && ret_val=1
++
++    rm $stderr
+     return $ret_val
+ }
+ 
diff --git a/SOURCES/openscap-1.3.3-remove-useless-warnings.patch b/SOURCES/openscap-1.3.3-remove-useless-warnings.patch
new file mode 100644
index 0000000..a9fedfe
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-remove-useless-warnings.patch
@@ -0,0 +1,28 @@
+diff --git a/src/OVAL/probes/public/probe-api.h b/src/OVAL/probes/public/probe-api.h
+index 24cf756cb..c1178956f 100644
+--- a/src/OVAL/probes/public/probe-api.h
++++ b/src/OVAL/probes/public/probe-api.h
+@@ -488,11 +488,9 @@ OSCAP_API SEXP_t *probe_item_create(oval_subtype_t item_subtype, probe_elmatr_t
+ 		SEXP_t *___r;					\
+ 								\
+ 		if ((___r = probe_ent_getval(ent)) == NULL) {	\
+-			dW("Entity has no value!");		\
+ 			invalid_exp				\
+ 		} else {					\
+ 			if (!SEXP_stringp(___r)) {		\
+-				dE("Invalid type");		\
+ 				SEXP_free(___r);		\
+ 				invalid_exp			\
+ 			}					\
+@@ -511,11 +509,9 @@ OSCAP_API SEXP_t *probe_item_create(oval_subtype_t item_subtype, probe_elmatr_t
+ 		SEXP_t *___r;					\
+ 								\
+ 		if ((___r = probe_ent_getval(ent)) == NULL) {	\
+-			dW("Entity has no value!");		\
+ 			nil_exp;				\
+ 		} else {					\
+ 			if (!SEXP_numberp(___r)) {		\
+-				dE("Invalid type");		\
+ 				SEXP_free(___r);		\
+ 				invalid_exp;			\
+ 			} else {				\
diff --git a/SOURCES/openscap-1.3.3-rpmverifyfile-tests.patch b/SOURCES/openscap-1.3.3-rpmverifyfile-tests.patch
new file mode 100644
index 0000000..b08183b
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-rpmverifyfile-tests.patch
@@ -0,0 +1,52 @@
+diff --git a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.sh b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.sh
+index cefde6b75..e913a56c4 100755
+--- a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.sh
++++ b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.sh
+@@ -41,7 +41,7 @@ function test_probes_rpmverifyfile {
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:release'
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:arch'
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath'
+-    assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath[text()="/etc/os-release"]'
++    assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath[text()="/usr/bin/true"]'
+     sc='oval_results/results/system/oval_system_characteristics/'
+     sd=$sc'system_data/'
+     assert_exists 1 $sc'collected_objects/object'
+diff --git a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.xml b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.xml
+index ecdecc75c..e3faa2631 100644
+--- a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.xml
++++ b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile.xml
+@@ -30,7 +30,7 @@
+         <lin-def:version operation="pattern match"/>
+         <lin-def:release operation="pattern match"/>
+         <lin-def:arch operation="pattern match"/>
+-        <lin-def:filepath>/etc/os-release</lin-def:filepath>
++        <lin-def:filepath>/usr/bin/true</lin-def:filepath>
+     </lin-def:rpmverifyfile_object>
+   </objects>
+ 
+diff --git a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.sh b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.sh
+index 3cb63eebe..da74e4671 100755
+--- a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.sh
++++ b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.sh
+@@ -40,7 +40,7 @@ function test_probes_rpmverifyfile {
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:release'
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:arch'
+     assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath'
+-    assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath[text()="/etc/os-release"]'
++    assert_exists 1 'oval_results/oval_definitions/objects/lin-def:rpmverifyfile_object/lin-def:filepath[text()="/usr/bin/true"]'
+     sc='oval_results/results/system/oval_system_characteristics/'
+     sd=$sc'system_data/'
+     assert_exists 1 $sc'collected_objects/object'
+diff --git a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.xml b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.xml
+index 73f9e76a3..420485146 100644
+--- a/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.xml
++++ b/tests/probes/rpm/rpmverifyfile/test_probes_rpmverifyfile_older.xml
+@@ -30,7 +30,7 @@
+         <lin-def:version operation="pattern match"/>
+         <lin-def:release operation="pattern match"/>
+         <lin-def:arch operation="pattern match"/>
+-        <lin-def:filepath>/etc/os-release</lin-def:filepath>
++        <lin-def:filepath>/usr/bin/true</lin-def:filepath>
+     </lin-def:rpmverifyfile_object>
+   </objects>
+ 
diff --git a/SOURCES/openscap-1.3.3-systemdunit-segfault.patch b/SOURCES/openscap-1.3.3-systemdunit-segfault.patch
new file mode 100644
index 0000000..4cd36b2
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-systemdunit-segfault.patch
@@ -0,0 +1,134 @@
+diff --git a/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c b/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
+index 2f194ce07..e2cbdb7d2 100644
+--- a/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
++++ b/src/OVAL/probes/unix/linux/systemdunitdependency_probe.c
+@@ -37,6 +37,8 @@
+ #include <string.h>
+ #include "systemdunitdependency_probe.h"
+ 
++static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units);
++
+ static char *get_property_by_unit_path(DBusConnection *conn, const char *unit_path, const char *property)
+ {
+ 	DBusMessage *msg = NULL;
+@@ -135,7 +137,38 @@ static bool is_unit_name_a_target(const char *unit)
+ 	return strncmp(unit + len - suffix_len, suffix, suffix_len) == 0;
+ }
+ 
+-static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, int(*callback)(const char *, void *), void *cbarg, bool include_requires, bool include_wants)
++static int add_unit_dependency(const char *dependency, SEXP_t *item, struct oscap_htable *visited_units)
++{
++	if (oscap_htable_get(visited_units, dependency) != NULL) {
++		return 1;
++	}
++	oscap_htable_add(visited_units, dependency, (void *) true);
++	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
++	probe_item_ent_add(item, "dependency", NULL, se_dependency);
++	SEXP_free(se_dependency);
++	return 0;
++}
++
++static void process_unit_property(const char *property, DBusConnection *conn, const char *path, SEXP_t *item, struct oscap_htable *visited_units)
++{
++	char *values_s = get_property_by_unit_path(conn, path, property);
++	if (values_s) {
++		char **values = oscap_split(values_s, ", ");
++		for (int i = 0; values[i] != NULL; ++i) {
++			if (oscap_strcmp(values[i], "") == 0) {
++				continue;
++			}
++
++			if (add_unit_dependency(values[i], item, visited_units) == 0) {
++				get_all_dependencies_by_unit(conn, values[i], item, visited_units);
++			}
++		}
++		free(values);
++	}
++	free(values_s);
++}
++
++static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units)
+ {
+ 	if (!unit || strcmp(unit, "(null)") == 0)
+ 		return;
+@@ -146,66 +179,12 @@ static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit,
+ 
+ 	char *path = get_path_by_unit(conn, unit);
+ 
+-	if (include_requires) {
+-		char *requires_s = get_property_by_unit_path(conn, path, "Requires");
+-		if (requires_s) {
+-			char **requires = oscap_split(requires_s, ", ");
+-			for (int i = 0; requires[i] != NULL; ++i) {
+-				if (oscap_strcmp(requires[i], "") == 0)
+-					continue;
+-
+-				if (callback(requires[i], cbarg) == 0) {
+-					get_all_dependencies_by_unit(conn, requires[i],
+-									callback, cbarg,
+-									include_requires, include_wants);
+-				} else {
+-					free(requires);
+-					free(requires_s);
+-					free(path);
+-					return;
+-				}
+-			}
+-			free(requires);
+-		}
+-		free(requires_s);
+-	}
+-
+-	if (include_wants) {
+-		char *wants_s = get_property_by_unit_path(conn, path, "Wants");
+-		if (wants_s)
+-		{
+-			char **wants = oscap_split(wants_s, ", ");
+-			for (int i = 0; wants[i] != NULL; ++i) {
+-				if (oscap_strcmp(wants[i], "") == 0)
+-					continue;
+-
+-				if (callback(wants[i], cbarg) == 0) {
+-					get_all_dependencies_by_unit(conn, wants[i],
+-									callback, cbarg,
+-									include_requires, include_wants);
+-				} else {
+-					free(wants);
+-					free(wants_s);
+-					free(path);
+-					return;
+-				}
+-			}
+-			free(wants);
+-		}
+-		free(wants_s);
+-	}
++	process_unit_property("Requires", conn, path, item, visited_units);
++	process_unit_property("Wants", conn, path, item, visited_units);
+ 
+ 	free(path);
+ }
+ 
+-static int dependency_callback(const char *dependency, void *cbarg)
+-{
+-	SEXP_t *item = (SEXP_t *)cbarg;
+-	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
+-	probe_item_ent_add(item, "dependency", NULL, se_dependency);
+-	return 0;
+-}
+-
+ static int unit_callback(const char *unit, void *cbarg)
+ {
+ 	struct unit_callback_vars *vars = (struct unit_callback_vars *)cbarg;
+@@ -221,8 +200,9 @@ static int unit_callback(const char *unit, void *cbarg)
+ 					 "unit", OVAL_DATATYPE_SEXP, se_unit,
+ 					 NULL);
+ 
+-	get_all_dependencies_by_unit(vars->dbus_conn, unit,
+-				     dependency_callback, item, true, true);
++	struct oscap_htable *visited_units = oscap_htable_new();
++	get_all_dependencies_by_unit(vars->dbus_conn, unit, item, visited_units);
++	oscap_htable_free(visited_units, NULL);
+ 
+ 	probe_item_collect(vars->ctx, item);
+ 	SEXP_free(se_unit);
diff --git a/SOURCES/openscap-1.3.3-textfilecontent-crash.patch b/SOURCES/openscap-1.3.3-textfilecontent-crash.patch
new file mode 100644
index 0000000..4ee29c6
--- /dev/null
+++ b/SOURCES/openscap-1.3.3-textfilecontent-crash.patch
@@ -0,0 +1,522 @@
+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 <probe/option.h>
+ #include <oval_fts.h>
+ #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 <probe/option.h>
+ #include <oval_fts.h>
+ #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 <limits.h>
+ #include <stdarg.h>
+ #include <math.h>
++#include <pcre.h>
+ 
+ #include "util.h"
+ #include "_error.h"
+ #include "oscap.h"
+ #include "oscap_helpers.h"
++#include "debug_priv.h"
+ 
+ #ifdef OS_WINDOWS
+ #include <stdlib.h>
+@@ -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 <stdarg.h>
+ #include <string.h>
++#include <pcre.h>
+ #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 @@
++<?xml version="1.0"?>
++<oval_definitions xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5" xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5" xmlns:ind="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ind-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" xmlns:unix-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix" xmlns:lin-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5" xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd">
++  <generator>
++    <oval:schema_version>5.11.1</oval:schema_version>
++    <oval:timestamp>0001-01-01T00:00:00+00:00</oval:timestamp>
++  </generator>
++
++  <definitions>
++    <definition class="compliance" version="1" id="oval:x:def:1">
++      <metadata>
++        <title>The regular expression and the provided file should exceed recursion limits within pcre_exec used in the probe and cause a segfault.</title>
++        <description>x</description>
++        <affected family="unix">
++          <platform>x</platform>
++        </affected>
++      </metadata>
++      <criteria>
++        <criterion test_ref="oval:x:tst:1" comment="always pass"/>
++      </criteria>
++    </definition>
++  </definitions>
++
++  <tests>
++    <ind:textfilecontent54_test id="oval:x:tst:1" version="1" comment="Match 3 audit rules"  check="all">
++      <ind:object object_ref="oval:x:obj:1"/>
++    </ind:textfilecontent54_test>
++  </tests>
++
++  <objects>
++    <ind:textfilecontent54_object id="oval:x:obj:1" version="1" comment="Object representing file">
++      <ind:path>/tmp</ind:path>
++      <ind:filename>30-ospp-v42.rules</ind:filename>
++      <ind:pattern operation="pattern match">-a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&amp;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&amp;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</ind:pattern>
++      <ind:instance datatype="int" operation="greater than or equal">1</ind:instance>
++    </ind:textfilecontent54_object>
++  </objects>
++
++</oval_definitions>
+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
diff --git a/SPECS/openscap.spec b/SPECS/openscap.spec
index c1e87db..4007e65 100644
--- a/SPECS/openscap.spec
+++ b/SPECS/openscap.spec
@@ -1,6 +1,6 @@
 Name:           openscap
 Version:        1.3.2
-Release:        6%{?dist}
+Release:        9%{?dist}
 Summary:        Set of open source libraries enabling integration of the SCAP line of standards
 Group:          System Environment/Libraries
 License:        LGPLv2+
@@ -13,6 +13,14 @@ Patch3:         03-fix-cmake-test-for-libcap-xattr-h.patch
 Patch4:         04-oscap-podman-detect-ambiguous-targets.patch
 Patch5:         openscap-1.3.2-covscan_ux_fix.patch
 Patch6:         openscap-1.3.3-fix-cmake-findacl.patch
+Patch7:         openscap-1.3.3-systemdunit-segfault.patch
+Patch8:         openscap-1.3.3-textfilecontent-crash.patch
+Patch9:         openscap-1.3.3-ansible-newlines.patch
+Patch10:        openscap-1.2.18-oscap-ssh-sudo.patch
+Patch11:        openscap-1.3.3-remove-useless-warnings.patch
+Patch12:        openscap-1.3.3-remove-useless-warnings-tests.patch
+Patch13:        openscap-1.3.3-rpmverifyfile-tests.patch
+Patch14:        openscap-1.3.3-generate-guide-tailoring.patch
 # END PATCHES FOR 1.3.2
 BuildRequires:  cmake >= 2.6
 BuildRequires:  swig libxml2-devel libxslt-devel perl-generators perl-XML-Parser
@@ -137,6 +145,14 @@ for developing applications that use %{name}-engine-sce.
 %patch4 -p1
 %patch5 -p1
 %patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
 mkdir build
 
 %build
@@ -222,6 +238,19 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/oscap-run-sce-script
 
 %changelog
+* Fri Mar 27 2020 Jan Černý <jcerny@redhat.com> - 1.3.2-9
+- Generate HTML guides from tailored profiles (RHBZ#1743835)
+
+* Wed Mar 18 2020 Jan Černý <jcerny@redhat.com> - 1.3.2-8
+- Fix tests for rpmverifyfileprobe (RHBZ#1814726)
+
+* Thu Mar 12 2020 Jan Černý <jcerny@redhat.com> - 1.3.2-7
+- Fix segmentation fault in systemdunitdependency_probe (RHBZ#1793050)
+- Fix crash in textfilecontent probe (RHBZ#1686467)
+- Do not drop empty lines from Ansible remediations (RHBZ#1795563)
+- Fix oscap-ssh --sudo (RHBZ#1803116)
+- Remove useless warnings (RHBZ#1764139)
+
 * Thu Jan 23 2020 Jan Černý <jcerny@redhat.com> - 1.3.2-6
 - Fix FindACL.cmake