diff --git a/build/pcre.m4 b/build/pcre.m4 new file mode 100644 index 00000000..001e1954 --- /dev/null +++ b/build/pcre.m4 @@ -0,0 +1,91 @@ +dnl Check for PCRE Libraries +dnl CHECK_PCRE(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +dnl Sets: +dnl PCRE_CFLAGS +dnl PCRE_LIBS + +PCRE_CONFIG="" +PCRE_VERSION="" +PCRE_CPPFLAGS="" +PCRE_CFLAGS="" +PCRE_LDFLAGS="" +PCRE_LDADD="" +PCRE_LD_PATH="" + +AC_DEFUN([CHECK_PCRE], +[dnl + +AC_ARG_WITH( + pcre, + [AC_HELP_STRING([--with-pcre=PATH],[Path to pcre prefix or config script])], + [test_paths="${with_pcre}"], + [test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr"]) + +AC_MSG_CHECKING([for libpcre config script]) + +dnl # Determine pcre lib directory +if test -z "${with_pcre}"; then + test_paths="/usr/local/pcre /usr/local /usr" +else + test_paths="${with_pcre}" +fi + +for x in ${test_paths}; do + dnl # Determine if the script was specified and use it directly + if test ! -d "$x" -a -e "$x"; then + PCRE_CONFIG=$x + pcre_path="no" + break + fi + + dnl # Try known config script names/locations + for PCRE_CONFIG in pcre-config; do + if test -e "${x}/bin/${PCRE_CONFIG}"; then + pcre_path="${x}/bin" + break + elif test -e "${x}/${PCRE_CONFIG}"; then + pcre_path="${x}" + break + else + pcre_path="" + fi + done + if test -n "$pcre_path"; then + break + fi +done + +if test -n "${pcre_path}"; then + if test "${pcre_path}" != "no"; then + PCRE_CONFIG="${pcre_path}/${PCRE_CONFIG}" + fi + AC_MSG_RESULT([${PCRE_CONFIG}]) + PCRE_VERSION="`${PCRE_CONFIG} --version`" + if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(pcre VERSION: $PCRE_VERSION); fi + PCRE_CFLAGS="`${PCRE_CONFIG} --cflags`" + if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(pcre CFLAGS: $PCRE_CFLAGS); fi + PCRE_LDADD="`${PCRE_CONFIG} --libs`" + if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(pcre LDADD: $PCRE_LDADD); fi + PCRE_LD_PATH="/`${PCRE_CONFIG} --libs | cut -d'/' -f2,3,4,5,6 | cut -d ' ' -f1`" + if test "$verbose_output" -eq 1; then AC_MSG_NOTICE(pcre PCRE_LD_PATH: $PCRE_LD_PATH); fi +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST(PCRE_CONFIG) +AC_SUBST(PCRE_VERSION) +AC_SUBST(PCRE_CPPFLAGS) +AC_SUBST(PCRE_CFLAGS) +AC_SUBST(PCRE_LDFLAGS) +AC_SUBST(PCRE_LDADD) +AC_SUBST(PCRE_LD_PATH) + +if test -z "${PCRE_VERSION}"; then + AC_MSG_NOTICE([*** pcre library not found.]) + ifelse([$2], , AC_MSG_ERROR([pcre library is required]), $2) +else + AC_MSG_NOTICE([using pcre v${PCRE_VERSION}]) + ifelse([$1], , , $1) + PCRE_LDADD="${PCRE_LDADD} -lpcrecpp" +fi +]) diff --git a/configure.ac b/configure.ac index 9cd2e907..6af67d79 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,12 @@ else fi +# +# Check for libpcre +# +CHECK_PCRE + + # Checks for header files. AC_HEADER_STDC diff --git a/src/Makefile.am b/src/Makefile.am index 7bb4e71c..623715bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,6 +102,7 @@ UTILS = \ utils/ip_tree.cc \ utils/md5.cc \ utils/msc_tree.cc \ + utils/regex.cc \ utils/sha1.cc @@ -174,12 +175,14 @@ libmodsecurity_la_CPPFLAGS = \ -I.. \ -g \ -O0 \ - -I ../headers + -I ../headers \ + $(PCRE_CPPFLAGS) libmodsecurity_la_LIBADD = \ $(CURL_LDADD) \ $(GEOIP_LDADD) \ @LEXLIB@ \ + $(PCRE_LDADD) \ $(YAJL_LDADD) diff --git a/src/audit_log.cc b/src/audit_log.cc index f1508bcc..e669b647 100644 --- a/src/audit_log.cc +++ b/src/audit_log.cc @@ -20,10 +20,10 @@ #include #include -#include #include "src/audit_log_writer_parallel.h" #include "src/audit_log_writer_serial.h" +#include "utils/regex.h" #define PARTS_CONSTAINS(a, c) \ if (new_parts.find(toupper(a)) != std::string::npos \ @@ -134,7 +134,8 @@ bool AuditLog::init() { bool AuditLog::isRelevant(int status) { std::string sstatus = std::to_string(status); - return std::regex_search(sstatus, std::regex(this->m_relevant)) != 0; + return Utils::regex_search(sstatus, + Utils::Regex(this->m_relevant)) != 0; } diff --git a/src/utils/regex.cc b/src/utils/regex.cc new file mode 100644 index 00000000..a2624b9e --- /dev/null +++ b/src/utils/regex.cc @@ -0,0 +1,55 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "utils/regex.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "utils/geo_lookup.h" + +namespace ModSecurity { +namespace Utils { + + +Regex::Regex(const std::string& pattern_) + : pattern(pattern_) { + if (pattern.empty() == true) { + pattern.assign(".*"); + } +} + +int regex_search(const std::string& s, SMatch *match, + const Regex& regex) { + pcrecpp::RE re(regex.pattern, + pcrecpp::RE_Options(PCRE_DOTALL|PCRE_MULTILINE)); + match->size_ = re.PartialMatch(s); + return match->size_; +} + +int regex_search(const std::string& s, Regex regex) { + pcrecpp::RE re(regex.pattern); + return re.PartialMatch(s); +} + +} // namespace Utils +} // namespace ModSecurity diff --git a/src/utils/regex.h b/src/utils/regex.h new file mode 100644 index 00000000..be97c5db --- /dev/null +++ b/src/utils/regex.h @@ -0,0 +1,53 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include +#include +#include + +#ifndef SRC_UTILS_REGEX_H_ +#define SRC_UTILS_REGEX_H_ + + +namespace ModSecurity { +namespace Utils { + + +class Regex { + public: + explicit Regex(const std::string& pattern_); + std::string pattern; +}; + + +class SMatch { + public: + SMatch() : size_(0) { } + size_t size() { return size_; } + int size_; +}; + + +int regex_search(const std::string& s, SMatch *m, + const Regex& regex); + +int regex_search(const std::string& s, Regex r); + + + +} // namespace Utils +} // namespace ModSecurity + +#endif // SRC_UTILS_REGEX_H_ diff --git a/test/Makefile.am b/test/Makefile.am index c9221a26..f8842fd7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -27,6 +27,7 @@ unit_tests_LDADD = \ $(top_builddir)/src/.libs/libmodsecurity.a \ $(CURL_LDADD) \ $(GEOIP_LDADD) \ + $(PCRE_LDADD) \ $(YAJL_LDADD) unit_tests_CPPFLAGS = \ @@ -37,6 +38,7 @@ unit_tests_CPPFLAGS = \ -I$(top_builddir)/headers \ $(CURL_CFLAGS) \ $(GEOIP_CFLAGS) \ + $(PCRE_CPPFLAGS) \ $(YAJL_CFLAGS) @@ -51,6 +53,7 @@ regression_tests_LDADD = \ $(top_builddir)/src/.libs/libmodsecurity.a \ $(CURL_LDADD) \ $(GEOIP_LDADD) \ + $(PCRE_LDADD) \ $(YAJL_LDADD) regression_tests_CPPFLAGS = \ @@ -61,4 +64,5 @@ regression_tests_CPPFLAGS = \ -I$(top_builddir)/headers \ $(CURL_CFLAGS) \ $(GEOIP_CFLAGS) \ + $(PCRE_CPPFLAGS) \ $(YAJL_CFLAGS) diff --git a/test/benchmark/Makefile.am b/test/benchmark/Makefile.am index 11edcaa7..a8b07146 100644 --- a/test/benchmark/Makefile.am +++ b/test/benchmark/Makefile.am @@ -9,11 +9,14 @@ benchmark_LDADD = \ $(top_builddir)/src/.libs/libmodsecurity.a \ $(CURL_LDADD) \ $(GEOIP_LDADD) \ + $(PCRE_LDADD) \ $(YAJL_LDADD) benchmark_CPPFLAGS = \ -std=c++11 \ - -I$(top_builddir)/headers + -I$(top_builddir)/headers \ + $(PCRE_CPPFLAGS) + MAINTAINERCLEANFILES = \ Makefile.in diff --git a/test/regression/custom_debug_log.cc b/test/regression/custom_debug_log.cc index 7f1d82be..88124f20 100644 --- a/test/regression/custom_debug_log.cc +++ b/test/regression/custom_debug_log.cc @@ -17,9 +17,9 @@ #include #include -#include #include "modsecurity/debug_log.h" +#include "utils/regex.h" namespace modsecurity_test { @@ -34,10 +34,11 @@ bool CustomDebugLog::write_log(int level, const std::string& message) { bool CustomDebugLog::contains(const std::string& pattern) { - std::regex re(pattern); - std::smatch match; + ModSecurity::Utils::Regex re(pattern); + ModSecurity::Utils::SMatch match; std::string s = m_log.str(); - return (std::regex_search(s, match, re) && match.size() >= 1); + return (ModSecurity::Utils::regex_search(s, &match, re) + && match.size() >= 1); } std::string CustomDebugLog::log_messages() { diff --git a/test/regression/regression.cc b/test/regression/regression.cc index c23cf533..e1086859 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -19,7 +19,6 @@ #include #include #include -#include #include "modsecurity/modsecurity.h" #include "modsecurity/rules.h" @@ -28,12 +27,17 @@ #include "regression/regression_test.h" #include "common/modsecurity_test_results.h" #include "regression/custom_debug_log.h" +#include "utils/regex.h" using modsecurity_test::CustomDebugLog; using modsecurity_test::ModSecurityTest; using modsecurity_test::ModSecurityTestResults; using modsecurity_test::RegressionTest; +using ModSecurity::Utils::regex_search; +using ModSecurity::Utils::SMatch; +using ModSecurity::Utils::Regex; + std::string default_test_path = "test-cases/regression"; void print_help() { @@ -100,11 +104,11 @@ void perform_unit_test(std::vector *tests, return; } - std::regex re(t->parser_error); - std::smatch match; + Regex re(t->parser_error); + SMatch match; std::string s = modsec_rules->getParserError(); - if (std::regex_search(s, match, re) && match.size() >= 1) { + if (regex_search(s, &match, re) && match.size() >= 1) { std::cout << "passed!" << std::endl; return; } else {