Skip to content

Commit ced56c5

Browse files
authored
Merge pull request #2719 from SpiderLabs/v3/dev/pcre2_a
Support PCRE2
2 parents 5519f6c + f84614f commit ced56c5

File tree

9 files changed

+379
-17
lines changed

9 files changed

+379
-17
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
v3.x.y - YYYY-MMM-DD (to be released)
22
-------------------------------------
33

4+
- Support PCRE2
5+
[Issue #2668 - @martinhsv]
46
- Support SecRequestBodyNoFilesLimit
57
[Issue #2670 - @airween, @martinhsv]
68
- Fix misuses of LMDB API

build/pcre2.m4

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
dnl Check for PCRE2 Libraries
2+
dnl CHECK_PCRE2(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
3+
4+
AC_DEFUN([PROG_PCRE2], [
5+
6+
# Possible names for the pcre2 library/package (pkg-config)
7+
PCRE2_POSSIBLE_LIB_NAMES="pcre2 pcre2-8"
8+
9+
# Possible extensions for the library
10+
PCRE2_POSSIBLE_EXTENSIONS="so so0 la sl dll dylib so.0.0.0"
11+
12+
# Possible paths (if pkg-config was not found, proceed with the file lookup)
13+
PCRE2_POSSIBLE_PATHS="/usr/lib /usr/local/lib /usr/local/libpcre2-8 /usr/local/pcre2 /usr/local /opt/libpcre2-8 /opt/pcre2 /opt /usr /usr/lib64 /opt/local"
14+
15+
# Variables to be set by this very own script.
16+
PCRE2_VERSION=""
17+
PCRE2_CFLAGS=""
18+
PCRE2_CPPFLAGS=""
19+
PCRE2_LDADD=""
20+
PCRE2_LDFLAGS=""
21+
22+
AC_ARG_WITH(
23+
pcre2,
24+
AC_HELP_STRING(
25+
[--with-pcre2=PATH],
26+
[Path to pcre2 prefix or config script]
27+
)
28+
)
29+
30+
if test "x${with_pcre2}" == "xno"; then
31+
AC_DEFINE(HAVE_PCRE2, 0, [Support for PCRE2 was disabled by the utilization of --without-pcre2 or --with-pcre2=no])
32+
AC_MSG_NOTICE([Support for PCRE2 was disabled by the utilization of --without-pcre2 or --with-pcre2=no])
33+
PCRE2_DISABLED=yes
34+
else
35+
if test "x${with_pcre2}" == "xyes"; then
36+
PCRE2_MANDATORY=yes
37+
AC_MSG_NOTICE([PCRE2 support was marked as mandatory by the utilization of --with-pcre2=yes])
38+
fi
39+
# for x in ${PCRE2_POSSIBLE_LIB_NAMES}; do
40+
# CHECK_FOR_PCRE2_AT(${x})
41+
# if test -n "${PCRE2_VERSION}"; then
42+
# break
43+
# fi
44+
# done
45+
46+
# if test "x${with_pcre2}" != "xyes" or test "x${with_pcre2}" == "xyes"; then
47+
if test "x${with_pcre2}" == "x" || test "x${with_pcre2}" == "xyes"; then
48+
# Nothing about PCRE2 was informed, using the pkg-config to figure things out.
49+
if test -n "${PKG_CONFIG}"; then
50+
PCRE2_PKG_NAME=""
51+
for x in ${PCRE2_POSSIBLE_LIB_NAMES}; do
52+
if ${PKG_CONFIG} --exists ${x}; then
53+
PCRE2_PKG_NAME="$x"
54+
break
55+
fi
56+
done
57+
fi
58+
AC_MSG_NOTICE([Nothing about PCRE2 was informed during the configure phase. Trying to detect it on the platform...])
59+
if test -n "${PCRE2_PKG_NAME}"; then
60+
# Package was found using the pkg-config scripts
61+
PCRE2_VERSION="`${PKG_CONFIG} ${PCRE2_PKG_NAME} --modversion`"
62+
PCRE2_CFLAGS="`${PKG_CONFIG} ${PCRE2_PKG_NAME} --cflags`"
63+
PCRE2_LDADD="`${PKG_CONFIG} ${PCRE2_PKG_NAME} --libs-only-l`"
64+
PCRE2_LDFLAGS="`${PKG_CONFIG} ${PCRE2_PKG_NAME} --libs-only-L --libs-only-other`"
65+
PCRE2_DISPLAY="${PCRE2_LDADD}, ${PCRE2_CFLAGS}"
66+
else
67+
# If pkg-config did not find anything useful, go over file lookup.
68+
for x in ${PCRE2_POSSIBLE_PATHS}; do
69+
CHECK_FOR_PCRE2_AT(${x})
70+
if test -n "${PCRE2_VERSION}"; then
71+
break
72+
fi
73+
done
74+
fi
75+
fi
76+
if test "x${with_pcre2}" != "x"; then
77+
# An specific path was informed, lets check.
78+
PCRE2_MANDATORY=yes
79+
CHECK_FOR_PCRE2_AT(${with_pcre2})
80+
fi
81+
# fi
82+
fi
83+
84+
if test -z "${PCRE2_LDADD}"; then
85+
if test -z "${PCRE2_MANDATORY}"; then
86+
if test -z "${PCRE2_DISABLED}"; then
87+
AC_MSG_NOTICE([PCRE2 library was not found])
88+
PCRE2_FOUND=0
89+
else
90+
PCRE2_FOUND=2
91+
fi
92+
else
93+
AC_MSG_ERROR([PCRE2 was explicitly referenced but it was not found])
94+
PCRE2_FOUND=-1
95+
fi
96+
else
97+
if test -z "${PCRE2_MANDATORY}"; then
98+
PCRE2_FOUND=2
99+
AC_MSG_NOTICE([PCRE2 is disabled by default.])
100+
else
101+
PCRE2_FOUND=1
102+
AC_MSG_NOTICE([using PCRE2 v${PCRE2_VERSION}])
103+
PCRE2_CFLAGS="-DWITH_PCRE2 ${PCRE2_CFLAGS}"
104+
PCRE2_DISPLAY="${PCRE2_LDADD}, ${PCRE2_CFLAGS}"
105+
AC_SUBST(PCRE2_VERSION)
106+
AC_SUBST(PCRE2_LDADD)
107+
AC_SUBST(PCRE2_LIBS)
108+
AC_SUBST(PCRE2_LDFLAGS)
109+
AC_SUBST(PCRE2_CFLAGS)
110+
AC_SUBST(PCRE2_DISPLAY)
111+
fi
112+
fi
113+
114+
115+
AC_SUBST(PCRE2_FOUND)
116+
117+
]) # AC_DEFUN [PROG_PCRE2]
118+
119+
120+
AC_DEFUN([CHECK_FOR_PCRE2_AT], [
121+
path=$1
122+
echo "*** LOOKING AT PATH: " ${path}
123+
for y in ${PCRE2_POSSIBLE_EXTENSIONS}; do
124+
for z in ${PCRE2_POSSIBLE_LIB_NAMES}; do
125+
if test -e "${path}/${z}.${y}"; then
126+
pcre2_lib_path="${path}/"
127+
pcre2_lib_name="${z}"
128+
pcre2_lib_file="${pcre2_lib_path}/${z}.${y}"
129+
break
130+
fi
131+
if test -e "${path}/lib${z}.${y}"; then
132+
pcre2_lib_path="${path}/"
133+
pcre2_lib_name="${z}"
134+
pcre2_lib_file="${pcre2_lib_path}/lib${z}.${y}"
135+
break
136+
fi
137+
if test -e "${path}/lib/lib${z}.${y}"; then
138+
pcre2_lib_path="${path}/lib/"
139+
pcre2_lib_name="${z}"
140+
pcre2_lib_file="${pcre2_lib_path}/lib${z}.${y}"
141+
break
142+
fi
143+
if test -e "${path}/lib/x86_64-linux-gnu/lib${z}.${y}"; then
144+
pcre2_lib_path="${path}/lib/x86_64-linux-gnu/"
145+
pcre2_lib_name="${z}"
146+
pcre2_lib_file="${pcre2_lib_path}/lib${z}.${y}"
147+
break
148+
fi
149+
if test -e "${path}/lib/i386-linux-gnu/lib${z}.${y}"; then
150+
pcre2_lib_path="${path}/lib/i386-linux-gnu/"
151+
pcre2_lib_name="${z}"
152+
pcre2_lib_file="${pcre2_lib_path}/lib${z}.${y}"
153+
break
154+
fi
155+
done
156+
if test -n "$pcre2_lib_path"; then
157+
break
158+
fi
159+
done
160+
if test -e "${path}/include/pcre2.h"; then
161+
pcre2_inc_path="${path}/include"
162+
elif test -e "${path}/pcre2.h"; then
163+
pcre2_inc_path="${path}"
164+
elif test -e "${path}/include/pcre2/pcre2.h"; then
165+
pcre2_inc_path="${path}/include"
166+
fi
167+
168+
if test -n "${pcre2_lib_path}"; then
169+
AC_MSG_NOTICE([PCRE2 library found at: ${pcre2_lib_file}])
170+
fi
171+
172+
if test -n "${pcre2_inc_path}"; then
173+
AC_MSG_NOTICE([PCRE2 headers found at: ${pcre2_inc_path}])
174+
fi
175+
176+
if test -n "${pcre2_lib_path}" -a -n "${pcre2_inc_path}"; then
177+
# TODO: Compile a piece of code to check the version.
178+
PCRE2_CFLAGS="-I${pcre2_inc_path}"
179+
PCRE2_LDADD="-l${pcre2_lib_name}"
180+
PCRE2_LDFLAGS="-L${pcre2_lib_path}"
181+
PCRE2_DISPLAY="${pcre2_lib_file}, ${pcre2_inc_path}"
182+
fi
183+
]) # AC_DEFUN [CHECK_FOR_PCRE2_AT]

configure.ac

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ CHECK_LIBXML2
129129
CHECK_PCRE
130130

131131

132+
#
133+
# Check for pcre2
134+
#
135+
PROG_PCRE2
136+
AM_CONDITIONAL([PCRE2_CFLAGS], [test "PCRE2_CFLAGS" != ""])
137+
138+
132139
# Checks for header files.
133140
AC_HEADER_STDC
134141
AC_CHECK_HEADERS([string])
@@ -555,6 +562,23 @@ if test "x$LUA_FOUND" = "x2"; then
555562
fi
556563

557564

565+
## PCRE2
566+
if test "x$PCRE2_FOUND" = "x0"; then
567+
echo " + PCRE2 ....not found"
568+
fi
569+
if test "x$PCRE2_FOUND" = "x1"; then
570+
echo -n " + PCRE2 ....found "
571+
if ! test "x$PCRE2_VERSION" = "x"; then
572+
echo "v${PCRE2_VERSION}"
573+
else
574+
echo ""
575+
fi
576+
echo " ${PCRE2_DISPLAY}"
577+
fi
578+
if test "x$PCRE2_FOUND" = "x2"; then
579+
echo " + PCRE2 ....disabled"
580+
fi
581+
558582
echo " "
559583
echo " Other Options"
560584
if test $buildTestUtilities = true; then

src/Makefile.am

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ libmodsecurity_la_CPPFLAGS = \
324324
$(YAJL_CFLAGS) \
325325
$(LMDB_CFLAGS) \
326326
$(PCRE_CFLAGS) \
327+
$(PCRE2_CFLAGS) \
327328
$(SSDEEP_CFLAGS) \
328329
$(MAXMIND_CFLAGS) \
329330
$(LUA_CFLAGS) \
@@ -339,6 +340,7 @@ libmodsecurity_la_LDFLAGS = \
339340
$(LMDB_LDFLAGS) \
340341
$(LUA_LDFLAGS) \
341342
$(PCRE_LDFLAGS) \
343+
$(PCRE2_LDFLAGS) \
342344
$(SSDEEP_LDFLAGS) \
343345
$(MAXMIND_LDFLAGS) \
344346
$(YAJL_LDFLAGS) \
@@ -355,6 +357,7 @@ libmodsecurity_la_LIBADD = \
355357
../others/libinjection.la \
356358
../others/libmbedtls.la \
357359
$(PCRE_LDADD) \
360+
$(PCRE2_LDADD) \
358361
$(MAXMIND_LDADD) \
359362
$(SSDEEP_LDADD) \
360363
$(YAJL_LDADD)

src/operators/verify_cc.cc

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,28 @@
1515

1616
#include "src/operators/verify_cc.h"
1717

18-
#include <pcre.h>
1918
#include <iostream>
2019
#include <cstring>
2120
#include <vector>
2221

2322
#include "src/operators/operator.h"
2423

24+
#ifndef WITH_PCRE2
2525
#if PCRE_HAVE_JIT
2626
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE
2727
#else
2828
#define pcre_study_opt 0
2929
#endif
30+
#endif
3031

3132

3233
namespace modsecurity {
3334
namespace operators {
3435

3536
VerifyCC::~VerifyCC() {
37+
#if WITH_PCRE2
38+
pcre2_code_free(m_pc);
39+
#else
3640
if (m_pc != NULL) {
3741
pcre_free(m_pc);
3842
m_pc = NULL;
@@ -45,6 +49,7 @@ VerifyCC::~VerifyCC() {
4549
#endif
4650
m_pce = NULL;
4751
}
52+
#endif
4853
}
4954

5055
/**
@@ -90,6 +95,22 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
9095

9196

9297
bool VerifyCC::init(const std::string &param2, std::string *error) {
98+
#ifdef WITH_PCRE2
99+
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(m_param.c_str());
100+
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
101+
int errornumber = 0;
102+
PCRE2_SIZE erroroffset = 0;
103+
m_pc = pcre2_compile(pcre2_pattern, PCRE2_ZERO_TERMINATED,
104+
pcre2_options, &errornumber, &erroroffset, NULL);
105+
if (m_pc == NULL) {
106+
return false;
107+
} else {
108+
m_match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
109+
if (m_match_data == NULL) {
110+
return false;
111+
}
112+
}
113+
#else
93114
const char *errptr = NULL;
94115
int erroffset = 0;
95116

@@ -112,18 +133,33 @@ bool VerifyCC::init(const std::string &param2, std::string *error) {
112133
error->assign(errptr);
113134
return false;
114135
}
136+
#endif
115137

116138
return true;
117139
}
118140

119141

120142
bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
121143
const std::string& i, std::shared_ptr<RuleMessage> ruleMessage) {
144+
#ifdef WITH_PCRE2
145+
PCRE2_SIZE offset = 0;
146+
size_t target_length = i.length();
147+
PCRE2_SPTR pcre2_i = reinterpret_cast<PCRE2_SPTR>(i.c_str());
148+
149+
for (offset = 0; offset < target_length; offset++) {
150+
int ret = pcre2_match(m_pc, pcre2_i, target_length, offset, 0, m_match_data, NULL);
151+
152+
/* If there was no match, then we are done. */
153+
if (ret < 0) {
154+
break;
155+
}
156+
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(m_match_data);
157+
158+
#else
122159
int offset = 0;
123160
int target_length = i.length();
124161

125162
for (offset = 0; offset < target_length; offset++) {
126-
std::string match;
127163
int ovector[33];
128164
memset(ovector, 0, sizeof(ovector));
129165
int ret = pcre_exec(m_pc, m_pce, i.c_str(), i.size(), offset,
@@ -136,8 +172,9 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
136172
if (ret < 0) {
137173
return false;
138174
}
175+
#endif
139176
if (ret > 0) {
140-
match = std::string(i, ovector[0], ovector[1] - ovector[0]);
177+
std::string match = std::string(i, ovector[0], ovector[1] - ovector[0]);
141178
int is_cc = luhnVerify(match.c_str(), match.size());
142179
if (is_cc) {
143180
if (t) {

0 commit comments

Comments
 (0)