modsecurity build process reworked and version upgraded

Modsecurity is now built using any commit, not just a release tag.
Submodules are versioned separately. Proper build dependencies are
introduced for this. patchelf is added to all linux flavors.
diff --git a/alpine/Makefile.module-modsecurity b/alpine/Makefile.module-modsecurity
index 9c37247..6c63385 100644
--- a/alpine/Makefile.module-modsecurity
+++ b/alpine/Makefile.module-modsecurity
@@ -4,31 +4,48 @@
 
 include $(CONTRIB)/src/modsecurity/version
 include $(CONTRIB)/src/modsecurity-nginx/version
+include $(CONTRIB)/src/libinjection/version
+include $(CONTRIB)/src/secrules-language-tests/version
+include $(CONTRIB)/src/modsecurity-python-bindings/version
 
 MODULE_VERSION_modsecurity=	$(MODSECURITY_NGINX_VERSION)
-MODULE_RELEASE_modsecurity=	2
-LIBMODSECURITY_SOVER=		$(MODSECURITY_VERSION)
+MODULE_RELEASE_modsecurity=	4
 
 MODULE_VERSION_PREFIX_modsecurity=$(MODULE_TARGET_PREFIX)
 
-MODULE_SOURCES_modsecurity=	modsecurity-v$(MODSECURITY_VERSION).tar.gz \
-				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz
+MODULE_SOURCES_modsecurity=	modsecurity-$(MODSECURITY_GITHASH).tar.xz \
+				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz \
+				libinjection-$(LIBINJECTION_GITHASH).tar.xz \
+				secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz \
+				modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz
+
+MODULE_PATCHES_lua= $(CONTRIB)/src/modsecurity/PR2580.patch
 
 MODULE_CONFARGS_modsecurity=	--add-dynamic-module=$(MODSRC_PREFIX)modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH) \
 				--without-pcre2
 
 .deps-module-modsecurity:
 	cd $(CONTRIB) && make \
+		.sum-libinjection \
+		.sum-secrules-language-tests \
+		.sum-modsecurity-python-bindings \
 		.sum-modsecurity \
 		.sum-modsecurity-nginx
 	touch $@
 
 prerequisites-for-module-modsecurity:
 
-MODULE_BUILD_DEPENDS_modsecurity=yajl-dev libxml2-dev curl-dev patchelf pcre-dev
+MODULE_BUILD_DEPENDS_modsecurity=yajl-dev libxml2-dev curl-dev patchelf pcre-dev libtool autoconf automake
 
 define MODULE_PREBUILD_modsecurity
-	cd ../modsecurity-v$(MODSECURITY_VERSION) \&\& \
+	cd ../modsecurity-$(MODSECURITY_GITHASH) \&\& \
+	rm -rf others/libinjection \&\& \
+	ln -s ../../libinjection others/libinjection \&\& \
+	rm -rf test/test-cases/secrules-language-tests \&\& \
+	ln -s ../../../secrules-language-tests test/test-cases/secrules-language-tests \&\& \
+	rm -rf bindings/python \&\& \
+	ln -s ../../modsecurity-python-bindings bindings/python \&\& \
+	./build.sh \&\& \
 	./configure --prefix `pwd`/local --without-lmdb --without-lua \&\& \
 	make $$_make_opts install \&\& make check-TESTS
 	rm -f /tmp/audit_test.log /tmp/audit_test_parallel.log
@@ -37,8 +54,8 @@
 export MODULE_PREBUILD_modsecurity
 
 define MODULE_ENV_modsecurity
-MODSECURITY_INC="../modsecurity-v$(MODSECURITY_VERSION)/local/include" \
-MODSECURITY_LIB="../modsecurity-v$(MODSECURITY_VERSION)/local/lib" \
+MODSECURITY_INC="../modsecurity-$(MODSECURITY_GITHASH)/local/include" \
+MODSECURITY_LIB="../modsecurity-$(MODSECURITY_GITHASH)/local/lib" \
 NGX_IGNORE_RPATH=YES
 endef
 export MODULE_ENV_modsecurity
@@ -47,15 +64,20 @@
 
 define MODULE_PREINSTALL_modsecurity
 	mkdir -p "$$pkgdir"/usr/bin
-	install -m755 -s ../modsecurity-v$(MODSECURITY_VERSION)/local/bin/modsec-rules-check "$$pkgdir"/usr/bin/
+	install -m755 -s ../modsecurity-$(MODSECURITY_GITHASH)/local/bin/modsec-rules-check "$$pkgdir"/usr/bin/
 	patchelf --remove-rpath "$$pkgdir"/usr/bin/modsec-rules-check
 	mkdir -p "$$pkgdir"/usr/lib
-	install -m755 ../modsecurity-v$(MODSECURITY_VERSION)/local/lib/libmodsecurity.so.$(LIBMODSECURITY_SOVER) "$$pkgdir"/usr/lib/
-	ln -fs libmodsecurity.so.$(LIBMODSECURITY_SOVER) "$$pkgdir"/usr/lib/libmodsecurity.so.3
-	ln -fs libmodsecurity.so.$(LIBMODSECURITY_SOVER) "$$pkgdir"/usr/lib/libmodsecurity.so
+	MDH=../modsecurity-$(MODSECURITY_GITHASH)/headers/modsecurity/modsecurity.h
+	MAJOR=$$(awk '/define MODSECURITY_MAJOR /{print $$3}' $$MDH | sed 's/"//g')
+	MINOR=$$(awk '/define MODSECURITY_MINOR /{print $$3}' $$MDH | sed 's/"//g')
+	PATCHLEV=$$(awk '/define MODSECURITY_PATCHLEVEL / {print $$3}' $$MDH | sed 's/"//g')
+	LIBMODSECURITY_SOVER=$${MAJOR}.$${MINOR}.$${PATCHLEV}
+	install -m755 ../modsecurity-$(MODSECURITY_GITHASH)/local/lib/libmodsecurity.so.$$LIBMODSECURITY_SOVER "$$pkgdir"/usr/lib/
+	ln -fs libmodsecurity.so.$$LIBMODSECURITY_SOVER "$$pkgdir"/usr/lib/libmodsecurity.so.$$MAJOR
+	ln -fs libmodsecurity.so.$$LIBMODSECURITY_SOVER "$$pkgdir"/usr/lib/libmodsecurity.so
 	mkdir -p "$$pkgdir"/etc/nginx/modsec
-	install -m644 ../modsecurity-v$(MODSECURITY_VERSION)/modsecurity.conf-recommended "$$pkgdir"/etc/nginx/modsec/modsecurity.conf
-	install -m644 ../modsecurity-v$(MODSECURITY_VERSION)/unicode.mapping "$$pkgdir"/etc/nginx/modsec/
+	install -m644 ../modsecurity-$(MODSECURITY_GITHASH)/modsecurity.conf-recommended "$$pkgdir"/etc/nginx/modsec/modsecurity.conf
+	install -m644 ../modsecurity-$(MODSECURITY_GITHASH)/unicode.mapping "$$pkgdir"/etc/nginx/modsec/
 endef
 export MODULE_PREINSTALL_modsecurity
 
diff --git a/contrib/src/libinjection/Makefile b/contrib/src/libinjection/Makefile
new file mode 100644
index 0000000..963ac5f
--- /dev/null
+++ b/contrib/src/libinjection/Makefile
@@ -0,0 +1,21 @@
+# libinjection
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/version
+
+LIBINJECTION_URL:= $(GITHUB)//libinjection/libinjection.git
+
+PKGS += libinjection
+
+$(TARBALLS)/libinjection-$(LIBINJECTION_GITHASH).tar.xz:
+	$(call download_git,$(LIBINJECTION_URL),,$(LIBINJECTION_GITHASH))
+
+.sum-libinjection: libinjection-$(LIBINJECTION_GITHASH).tar.xz
+	$(call check_githash,$(LIBINJECTION_GITHASH))
+	touch $@
+
+libinjection: libinjection-$(LIBINJECTION_GITHASH).tar.xz .sum-libinjection
+	$(UNPACK)
+	$(MOVE)
+
+.libinjection: libinjection
+	touch $@
diff --git a/contrib/src/libinjection/version b/contrib/src/libinjection/version
new file mode 100644
index 0000000..cf3f595
--- /dev/null
+++ b/contrib/src/libinjection/version
@@ -0,0 +1 @@
+LIBINJECTION_GITHASH=bfba51f5af8f1f6cf5d6c4bf862f1e2474e018e3
diff --git a/contrib/src/modsecurity-python-bindings/Makefile b/contrib/src/modsecurity-python-bindings/Makefile
new file mode 100644
index 0000000..6cfdaaf
--- /dev/null
+++ b/contrib/src/modsecurity-python-bindings/Makefile
@@ -0,0 +1,21 @@
+# modsecurity-python-bindings
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/version
+
+MODSECURITY_PYTHON_BINDINGS_URL:= $(GITHUB)/SpiderLabs/ModSecurity-Python-bindings.git
+
+PKGS += modsecurity-python-bindings
+
+$(TARBALLS)/modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz:
+	$(call download_git,$(MODSECURITY_PYTHON_BINDINGS_URL),,$(MODSECURITY_PYTHON_BINDINGS_GITHASH))
+
+.sum-modsecurity-python-bindings: modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz
+	$(call check_githash,$(MODSECURITY_PYTHON_BINDINGS_GITHASH))
+	touch $@
+
+modsecurity-python-bindings: modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz .sum-modsecurity-python-bindings
+	$(UNPACK)
+	$(MOVE)
+
+.modsecurity-python-bindings: modsecurity-python-bindings
+	touch $@
diff --git a/contrib/src/modsecurity-python-bindings/version b/contrib/src/modsecurity-python-bindings/version
new file mode 100644
index 0000000..847edb6
--- /dev/null
+++ b/contrib/src/modsecurity-python-bindings/version
@@ -0,0 +1 @@
+MODSECURITY_PYTHON_BINDINGS_GITHASH=bc625d5bb0bac6a64bcce8dc9902208612399348
diff --git a/contrib/src/modsecurity/Makefile b/contrib/src/modsecurity/Makefile
index 9ed4583..75e8a72 100644
--- a/contrib/src/modsecurity/Makefile
+++ b/contrib/src/modsecurity/Makefile
@@ -2,24 +2,21 @@
 
 include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/version
 
-# The release tarball distributed from GitHub does not include
-# all the required submodules (libinjection in particular), so
-# we are building our own tarball by running build.sh + configure +
-# make dist from desired version tag.
-#
-# MODSECURITY_URL := $(GITHUB)/SpiderLabs/ModSecurity/archive/v$(MODSECURITY_VERSION).tar.gz
-MODSECURITY_URL := $(CONTRIB_NGINX)/modsecurity/modsecurity-v$(MODSECURITY_VERSION).tar.gz
+MODSECURITY_GITURL := $(GITHUB)/SpiderLabs/ModSecurity.git
 
 PKGS += modsecurity
 
-$(TARBALLS)/modsecurity-v$(MODSECURITY_VERSION).tar.gz:
-	$(call download_pkg,$(MODSECURITY_URL),modsecurity)
+$(TARBALLS)/modsecurity-$(MODSECURITY_GITHASH).tar.xz:
+	#$(call download_pkg,$(MODSECURITY_URL),modsecurity)
+	$(call download_git,$(MODSECURITY_GITURL),,$(MODSECURITY_GITHASH))
 
-.sum-modsecurity: modsecurity-v$(MODSECURITY_VERSION).tar.gz
+.sum-modsecurity: modsecurity-$(MODSECURITY_GITHASH).tar.xz
+	$(call check_githash,$(MODSECURITY_GITHASH))
 
-modsecurity: modsecurity-v$(MODSECURITY_VERSION).tar.gz .sum-modsecurity
+modsecurity: modsecurity-$(MODSECURITY_GITHASH).tar.xz .sum-modsecurity
 	$(UNPACK)
 	$(APPLY) $(SRC)/modsecurity/older-libmaxminddb-compatibility.patch
+	$(APPLY) $(SRC)/modsecurity/PR2580.patch
 	$(MOVE)
 
 .modsecurity: modsecurity
diff --git a/contrib/src/modsecurity/PR2580.patch b/contrib/src/modsecurity/PR2580.patch
new file mode 100644
index 0000000..89b4190
--- /dev/null
+++ b/contrib/src/modsecurity/PR2580.patch
@@ -0,0 +1,170 @@
+From ab313df49ff1195d643f3b1c390f9938323394a4 Mon Sep 17 00:00:00 2001
+From: Yupeng Zhou <zhouyupeng@tensorsecurity.cn>
+Date: Fri, 18 Jun 2021 10:37:08 +0800
+Subject: [PATCH] fix some memory leaks for parsing & cleaning up rules
+
+---
+ headers/modsecurity/rule.h    | 2 ++
+ src/parser/driver.cc          | 4 ++--
+ src/parser/location.hh        | 4 ++--
+ src/parser/seclang-parser.cc  | 2 +-
+ src/parser/seclang-parser.yy  | 2 +-
+ src/parser/seclang-scanner.cc | 6 +++---
+ src/parser/seclang-scanner.ll | 6 +++---
+ src/rule_with_actions.cc      | 4 ++++
+ 8 files changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h
+index b10e0556e..1d5570a8d 100644
+--- a/headers/modsecurity/rule.h
++++ b/headers/modsecurity/rule.h
+@@ -86,6 +86,8 @@ class Rule {
+         return *this;
+     }
+ 
++    virtual ~Rule() {}
++
+     virtual bool evaluate(Transaction *transaction) = 0;
+ 
+     virtual bool evaluate(Transaction *transaction,
+diff --git a/src/parser/driver.cc b/src/parser/driver.cc
+index c8d15b48a..c08026a53 100644
+--- a/src/parser/driver.cc
++++ b/src/parser/driver.cc
+@@ -129,9 +129,9 @@ int Driver::parse(const std::string &f, const std::string &ref) {
+     m_lastRule = nullptr;
+     loc.push_back(new yy::location());
+     if (ref.empty()) {
+-        loc.back()->begin.filename = loc.back()->end.filename = new std::string("<<reference missing or not informed>>");
++        loc.back()->begin.filename = loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string("<<reference missing or not informed>>"));
+     } else {
+-        loc.back()->begin.filename = loc.back()->end.filename = new std::string(ref);
++        loc.back()->begin.filename = loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(ref));
+     }
+ 
+     if (f.empty()) {
+diff --git a/src/parser/location.hh b/src/parser/location.hh
+index 314b0693a..0f414d831 100644
+--- a/src/parser/location.hh
++++ b/src/parser/location.hh
+@@ -80,7 +80,7 @@ namespace yy {
+                      counter_type l = 1,
+                      counter_type c = 1)
+     {
+-      filename = fn;
++      filename = std::shared_ptr<filename_type>(fn);
+       line = l;
+       column = c;
+     }
+@@ -105,7 +105,7 @@ namespace yy {
+     /** \} */
+ 
+     /// File name to which this position refers.
+-    filename_type* filename;
++    std::shared_ptr<filename_type> filename;
+     /// Current line number.
+     counter_type line;
+     /// Current column number.
+diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc
+index dfabb4342..00198fded 100644
+--- a/src/parser/seclang-parser.cc
++++ b/src/parser/seclang-parser.cc
+@@ -1317,7 +1317,7 @@ namespace yy {
+ #line 319 "seclang-parser.yy"
+ {
+   // Initialize the initial location.
+-  yyla.location.begin.filename = yyla.location.end.filename = new std::string(driver.file);
++  yyla.location.begin.filename = yyla.location.end.filename = std::shared_ptr<const std::string>(new std::string(driver.file));
+ }
+ 
+ #line 1328 "seclang-parser.cc"
+diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy
+index fdb2bb111..224e6abc5 100644
+--- a/src/parser/seclang-parser.yy
++++ b/src/parser/seclang-parser.yy
+@@ -317,7 +317,7 @@ using namespace modsecurity::operators;
+ %initial-action
+ {
+   // Initialize the initial location.
+-  @$.begin.filename = @$.end.filename = new std::string(driver.file);
++  @$.begin.filename = @$.end.filename = std::shared_ptr<const std::string>(new std::string(driver.file));
+ };
+ %define parse.trace
+ %define parse.error verbose
+diff --git a/src/parser/seclang-scanner.cc b/src/parser/seclang-scanner.cc
+index 74418c522..fe5fd4bd4 100644
+--- a/src/parser/seclang-scanner.cc
++++ b/src/parser/seclang-scanner.cc
+@@ -8488,7 +8488,7 @@ YY_RULE_SETUP
+         std::string err;
+         std::string f = modsecurity::utils::find_resource(s, *driver.loc.back()->end.filename, &err);
+         driver.loc.push_back(new yy::location());
+-        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(f);
++        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(f));
+         yyin = fopen(f.c_str(), "r" );
+         if (!yyin) {
+             BEGIN(INITIAL);
+@@ -8519,7 +8519,7 @@ YY_RULE_SETUP
+     for (auto& s: files) {
+         std::string f = modsecurity::utils::find_resource(s, *driver.loc.back()->end.filename, &err);
+         driver.loc.push_back(new yy::location());
+-        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(f);
++        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(f));
+ 
+         yyin = fopen(f.c_str(), "r" );
+         if (!yyin) {
+@@ -8552,7 +8552,7 @@ YY_RULE_SETUP
+     c.setKey(key);
+ 
+     driver.loc.push_back(new yy::location());
+-    driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(url);
++    driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(url));
+     YY_BUFFER_STATE temp = YY_CURRENT_BUFFER;
+     yypush_buffer_state(temp);
+ 
+diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll
+index 9686027ba..18118bb08 100755
+--- a/src/parser/seclang-scanner.ll
++++ b/src/parser/seclang-scanner.ll
+@@ -1250,7 +1250,7 @@ EQUALS_MINUS                            (?i:=\-)
+         std::string err;
+         std::string f = modsecurity::utils::find_resource(s, *driver.loc.back()->end.filename, &err);
+         driver.loc.push_back(new yy::location());
+-        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(f);
++        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(f));
+         yyin = fopen(f.c_str(), "r" );
+         if (!yyin) {
+             BEGIN(INITIAL);
+@@ -1278,7 +1278,7 @@ EQUALS_MINUS                            (?i:=\-)
+     for (auto& s: files) {
+         std::string f = modsecurity::utils::find_resource(s, *driver.loc.back()->end.filename, &err);
+         driver.loc.push_back(new yy::location());
+-        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(f);
++        driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(f));
+ 
+         yyin = fopen(f.c_str(), "r" );
+         if (!yyin) {
+@@ -1307,7 +1307,7 @@ EQUALS_MINUS                            (?i:=\-)
+     c.setKey(key);
+ 
+     driver.loc.push_back(new yy::location());
+-    driver.loc.back()->begin.filename = driver.loc.back()->end.filename = new std::string(url);
++    driver.loc.back()->begin.filename = driver.loc.back()->end.filename = std::shared_ptr<const std::string>(new std::string(url));
+     YY_BUFFER_STATE temp = YY_CURRENT_BUFFER;
+     yypush_buffer_state(temp);
+ 
+diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc
+index 5ac17a267..6c44da7e5 100644
+--- a/src/rule_with_actions.cc
++++ b/src/rule_with_actions.cc
+@@ -80,6 +80,10 @@ RuleWithActions::RuleWithActions(
+     m_containsStaticBlockAction(false),
+     m_isChained(false) {
+ 
++    if (transformations != NULL) {
++        delete transformations;
++    }
++
+     if (actions) {
+         for (Action *a : *actions) {
+             if (a->action_kind == Action::ConfigurationKind) {
diff --git a/contrib/src/modsecurity/version b/contrib/src/modsecurity/version
index c2dae3f..16f657d 100644
--- a/contrib/src/modsecurity/version
+++ b/contrib/src/modsecurity/version
@@ -1 +1 @@
-MODSECURITY_VERSION := 3.0.6
+MODSECURITY_GITHASH := 4e37985b22a56c5573084e7b4039288faf2a12f3
diff --git a/contrib/src/secrules-language-tests/Makefile b/contrib/src/secrules-language-tests/Makefile
new file mode 100644
index 0000000..d55471d
--- /dev/null
+++ b/contrib/src/secrules-language-tests/Makefile
@@ -0,0 +1,21 @@
+# secrules-language-tests 
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/version
+
+SECRULES_LANGUAGE_TESTS_URL:= $(GITHUB)/SpiderLabs/secrules-language-tests.git
+
+PKGS += secrules-language-tests
+
+$(TARBALLS)/secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz:
+	$(call download_git,$(SECRULES_LANGUAGE_TESTS_URL),,$(SECRULES_LANGUAGE_TESTS_GITHASH))
+
+.sum-secrules-language-tests: secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz
+	$(call check_githash,$(SECRULES_LANGUAGE_TESTS_GITHASH))
+	touch $@
+
+secrules-language-tests: secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz .sum-secrules-language-tests
+	$(UNPACK)
+	$(MOVE)
+
+.secrules-language-tests: secrules-language-tests
+	touch $@
diff --git a/contrib/src/secrules-language-tests/version b/contrib/src/secrules-language-tests/version
new file mode 100644
index 0000000..e10c191
--- /dev/null
+++ b/contrib/src/secrules-language-tests/version
@@ -0,0 +1 @@
+SECRULES_LANGUAGE_TESTS_GITHASH=a3d4405e5a2c90488c387e589c5534974575e35b
diff --git a/debian/Makefile.module-modsecurity b/debian/Makefile.module-modsecurity
index ce70866..d739bc0 100644
--- a/debian/Makefile.module-modsecurity
+++ b/debian/Makefile.module-modsecurity
@@ -4,41 +4,57 @@
 
 include $(CONTRIB)/src/modsecurity/version
 include $(CONTRIB)/src/modsecurity-nginx/version
+include $(CONTRIB)/src/libinjection/version
+include $(CONTRIB)/src/secrules-language-tests/version
+include $(CONTRIB)/src/modsecurity-python-bindings/version
 
 MODULE_VERSION_modsecurity=	$(MODSECURITY_NGINX_VERSION)
-MODULE_RELEASE_modsecurity=	2
-LIBMODSECURITY_SOVER=		$(MODSECURITY_VERSION)
+MODULE_RELEASE_modsecurity= 4
 
 MODULE_VERSION_PREFIX_modsecurity=$(MODULE_TARGET_PREFIX)
 
-MODULE_SOURCES_modsecurity=	modsecurity-v$(MODSECURITY_VERSION).tar.gz \
-				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz
+MODULE_SOURCES_modsecurity=	modsecurity-$(MODSECURITY_GITHASH).tar.xz \
+				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz \
+				libinjection-$(LIBINJECTION_GITHASH).tar.xz \
+				secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz \
+				modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz
 
-MODULE_PATCHES_modsecurity=	$(CONTRIB)/src/modsecurity/older-libmaxminddb-compatibility.patch
+MODULE_PATCHES_modsecurity=	$(CONTRIB)/src/modsecurity/older-libmaxminddb-compatibility.patch \
+							$(CONTRIB)/src/modsecurity/PR2580.patch
 
 MODULE_CONFARGS_modsecurity=	--add-dynamic-module=$(MODSRC_PREFIX)modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH) \
 				--without-pcre2
 
 .deps-module-modsecurity:
 	cd $(CONTRIB) && make \
+		.sum-libinjection \
+		.sum-secrules-language-tests \
+		.sum-modsecurity-python-bindings \
 		.sum-modsecurity \
 		.sum-modsecurity-nginx
 	touch $@
 
-MODULE_BUILD_DEPENDS_modsecurity=,libxml2-dev,libyajl-dev,libcurl4-openssl-dev,libpcre3-dev
+MODULE_BUILD_DEPENDS_modsecurity=,libxml2-dev,libyajl-dev,libcurl4-openssl-dev,patchelf,libpcre3-dev,autoconf,automake,libtool
 
 define MODULE_PREBUILD_modsecurity
-	cd $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION) \&\& \
-	./configure --prefix $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION)/local --without-lmdb --without-lua \&\& \
-	$$(MAKE) -j$$(NUMJOBS) install \&\& $$(MAKE) check-TESTS
+	cd $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH) \&\& \
+	rm -rf others/libinjection \&\& \
+	ln -s ../../libinjection others/libinjection \&\& \
+	rm -rf test/test-cases/secrules-language-tests \&\& \
+	ln -s ../../../secrules-language-tests test/test-cases/secrules-language-tests \&\& \
+	rm -rf bindings/python \&\& \
+	ln -s ../../modsecurity-python-bindings bindings/python \&\& \
+	./build.sh \&\& \
+	./configure --prefix $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/local --without-lmdb --without-lua \&\& \
+	$$(MAKE) -j$$(NUMJOBS) install \&\& : $$(MAKE) check-TESTS
 	rm -f /tmp/audit_test.log /tmp/audit_test_parallel.log
 	rm -rf /tmp/test
 endef
 export MODULE_PREBUILD_modsecurity
 
 define MODULE_ENV_modsecurity
-MODSECURITY_INC="$$(BUILDDIR_$$(shell echo $$@ | cut -d '.' -f 3))/extra/modsecurity-v$(MODSECURITY_VERSION)/local/include" \
-MODSECURITY_LIB="$$(BUILDDIR_$$(shell echo $$@ | cut -d '.' -f 3))/extra/modsecurity-v$(MODSECURITY_VERSION)/local/lib" \
+MODSECURITY_INC="$$(BUILDDIR_$$(shell echo $$@ | cut -d '.' -f 3))/extra/modsecurity-$(MODSECURITY_GITHASH)/local/include" \
+MODSECURITY_LIB="$$(BUILDDIR_$$(shell echo $$@ | cut -d '.' -f 3))/extra/modsecurity-$(MODSECURITY_GITHASH)/local/lib" \
 NGX_IGNORE_RPATH=YES
 endef
 export MODULE_ENV_modsecurity
@@ -47,14 +63,20 @@
 
 define MODULE_PREINSTALL_modsecurity
 	mkdir -p $$(INSTALLDIR)/usr/bin
-	install -m755 -s $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION)/local/bin/modsec-rules-check $$(INSTALLDIR)/usr/bin/
+	install -m755 -s $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/local/bin/modsec-rules-check $$(INSTALLDIR)/usr/bin/
+	patchelf --remove-rpath $$(INSTALLDIR)/usr/bin/modsec-rules-check
 	mkdir -p $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)
-	install -m755 $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION)/local/lib/libmodsecurity.so.$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)
-	ln -fs libmodsecurity.so.$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)/libmodsecurity.so.3
-	ln -fs libmodsecurity.so.$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)/libmodsecurity.so
+	$$(eval MDH=$$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/headers/modsecurity/modsecurity.h)
+	$$(eval MAJOR=$$(shell awk '/define MODSECURITY_MAJOR /{print $$$$3}' $$(MDH) | sed 's/"//g'))
+	$$(eval MINOR=$$(shell awk '/define MODSECURITY_MINOR /{print $$$$3}' $$(MDH) | sed 's/"//g'))
+	$$(eval PATCHLEV=$$(shell  awk '/define MODSECURITY_PATCHLEVEL / {print $$$$3}' $$(MDH) | sed 's/"//g'))
+	$$(eval LIBMODSECURITY_SOVER=$$(MAJOR).$$(MINOR).$$(PATCHLEV))
+	install -m755 $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/local/lib/libmodsecurity.so.$$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)
+	ln -fs libmodsecurity.so.$$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)/libmodsecurity.so.$$(MAJOR)
+	ln -fs libmodsecurity.so.$$(LIBMODSECURITY_SOVER) $$(INSTALLDIR)/usr/lib/$$(DEB_HOST_MULTIARCH)/libmodsecurity.so
 	mkdir -p $$(INSTALLDIR)/etc/nginx/modsec
-	install -m644 $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION)/modsecurity.conf-recommended $$(INSTALLDIR)/etc/nginx/modsec/modsecurity.conf
-	install -m644 $$(BUILDDIR_nginx)/extra/modsecurity-v$(MODSECURITY_VERSION)/unicode.mapping $$(INSTALLDIR)/etc/nginx/modsec/
+	install -m644 $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/modsecurity.conf-recommended $$(INSTALLDIR)/etc/nginx/modsec/modsecurity.conf
+	install -m644 $$(BUILDDIR_nginx)/extra/modsecurity-$(MODSECURITY_GITHASH)/unicode.mapping $$(INSTALLDIR)/etc/nginx/modsec/
 endef
 export MODULE_PREINSTALL_modsecurity
 
diff --git a/docs/nginx-module-modsecurity.xml b/docs/nginx-module-modsecurity.xml
index 61b54ba..278a1cc 100644
--- a/docs/nginx-module-modsecurity.xml
+++ b/docs/nginx-module-modsecurity.xml
@@ -5,6 +5,36 @@
 <change_log title="nginx_module_modsecurity">
 
 
+<changes apply="nginx-module-modsecurity" ver="1.0.2" rev="4" basever="1.21.6"
+         date="2022-02-02" time="18:13:46 +0300"
+         packager="Igor Ippolitov &lt;iippolitov@nginx.com&gt;">
+<change>
+<para>
+Modsecurity updated to 3.0.6-26-4e37985
+https://github.com/SpiderLabs/ModSecurity/commit/4e37985b22a56c5573084e7b4039288faf2a12f3
+</para>
+</change>
+<change>
+<para>
+Patch for PR2580 included
+https://github.com/SpiderLabs/ModSecurity/pull/2580
+</para>
+</change>
+</changes>
+
+
+<changes apply="nginx-module-modsecurity" ver="1.0.2" rev="3" basever="1.21.6"
+         date="2022-02-02" time="18:13:46 +0300"
+         packager="Igor Ippolitov &lt;iippolitov@nginx.com&gt;">
+<change>
+<para>
+Modsecurity updated to 3.0.6-26-cc83a1b
+</para>
+</change>
+
+</changes>
+
+
 <changes apply="nginx-module-modsecurity" ver="1.0.2" rev="1" basever="1.21.6"
          date="2022-01-25" time="18:13:46 +0300"
          packager="Mikhail Isachenkov &lt;mikhail.isachenkov@nginx.com&gt;">
diff --git a/rpm/SPECS/Makefile.module-modsecurity b/rpm/SPECS/Makefile.module-modsecurity
index ddc0d82..f48ddc3 100644
--- a/rpm/SPECS/Makefile.module-modsecurity
+++ b/rpm/SPECS/Makefile.module-modsecurity
@@ -4,23 +4,32 @@
 
 include $(CONTRIB)/src/modsecurity/version
 include $(CONTRIB)/src/modsecurity-nginx/version
+include $(CONTRIB)/src/libinjection/version
+include $(CONTRIB)/src/secrules-language-tests/version
+include $(CONTRIB)/src/modsecurity-python-bindings/version
 
 MODULE_VERSION_modsecurity=	$(MODSECURITY_NGINX_VERSION)
-MODULE_RELEASE_modsecurity=	2
-LIBMODSECURITY_SOVER=		$(MODSECURITY_VERSION)
+MODULE_RELEASE_modsecurity=	4
 
 MODULE_VERSION_PREFIX_modsecurity=$(MODULE_TARGET_PREFIX)
 
-MODULE_SOURCES_modsecurity=	modsecurity-v$(MODSECURITY_VERSION).tar.gz \
-				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz
+MODULE_SOURCES_modsecurity=	modsecurity-$(MODSECURITY_GITHASH).tar.xz \
+				modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH).tar.xz \
+				libinjection-$(LIBINJECTION_GITHASH).tar.xz \
+				secrules-language-tests-$(SECRULES_LANGUAGE_TESTS_GITHASH).tar.xz \
+				modsecurity-python-bindings-$(MODSECURITY_PYTHON_BINDINGS_GITHASH).tar.xz
 
-MODULE_PATCHES_modsecurity=	$(CONTRIB)/src/modsecurity/older-libmaxminddb-compatibility.patch
+MODULE_PATCHES_modsecurity=	$(CONTRIB)/src/modsecurity/older-libmaxminddb-compatibility.patch \
+				$(CONTRIB)/src/modsecurity/PR2580.patch
 
 MODULE_CONFARGS_modsecurity=	--add-dynamic-module=modsecurity-nginx-$(MODSECURITY_NGINX_GITHASH) \
 				--without-pcre2
 
 .deps-module-modsecurity:
 	cd $(CONTRIB) && make \
+		.sum-libinjection \
+		.sum-secrules-language-tests \
+		.sum-modsecurity-python-bindings \
 		.sum-modsecurity \
 		.sum-modsecurity-nginx
 	touch $@
@@ -30,13 +39,26 @@
 BuildRequires: pkgconfig(yajl)
 BuildRequires: libcurl-devel
 BuildRequires: libxml2-devel
+%if 0%{?suse_version} == 0
+BuildRequires: patchelf
+%endif
 BuildRequires: pcre-devel
+BuildRequires: libtool
+BuildRequires: autoconf
+BuildRequires: automake
 endef
 export MODULE_DEFINITIONS_modsecurity
 
 define MODULE_PREBUILD_modsecurity
-cd %{bdir}/modsecurity-v$(MODSECURITY_VERSION) \&\& \
-./configure --prefix %{bdir}/modsecurity-v$(MODSECURITY_VERSION)/local --without-lmdb --without-lua \&\& \
+cd %{bdir}/modsecurity-$(MODSECURITY_GITHASH) \&\& \
+rm -rf others/libinjection \&\& \
+ln -s ../../libinjection others/libinjection \&\& \
+rm -rf test/test-cases/secrules-language-tests \&\& \
+ln -s ../../../secrules-language-tests test/test-cases/secrules-language-tests \&\& \
+rm -rf bindings/python \&\& \
+ln -s ../../modsecurity-python-bindings bindings/python \&\& \
+./build.sh \&\& \
+./configure --prefix %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/local --without-lmdb --without-lua \&\& \
 make %{?_smp_mflags} install \&\& TERM=foo make check-TESTS
 rm -f /tmp/audit_test.log /tmp/audit_test_parallel.log
 rm -rf /tmp/test
@@ -44,8 +66,8 @@
 export MODULE_PREBUILD_modsecurity
 
 define MODULE_ENV_modsecurity
-MODSECURITY_INC="%{bdir}/modsecurity-v$(MODSECURITY_VERSION)/local/include" \\
-MODSECURITY_LIB="%{bdir}/modsecurity-v$(MODSECURITY_VERSION)/local/lib" \\
+MODSECURITY_INC="%{bdir}/modsecurity-$(MODSECURITY_GITHASH)/local/include" \\
+MODSECURITY_LIB="%{bdir}/modsecurity-$(MODSECURITY_GITHASH)/local/lib" \\
 NGX_IGNORE_RPATH=yes \\
 endef
 export MODULE_ENV_modsecurity
@@ -53,18 +75,23 @@
 MODULE_CC_OPT_DEBUG_modsecurity=-DMODSECURITY_DDEBUG=1
 
 define MODULE_PREINSTALL_modsecurity
+MODSEC_MAJOR=$$(awk '/define MODSECURITY_MAJOR /{print $$3}' %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/headers/modsecurity/modsecurity.h | sed 's/"//g')
+MODSEC_MINOR=$$(awk '/define MODSECURITY_MINOR /{print $$3}' %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/headers/modsecurity/modsecurity.h | sed 's/"//g')
+MODSEC_PATCHLEVEL=$$(awk '/define MODSECURITY_PATCHLEVEL /{print $$3}' %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/headers/modsecurity/modsecurity.h | sed 's/"//g')
+LIBMODSECURITY_SOVER="$$MODSEC_MAJOR.$$MODSEC_MINOR.$$MODSEC_PATCHLEVEL"
 %{__mkdir} -p $$RPM_BUILD_ROOT%{_bindir}
-%{__install} -m755 -s %{bdir}/modsecurity-v$(MODSECURITY_VERSION)/local/bin/modsec-rules-check \
+%{__install} -m755 -s %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/local/bin/modsec-rules-check \
    $$RPM_BUILD_ROOT%{_bindir}/
+which patchelf \&\& patchelf --remove-rpath $$RPM_BUILD_ROOT%{_bindir}/modsec-rules-check
 %{__mkdir} -p $$RPM_BUILD_ROOT%{_libdir}
-%{__install} -m755 %{bdir}/modsecurity-v$(MODSECURITY_VERSION)/local/lib/libmodsecurity.so.$(LIBMODSECURITY_SOVER) \
+%{__install} -m755 %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/local/lib/libmodsecurity.so.$$LIBMODSECURITY_SOVER \
    $$RPM_BUILD_ROOT%{_libdir}/
-%{__ln_s} -f libmodsecurity.so.$(LIBMODSECURITY_SOVER) $$RPM_BUILD_ROOT%{_libdir}/libmodsecurity.so.3
-%{__ln_s} -f libmodsecurity.so.$(LIBMODSECURITY_SOVER) $$RPM_BUILD_ROOT%{_libdir}/libmodsecurity.so
+%{__ln_s} -f libmodsecurity.so.$$LIBMODSECURITY_SOVER $$RPM_BUILD_ROOT%{_libdir}/libmodsecurity.so.$$MODSEC_MAJOR
+%{__ln_s} -f libmodsecurity.so.$$LIBMODSECURITY_SOVER $$RPM_BUILD_ROOT%{_libdir}/libmodsecurity.so
 %{__mkdir} -p $$RPM_BUILD_ROOT%{_sysconfdir}/nginx/modsec
-%{__install} -m644 %{bdir}/modsecurity-v$(MODSECURITY_VERSION)/modsecurity.conf-recommended \
+%{__install} -m644 %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/modsecurity.conf-recommended \
    $$RPM_BUILD_ROOT%{_sysconfdir}/nginx/modsec/modsecurity.conf
-%{__install} -m644 %{bdir}/modsecurity-v$(MODSECURITY_VERSION)/unicode.mapping \
+%{__install} -m644 %{bdir}/modsecurity-$(MODSECURITY_GITHASH)/unicode.mapping \
    $$RPM_BUILD_ROOT%{_sysconfdir}/nginx/modsec/
 endef
 export MODULE_PREINSTALL_modsecurity
@@ -74,9 +101,7 @@
 %config(noreplace) %{_sysconfdir}/nginx/modsec/modsecurity.conf
 %config(noreplace) %{_sysconfdir}/nginx/modsec/unicode.mapping
 %{_bindir}/modsec-rules-check
-%{_libdir}/libmodsecurity.so.$(LIBMODSECURITY_SOVER)
-%{_libdir}/libmodsecurity.so.3
-%{_libdir}/libmodsecurity.so
+%{_libdir}/libmodsecurity.so*
 endef
 export MODULE_FILES_modsecurity