diff --git a/docs/libxml2-json-review-2026-04-14.md b/docs/libxml2-json-review-2026-04-14.md new file mode 100644 index 0000000000..c2fb80b4cf --- /dev/null +++ b/docs/libxml2-json-review-2026-04-14.md @@ -0,0 +1,377 @@ +# libxml2 Security-/Architektur-/Dependency-Audit (Stand: 2026-04-14) + +## 1. Executive Summary + +### Im Repo belegt +- libxml2 wird aktiv für XML-Request-Body-Parsing, XPath-Variablen und DTD/XSD-Validierung verwendet. +- Die Integration ist buildseitig optional (`WITH_LIBXML2`), funktional aber kritisch für XML-Regeln. +- JSON ist bereits über eine klarere Backend-Abstraktion (simdjson/jsoncons + `JSONAdapter`/`JsonEventSink`) modularisiert. +- YAJL ist im C/C++-Codepfad nicht mehr nachweisbar, aber in README/CI weiterhin als Dependency referenziert. + +### Extern belegt +- Upstream libxml2 steht bei 2.15.2 (März 2026). +- Offizielle API-Doku markiert die im Repo genutzte globale Loader-Umschaltung als deprecated. +- Debian/Ubuntu zeigen, dass numerisch ältere Paketstände weiterhin Security-Backports erhalten; Fedora und Homebrew liegen näher an aktuellen Upstream-Ständen. + +### Schlussfolgerung +- **libxml2 sollte modernisiert werden** (Version-/Security-/API-Härtung). +- **libxml2 ist aktuell nicht der Primär-Blocker für JSON-Migration**. +- **Modularisierung von libxml2 ist sinnvoll, aber gestaffelt** (nicht als Big-Bang parallel zur JSON-Ablösung). +- **Release-/Advisory-Monitoring-Workflow ist empfehlenswert**, aber als „monitor + report + manuelle Freigabe“, nicht als blindes Auto-Upgrade. + +### Unsicherheit / nicht verifizierbar +- Produktiv tatsächlich eingesetzte libxml2-Versionen außerhalb CI/Windows-Conan: **Nicht verifizierbar.** + +--- + +## 2. Repo-Befunde zu libxml2 + +### Im Repo belegt + +#### Code-Nutzung +- Globale Initialisierung/Shutdown: `xmlInitParser()`/`xmlCleanupParser()` in `src/modsecurity.cc`. +- Request-Body-XML-Parsing: Push-Parser + SAX in `src/request_body_processor/xml.cc`. +- XPath-Auswertung: `src/variables/xml.cc`. +- DTD-Validierung: `src/operators/validate_dtd.cc`. +- XSD-Validierung: `src/operators/validate_schema.cc`. +- Dispatcher XML/JSON: `src/transaction.cc`. + +#### Sicherheitsrelevante Befunde +- Externe Entitäten werden über `SecXMLExternalEntity` via globalen Loader-Callback gesteuert (`xmlParserInputBufferCreateFilenameDefault`). +- Parseroptionen setzen sichtbar `XML_PARSE_NOWARNING | XML_PARSE_NOERROR`. +- Sichtbarer Einsatz von `XML_PARSE_NO_XXE` im XML-Body-Parserpfad: nicht belegt. + +#### Build/Dependency +- Autotools-Mindestversion für libxml2: `2.6.29`. +- Windows-Conan pinnt `libxml2/2.12.6`. +- CI testet mit und ohne `--without-libxml`. + +#### Tests/Fuzzing +- Mehrere Regressionsfälle mit Resource-Gate `libxml2`. +- Expliziter XXE-Regressionsfall (`config-xml_external_entity.json`). +- Fuzzer-Linking enthält `$(LIBXML2_LDADD)`. + +### Extern belegt +- Keine externen Quellen für diese Repo-internen Fakten erforderlich. + +### Schlussfolgerung +- libxml2 ist für XML-Features technisch zentral. +- Sicherheitskontrolle ist vorhanden, aber über global/deprecated Mechanismus statt moderner, kontextbezogener API. +- Versionierungsstrategie wirkt inkonsistent (sehr alte Mindestgrenze vs. neuerer Windows-Pin). + +### Unsicherheit / nicht verifizierbar +- Thread-Safety-Auswirkungen des globalen Loader-Umschaltens unter realer Parallelität sind aus dem Repo allein **nicht vollständig verifizierbar**. + +--- + +## 3. Repo-Befunde zur JSON-Migration (YAJL → neue Bibliothek) + +### Im Repo belegt +- `configure.ac` unterstützt `--with-json-backend=simdjson|jsoncons`. +- JSON-Backends sind separat implementiert (`json_backend_simdjson.cc`, `json_backend_jsoncons.cc`) und über `JSONAdapter` abstrahiert. +- `JsonEventSink`/`JsonParseResult` bilden ein konsistentes Contract-Modell. +- Es existieren dedizierte Backend-Tests (`json_backend_depth_tests`) und eine Matrix-Ausführung (`test/run-json-backend-matrix.sh`). +- YAJL-Nutzung im C/C++-Codepfad: durch Suche nach `yajl`/YAJL-Includes nicht belegt. +- YAJL-Referenzen verbleiben in README und CI-Paketinstallation. + +### Extern belegt +- Nicht erforderlich für Repo-Befund. + +### Schlussfolgerung +- Die neue JSON-Schicht ist klar modularer als XML. +- Der Zustand ist konsistent mit einer laufenden/weit fortgeschrittenen Ablösung von YAJL im Kerncode, bei verbleibenden Dokumentations-/CI-Resten. + +### Unsicherheit / nicht verifizierbar +- Exakter Migrationsstatus in nicht sichtbaren Branches/Downstreams: **Nicht verifizierbar.** + +--- + +## 4. Aktueller externer Stand zu libxml2 + +### Extern belegt +- GNOME Release-Index führt libxml2 2.15.x, inklusive `LATEST-IS-2.15.2`. +- 2.14.0 Release Notes: SONAME-Änderung (`libxml2.so.2` → `libxml2.so.16`) und ABI-Hinweise. +- 2.15.0 Release Notes: u. a. Wegfall built-in HTTP/LZMA-Komponenten. +- 2.15.2 Release Notes: mehrere Security-Fixes/CVE-Referenzen. +- 2.12.10 Release Notes enthalten u. a. CVE-2025-24928 / CVE-2024-56171. +- NVD führt CVE-2025-24928 mit betroffenen älteren Versionen. +- Offizielle API-Doku: + - `xmlParserInputBufferCreateFilenameDefault` deprecated (`xmlIO_8h`). + - `XML_PARSE_NO_XXE` als relevante Sicherheitsoption (`parser_8h`). + +### Im Repo belegt +- Nicht anwendbar. + +### Schlussfolgerung +- Upstream entwickelt sich sicherheits- und API-seitig aktiv; mittelfristiges „stehen bleiben“ erhöht Wartungs- und Security-Risiko. + +### Unsicherheit / nicht verifizierbar +- Vollständige CVE-Enrichment-Konsistenz über alle Datenbanken am selben Tag: **Nicht verifizierbar.** + +--- + +## 5. Linux- und macOS-Versions-/Packaging-Vergleich + +### Extern belegt + +#### Linux +- Debian Security Tracker zeigt für stabile Releases numerisch ältere Versionsstände mit separaten Security-Updates/DSA/DLA (Backport-Modell). +- Ubuntu Paket-/USN-Seiten zeigen ebenfalls ältere Versionsnummern mit Security-Notices/Updates. +- Fedora-Paketseite listet deutlich neuere Stände (z. B. 2.12.10 in Fedora-Releases laut gelisteter Übersicht). + +#### macOS +- Homebrew `libxml2`-API zeigt `stable: 2.15.2`, `keg_only` mit Grund `provided_by_macos`. +- Das belegt zugleich die Trennung zwischen systembereitgestellter libxml2 und explizit installierter Homebrew-Variante. + +### Im Repo belegt +- CI installiert auf Linux `libxml2-dev` (APT) und auf macOS `brew install libxml2`. + +### Schlussfolgerung +- Reiner Versionsnummernvergleich reicht nicht: Debian/Ubuntu können numerisch ältere, aber security-gepflegte Pakete liefern. +- Für reproduzierbare Sicherheitsbewertung muss das Projekt klarer festlegen, ob Systempakete, Homebrew/Conan oder pin-basierte Vendor-Strategie maßgeblich sind. + +### Unsicherheit / nicht verifizierbar +- Exakte Backport-Abdeckung aller relevanten CVEs je Distribution/Release ohne vollständige Advisory-Matrix: **Nicht verifizierbar.** + +--- + +## 6. Sicherheitsbewertung + +### Im Repo belegt +- XML-Eingaben sind untrusted Request-Body-Daten. +- Schutz gegen externe Entitäten basiert aktuell auf globalem Loader-Override. +- `XML_PARSE_NO_XXE`-Setzung im gezeigten XML-Body-Pfad ist nicht belegt. +- XML und JSON laufen beide über denselben Request-Body-Dispatcher, aber mit separaten Prozessoren. + +### Extern belegt +- Deprecated-Status des globalen Loader-Mechanismus. +- Vorhandensein aktueller Sicherheitsfixes in neueren libxml2-Releases. + +### Schlussfolgerung +- Sicherheit ist **teilweise abgesichert**, aber nicht auf dem robustesten verfügbaren Mechanismus. +- Zentralisierte Sicherheitsdefaults in einer XML-Fassade würden das Risiko inkonsistenter Parser-Konfiguration senken. + +### Unsicherheit / nicht verifizierbar +- Ob alle Angriffsvektoren (insb. Race-/Global-State-Randfälle) unter Produktionslast abgedeckt sind: **Nicht verifizierbar.** + +--- + +## 7. Architekturvergleich: libxml2 vs. neue JSON-Schicht + +### Im Repo belegt +- JSON: klarer Backend-Contract (`JsonEventSink`, Result-Typen), Adapter (`JSONAdapter`), austauschbare Implementierungen, dedizierte Backendspezifik-Tests. +- XML: direkte libxml2-Aufrufe in mehreren Fachkomponenten ohne zentrales XML-Backend-Interface. + +### Extern belegt +- Nicht erforderlich. + +### Schlussfolgerung +- JSON ist architektonisch stärker entkoppelt. +- Das JSON-Muster ist ein konkreter Referenzentwurf für ein XML-Modul (Facade/Adapter/Options/Result-Contract). + +### Unsicherheit / nicht verifizierbar +- Netto-Performanceeffekt einer XML-Adapter-Schicht ohne Benchmarks: **Nicht verifizierbar.** + +--- + +## 8. Bewertung: libxml2 als Modul integrieren oder nicht + +### Kategorie +**Ja, aber nur in einem gestaffelten Ansatz.** + +### Im Repo belegt +- XML ist aktuell weniger modular als JSON. +- Direkte libxml2-Nutzung existiert an mehreren Stellen. + +### Extern belegt +- Upstream/API-Situation (deprecated global loader + laufende Security-Fixes) stützt die Notwendigkeit zentraler Kontrolle. + +### Schlussfolgerung +- Modulgrenze bringt Vorteile bei Wartbarkeit, Testbarkeit, Sicherheitsstandardisierung und späteren Upgrades. +- Parallel als Big-Bang zur JSON-Migration wäre unnötig riskant; sinnvoll ist eine sequenzierte Einführung. + +### Unsicherheit / nicht verifizierbar +- Konkreter Refactoring-Aufwand bis auf Funktions-/Dateiebene ohne Spike-Implementierung: **Nicht verifizierbar.** + +--- + +## 9. Bewertung: Ist direkte Modulbildung sicher + +### Im Repo belegt +- Es gibt aktuell globale libxml2-Steuerungspunkte und direkte API-Aufrufe in Fachcode. + +### Extern belegt +- Deprecated API-Hinweise unterstützen eine Umstellung auf zentral kontrollierte, kontextbezogene Ressourcen-/Parserkonfiguration. + +### Schlussfolgerung +- **Direkte Modulbildung ist nicht automatisch „sicher“, aber kann sicherer werden**, wenn Guardrails verpflichtend sind: + 1. Zentrale Parser-Defaults (inkl. XXE-/Resource-Policy) im Modul. + 2. Harte Limits (Depth/Size/Entity-Policy) im Modul-Contract. + 3. Einheitliche Fehlerklassifikation und Auditierbarkeit. + 4. Explizite Trennung trusted/untrusted Inputs. + 5. Verbot neuer direkter libxml2-Aufrufe außerhalb des Moduls (CI-Lint/Codeowners). + +### Unsicherheit / nicht verifizierbar +- Ohne diese Guardrails ist die Aussage „Modulbildung ist sicher genug“ **nicht verifizierbar**. + +--- + +## 10. Bewertung: Release-/Security-Monitoring-Workflow + +### Im Repo belegt +- CI testet Build-Varianten, aber ein dediziertes Release-/Advisory-Monitoring für libxml2 + JSON-Backend ist nicht als eigener Workflow ersichtlich. + +### Extern belegt +- Upstream-Releases (libxml2, simdjson/jsoncons) ändern sich regelmäßig. +- Distributionen liefern teils Backports, daher reicht „nur Upstream-Version vergleichen“ nicht. + +### Schlussfolgerung +**Empfehlung: beobachten + reporten + manuell freigegebene Updates.** + +- **Release Monitoring:** Ja (Upstream libxml2 + verwendetes JSON-Backend). +- **Security Advisory Monitoring:** Ja (CVE/NVD + distro advisories). +- **Automatisches Upgrade:** Nein, nicht blind. +- **Manuell freigegebener Update-Prozess:** Ja. + +Pragmatisches Modell: +1. Geplanter Workflow (z. B. wöchentlich) sammelt Versionen/Advisories. +2. Erzeugt Report + optional GitHub Issue/PR-Kommentar. +3. Menschen entscheiden über Upgrade/Patchbackport nach Testmatrix. + +### Unsicherheit / nicht verifizierbar +- Konkretes Signal-zu-Rauschen-Verhältnis ohne Pilotlauf: **Nicht verifizierbar.** + +--- + +## 11. Klare Gesamtentscheidungen + +1. **Soll libxml2 aktualisiert oder erneuert werden?** + - **Ja, Aktualisierung/Modernisierung empfohlen.** + - Belege: Upstream 2.15.2, Security-Fixes, deprecated API-Hinweise, Repo nutzt alte Mindestgrenze + globalen Mechanismus. + - Hauptrisiko: Migrations-/Kompatibilitätsaufwand. + - Unsicherheit: konkrete Upgrade-Auswirkungen je Zielplattform **nicht vollständig verifizierbar**. + +2. **Soll libxml2 als eigenes Modul integriert werden?** + - **Ja, aber nur in gestaffeltem Ansatz.** + - Belege: JSON-Adaptermuster vorhanden; XML aktuell weniger entkoppelt. + - Hauptrisiko: Refactoring-Komplexität. + +3. **Ist jetzt wegen YAJL-Ablösung ein guter Zeitpunkt dafür?** + - **Teilweise ja: vorbereiten jetzt, harte Umstellung gestaffelt.** + - Belege: JSON-Migrationsarchitektur liefert Muster; gleichzeitiger Big-Bang erhöht Risiko. + +4. **Ist direkte Modulbildung sicher genug?** + - **Nur mit Guardrails.** + - Ohne zentrale Sicherheitsdefaults/Limits/Policy-Enforcement: **nicht sicher genug belastbar belegt**. + +5. **Soll ein Workflow zur Abfrage aktueller Releases/Sicherheitsstände eingeführt werden?** + - **Ja: Monitoring + Reporting + manuelle Freigabe.** + - Kein blindes Auto-Upgrade. + +--- + +## 12. Priorisierte Maßnahmen + +## Kurzfristig +1. **Repo-Hygiene YAJL-Reste bereinigen** +- Änderung: README/CI-Dependency-Liste gegen tatsächliche JSON-Backends konsolidieren. +- Ziel: Architektur- und Security-Transparenz. +- Risiko bei Nicht-Umsetzung: falsche Annahmen in Betrieb/Audit. +- Eingriffsgrad: niedrig. +- Plattformauswirkung: gering. +- Testbedarf: CI-Konfig-Tests. +- Sicherheitsauswirkung: indirekt positiv (weniger Drift). + +2. **XML-Sicherheits-Baseline dokumentieren und härten** +- Änderung: explizite Policy für XXE/DTD/externes Laden, Limits, Fehlermeldungsstrategie. +- Eingriffsgrad: niedrig-mittel. +- Sicherheitsauswirkung: hoch. + +3. **Monitoring-Workflow als Report-only einführen** +- Änderung: geplanter Job sammelt libxml2 + JSON-Backend Releases, CVE/NVD, Debian/Ubuntu/Fedora, Homebrew-Stände. +- Ausgabe: maschinenlesbarer Report + optional Issue. +- Sicherheitsauswirkung: hoch. + +## Mittelfristig +4. **XML-Fassade (intern) einführen** +- Änderung: `XmlParseOptions`, `XmlParseResult`, zentrale `XmlProcessor`-Schnittstelle. +- Ziel: Entkopplung/Standardisierung. +- Risiko: Regressionen. +- Eingriffsgrad: mittel-hoch. +- Testbedarf: neue Unit-/Integrationstests + bestehende Regressionen. + +5. **Direkte libxml2-Aufrufe schrittweise konsolidieren** +- Kandidaten: `request_body_processor/xml.cc`, `variables/xml.cc`, `operators/validate_*`. +- Ziel: keine direkten libxml2-Calls außerhalb XML-Modul. +- Sicherheitsauswirkung: mittel-hoch. + +## Langfristig +6. **Formatübergreifendes Parsing-Contract (JSON/XML) harmonisieren** +- Änderung: gemeinsame Prinzipien für Optionen, Limits, Errors, Telemetrie. +- Ziel: konsistente Security- und Wartbarkeitseigenschaften. + +7. **Governance-Prozess für Abhängigkeiten** +- Änderung: feste Review-Kadenz, Security-Triage, manuelle Freigabegates. +- Sicherheitsauswirkung: hoch. + +--- + +## 13. Offene Unsicherheiten / nicht verifizierbare Punkte + +- Produktiv verwendete libxml2-Version je Deployment: **Nicht verifizierbar.** +- Vollständige Backport-Abdeckung aller relevanten CVEs je Linux-Distribution/Release: **Nicht verifizierbar.** +- Genaue Upgrade-Kompatibilität (ABI/API) für alle Downstreams: **Nicht verifizierbar.** +- Exakter Performance-Impact einer XML-Fassade ohne Benchmarks: **Nicht verifizierbar.** +- Eindeutiger Abschlussstatus der YAJL-Migration außerhalb sichtbarer Repo-Artefakte: **Nicht verifizierbar.** + +--- + +## 14. Quellenliste + +## Repository +- `src/modsecurity.cc` +- `src/transaction.cc` +- `src/request_body_processor/xml.cc` +- `src/variables/xml.cc` +- `src/operators/validate_dtd.cc` +- `src/operators/validate_schema.cc` +- `src/request_body_processor/json_backend.h` +- `src/request_body_processor/json_adapter.cc` +- `src/request_body_processor/json_backend_simdjson.cc` +- `src/request_body_processor/json_backend_jsoncons.cc` +- `configure.ac` +- `build/libxml.m4` +- `build/win32/conanfile.txt` +- `build/win32/README.md` +- `.github/workflows/ci.yml` +- `.github/workflows/ci_new.yml` +- `README.md` +- `test/run-json-backend-matrix.sh` +- `test/unit/json_backend_depth_tests.cc` +- `test/test-cases/regression/config-xml_external_entity.json` +- `test/fuzzer/Makefile.am` + +## Externe Primärquellen +- libxml2 Upstream Releases/Archive: + - https://download.gnome.org/sources/libxml2/ + - https://download.gnome.org/sources/libxml2/2.15/ + - https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.2.news + - https://download.gnome.org/sources/libxml2/2.15/libxml2-2.15.0.news + - https://download.gnome.org/sources/libxml2/2.14/libxml2-2.14.0.news + - https://download.gnome.org/sources/libxml2/2.12/libxml2-2.12.10.news +- Offizielle API-Dokumentation: + - https://gnome.pages.gitlab.gnome.org/libxml2/html/parser_8h.html + - https://gnome.pages.gitlab.gnome.org/libxml2/html/xmlIO_8h.html +- CVE-Datenbank: + - https://nvd.nist.gov/vuln/detail/CVE-2025-24928 +- Linux-Paketquellen: + - Debian Security Tracker: https://security-tracker.debian.org/tracker/source-package/libxml2 + - Ubuntu Packages (noble): https://packages.ubuntu.com/noble/libxml2-dev + - Ubuntu Security Notice (USN-7743-1): https://ubuntu.com/security/notices/USN-7743-1 + - Fedora Packages: https://packages.fedoraproject.org/pkgs/libxml2/libxml2/ +- macOS/Packaging: + - Homebrew libxml2 API: https://formulae.brew.sh/api/formula/libxml2.json + - Homebrew simdjson API: https://formulae.brew.sh/api/formula/simdjson.json +- JSON-Backend Upstream-Releases: + - simdjson Releases: https://github.com/simdjson/simdjson/releases + - jsoncons Releases: https://github.com/danielaparker/jsoncons/releases diff --git a/headers/modsecurity/audit_log.h b/headers/modsecurity/audit_log.h index ab1e798dd7..dce0175873 100644 --- a/headers/modsecurity/audit_log.h +++ b/headers/modsecurity/audit_log.h @@ -17,6 +17,7 @@ #include #include #include +#include #endif #ifndef HEADERS_MODSECURITY_AUDIT_LOG_H_ diff --git a/headers/modsecurity/rules_set_phases.h b/headers/modsecurity/rules_set_phases.h index 849d8ec1bf..473d939f8e 100644 --- a/headers/modsecurity/rules_set_phases.h +++ b/headers/modsecurity/rules_set_phases.h @@ -20,6 +20,7 @@ #ifdef __cplusplus #include #include +#include #include #include #include @@ -60,4 +61,4 @@ class RulesSetPhases { } // namespace modsecurity #endif -#endif // HEADERS_MODSECURITY_RULES_SET_PHASES_H_ \ No newline at end of file +#endif // HEADERS_MODSECURITY_RULES_SET_PHASES_H_ diff --git a/headers/modsecurity/rules_set_properties.h b/headers/modsecurity/rules_set_properties.h index e16db04665..19a310fbe7 100644 --- a/headers/modsecurity/rules_set_properties.h +++ b/headers/modsecurity/rules_set_properties.h @@ -25,6 +25,7 @@ #ifdef __cplusplus #include #include +#include #include #include #include diff --git a/src/actions/ctl/rule_remove_by_id.h b/src/actions/ctl/rule_remove_by_id.h index f731db31cc..53cd379e76 100644 --- a/src/actions/ctl/rule_remove_by_id.h +++ b/src/actions/ctl/rule_remove_by_id.h @@ -13,7 +13,9 @@ * */ +#include #include +#include #include "modsecurity/actions/action.h" #include "modsecurity/transaction.h" diff --git a/src/anchored_set_variable.cc b/src/anchored_set_variable.cc index 4c81dab412..eb04adf410 100644 --- a/src/anchored_set_variable.cc +++ b/src/anchored_set_variable.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/anchored_variable.cc b/src/anchored_variable.cc index 51860d1fe6..83f4209a3e 100644 --- a/src/anchored_variable.cc +++ b/src/anchored_variable.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/audit_log/audit_log.cc b/src/audit_log/audit_log.cc index 4115d5f34a..3068cbdd63 100644 --- a/src/audit_log/audit_log.cc +++ b/src/audit_log/audit_log.cc @@ -20,6 +20,7 @@ #include #include +#include #include "modsecurity/transaction.h" #include "modsecurity/rule_message.h" diff --git a/src/operators/pm_from_file.cc b/src/operators/pm_from_file.cc index 52651e95cc..7bd778dc62 100644 --- a/src/operators/pm_from_file.cc +++ b/src/operators/pm_from_file.cc @@ -15,6 +15,7 @@ #include "src/operators/pm_from_file.h" +#include #include #include "src/operators/operator.h" diff --git a/src/operators/validate_byte_range.cc b/src/operators/validate_byte_range.cc index 9ad4d2921c..2ee7725c70 100644 --- a/src/operators/validate_byte_range.cc +++ b/src/operators/validate_byte_range.cc @@ -15,6 +15,7 @@ #include "src/operators/validate_byte_range.h" +#include #include #include #include diff --git a/src/request_body_processor/json.cc b/src/request_body_processor/json.cc index 502f8ec369..800377cd54 100644 --- a/src/request_body_processor/json.cc +++ b/src/request_body_processor/json.cc @@ -20,10 +20,12 @@ #include "src/request_body_processor/json.h" #include +#include #include #include #include +#include "modsecurity/transaction.h" #include "src/request_body_processor/json_adapter.h" #include "src/request_body_processor/json_instrumentation.h" @@ -31,7 +33,8 @@ namespace modsecurity::RequestBodyProcessor { static const double json_depth_limit_default = 10000.0; -static const char* json_depth_limit_exceeded_msg = ". Parsing depth limit exceeded"; +static const char *const json_depth_limit_exceeded_msg = + ". Parsing depth limit exceeded"; namespace { @@ -119,11 +122,7 @@ JsonSinkStatus addStringViewAsSinkStatus(JSON *json, std::string_view value) { } // namespace JSON::JSON(Transaction *transaction) : m_transaction(transaction), - m_current_key(""), - m_data(""), - m_max_depth(json_depth_limit_default), - m_current_depth(0), - m_depth_limit_exceeded(false) { + m_max_depth(json_depth_limit_default) { } @@ -185,11 +184,11 @@ bool JSON::complete(std::string *err) { int JSON::addArgument(const std::string& value) { - std::string data(""); + std::string data; std::string path; - for (size_t i = 0; i < m_containers.size(); i++) { - const JSONContainerArray *a = dynamic_cast( + for (size_t i = 0; i < m_containers.size(); i++) { + const auto *a = dynamic_cast( m_containers[i].get()); path = path + m_containers[i]->m_name; if (a != nullptr) { @@ -199,8 +198,8 @@ int JSON::addArgument(const std::string& value) { } } - if (m_containers.size() > 0) { - JSONContainerArray *a = dynamic_cast( + if (!m_containers.empty()) { + auto *a = dynamic_cast( m_containers.back().get()); if (a) { a->m_elementCounter++; diff --git a/src/request_body_processor/json.h b/src/request_body_processor/json.h index 9c70c2ebcf..79c0da958a 100644 --- a/src/request_body_processor/json.h +++ b/src/request_body_processor/json.h @@ -16,15 +16,19 @@ #ifndef SRC_REQUEST_BODY_PROCESSOR_JSON_H_ #define SRC_REQUEST_BODY_PROCESSOR_JSON_H_ +#include #include #include #include #include +#include -#include "modsecurity/transaction.h" -#include "modsecurity/rules_set.h" #include "src/request_body_processor/json_backend.h" +namespace modsecurity { +class Transaction; +} + namespace modsecurity::RequestBodyProcessor { @@ -32,22 +36,21 @@ namespace modsecurity::RequestBodyProcessor { class JSONContainer { public: explicit JSONContainer(const std::string &name) : m_name(name) { } - virtual ~JSONContainer() { } + virtual ~JSONContainer() = default; std::string m_name; }; class JSONContainerArray : public JSONContainer { public: - explicit JSONContainerArray(const std::string &name) : JSONContainer(name), - m_elementCounter(0) { } - size_t m_elementCounter; + using JSONContainer::JSONContainer; + size_t m_elementCounter = 0; }; class JSONContainerMap : public JSONContainer { public: - explicit JSONContainerMap(const std::string &name) : JSONContainer(name) { } + using JSONContainer::JSONContainer; }; @@ -88,7 +91,7 @@ class JSON : public JsonEventSink { std::string getCurrentKey(bool emptyIsNull = false) { std::string ret(m_current_key); - if (m_containers.size() == 0) { + if (m_containers.empty()) { return "json"; } if (m_current_key.empty()) { @@ -109,12 +112,12 @@ class JSON : public JsonEventSink { void clearContainers(); std::deque> m_containers; - Transaction *m_transaction; + Transaction *m_transaction = nullptr; std::string m_current_key; std::string m_data; - double m_max_depth; - int64_t m_current_depth; - bool m_depth_limit_exceeded; + double m_max_depth = 0.0; + int64_t m_current_depth = 0; + bool m_depth_limit_exceeded = false; }; diff --git a/src/request_body_processor/json_backend_jsoncons.cc b/src/request_body_processor/json_backend_jsoncons.cc index 5c64d96929..32fc0b3989 100644 --- a/src/request_body_processor/json_backend_jsoncons.cc +++ b/src/request_body_processor/json_backend_jsoncons.cc @@ -22,11 +22,11 @@ #include #include +#include #include #include #include #include -#include #include "src/request_body_processor/json_instrumentation.h" #include @@ -704,7 +704,7 @@ JsonParseResult parseDocumentWithJsoncons(const std::string &input, std::chrono::steady_clock::now() - event_loop_start).count())); }; const auto finish_with_event_loop = [&record_event_loop]( - JsonParseResult result) { + const JsonParseResult &result) { record_event_loop(); return result; }; @@ -717,8 +717,9 @@ JsonParseResult parseDocumentWithJsoncons(const std::string &input, cursor.current(), cursor.context()); !result.ok()) { #ifdef MSC_JSON_AUDIT_INSTRUMENTATION return finish_with_event_loop(result); -#endif +#else return result; +#endif } cursor.next(error); @@ -726,8 +727,9 @@ JsonParseResult parseDocumentWithJsoncons(const std::string &input, #ifdef MSC_JSON_AUDIT_INSTRUMENTATION return finish_with_event_loop( fromJsonconsError(error, cursor.context())); -#endif +#else return fromJsonconsError(error, cursor.context()); +#endif } } @@ -736,8 +738,9 @@ JsonParseResult parseDocumentWithJsoncons(const std::string &input, #ifdef MSC_JSON_AUDIT_INSTRUMENTATION return finish_with_event_loop(fromJsonconsError(error, cursor.context())); -#endif +#else return fromJsonconsError(error, cursor.context()); +#endif } #ifdef MSC_JSON_AUDIT_INSTRUMENTATION diff --git a/src/request_body_processor/json_backend_simdjson.cc b/src/request_body_processor/json_backend_simdjson.cc index ac7108b5e2..525c1560b3 100644 --- a/src/request_body_processor/json_backend_simdjson.cc +++ b/src/request_body_processor/json_backend_simdjson.cc @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -107,12 +108,12 @@ simdjson::ondemand::parser &getReusableSimdjsonParser() { if (parser == nullptr) { #ifdef MSC_JSON_AUDIT_INSTRUMENTATION const auto parser_start = std::chrono::steady_clock::now(); - parser.reset(new simdjson::ondemand::parser()); + parser = std::make_unique(); recordSimdjsonParserConstruction(static_cast( std::chrono::duration_cast( std::chrono::steady_clock::now() - parser_start).count())); #else - parser.reset(new simdjson::ondemand::parser()); + parser = std::make_unique(); #endif } return *parser; @@ -398,7 +399,7 @@ class JsonBackendWalker { "handling a boolean"); } - JsonParseResult enforceTechnicalDepth(simdjson::ondemand::value value) { + JsonParseResult enforceTechnicalDepth(simdjson::ondemand::value value) const { const int32_t current_depth = value.current_depth(); if (current_depth <= 0) { return makeResult(JsonParseStatus::InternalError, diff --git a/src/request_body_processor/json_instrumentation.cc b/src/request_body_processor/json_instrumentation.cc index b5fae287e6..1d241e84d5 100644 --- a/src/request_body_processor/json_instrumentation.cc +++ b/src/request_body_processor/json_instrumentation.cc @@ -5,6 +5,8 @@ #include "src/request_body_processor/json_instrumentation.h" #include +#include +#include namespace modsecurity::RequestBodyProcessor { namespace { diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index 3ae591671e..02d7f5daf5 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -15,6 +15,7 @@ #include "src/request_body_processor/multipart.h" +#include #include #include #include diff --git a/src/request_body_processor/multipart.h b/src/request_body_processor/multipart.h index 08d4ffe920..48c1de304e 100644 --- a/src/request_body_processor/multipart.h +++ b/src/request_body_processor/multipart.h @@ -13,11 +13,14 @@ * */ +#include +#include #include #include #include #include #include +#include #ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ #define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ diff --git a/src/request_body_processor/xml.cc b/src/request_body_processor/xml.cc index cbb7894c9b..48ebd6dae2 100644 --- a/src/request_body_processor/xml.cc +++ b/src/request_body_processor/xml.cc @@ -15,38 +15,33 @@ #include "src/request_body_processor/xml.h" -#include -#include +#include #include +#include "modsecurity/rules_set.h" +#include "modsecurity/rules_set_properties.h" +#include "modsecurity/transaction.h" -namespace modsecurity { -namespace RequestBodyProcessor { + +namespace modsecurity::RequestBodyProcessor { #ifdef WITH_LIBXML2 /* * NodeData for parsing XML into args */ -NodeData::NodeData() { - has_child = false; -} +NodeData::NodeData() = default; -NodeData::~NodeData() {}; +NodeData::~NodeData() = default; /* * XMLNodes for parsing XML into args */ XMLNodes::XMLNodes(Transaction *transaction) - : nodes{}, - node_depth(0), - currpath(""), - currval(""), - currval_is_set(false), - m_transaction(transaction) + : m_transaction(transaction) {} -XMLNodes::~XMLNodes() {}; +XMLNodes::~XMLNodes() = default; /* * SAX handler for parsing XML into args @@ -57,59 +52,56 @@ class MSCSAXHandler { std::string name = reinterpret_cast(localname); - XMLNodes* xml_data = static_cast(ctx); + auto *xml_data = static_cast(ctx); xml_data->nodes.push_back(std::make_shared()); xml_data->node_depth++; - // FIXME - later if we want to check the depth of XML tree - /* if (max_depth > 0 && max_depth > xml_data->node_depth) { - std::cout << "Depth of XML tree reached the given maximum value " << xml_data->node_depth << std::endl; - exit(1); - } */ // if it's not the first (root) item, then append a '.' // note, the condition should always be true because there is always a pseudo root element: 'xml' if (xml_data->nodes.size() > 1) { xml_data->currpath.append("."); - xml_data->nodes[xml_data->nodes.size()-2]->has_child = true; + const std::size_t parent_index = xml_data->nodes.size() - 2; + xml_data->nodes[parent_index]->has_child = true; } xml_data->currpath.append(name); // set the current value empty // this is necessary because if there is any text between the tags (new line, etc) // it will be added to the current value - xml_data->currval = ""; + xml_data->currval.clear(); xml_data->currval_is_set = false; } void onEndElement(void * ctx, const xmlChar *localname) { std::string name = reinterpret_cast(localname); - XMLNodes* xml_data = static_cast(ctx); - const std::shared_ptr& nd = xml_data->nodes[xml_data->nodes.size()-1]; - if (nd->has_child == false) { + auto *xml_data = static_cast(ctx); + if (const auto &nd = + xml_data->nodes.back(); + !nd->has_child && !xml_data->m_transaction->addArgument( + "XML", xml_data->currpath, xml_data->currval, 0)) { // check the return value // if false, then stop parsing // this means the number of arguments reached the limit - if (xml_data->m_transaction->addArgument("XML", xml_data->currpath, xml_data->currval, 0) == false) { - xmlStopParser(xml_data->parsing_ctx_arg); - } + xmlStopParser(xml_data->parsing_ctx_arg); } - if (xml_data->currpath.length() > 0) { + if (!xml_data->currpath.empty()) { // set an offset to store whether this is the first item, in order to know whether to remove the '.' - int offset = (xml_data->nodes.size() > 1) ? 1 : 0; - xml_data->currpath.erase(xml_data->currpath.length() - (name.length()+offset)); + const std::size_t offset = (xml_data->nodes.size() > 1) ? 1 : 0; + xml_data->currpath.erase( + xml_data->currpath.size() - (name.size() + offset)); } xml_data->nodes.pop_back(); xml_data->node_depth--; - xml_data->currval = ""; + xml_data->currval.clear(); xml_data->currval_is_set = false; } void onCharacters(void *ctx, const xmlChar *ch, int len) { - XMLNodes* xml_data = static_cast(ctx); + auto *xml_data = static_cast(ctx); std::string content(reinterpret_cast(ch), len); // libxml2 SAX parser will call this function multiple times // during the parsing of a single node, if the value has multibyte // characters, so we need to concatenate the values - if (xml_data->currval_is_set == false) { + if (!xml_data->currval_is_set) { xml_data->currval = content; xml_data->currval_is_set = true; } else { @@ -121,64 +113,56 @@ class MSCSAXHandler { extern "C" { void MSC_startElement(void *userData, const xmlChar *name, - const xmlChar *prefix, - const xmlChar *URI, - int nb_namespaces, - const xmlChar **namespaces, - int nb_attributes, - int nb_defaulted, - const xmlChar **attributes) { - - MSCSAXHandler* handler = static_cast(userData); + const xmlChar *, + const xmlChar *, + int, + const xmlChar **, + int, + int, + const xmlChar **) { + + auto *handler = static_cast(userData); handler->onStartElement(userData, name); } void MSC_endElement( void *userData, const xmlChar *name, - const xmlChar* prefix, - const xmlChar* URI) { + const xmlChar*, + const xmlChar*) { - MSCSAXHandler* handler = static_cast(userData); + auto *handler = static_cast(userData); handler->onEndElement(userData, name); } void MSC_xmlcharacters(void *userData, const xmlChar *ch, int len) { - MSCSAXHandler* handler = static_cast(userData); + auto *handler = static_cast(userData); handler->onCharacters(userData, ch, len); } } XML::XML(Transaction *transaction) - : m_transaction(transaction) { - m_data.doc = NULL; - m_data.parsing_ctx = NULL; - m_data.sax_handler = NULL; - m_data.xml_error = ""; - m_data.parsing_ctx_arg = NULL; - m_data.xml_parser_state = NULL; -} + : m_transaction(transaction) { } XML::~XML() { - if (m_data.parsing_ctx != NULL) { + if (m_data.parsing_ctx != nullptr) { xmlFreeParserCtxt(m_data.parsing_ctx); - m_data.parsing_ctx = NULL; + m_data.parsing_ctx = nullptr; } - if (m_data.doc != NULL) { + if (m_data.doc != nullptr) { xmlFreeDoc(m_data.doc); - m_data.doc = NULL; + m_data.doc = nullptr; } } bool XML::init() { - //xmlParserInputBufferCreateFilenameFunc entity; if (m_transaction->m_rules->m_secXMLExternalEntity == RulesSetProperties::TrueConfigBoolean) { - /*entity = */xmlParserInputBufferCreateFilenameDefault( + xmlParserInputBufferCreateFilenameDefault( __xmlParserInputBufferCreateFilename); } else { - /*entity = */xmlParserInputBufferCreateFilenameDefault( + xmlParserInputBufferCreateFilenameDefault( this->unloadExternalEntity); } if (m_transaction->m_secXMLParseXmlIntoArgs @@ -198,8 +182,6 @@ bool XML::init() { // set the parser state struct m_data.xml_parser_state = std::make_unique(m_transaction); - m_data.xml_parser_state->node_depth = 0; - m_data.xml_parser_state->currval = ""; // the XML will contain at least one node, which is the pseudo root node 'xml' m_data.xml_parser_state->currpath = "xml."; } @@ -208,9 +190,9 @@ bool XML::init() { } -xmlParserInputBufferPtr XML::unloadExternalEntity(const char *URI, - xmlCharEncoding enc) { - return NULL; +xmlParserInputBufferPtr XML::unloadExternalEntity(const char *, + xmlCharEncoding) { + return nullptr; } @@ -220,30 +202,17 @@ bool XML::processChunk(const char *buf, unsigned int size, * enable us to pass it the first chunk of data so that * it can attempt to auto-detect the encoding. */ - if (m_data.parsing_ctx == NULL && m_data.parsing_ctx_arg == NULL) { + if (m_data.parsing_ctx == nullptr && m_data.parsing_ctx_arg == nullptr) { /* First invocation. */ ms_dbg_a(m_transaction, 4, "XML: Initialising parser."); - /* NOTE When Sax interface is used libxml will not - * create the document object, but we need it. - - msr->xml->sax_handler = (xmlSAXHandler *)apr_pcalloc(msr->mp, - sizeof(xmlSAXHandler)); - if (msr->xml->sax_handler == NULL) return -1; - msr->xml->sax_handler->error = xml_receive_sax_error; - msr->xml->sax_handler->warning = xml_receive_sax_error; - msr->xml->parsing_ctx = xmlCreatePushParserCtxt(msr->xml->sax_handler, - msr, buf, size, "body.xml"); - - */ - if (m_transaction->m_secXMLParseXmlIntoArgs != RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) { - m_data.parsing_ctx = xmlCreatePushParserCtxt(NULL, NULL, + m_data.parsing_ctx = xmlCreatePushParserCtxt(nullptr, nullptr, buf, size, "body.xml"); - if (m_data.parsing_ctx == NULL) { + if (m_data.parsing_ctx == nullptr) { ms_dbg_a(m_transaction, 4, "XML: Failed to create parsing context."); error->assign("XML: Failed to create parsing context."); @@ -262,8 +231,8 @@ bool XML::processChunk(const char *buf, unsigned int size, m_data.xml_parser_state.get(), buf, size, - NULL); - if (m_data.parsing_ctx_arg == NULL) { + nullptr); + if (m_data.parsing_ctx_arg == nullptr) { error->assign("XML: Failed to create parsing context for ARGS."); return false; } @@ -275,7 +244,7 @@ bool XML::processChunk(const char *buf, unsigned int size, } /* Not a first invocation. */ - if (m_data.parsing_ctx != NULL && + if (m_data.parsing_ctx != nullptr && m_transaction->m_secXMLParseXmlIntoArgs != RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) { xmlParseChunk(m_data.parsing_ctx, buf, size, 0); @@ -287,7 +256,7 @@ bool XML::processChunk(const char *buf, unsigned int size, } } - if (m_data.parsing_ctx_arg != NULL && + if (m_data.parsing_ctx_arg != nullptr && ( m_transaction->m_secXMLParseXmlIntoArgs == RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs @@ -309,12 +278,12 @@ bool XML::processChunk(const char *buf, unsigned int size, bool XML::complete(std::string *error) { /* Only if we have a context, meaning we've done some work. */ - if (m_data.parsing_ctx != NULL || m_data.parsing_ctx_arg != NULL) { - if (m_data.parsing_ctx != NULL && + if (m_data.parsing_ctx != nullptr || m_data.parsing_ctx_arg != nullptr) { + if (m_data.parsing_ctx != nullptr && m_transaction->m_secXMLParseXmlIntoArgs != RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) { /* This is how we signal the end of parsing to libxml. */ - xmlParseChunk(m_data.parsing_ctx, NULL, 0, 1); + xmlParseChunk(m_data.parsing_ctx, nullptr, 0, 1); /* Preserve the results for our reference. */ m_data.well_formed = m_data.parsing_ctx->wellFormed; @@ -322,7 +291,7 @@ bool XML::complete(std::string *error) { /* Clean up everything else. */ xmlFreeParserCtxt(m_data.parsing_ctx); - m_data.parsing_ctx = NULL; + m_data.parsing_ctx = nullptr; ms_dbg_a(m_transaction, 4, "XML: Parsing complete (well_formed " \ + std::to_string(m_data.well_formed) + ")."); @@ -332,7 +301,7 @@ bool XML::complete(std::string *error) { return false; } } - if (m_data.parsing_ctx_arg != NULL && + if (m_data.parsing_ctx_arg != nullptr && ( m_transaction->m_secXMLParseXmlIntoArgs == RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs @@ -341,19 +310,19 @@ bool XML::complete(std::string *error) { == RulesSetProperties::TrueConfigXMLParseXmlIntoArgs) ) { /* This is how we signale the end of parsing to libxml. */ - if (xmlParseChunk(m_data.parsing_ctx_arg, NULL, 0, 1) != 0) { - if (m_data.xml_error != "") { + if (xmlParseChunk(m_data.parsing_ctx_arg, nullptr, 0, 1) != 0) { + if (!m_data.xml_error.empty()) { error->assign(m_data.xml_error); } else { error->assign("XML: Failed to parse document for ARGS."); } xmlFreeParserCtxt(m_data.parsing_ctx_arg); - m_data.parsing_ctx_arg = NULL; + m_data.parsing_ctx_arg = nullptr; return false; } xmlFreeParserCtxt(m_data.parsing_ctx_arg); - m_data.parsing_ctx_arg = NULL; + m_data.parsing_ctx_arg = nullptr; } } @@ -362,5 +331,4 @@ bool XML::complete(std::string *error) { #endif -} // namespace RequestBodyProcessor -} // namespace modsecurity +} // namespace modsecurity::RequestBodyProcessor diff --git a/src/request_body_processor/xml.h b/src/request_body_processor/xml.h index df766d03b7..87f614fee2 100644 --- a/src/request_body_processor/xml.h +++ b/src/request_body_processor/xml.h @@ -19,18 +19,19 @@ #include #endif +#include #include -#include - -#include "modsecurity/transaction.h" -#include "modsecurity/rules_set.h" +#include #ifndef SRC_REQUEST_BODY_PROCESSOR_XML_H_ #define SRC_REQUEST_BODY_PROCESSOR_XML_H_ - namespace modsecurity { -namespace RequestBodyProcessor { +class Transaction; +} + + +namespace modsecurity::RequestBodyProcessor { #ifdef WITH_LIBXML2 @@ -42,7 +43,7 @@ class NodeData { explicit NodeData(); ~NodeData(); - bool has_child; + bool has_child = false; }; /* @@ -51,14 +52,14 @@ class NodeData { class XMLNodes { public: std::vector> nodes; - unsigned long int node_depth; + unsigned long int node_depth = 0; std::string currpath; std::string currval; - bool currval_is_set; - Transaction *m_transaction; + bool currval_is_set = false; + Transaction *m_transaction = nullptr; // need to store context - this is the same as in xml_data // need to stop parsing if the number of arguments reached the limit - xmlParserCtxtPtr parsing_ctx_arg; + xmlParserCtxtPtr parsing_ctx_arg = nullptr; explicit XMLNodes (Transaction *); ~XMLNodes(); @@ -66,23 +67,21 @@ class XMLNodes { struct xml_data { std::unique_ptr sax_handler; - xmlParserCtxtPtr parsing_ctx; - xmlDocPtr doc; + xmlParserCtxtPtr parsing_ctx = nullptr; + xmlDocPtr doc = nullptr; - unsigned int well_formed; + unsigned int well_formed = 0; /* error reporting and XML array flag */ std::string xml_error; /* additional parser context for arguments */ - xmlParserCtxtPtr parsing_ctx_arg; + xmlParserCtxtPtr parsing_ctx_arg = nullptr; /* parser state for SAX parser */ std::unique_ptr xml_parser_state; }; -typedef struct xml_data xml_data; - class XML { public: explicit XML(Transaction *transaction); @@ -96,13 +95,12 @@ class XML { xml_data m_data; private: - Transaction *m_transaction; + Transaction *m_transaction = nullptr; std::string m_header; }; #endif -} // namespace RequestBodyProcessor -} // namespace modsecurity +} // namespace modsecurity::RequestBodyProcessor #endif // SRC_REQUEST_BODY_PROCESSOR_XML_H_ diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index f6642b67e6..7469be8fe9 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "modsecurity/rules_set.h" #include "src/operators/operator.h" diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 9c356b8fb0..0f8b14c4bb 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -18,12 +18,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include "modsecurity/rules_set.h" #include "src/operators/operator.h" diff --git a/src/rules_exceptions.cc b/src/rules_exceptions.cc index 2fb0cf857f..352d3cab83 100644 --- a/src/rules_exceptions.cc +++ b/src/rules_exceptions.cc @@ -15,7 +15,10 @@ #include "modsecurity/rules_exceptions.h" +#include #include +#include +#include #include "src/utils/string.h" #include "src/variables/variable.h" diff --git a/src/rules_set_phases.cc b/src/rules_set_phases.cc index a781930498..88731edda9 100644 --- a/src/rules_set_phases.cc +++ b/src/rules_set_phases.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/run_time_string.cc b/src/run_time_string.cc index 45f298bc3d..48feeef38b 100644 --- a/src/run_time_string.cc +++ b/src/run_time_string.cc @@ -15,6 +15,7 @@ #include +#include #include "src/run_time_string.h" diff --git a/src/transaction.cc b/src/transaction.cc index 935da02462..c9e1401b7a 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -23,12 +23,16 @@ #include #include +#include #include #include #include #include +#include #include +#include #include +#include #include #include "modsecurity/actions/action.h" diff --git a/src/utils/json_writer.cc b/src/utils/json_writer.cc index 4cd7b1ba5d..1be155f123 100644 --- a/src/utils/json_writer.cc +++ b/src/utils/json_writer.cc @@ -15,6 +15,7 @@ #include "src/utils/json_writer.h" +#include #include #include diff --git a/src/utils/json_writer.h b/src/utils/json_writer.h index ac549d592b..130ec022ea 100644 --- a/src/utils/json_writer.h +++ b/src/utils/json_writer.h @@ -16,6 +16,7 @@ #ifndef SRC_UTILS_JSON_WRITER_H_ #define SRC_UTILS_JSON_WRITER_H_ +#include #include #include #include diff --git a/src/utils/sha1.h b/src/utils/sha1.h index a40d7fa1c8..aa9132c652 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -16,7 +16,9 @@ #ifndef SRC_UTILS_SHA1_H_ #define SRC_UTILS_SHA1_H_ +#include #include +#include #include #include "src/utils/string.h" diff --git a/src/utils/string.h b/src/utils/string.h index ca2967aa5f..8933a5f884 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/src/variables/variable.cc b/src/variables/variable.cc index caf8f6fd88..ca1eacfe56 100644 --- a/src/variables/variable.cc +++ b/src/variables/variable.cc @@ -16,6 +16,7 @@ #include "src/variables/variable.h" #include +#include #include #include #include