2016-06-30 20:44:51 -03:00

454 lines
12 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/collection/collections.h"
#include "modsecurity/collection/variable.h"
#include "modsecurity/collection/collection.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 RuleMessage;
namespace actions {
class Action;
enum AllowType : short;
}
namespace RequestBodyProcessor {
class XML;
class JSON;
}
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 code, const std::string& proto);
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();
bool intervention(ModSecurityIntervention *it);
bool addArgument(const std::string& orig, const std::string& key,
const std::string& value);
bool extractArguments(const std::string &orig, const std::string& buf);
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;
/**
* Holds the request body "processor"
*/
RequestBodyType m_requestBodyProcessor;
/**
* 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 amount of rules that should be skipped. If bigger than 0 the
* current rule should be skipped and the number needs to be decreased.
*/
int m_skip_next;
/**
* If allow action was utilized, this variable holds the allow type.
*/
modsecurity::actions::AllowType m_allowType;
/**
* 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.
*/
collection::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;
RequestBodyProcessor::XML *m_xml;
RequestBodyProcessor::JSON *m_json;
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, int code,
const char* protocol);
/** @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);
#ifdef __cplusplus
}
} // namespace modsecurity
#endif
#endif // HEADERS_MODSECURITY_TRANSACTION_H_