aboutsummaryrefslogtreecommitdiff
;;; Copyright © 2025 Wojtek Kosior <koszko@koszko.org>
;;; Licensed under the Creative Commons Zero v1.0.

(define-module (gnu packages modsecurity)
  #:use-module ((gnu packages apr) #:select (apr apr-util))
  #:use-module ((gnu packages autotools) #:select (autoconf automake libtool))
  #:use-module ((gnu packages bison) #:select (bison))
  #:use-module ((gnu packages curl) #:select (curl))
  #:use-module ((gnu packages databases) #:select (lmdb))
  #:use-module ((gnu packages datastructures) #:select (ssdeep))
  #:use-module ((gnu packages documentation) #:select (doxygen))
  #:use-module ((gnu packages flex) #:select (flex))
  #:use-module ((gnu packages geo) #:select (libmaxminddb))
  #:use-module ((gnu packages lua) #:select (lua))
  #:use-module ((gnu packages pcre) #:select (pcre pcre2))
  #:use-module ((gnu packages perl) #:select (perl))
  #:use-module ((gnu packages pkg-config) #:select (pkg-config))
  #:use-module ((gnu packages xml) #:select (libxml2))
  #:use-module ((gnu packages valgrind) #:select (valgrind))
  #:use-module ((gnu packages web) #:select (httpd yajl))
  #:use-module ((guix build-system gnu) #:select (gnu-build-system))
  #:use-module ((guix gexp) #:select (gexp file-append))
  #:use-module ((guix git-download) #:select
                (git-fetch git-file-name git-reference))
  #:use-module ((guix licenses) #:select (asl2.0 bsd-3))
  #:use-module ((guix packages) #:select
                (base32 delete modify-inputs origin package package-arguments
                 package-inputs replace))
  #:use-module ((guix utils) #:select (substitute-keyword-arguments)))



(define-public libmodsecurity
  (package
   (name "libmodsecurity")
   (version "3.0.13")
   (source (origin
            (method git-fetch)
            (uri (git-reference
                  (url "https://github.com/owasp-modsecurity/ModSecurity")
                  (commit (format #f "v~a" version))
                  (recursive? #t)))
            (file-name (git-file-name name version))
            (sha256 (base32
                     "0khzm7wfd34w3zdhinq8z46c21pwcczb5jvg2j0b0d1v9nvzaggv"))))
   (build-system gnu-build-system)
   (arguments (list
               #:configure-flags
               #~(cons* "--with-pcre2"
                        (map (lambda (name)
                               (format #f "--with-~a=~a" name
                                       (assoc-ref %build-inputs name)))
                             '("curl" "lmdb" "ssdeep")))
               #:phases
               #~(modify-phases %standard-phases
                   (add-after 'patch-source-shebangs 'patch-prog-paths-in-tests
                     (lambda _
                       (let* ((PATH (string-split (getenv "PATH") #\:))
                              (/bin/echo (search-path PATH "echo"))
                              (/bin/ech (string-drop-right /bin/echo 1))
                              (regression "test/test-cases/regression"))
                         (for-each
                          (lambda (test)
                            (substitute*
                                (format #f "test/test-cases/regression/~a.json"
                                        test)
                              (("/bin/ech") /bin/ech)))
                          '("action-exec" "operator-inpectFile")))))
                   (add-before 'configure 'fix-ssdeep-searching
                     (lambda _
                       (substitute* "build/ssdeep.m4"
                         (("\\[Path to ssdeep prefix\\]\\)\\]" matched)
                          (string-append
                           matched
                           ",[SSDEEP_POSSIBLE_PATHS=\"${with_ssdeep}\";"
                           " with_ssdeep=yes]"))))))))
   (inputs (list curl libmaxminddb libxml2 lmdb lua pcre2 ssdeep yajl))
   (native-inputs (list autoconf
                        automake
                        bison
                        doxygen
                        libtool
                        flex
                        perl
                        pkg-config
                        valgrind))
   (synopsis "Free software web application firewall (WAF) library")
   (description "Libmodsecurity is one component of the ModSecurity v3 project.
The library codebase serves as an interface to ModSecurity Connectors taking in
web traffic and applying traditional ModSecurity processing.")
   (home-page "https://modsecurity.org/")
   (license (list asl2.0 ;; libmodsecurity, Mbed TLS
                  bsd-3)))) ;; libinjection

(define httpd-modsecurity-with-older-pcre
  (package
   (name "httpd-modsecurity")
   (version "2.9.8")
   (source (origin
            (method git-fetch)
            (uri (git-reference
                  (url "https://github.com/owasp-modsecurity/ModSecurity")
                  (commit (format #f "v~a" version))))
            (file-name (git-file-name name version))
            (sha256 (base32
                     "04mjmc0kp3k56lvi4s8vmksiqsamspsj5cqbk14bkr36xrw5g7kw"))))
   (build-system gnu-build-system)
   (arguments (list
               #:configure-flags
               #~(let ((inputs `(("apu" . ,(assoc-ref %build-inputs "apr-util"))
                                 ("apxs" . ,(assoc-ref %build-inputs "httpd"))
                                 . ,%build-inputs)))
                   (map (lambda (name)
                          (format #f "--with-~a=~a"
                                  name (assoc-ref inputs name)))
                        '("apr" "apu" "apxs" "curl" "pcre" "ssdeep")))
               #:phases
               #~(modify-phases %standard-phases
                   (add-after 'unpack 'supply-id_log-for-test-linking
                     (lambda _
                       (let ((port (open-file "tests/msc_test.c" "a")))
                         ;; True `id_log' is in `apache2/apache2_config.c' which
                         ;; isn't and cannot (easily) be linked with the test.
                         (format port "const char* id_log(msre_rule* _) ~
                                       {return \"DUMMY\";}")
                         (close port))))
                   (add-after 'unpack 'fix-module-installation-prefix
                     (lambda _
                       (substitute* "apache2/Makefile.am"
                         (("(\\$.DESTDIR.)(\\$.APXS_MODULES.)" _ dst apxs_mods)
                          (format #f "~a$(prefix)~a" dst apxs_mods)))))
                   (add-after 'install-license-files 'install-NOTICE-file
                     (lambda* (#:key outputs #:allow-other-keys)
                       (let* ((out (assoc-ref outputs "out"))
                              (package (strip-store-file-name out)))
                         (install-file "NOTICE" (format #f "~a/share/doc/~a"
                                                        out package))))))))
   (inputs (list apr
                 apr-util
                 curl
                 httpd
                 libxml2
                 lua
                 (list pcre "bin")
                 ssdeep
                 yajl))
   (native-inputs (list autoconf automake httpd libtool perl pkg-config))
   (synopsis "Free software web application firewall (WAF) module")
   (description "ModSecurity enables web application defenders to gain
visibility into HTTP(S) and provides a power rules language and API to implement
advanced protections.")
   (home-page "https://modsecurity.org/")
   (license (list asl2.0))))

(define-public httpd-modsecurity
  (let ((base httpd-modsecurity-with-older-pcre))
    (package
      (inherit base)
      (arguments (substitute-keyword-arguments (package-arguments base)
                   ;; Sadly, tests don't seem to work with PRCE2.
                   ((#:tests? _ #f) #f)
                   ((#:configure-flags flags)
                    #~(cons (format #f "--with-pcre2=~a"
                                    (assoc-ref %build-inputs "pcre2"))
                            #$flags))))
      (inputs (modify-inputs (package-inputs base)
                (delete "pcre")
                (append pcre2))))))