From 8d052853a82bbed55baacf1d1237c15d09f29f6d Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Sat, 2 Apr 2016 14:44:46 -0300 Subject: [PATCH] Adds support to https audit log output This functionality was built for test only. --- src/Makefile.am | 1 + src/audit_log/audit_log.cc | 4 +++ src/audit_log/audit_log.h | 1 + src/audit_log/writer/https.cc | 61 +++++++++++++++++++++++++++++++++ src/audit_log/writer/https.h | 64 +++++++++++++++++++++++++++++++++++ src/parser/seclang-parser.yy | 5 +++ src/parser/seclang-scanner.ll | 4 ++- src/utils/https_client.cc | 19 +++++++++++ src/utils/https_client.h | 8 ++++- 9 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 src/audit_log/writer/https.cc create mode 100644 src/audit_log/writer/https.h diff --git a/src/Makefile.am b/src/Makefile.am index 71539cc1..611f216e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,6 +182,7 @@ libmodsecurity_la_SOURCES = \ transaction.cc \ audit_log/audit_log.cc \ audit_log/writer.cc \ + audit_log/writer/https.cc \ audit_log/writer/serial.cc \ audit_log/writer/parallel.cc \ modsecurity.cc \ diff --git a/src/audit_log/audit_log.cc b/src/audit_log/audit_log.cc index 6430213d..2dd4956f 100644 --- a/src/audit_log/audit_log.cc +++ b/src/audit_log/audit_log.cc @@ -21,6 +21,7 @@ #include +#include "audit_log/writer/https.h" #include "audit_log/writer/parallel.h" #include "audit_log/writer/serial.h" #include "utils/regex.h" @@ -184,6 +185,9 @@ bool AuditLog::init() { if (m_type == SerialAuditLogType) { m_writer = new audit_log::writer::Serial(this); } + if (m_type == HttpsAuditLogType) { + m_writer = new audit_log::writer::Https(this); + } m_writer->refCountIncrease(); if (m_writer == NULL || m_writer->init() == false) { diff --git a/src/audit_log/audit_log.h b/src/audit_log/audit_log.h index 31622e1c..8eca8611 100644 --- a/src/audit_log/audit_log.h +++ b/src/audit_log/audit_log.h @@ -42,6 +42,7 @@ class AuditLog { enum AuditLogType { SerialAuditLogType, ParallelAuditLogType, + HttpsAuditLogType }; enum AuditLogStatus { diff --git a/src/audit_log/writer/https.cc b/src/audit_log/writer/https.cc new file mode 100644 index 00000000..52289459 --- /dev/null +++ b/src/audit_log/writer/https.cc @@ -0,0 +1,61 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "audit_log/writer/https.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "audit_log/audit_log.h" +#include "modsecurity/transaction.h" +#include "src/utils.h" +#include "utils/md5.h" +#include "utils/https_client.h" + +namespace modsecurity { +namespace audit_log { +namespace writer { + + +Https::~Https() { +} + + +bool Https::init() { + return true; +} + + +bool Https::write(Transaction *transaction, int parts) { + Utils::HttpsClient m_http_client; + transaction->debug(7, "Sending logs to: " + m_audit->m_path1); + + std::string log = transaction->toJSON(parts); + m_http_client.setRequestType("application/json"); + m_http_client.setRequestBody(log.c_str()); + m_http_client.download(m_audit->m_path1); + return true; +} + +} // namespace writer +} // namespace audit_log +} // namespace modsecurity diff --git a/src/audit_log/writer/https.h b/src/audit_log/writer/https.h new file mode 100644 index 00000000..4011c6b8 --- /dev/null +++ b/src/audit_log/writer/https.h @@ -0,0 +1,64 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifdef __cplusplus +#include +#include +#include +#endif + +#ifndef SRC_AUDIT_LOG_WRITER_HTTPS_H_ +#define SRC_AUDIT_LOG_WRITER_HTTPS_H_ + +#include "audit_log/writer.h" +#include "modsecurity/transaction.h" + +#ifdef __cplusplus + +namespace modsecurity { +namespace audit_log { +namespace writer { + +/** @ingroup ModSecurity_CPP_API */ +class Https : public audit_log::Writer { + public: + explicit Https(audit_log::AuditLog *audit) + : audit_log::Writer(audit) { } + + ~Https() override; + + void refCountIncrease() override { + m_refereceCount++; + } + + + void refCountDecreaseAndCheck() override { + m_refereceCount--; + if (m_refereceCount == 0) { + delete this; + } + } + + bool init() override; + bool write(Transaction *transaction, int parts) override; + +}; + +} // namespace writer +} // namespace audit_log +} // namespace modsecurity +#endif + +#endif // SRC_AUDIT_LOG_WRITER_HTTPS_H_ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index b7edcddf..7f33ba66 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -180,6 +180,7 @@ using modsecurity::Variables::Tx; %token CONFIG_VALUE_ON %token CONFIG_VALUE_OFF %token CONFIG_VALUE_DETC +%token CONFIG_VALUE_HTTPS %token CONFIG_VALUE_SERIAL %token CONFIG_VALUE_PARALLEL %token CONFIG_VALUE_RELEVANT_ONLY @@ -354,6 +355,10 @@ audit_log: { driver.audit_log->setType(modsecurity::audit_log::AuditLog::ParallelAuditLogType); } + | CONFIG_DIR_AUDIT_TPE CONFIG_VALUE_HTTPS + { + driver.audit_log->setType(modsecurity::audit_log::AuditLog::HttpsAuditLogType); + } ; actings: diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index f3579536..e60574d1 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -144,6 +144,7 @@ CONFIG_VALUE_OFF (?i:Off) CONFIG_VALUE_DETC (?i:DetectionOnly) CONFIG_VALUE_SERIAL (?i:Serial) CONFIG_VALUE_PARALLEL (?i:Parallel|Concurrent) +CONFIG_VALUE_HTTPS (?i:https) CONFIG_VALUE_RELEVANT_ONLY (?i:RelevantOnly) CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial) @@ -152,7 +153,7 @@ CONFIG_VALUE_REJECT (?i:Reject) CONFIG_VALUE_ABORT (?i:Abort) CONFIG_VALUE_WARN (?i:Warn) -CONFIG_VALUE_PATH [0-9A-Za-z_/\.\-\*]+ +CONFIG_VALUE_PATH [0-9A-Za-z_\/\.\-\*\:]+ AUDIT_PARTS [ABCDEFHJKIZ]+ CONFIG_VALUE_NUMBER [0-9]+ @@ -294,6 +295,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile) {CONFIG_VALUE_OFF} { return yy::seclang_parser::make_CONFIG_VALUE_OFF(yytext, *driver.loc.back()); } {CONFIG_VALUE_SERIAL} { return yy::seclang_parser::make_CONFIG_VALUE_SERIAL(yytext, *driver.loc.back()); } {CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, *driver.loc.back()); } +{CONFIG_VALUE_HTTPS} { return yy::seclang_parser::make_CONFIG_VALUE_HTTPS(yytext, *driver.loc.back()); } {CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, *driver.loc.back()); } {CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, *driver.loc.back()); } {CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, *driver.loc.back()); } diff --git a/src/utils/https_client.cc b/src/utils/https_client.cc index 6c51698a..b7b30dc2 100644 --- a/src/utils/https_client.cc +++ b/src/utils/https_client.cc @@ -50,6 +50,15 @@ void HttpsClient::setKey(const std::string& key) { m_key = "ModSec-key: " + key; } +void HttpsClient::setRequestBody(const std::string& requestBody) { + m_requestBody = requestBody; +} + +void HttpsClient::setRequestType(const std::string& requestType) { + m_requestType = requestType; +} + + #ifdef MSC_WITH_CURL bool HttpsClient::download(const std::string &uri) { CURL *curl; @@ -68,6 +77,12 @@ bool HttpsClient::download(const std::string &uri) { headers_chunk = curl_slist_append(headers_chunk, uniqueId.c_str()); headers_chunk = curl_slist_append(headers_chunk, status.c_str()); + + if (m_requestType.empty() == false) { + std::string hdr = "Content-Type: " + m_requestType; + headers_chunk = curl_slist_append(headers_chunk, hdr.c_str()); + } + if (m_key.empty() == false) { headers_chunk = curl_slist_append(headers_chunk, m_key.c_str()); } @@ -91,6 +106,10 @@ bool HttpsClient::download(const std::string &uri) { /* We want Curl to return error in case there is an HTTP error code */ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + if (m_requestBody.empty() == false) { + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, m_requestBody.c_str()); + } + res = curl_easy_perform(curl); curl_slist_free_all(headers_chunk); diff --git a/src/utils/https_client.h b/src/utils/https_client.h index 3e0c5aca..3eca6fdd 100644 --- a/src/utils/https_client.h +++ b/src/utils/https_client.h @@ -36,7 +36,9 @@ class HttpsClient { HttpsClient() : content(""), error(""), - m_key("") { } + m_key(""), + m_requestBody(""), + m_requestType("") { } bool download(const std::string &uri); std::string content; @@ -44,10 +46,14 @@ class HttpsClient { static size_t handle(char * data, size_t size, size_t nmemb, void * p); size_t handle_impl(char * data, size_t size, size_t nmemb); void setKey(const std::string& key); + void setRequestType(const std::string& requestType); + void setRequestBody(const std::string& requestType); std::string error; private: std::string m_key; + std::string m_requestBody; + std::string m_requestType; };