diff --git a/configure.ac b/configure.ac index 1c6337b7..323ed261 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ AM_CONDITIONAL([YAJL_VERSION], [test "$YAJL_VERSION" != ""]) AC_HEADER_STDC AC_CHECK_HEADERS([string]) AC_CHECK_HEADERS([iostream]) +AC_CHECK_HEADERS([sys/utsname.h]) # ?? diff --git a/examples/simple_example_using_c/test.c b/examples/simple_example_using_c/test.c index 3d992fbe..f6668d42 100644 --- a/examples/simple_example_using_c/test.c +++ b/examples/simple_example_using_c/test.c @@ -35,7 +35,7 @@ int main (int argc, char **argv) assay = msc_new_assay(modsec, rules); - msc_process_connection(assay, "127.0.0.1"); + msc_process_connection(assay, "127.0.0.1", 12345, "127.0.0.1", 80); msc_process_uri(assay, "http://www.modsecurity.org/test?key1=value1&key2=value2&key3=value3&test=args&test=test"); msc_process_request_headers(assay); msc_process_request_body(assay); diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index 488f0120..9d14566c 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -85,7 +85,8 @@ class Assay { ~Assay(); /** TODO: Should be an structure that fits an IP address */ - int processConnection(const char *ip); + int processConnection(const char *client, int cPort, + const char *server, int sPort); int processURI(const char *uri); @@ -135,7 +136,10 @@ class Assay { private: std::ofstream myfile; Rules *m_rules; - const char *m_ipAddress; + const char *m_clientIpAddress; + const char *m_serverIpAddress; + int m_clientPort; + int m_serverPort; const char *m_uri; std::ostringstream m_requestBody; std::ostringstream m_responseBody; @@ -153,7 +157,8 @@ extern "C" { Assay *msc_new_assay(ModSecurity *ms, Rules *rules); /** @ingroup ModSecurity_C_API */ -int msc_process_connection(Assay *assay, const char *ip); +int msc_process_connection(Assay *assay, const char *client, int cPort, + const char *server, int sPort); /** @ingroup ModSecurity_C_API */ int msc_process_request_headers(Assay *assay); diff --git a/src/Makefile.am b/src/Makefile.am index c8ff5df7..478cc6a9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,8 @@ ACTIONS = \ actions/transformations/url_encode.cc \ actions/transformations/utf8_to_unicode.cc +UTILS = \ + utils/sha1.cc libmodsecurity_la_SOURCES = \ parser/seclang-parser.yy \ @@ -89,6 +91,7 @@ libmodsecurity_la_SOURCES = \ utils.cc \ debug_log.cc \ rule.cc \ + unique_id.cc \ variable.cc \ operators/operator.cc \ operators/detect_sqli.cc \ @@ -127,7 +130,8 @@ libmodsecurity_la_SOURCES = \ operators/str_eq.cc \ operators/str_match.cc \ operators/begins_with.cc \ - ${ACTIONS} + ${ACTIONS} \ + ${UTILS} diff --git a/src/assay.cc b/src/assay.cc index 9f01e570..7abf06d7 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -61,7 +61,7 @@ namespace ModSecurity { * rules->loadFromUri(rules_file); * * Assay *modsecAssay = new Assay(modsec, rules); - * modsecAssay->processConnection("127.0.0.1"); + * modsecAssay->processConnection("127.0.0.1", 33333, "127.0.0.1", 8080); * * if (modsecAssay->intervention()) { * std::cout << "There is an intervention" << std::endl; @@ -73,8 +73,11 @@ namespace ModSecurity { * */ Assay::Assay(ModSecurity *ms, Rules *rules) - : m_ipAddress(NULL), - m_uri(NULL), + : m_clientIpAddress(""), + m_serverIpAddress(""), + m_clientPort(0), + m_serverPort(0), + m_uri(""), m_rules(rules), save_in_auditlog(false), do_not_save_in_auditlog(false), @@ -115,19 +118,27 @@ void Assay::debug(int level, std::string message) { * * @note Remember to check for a possible intervention. * - * @param buf Client's IP address in text format. + * @param assay ModSecurity assay. + * @param client Client's IP address in text format. + * @param cPort Client's port + * @param server Server's IP address in text format. + * @param sPort Server's port * * @returns If the operation was successful or not. * @retval true Operation was successful. * @retval false Operation failed. * */ -int Assay::processConnection(const char *ipAddress) { - this->m_ipAddress = ipAddress; +int Assay::processConnection(const char *client, int cPort, const char *server, + int sPort) { + this->m_clientIpAddress = client; + this->m_serverIpAddress = server; + this->m_clientPort = cPort; + this->m_serverPort = sPort; debug(4, "Transaction context created (blah blah)"); debug(4, "Starting phase CONNECTION. (SecRules 0)"); - this->store_variable("REMOTE_ADDR", ipAddress); + this->store_variable("REMOTE_ADDR", m_clientIpAddress); this->m_rules->evaluate(ModSecurity::ConnectionPhase, this); return true; } @@ -711,15 +722,19 @@ extern "C" Assay *msc_new_assay(ModSecurity *ms, * @note Remember to check for a possible intervention. * * @param assay ModSecurity assay. - * @param buf Client's IP address in text format. + * @param client Client's IP address in text format. + * @param cPort Client's port + * @param server Server's IP address in text format. + * @param sPort Server's port * * @returns If the operation was successful or not. * @retval 1 Operation was successful. * @retval 0 Operation failed. * */ -extern "C" int msc_process_connection(Assay *assay, const char *buf) { - return assay->processConnection(buf); +extern "C" int msc_process_connection(Assay *assay, const char *client, + int cPort, const char *server, int sPort) { + return assay->processConnection(client, cPort, server, sPort); } diff --git a/src/modsecurity.cc b/src/modsecurity.cc index 1cd04727..8a9a7bf5 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -17,7 +17,8 @@ #include #include "modsecurity/modsecurity.h" -#include "src/utils.h" +#include "src/unique_id.h" + namespace ModSecurity { @@ -39,6 +40,7 @@ namespace ModSecurity { * @endcode */ ModSecurity::ModSecurity() { + UniqueId::uniqueId(); } diff --git a/src/unique_id.cc b/src/unique_id.cc new file mode 100644 index 00000000..508e7f74 --- /dev/null +++ b/src/unique_id.cc @@ -0,0 +1,230 @@ +/* + * 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 "src/unique_id.h" +#include "src/config.h" + +#ifdef WIN32 +#include +#include +#endif + +#if (defined(__linux__) || defined(__gnu_linux__)) || DARWIN +#include +#include +#include +#endif + +#ifdef DARWIN +#include +#include +#include +#include +#ifndef IFT_ETHER +#define IFT_ETHER 0x6 /* Ethernet CSMACD */ +#endif +#endif + +#if (defined(__linux__) || defined(__gnu_linux__)) +#include +#include +#include +#endif + +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#include +#include +#include + +#include "src/utils/sha1.h" + +namespace ModSecurity { + +void UniqueId::fillUniqueId() { + std::string macAddress; + std::string name; + Utils::SHA1 sha1; + + macAddress = ethernetMacAddress(); + name = machineName(); + + sha1.update(&macAddress); + sha1.update(&name); + + this->uniqueId_str = sha1.final(); +} + +// Based on: +// http://stackoverflow.com/questions/16858782/how-to-obtain-almost-unique-system-identifier-in-a-cross-platform-way +std::string UniqueId::machineName() { + char machine_name[MAX_MACHINE_NAME_SIZE]; + size_t len = MAX_MACHINE_NAME_SIZE; +#ifdef WIN32 + DWORD lenComputerName = len; +#endif + + memset(machine_name, '\0', sizeof(char) * len); + +#ifdef WIN32 + if (GetComputerName(machine_name, &lenComputerName) == 0) { + goto failed; + } +#endif + +#ifdef HAVE_SYS_UTSNAME_H + static struct utsname u; + + if (uname(&u) < 0) { + goto failed; + } + + snprintf(machine_name, len-1, "%s", u.nodename); +#endif + + return std::string(machine_name); + +failed: + return std::string(""); +} + +std::string UniqueId::ethernetMacAddress() { + char mac[MAC_ADDRESS_SIZE]; + memset(mac, '\0', sizeof(char)*(MAC_ADDRESS_SIZE)); +#ifdef DARWIN + struct ifaddrs* ifaphead; + struct ifaddrs* ifap; + int i = 0; + + if (getifaddrs(&ifaphead) != 0) { + goto failed; + } + + // iterate over the net interfaces + for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) { + struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifap->ifa_addr; + if (sdl && (sdl->sdl_family == AF_LINK) && (sdl->sdl_type == IFT_ETHER) + && mac[0] && mac[1] && mac[2] && i < 6) { + snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned char)LLADDR(sdl)[0], + (unsigned char)LLADDR(sdl)[1], + (unsigned char)LLADDR(sdl)[2], + (unsigned char)LLADDR(sdl)[3], + (unsigned char)LLADDR(sdl)[4], + (unsigned char)LLADDR(sdl)[5]); + goto end; + } + } + + freeifaddrs(ifaphead); +#endif + +#if (defined(__linux__) || defined(__gnu_linux__)) + struct ifconf conf; + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + struct ifreq* ifr; + if ( sock < 0 ) { + goto failed; + } + + char ifconfbuf[128 * sizeof(struct ifreq)]; + memset(ifconfbuf, 0, sizeof(ifconfbuf)); + conf.ifc_buf = ifconfbuf; + conf.ifc_len = sizeof(ifconfbuf); + if (ioctl(sock, SIOCGIFCONF, &conf)) { + close(sock); + goto failed; + } + + for (ifr = conf.ifc_req; ifr < conf.ifc_req + conf.ifc_len; ifr++) { + if (ioctl(sock, SIOCGIFFLAGS, ifr)) { + continue; // failed to get flags, skip it + } + + if (ioctl(sock, SIOCGIFHWADDR, ifr) == 0) { + int i = 0; + if (!ifr->ifr_addr.sa_data[0] && !ifr->ifr_addr.sa_data[1] + && !ifr->ifr_addr.sa_data[2]) { + continue; + } + + snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned char)ifr->ifr_addr.sa_data[0], + (unsigned char)ifr->ifr_addr.sa_data[1], + (unsigned char)ifr->ifr_addr.sa_data[2], + (unsigned char)ifr->ifr_addr.sa_data[3], + (unsigned char)ifr->ifr_addr.sa_data[4], + (unsigned char)ifr->ifr_addr.sa_data[5]); + + goto end; + } + } + close(sock); +#endif + +#if WIN32 + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = NULL; + DWORD dwRetVal = 0; + + ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); + pAdapterInfo = reinterpret_cast(malloc( \ + sizeof (IP_ADAPTER_INFO))); + if (!pAdapterInfo) { + goto failed; + } + + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + free(pAdapterInfo); + pAdapterInfo = reinterpret_castmalloc(ulOutBufLen)); + if (!pAdapterInfo) { + goto failed; + } + } + + dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); + if (dwRetVal != NO_ERROR) { + free(pAdapterInfo); + goto failed; + } + + pAdapter = pAdapterInfo; + while (pAdapter && !mac[0] && !mac[1] && !mac[2]) { + if (pAdapter->AddressLength > 4) { + apr_snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned char)pAdapter->Address[0], + (unsigned char)pAdapter->Address[1], + (unsigned char)pAdapter->Address[2], + (unsigned char)pAdapter->Address[3], + (unsigned char)pAdapter->Address[4], + (unsigned char)pAdapter->Address[5]); + goto end; + } + pAdapter = pAdapter->Next; + } + + free(pAdapterInfo); +#endif + +end: + return std::string(reinterpret_cast(mac)); +failed: + return std::string(""); +} + + +} // namespace ModSecurity diff --git a/src/unique_id.h b/src/unique_id.h new file mode 100644 index 00000000..b4c15a42 --- /dev/null +++ b/src/unique_id.h @@ -0,0 +1,67 @@ +/* + * 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 +#endif + +#ifndef SRC_UNIQUE_ID_H_ +#define SRC_UNIQUE_ID_H_ + + +#ifdef __cplusplus + +namespace ModSecurity { + +#define MAC_ADDRESS_SIZE 19 +#define MAX_MACHINE_NAME_SIZE 256 + +/** @ingroup ModSecurity_CPP_API */ +class UniqueId { + public: + static UniqueId& getInstance() { + static UniqueId instance; + return instance; + } + + static std::string uniqueId() { + if (UniqueId::getInstance().uniqueId_str.empty()) { + UniqueId::getInstance().fillUniqueId(); + } + + return UniqueId::getInstance().uniqueId_str; + } + + void fillUniqueId(); + std::string machineName(); + std::string ethernetMacAddress(); + + std::string uniqueId_str; + + private: + UniqueId() {} + // C++ 03 + UniqueId(UniqueId const&); + // void operator=(UniqueId const&); + + // C++ 11 + // UniqueId(UniqueId const&) = delete; + // void operator=(UniqueId const&) = delete; +}; + +} // namespace ModSecurity +#endif + +#endif // SRC_UNIQUE_ID_H_ diff --git a/src/utils/sha1.cc b/src/utils/sha1.cc new file mode 100644 index 00000000..cb8f4d70 --- /dev/null +++ b/src/utils/sha1.cc @@ -0,0 +1,268 @@ +/* + * 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. + * + */ + +/** TODO: Reimplement this on the same terms and/or check if we use it. */ +/* + sha1.cpp - source code of + + ============ + SHA-1 in C++ + ============ + + 100% Public Domain. + + Original C Code + -- Steve Reid + Small changes to fit into bglibs + -- Bruce Guenter + Translation to simpler C++ Code + -- Volker Grabsch +*/ + +#include "src/utils/sha1.h" + +#include +#include +#include + +namespace ModSecurity { +namespace Utils { + +SHA1::SHA1() { + reset(); +} + + +void SHA1::update(std::string *s) { + std::istringstream is(*s); + update(&is); +} + + +void SHA1::update(std::istream *is) { + std::string rest_of_buffer; + read(is, &rest_of_buffer, BLOCK_BYTES - buffer.size()); + buffer += rest_of_buffer; + + while (*is) { + uint32 block[BLOCK_INTS]; + buffer_to_block(buffer, block); + transform(block); + read(is, &buffer, BLOCK_BYTES); + } +} + + +std::string SHA1::final() { + /* Total number of hashed bits */ + uint64 total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; + + /* Padding */ + buffer += 0x80; + unsigned int orig_size = buffer.size(); + while (buffer.size() < BLOCK_BYTES) { + buffer += static_cast(0x00); + } + + uint32 block[BLOCK_INTS]; + buffer_to_block(buffer, block); + + if (orig_size > BLOCK_BYTES - 8) { + transform(block); + for (unsigned int i = 0; i < BLOCK_INTS - 2; i++) { + block[i] = 0; + } + } + + /* Append total_bits, split this uint64 into two uint32 */ + block[BLOCK_INTS - 1] = total_bits; + block[BLOCK_INTS - 2] = (total_bits >> 32); + transform(block); + + /* Hex std::string */ + std::ostringstream result; + for (unsigned int i = 0; i < DIGEST_INTS; i++) { + result << std::hex << std::setfill('0') << std::setw(8); + result << (digest[i] & 0xffffffff); + } + + /* Reset for next run */ + reset(); + + return result.str(); +} + + +void SHA1::reset() { + /* SHA1 initialization constants */ + digest[0] = 0x67452301; + digest[1] = 0xefcdab89; + digest[2] = 0x98badcfe; + digest[3] = 0x10325476; + digest[4] = 0xc3d2e1f0; + + /* Reset counters */ + transforms = 0; + buffer = ""; +} + + +void SHA1::transform(uint32 block[BLOCK_BYTES]) { + /* Copy digest[] to working vars */ + uint32 a = digest[0]; + uint32 b = digest[1]; + uint32 c = digest[2]; + uint32 d = digest[3]; + uint32 e = digest[4]; + + /* Help macros */ +#define rol(value, bits) (((value) << (bits)) \ + | (((value) & 0xffffffff) >> (32 - (bits)))) + +#define blk(i) (block[i&15] = rol(block[(i+13)&15] \ + ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15], 1)) + + /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v, w, x, y, z, i) z += ((w&(x^y))^y) + block[i] \ + + 0x5a827999 + rol(v, 5); w = rol(w, 30); +#define R1(v, w, x, y, z, i) z += ((w&(x^y))^y) + blk(i) \ + + 0x5a827999 + rol(v, 5); w = rol(w, 30); +#define R2(v, w, x, y, z, i) z += (w^x^y) + blk(i) \ + + 0x6ed9eba1 + rol(v, 5); w = rol(w, 30); +#define R3(v, w, x, y, z, i) z += (((w|x)&y)|(w&x)) + blk(i) \ + + 0x8f1bbcdc + rol(v, 5); w = rol(w, 30); +#define R4(v, w, x, y, z, i) z += (w^x^y) + blk(i) \ + + 0xca62c1d6 + rol(v, 5); w = rol(w, 30); + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + + /* Add the working vars back into digest[] */ + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; + digest[4] += e; + + /* Count the number of transformations */ + transforms++; +} + + +void SHA1::buffer_to_block(const std::string &buffer, + uint32 block[BLOCK_BYTES]) { + /* Convert the std::string (byte buffer) to a uint32 array (MSB) */ + for (unsigned int i = 0; i < BLOCK_INTS; i++) { + block[i] = (buffer[4 * i + 3] & 0xff) + | (buffer[4 * i + 2] & 0xff) << 8 + | (buffer[4 * i + 1] & 0xff) << 16 + | (buffer[4 * i + 0] & 0xff) << 24; + } +} + + +void SHA1::read(std::istream *is, std::string *s, int k_max) { + char sbuf[BLOCK_BYTES]; + + if (k_max > BLOCK_BYTES) { + return; + } + + is->read(sbuf, k_max); + s->assign(sbuf, is->gcount()); +} + +} // namespace Utils +} // namespace ModSecurity + diff --git a/src/utils/sha1.h b/src/utils/sha1.h new file mode 100644 index 00000000..4a7ef422 --- /dev/null +++ b/src/utils/sha1.h @@ -0,0 +1,79 @@ +/* + * 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. + * + */ + +/** TODO: Reimplement this on the same terms and/or check if we use it. */ +/* + sha1.h - header of + + ============ + SHA-1 in C++ + ============ + + 100% Public Domain. + + Original C Code + -- Steve Reid + Small changes to fit into bglibs + -- Bruce Guenter + Translation to simpler C++ Code + -- Volker Grabsch +*/ + +#ifndef SRC_UTILS_SHA1_H_ +#define SRC_UTILS_SHA1_H_ + +#include +#include +#include + +namespace ModSecurity { +namespace Utils { + +class SHA1 { + public: + SHA1(); + void update(std::string *s); + void update(std::istream *is); + std::string final(); + + private: + /* just needs to be at least 32bit */ + typedef unsigned long int uint32; + /* just needs to be at least 64bit */ + typedef unsigned long long uint64; + + /* number of 32bit integers per SHA1 digest */ + static const unsigned int DIGEST_INTS = 5; + /* number of 32bit integers per SHA1 block */ + static const unsigned int BLOCK_INTS = 16; + static const unsigned int BLOCK_BYTES = BLOCK_INTS * 4; + + uint32 digest[DIGEST_INTS]; + std::string buffer; + uint64 transforms; + + void reset(); + void transform(uint32 block[BLOCK_BYTES]); + + static void buffer_to_block(const std::string &buffer, + uint32 block[BLOCK_BYTES]); + + void read(std::istream *is, std::string *s, int max); +}; + +} // namespace Utils +} // namespace ModSecurity + +#endif // SRC_UTILS_SHA1_H_ diff --git a/test/benchmark/benchmark.cc b/test/benchmark/benchmark.cc index fdf491f9..cbf1e028 100644 --- a/test/benchmark/benchmark.cc +++ b/test/benchmark/benchmark.cc @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) { std::cout << "Proceding with request " << i << std::endl; Assay *modsecAssay = new Assay(modsec, rules); - modsecAssay->processConnection(ip); + modsecAssay->processConnection(ip, 12345, "127.0.0.1", 80); if (modsecAssay->intervention()) { std::cout << "There is an intervention" << std::endl; diff --git a/test/regression/regression.cc b/test/regression/regression.cc index 9ab7788e..cc42b511 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -78,13 +78,12 @@ void perform_unit_test(std::vector *tests, } modsec_assay = new ModSecurity::Assay(modsec, modsec_rules); - if (t->ip.empty() == false) { - // FIXME: no cast please. - modsec_assay->processConnection(t->ip.c_str()); - actions(&r, modsec_assay->intervention()); - if (r.status != 200) { - goto end; - } + modsec_assay->processConnection(t->clientIp.c_str(), + t->clientPort, t->serverIp.c_str(), t->serverPort); + + actions(&r, modsec_assay->intervention()); + if (r.status != 200) { + goto end; } if (t->uri.empty() == false) { modsec_assay->processURI(t->uri.c_str()); diff --git a/test/regression/regression_test.cc b/test/regression/regression_test.cc index 84b41daf..97d8286f 100644 --- a/test/regression/regression_test.cc +++ b/test/regression/regression_test.cc @@ -107,6 +107,32 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) { if (strcmp(key, "github_issue") == 0) { u->github_issue = YAJL_GET_INTEGER(val); } + if (strcmp(key, "client") == 0) { + for (int j = 0; j < val->u.object.len; j++) { + const char *key2 = val->u.object.keys[j]; + yajl_val val2 = val->u.object.values[j]; + + if (strcmp(key2, "ip") == 0) { + u->clientIp = YAJL_GET_STRING(val2); + } + if (strcmp(key2, "port") == 0) { + u->clientPort = YAJL_GET_INTEGER(val2); + } + } + } + if (strcmp(key, "server") == 0) { + for (int j = 0; j < val->u.object.len; j++) { + const char *key2 = val->u.object.keys[j]; + yajl_val val2 = val->u.object.values[j]; + + if (strcmp(key2, "ip") == 0) { + u->serverIp = YAJL_GET_STRING(val2); + } + if (strcmp(key2, "port") == 0) { + u->serverPort = YAJL_GET_INTEGER(val2); + } + } + } if (strcmp(key, "request") == 0) { for (int j = 0; j < val->u.object.len; j++) { const char *key2 = val->u.object.keys[j]; @@ -115,9 +141,6 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) { if (strcmp(key2, "uri") == 0) { u->uri = YAJL_GET_STRING(val2); } - if (strcmp(key2, "ip") == 0) { - u->ip = YAJL_GET_STRING(val2); - } if (strcmp(key2, "headers") == 0) { u->request_headers = yajl_array_to_map(val2); } diff --git a/test/regression/regression_test.h b/test/regression/regression_test.h index ceda4d30..70b3f8d5 100644 --- a/test/regression/regression_test.h +++ b/test/regression/regression_test.h @@ -51,7 +51,11 @@ class RegressionTest { std::string debug_log; std::string error_log; - std::string ip; + std::string clientIp; + std::string serverIp; + int clientPort; + int serverPort; + std::string uri; static inline std::string yajl_array_to_str(const yajl_val &node); diff --git a/test/test-cases/regression/actions.json b/test/test-cases/regression/actions.json index 15b7652d..631fceef 100644 --- a/test/test-cases/regression/actions.json +++ b/test/test-cases/regression/actions.json @@ -4,8 +4,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: trim,block", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -56,8 +63,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: trim,redirect:http://www.google.com", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -109,8 +123,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: trim,status:500,redirect:http://www.google.com", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -162,8 +183,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: trim,status:500", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -214,8 +242,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: phase:1,trim,status:500", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -266,8 +301,15 @@ "version_min": 300000, "version_max": 0, "title": "actions :: phase:4,trim,status:500", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", diff --git a/test/test-cases/regression/auditlog.json b/test/test-cases/regression/auditlog.json index 20d506a3..e6508fc8 100644 --- a/test/test-cases/regression/auditlog.json +++ b/test/test-cases/regression/auditlog.json @@ -4,8 +4,15 @@ "version_min": 300000, "version_max": 0, "title": "auditlog : basic parser test", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "www.modsecurity.org", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", diff --git a/test/test-cases/regression/debug_log.json b/test/test-cases/regression/debug_log.json index 185af307..06677ffe 100644 --- a/test/test-cases/regression/debug_log.json +++ b/test/test-cases/regression/debug_log.json @@ -4,8 +4,15 @@ "version_min": 300000, "version_max": 0, "title": "Debug log", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", diff --git a/test/test-cases/regression/issue-394.json b/test/test-cases/regression/issue-394.json index ac2c318a..dc49bd59 100644 --- a/test/test-cases/regression/issue-394.json +++ b/test/test-cases/regression/issue-394.json @@ -6,6 +6,14 @@ "title": "Segmentation fault when uploading file with SecStreamInBodyInspection enabled", "url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/394", "gihub_issue": 394, + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, "request": { "headers": "", "body": "" diff --git a/test/test-cases/regression/transformations.json b/test/test-cases/regression/transformations.json index b52a6d7f..8381104f 100644 --- a/test/test-cases/regression/transformations.json +++ b/test/test-cases/regression/transformations.json @@ -4,8 +4,15 @@ "version_min": 300000, "version_max": 0, "title": "Testing transformations :: pass,t:trim", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)", @@ -55,8 +62,15 @@ "version_min": 300000, "version_max": 0, "title": "Testing transformations :: pass,t:trim,t:lowercase", - "request": { + "client": { "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { "headers": { "Host": "net.tutsplus.com", "User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",