Felipe Zimmerle ed8b0c85d7 Fix `capture' memory management
The capture action was implemented before the transaction concept.
While partially ported to use the transaction, some of the elements
were not freed correctly. Now it is fully ported to use the class
Transaction.
2016-02-16 23:24:15 -03:00

426 lines
11 KiB
C++

/*
* 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 <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#endif
#include <stdlib.h>
#include <stddef.h>
#ifndef HEADERS_MODSECURITY_TRANSACTION_H_
#define HEADERS_MODSECURITY_TRANSACTION_H_
#ifndef __cplusplus
typedef struct ModSecurity_t ModSecurity;
typedef struct Transaction_t Transaction;
typedef struct Rules_t Rules;
#endif
#include "modsecurity/intervention.h"
#include "modsecurity/transaction/collections.h"
#include "modsecurity/transaction/variable.h"
#include "modsecurity/transaction/variables.h"
#define LOGFY_ADD(a, b) \
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(a), strlen(a)); \
if (b == NULL) { \
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(""), \
strlen("")); \
} else { \
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(b), \
strlen(b)); \
}
#define LOGFY_ADD_INT(a, b) \
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(a), strlen(a)); \
yajl_gen_number(g, reinterpret_cast<const char*>(b), strlen(b));
#define LOGFY_ADD_NUM(a, b) \
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(a), strlen(a)); \
yajl_gen_integer(g, b);
#ifdef __cplusplus
namespace modsecurity {
class ModSecurity;
class Transaction;
class Rules;
class Collections;
class RuleMessage;
namespace actions {
class Action;
}
namespace operators {
class Operator;
}
/** @ingroup ModSecurity_CPP_API */
class Transaction {
public:
Transaction(ModSecurity *transaction, Rules *rules, void *logCbData);
~Transaction();
/** TODO: Should be an structure that fits an IP address */
int processConnection(const char *client, int cPort,
const char *server, int sPort);
int processURI(const char *uri, const char *protocol,
const char *http_version);
/**
* Types of request body that ModSecurity may give a special treatment
* for the data.
*/
enum RequestBodyType {
/**
*
*/
UnknownFormat,
/**
*
*/
MultiPartRequestBody,
/**
*
*/
WWWFormUrlEncoded,
/**
*
*/
JSONRequestBody,
/**
*
*/
XMLRequestBody
};
int processRequestHeaders();
int addRequestHeader(const std::string& key, const std::string& value);
int addRequestHeader(const unsigned char *key, const unsigned char *value);
int addRequestHeader(const unsigned char *key, size_t len_key,
const unsigned char *value, size_t len_value);
int processRequestBody();
int appendRequestBody(const unsigned char *body, size_t size);
int requestBodyFromFile(const char *path);
int processResponseHeaders();
int addResponseHeader(const std::string& key, const std::string& value);
int addResponseHeader(const unsigned char *key, const unsigned char *value);
int addResponseHeader(const unsigned char *key, size_t len_key,
const unsigned char *value, size_t len_value);
int processResponseBody();
int appendResponseBody(const unsigned char *body, size_t size);
int processLogging(int status_code);
bool intervention(ModSecurityIntervention *it);
const char *getResponseBody();
int getResponseBodyLenth();
#ifndef NO_LOGS
void debug(int, std::string);
#endif
void serverLog(const std::string& msg);
std::string toJSON(int parts);
std::string toOldAuditLogFormat(int parts, const std::string &trailer);
std::string toOldAuditLogFormatIndex(const std::string &filename,
double size, const std::string &md5);
/**
* This variable is basically set by the `autidlog' action. It means
* that this particular transaction was marked to be saved as part of
* the auditlogs, even if it is not originally classified to be saved
* by `SecAuditLogRelevantStatus'.
*/
bool m_toBeSavedInAuditlogs;
/**
* Set by `noauditlog' action, it means that this particular should
* not be saved. Regardless of `SecAuditLogRelevantStatus'.
*
* @note It is possible to have `auditlog' and `noauditlog' actions
* in a same rule, in that case prevails the last input.
*/
bool m_toNotBeSavedInAuditLogs;
/**
* Filled during the class instantiation, this variable can be later
* used to fill the SecRule variable `duration'. The variable `duration'
* is dynamic calculated, it is always relative to the value found in
* m_creationTimeStamp.
*
* @note There is space for performance improvement. This value don't
* need to be filled if there is no rule using the variable
* `duration'.
*/
clock_t m_creationTimeStamp;
/**
* Holds the client IP address.
*/
const char *m_clientIpAddress;
/**
* Holds the HTTP version: 1.2, 2.0, 3.0 and so on....
*/
const char *m_httpVersion;
/**
* Holds the request method: GET, POST, HEAD ...
*/
const char *m_method;
/**
* Holds the server IP Address
*/
const char *m_serverIpAddress;
/**
* Holds the raw URI that was requestd.
*/
const char *m_uri;
/**
* Holds the combined size of all arguments, later used to fill the
* variable ARGS_COMBINED_SIZE.
*/
double m_ARGScombinedSize;
/**
* Client tcp port.
*/
int m_clientPort;
/**
* This variable is set by the action `severity' and later can be
* consulted via the SecLanguage variable HIGHEST_SEVERITY.
*/
int m_highestSeverityAction;
/**
* Holds the HTTP return code when it is known. If 0 nothing was
* set.
*/
int m_httpCodeReturned;
/**
* Holds the server port.
*/
int m_serverPort;
/**
* ModSecurity instance used to start this transaction. Basically used
* to fill the server log whenever is needed.
*/
ModSecurity *m_ms;
/**
* Holds the type of the request body, in case there is one.
*/
RequestBodyType m_requestBodyType;
/**
* Rules object utilized during this specific transaction.
*/
Rules *m_rules;
/**
* The list m_auditLogModifier contains modifications to the `auditlogs'
* for this specific request, those modifications can happens via the
* utilization of the action: `ctl:auditLogParts='
*
*/
std::list< std::pair<int, std::string> > m_auditLogModifier;
/**
* This variable holds all the messages asked to be save by the utilization
* of the actions: `log_data' and `msg'. These should be included on the
* auditlogs.
*/
std::list<modsecurity::RuleMessage *> m_rulesMessages;
/**
* Holds the request body, in case of any.
*/
std::ostringstream m_requestBody;
/**
* Holds the response body, in case of any.
*/
std::ostringstream m_responseBody;
/**
* Contains the unique ID of the transaction. Use by the variable
* `UNIQUE_ID'. This unique id is also saved as part of the AuditLog.
*/
std::string m_id;
/**
* Holds the SecMarker name that this transaction should wait to perform
* rules evaluation again.
*/
std::string m_marker;
/**
* Holds the decode URI. Notice that m_uri holds the raw version
* of the URI.
*/
std::string m_uri_decoded;
/**
* Actions (disruptive?) that should be taken by the connector related to
* that transaction.
*/
std::vector<actions::Action *> m_actions;
/**
* Holds the creation time stamp, using std::time.
*
* TODO: m_timeStamp and m_creationTimeStamp may be merged into a single
* variable.
*/
time_t m_timeStamp;
/**
* Holds all the collections related to that transaction.
*/
transaction::Collections m_collections;
/**
* Holds the whatever matched in the operation utilization.
* That variable will be further used by the capture action.
*
*/
std::list<std::string> m_matched;
private:
std::string *m_ARGScombinedSizeStr;
std::string *m_namesArgs;
std::string *m_namesArgsGet;
std::string *m_namesArgsPost;
std::string *m_requestHeadersNames;
std::string *m_responseContentType;
std::string *m_responseHeadersNames;
/**
* Pointer to the callback function that will be called to fill
* the web server (connector) log.
*/
void *m_logCbData;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @ingroup ModSecurity_C_API */
Transaction *msc_new_transaction(ModSecurity *ms,
Rules *rules, void *logCbData);
/** @ingroup ModSecurity_C_API */
int msc_process_connection(Transaction *transaction,
const char *client, int cPort, const char *server, int sPort);
/** @ingroup ModSecurity_C_API */
int msc_process_request_headers(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_add_request_header(Transaction *transaction, const unsigned char *key,
const unsigned char *value);
/** @ingroup ModSecurity_C_API */
int msc_add_n_request_header(Transaction *transaction,
const unsigned char *key, size_t len_key, const unsigned char *value,
size_t len_value);
/** @ingroup ModSecurity_C_API */
int msc_process_request_body(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_append_request_body(Transaction *transaction,
const unsigned char *body, size_t size);
/** @ingroup ModSecurity_C_API */
int msc_request_body_from_file(Transaction *transaction, const char *path);
/** @ingroup ModSecurity_C_API */
int msc_process_response_headers(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_add_response_header(Transaction *transaction,
const unsigned char *key, const unsigned char *value);
/** @ingroup ModSecurity_C_API */
int msc_add_n_response_header(Transaction *transaction,
const unsigned char *key, size_t len_key, const unsigned char *value,
size_t len_value);
/** @ingroup ModSecurity_C_API */
int msc_process_response_body(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_append_response_body(Transaction *transaction,
const unsigned char *body, size_t size);
/** @ingroup ModSecurity_C_API */
int msc_process_uri(Transaction *transaction, const char *uri,
const char *protocol, const char *http_version);
/** @ingroup ModSecurity_C_API */
const char *msc_get_response_body(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_get_response_body_length(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
void msc_transaction_cleanup(Transaction *transaction);
/** @ingroup ModSecurity_C_API */
int msc_intervention(Transaction *transaction, ModSecurityIntervention *it);
/** @ingroup ModSecurity_C_API */
int msc_process_logging(Transaction *transaction, int code);
#ifdef __cplusplus
}
} // namespace modsecurity
#endif
#endif // HEADERS_MODSECURITY_TRANSACTION_H_