From: Tom Peters Date: Thu, 5 Jun 2014 16:07:14 +0000 (-0400) Subject: Many changes including PAF implementation and rename of source files X-Git-Tag: 3.0.0-233~1495^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=55ab7d9bafa6901bc26cce079726c5a8f0b56a8a;p=thirdparty%2Fsnort3.git Many changes including PAF implementation and rename of source files --- diff --git a/src/service_inspectors/nhttp_inspect/nhttp_flowdata.cc b/src/service_inspectors/nhttp_inspect/nhttp_flowdata.cc deleted file mode 100644 index 2ac2a73ef..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_flowdata.cc +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Flow Data object used to store session information with Streams -// - -#include -#include -#include -#include "snort.h" -#include "flow/flow.h" -#include "nhttp_enum.h" -#include "nhttp_flowdata.h" - -unsigned NHttpFlowData::nhttp_flow_id = 0; - -NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) -{ -} - -NHttpFlowData::~NHttpFlowData() -{ -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_flowdata.h b/src/service_inspectors/nhttp_inspect/nhttp_flowdata.h deleted file mode 100644 index 9d865f9ad..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_flowdata.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Converts protocol constant string to enum -// - -#ifndef NHTTP_FLOWDATA_H -#define NHTTP_FLOWDATA_H - -class NHttpFlowData : public FlowData -{ -public: - NHttpFlowData(); - ~NHttpFlowData(); - static unsigned nhttp_flow_id; - static void init() { nhttp_flow_id = FlowData::get_flow_id(); }; - - // PAF data - NHttpEnums::SourceId sourceId = NHttpEnums::SRC_CLIENT; - bool tcpClose = false; - uint64_t infractions = 0; - - // Client message data - NHttpEnums::SectionType clientTypeExpected = NHttpEnums::SEC_HEADER; - int32_t clientOctetsExpected = NHttpEnums::STAT_NOTPRESENT; - - // Server message data - NHttpEnums::SectionType serverTypeExpected = NHttpEnums::SEC_HEADER; - int32_t serverOctetsExpected = NHttpEnums::STAT_NOTPRESENT; - - // Session data -}; - -#endif - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_headnorm.cc b/src/service_inspectors/nhttp_inspect/nhttp_headnorm.cc deleted file mode 100644 index cd5b960f5..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_headnorm.cc +++ /dev/null @@ -1,187 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief HeaderNormalizer class -// - - -#include -#include -#include - -#include "snort.h" -#include "snort_types.h" - -#include "nhttp_enum.h" -#include "nhttp_scratchpad.h" -#include "nhttp_strtocode.h" -#include "nhttp_headnorm.h" - -using namespace NHttpEnums; - -// This derivation removes embedded CRLFs (wrapping), omits leading and trailing white space, and replaces internal strings of and with a single -int32_t HeaderNormalizer::deriveHeaderContent(const uint8_t *value, int32_t length, uint8_t *buffer) const { - int32_t outLength = 0; - bool lastWhite = true; - for (int k=0; k < length; k++) { - if ((value[k] == '\r') && (k+1 < length) && (value[k+1] == '\n')) k++; - else if ((value[k] != ' ') && (value[k] != '\t')) { - lastWhite = false; - buffer[outLength++] = value[k]; - } - else if (!lastWhite) { - lastWhite = true; - buffer[outLength++] = ' '; - } - } - if ((outLength > 0) && (buffer[outLength - 1] == ' ')) outLength--; - return outLength; -} - -void HeaderNormalizer::normalize(ScratchPad &scratchPad, uint64_t &infractions, HeaderId headId, const HeaderId headerNameId[], const field headerValue[], int32_t numHeaders, - field &resultField) const { - // This method normalizes the header field value for headId. - if (format == NORM_NULL) { - resultField.length = STAT_NOTCONFIGURED; - return; - } - - // Search Header IDs from all the headers in this message. A critical issue is whether the header can be present more than once in a message. concatenateRepeats means the - // header can be present more than once. The standard normalization is to concatenate all the repeated field values into a comma-separated list. Otherwise there should not - // be more than one instance of this header. infractRepeats causes us to inspect for improper repeated headers. Regardless of whether we look for these extra values only - // the first value will be normalized. - - int numMatches = 0; - int32_t bufferLength = 0; - int firstMatch = -1; - for (int k=0; k < numHeaders; k++) { - if (headerNameId[k] == HEAD__NOTCOMPUTE) break; - if (headerNameId[k] == headId) { - numMatches++; - if (numMatches == 1) firstMatch = k; - if ((numMatches == 1) || concatenateRepeats) bufferLength += headerValue[k].length; - if (!concatenateRepeats && !infractRepeats) break; - } - } - if (numMatches == 0) { - resultField.length = STAT_NOTPRESENT; - return; - } - if (infractRepeats && (numMatches >= 2)) infractions |= INF_BADHEADERREPS; - - // The scratchPad provides the space to store the normalized value. We are allocating twice as much memory as we need to store the normalized field value. The raw field - // value will be copied into one half of the buffer. Concatenation and white space normalization happen during this step. Next a series of normalization functions will - // transform the value into final form. Each normalization copies the value from one half of the buffer to the other. Based on whether the number of normalization functions - // is odd or even, the initial placement in the buffer is chosen so that the final normalization leaves the field value at the front of the buffer. The buffer space actually - // used is locked down in the scratchPad. The remainder of the first half and all of the second half are returned to the scratchPad for future use. - if (concatenateRepeats) bufferLength += numMatches - 1; // allow space for concatenation commas - bufferLength += (4-bufferLength%4)%4 + 200; // &&& 200 is a "way too big" fudge factor to allow for modest expansion of field size during normalization. Needs improvement. - uint8_t *scratch; - if ((scratch = scratchPad.request(2*bufferLength)) == nullptr) { - resultField.length = STAT_INSUFMEMORY; - return; - } - - uint8_t * const frontHalf = scratch; - uint8_t * const backHalf = scratch + bufferLength; - uint8_t *working = (numNormalizers%2 == 0) ? frontHalf : backHalf; - int currMatch = firstMatch; - int32_t growth; - int32_t dataLength = 0; - for (int j=0; j < numMatches; j++) { - if (j >= 1) { - *working++ = ','; - dataLength++; - while (headerNameId[++currMatch] != headId); - } - growth = deriveHeaderContent(headerValue[currMatch].start, headerValue[currMatch].length, working); - working += growth; - dataLength += growth; - if (!concatenateRepeats) break; - } - - for (int i=0; i < numNormalizers; i++) { - if (i%2 != numNormalizers%2) dataLength = normalizer[i](backHalf, dataLength, frontHalf, infractions, normArg[i]); - else dataLength = normalizer[i](frontHalf, dataLength, backHalf, infractions, normArg[i]); - if (dataLength <= 0) { - resultField.length = dataLength; - return; - } - } - resultField.start = scratch; - resultField.length = dataLength; - scratchPad.commit(dataLength); -} - -// Collection of stock normalization functions. This will probably grow throughout the life of the software. New functions must follow the standard signature. -// The void* at the end is for any special configuration data the function requires. - -int32_t normDecimalInteger(const uint8_t* inBuf, int32_t inLength, uint8_t* outBuf, uint64_t& infractions, const void *notUsed) { - uint32_t total = 0; - int value; - for (int32_t k=0; k < inLength; k++) { - value = inBuf[k] - '0'; - if ((value < 0) || (value > 9)) { - infractions |= INF_BADHEADERDATA; - return STAT_PROBLEMATIC; - } - total = total*10 + value; - } - ((uint32_t*)outBuf)[0] = total; - return sizeof(uint32_t); -} - - -int32_t norm2Lower(const uint8_t* inBuf, int32_t inLength, uint8_t* outBuf, uint64_t& infractions, const void *notUsed) { - for (int32_t k=0; k < inLength; k++) { - outBuf[k] = ((inBuf[k] < 'A') || (inBuf[k] > 'Z')) ? inBuf[k] : inBuf[k] - ('A' - 'a'); - } - return inLength; -} - - -int32_t normStrCode(const uint8_t* inBuf, int32_t inLength, uint8_t* outBuf, uint64_t& infractions, const void *table) { - ((uint32_t*)outBuf)[0] = strToCode(inBuf, inLength, (const StrCode*)table); - return sizeof(uint32_t); -} - -int32_t normSeqStrCode(const uint8_t* inBuf, int32_t inLength, uint8_t* outBuf, uint64_t& infractions, const void *table) { - int32_t numCodes = 0; - const uint8_t* start = inBuf; - int32_t length = 0; - while (true) { - start += length; - for (length = 0; (start + length < inBuf + inLength) && (start[length] != ','); length++); - if (length == 0) ((uint32_t*)outBuf)[numCodes++] = STAT_EMPTYSTRING; - else ((uint32_t*)outBuf)[numCodes++] = strToCode(start, length, (const StrCode*)table); - if (start + length++ >= inBuf + inLength) break; - } - return numCodes * sizeof(uint32_t); -} - - - - - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_headnorm.h b/src/service_inspectors/nhttp_inspect/nhttp_headnorm.h deleted file mode 100644 index 5a3162660..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_headnorm.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief HeaderNormalizer class declaration -// - -#ifndef NHTTP_HEADNORM_H -#define NHTTP_HEADNORM_H - - -//------------------------------------------------------------------------- -// HeaderNormalizer class -// Strategies for normalizing HTTP header field values -//------------------------------------------------------------------------- - -// Three normalization functions per HeaderNormalizer seems likely to be enough. Nothing subtle will break if you choose to expand it to four or more. Just a whole bunch of -// signatures and initializers to update. -// When defining a HeaderNormalizer don't leave holes in the normalizer list. E.g. if you have two normalizers they must be first and second. If you do first and third -// instead it won't explode but the third one won't be used either. - -class HeaderNormalizer { -public: - constexpr HeaderNormalizer(NHttpEnums::NormFormat _format, bool _concatenateRepeats, bool _infractRepeats, int32_t (*f1)(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void*), - const void *f1Arg, int32_t (*f2)(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void*), const void *f2Arg, int32_t (*f3)(const uint8_t*, int32_t, uint8_t*, uint64_t&, - const void*), const void *f3Arg) : - format(_format), - concatenateRepeats(_concatenateRepeats), - infractRepeats(_infractRepeats), - normalizer { f1, f2, f3 }, - normArg { f1Arg, f2Arg, f3Arg }, - numNormalizers((f1 != nullptr) + (f1 != nullptr)*(f2 != nullptr) + (f1 != nullptr)*(f2 != nullptr)*(f3 != nullptr)) {}; - void normalize(ScratchPad &scratchPad, uint64_t &infractions, NHttpEnums::HeaderId headId, const NHttpEnums::HeaderId headerNameId[], const field headerName[], int32_t numHeaders, - field &resultField) const; - NHttpEnums::NormFormat getFormat() const {return format;}; - -private: - int32_t deriveHeaderContent(const uint8_t *value, int32_t length, uint8_t *buffer) const; - - const NHttpEnums::NormFormat format; - const bool concatenateRepeats; - const bool infractRepeats; - int32_t (* const normalizer[3])(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void*); - const void * normArg[3]; - const int numNormalizers; -}; - -// Normalizer functions - -int32_t normDecimalInteger(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void* notUsed); -int32_t norm2Lower(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void* notUsed); -int32_t normStrCode(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void*); -int32_t normSeqStrCode(const uint8_t*, int32_t, uint8_t*, uint64_t&, const void*); - -#endif - - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msgheader.cc b/src/service_inspectors/nhttp_inspect/nhttp_msgheader.cc deleted file mode 100644 index cbaaff2f7..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_msgheader.cc +++ /dev/null @@ -1,412 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief NHttpMsgHeader class analyzes individual HTTP messages. -// - - -#include -#include -#include -#include - -#include "snort.h" -#include "flow/flow.h" -#include "detection/detection_util.h" -#include "nhttp_enum.h" -#include "nhttp_scratchpad.h" -#include "nhttp_strtocode.h" -#include "nhttp_headnorm.h" -#include "nhttp_flowdata.h" -#include "nhttp_msgheader.h" - -using namespace NHttpEnums; - -// Return the number of octets before the first CRLF. Return length if CRLF not present. -// -// wrappable: CRLF does not count in a header field when immediately followed by or . These whitespace characters -// at the beginning of the next line indicate that the previous header has wrapped and is continuing on the next line. -uint32_t NHttpMsgHeader::findCrlf(const uint8_t* buffer, uint32_t length, bool wrappable) { - for (uint32_t k=0; k < length-1; k++) { - if ((buffer[k] == '\r') && (buffer[k+1] == '\n')) - if (!wrappable || (k+2 >= length) || ((buffer[k+2] != ' ') && (buffer[k+2] != '\t'))) return k; - } - return length; -} - -// Reinitialize everything and load a new message -void NHttpMsgHeader::loadMessage(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_) { - length = (bufsize <= MAXOCTETS) ? bufsize : MAXOCTETS; - memcpy(rawBuf, buffer, length); - - sessionData = sessionData_; - infractions = sessionData->infractions; - sourceId = sessionData->sourceId; - tcpClose = sessionData->tcpClose; - - scratchPad.reinit(); - - startLine.length = STAT_NOTCOMPUTE; - version.length = STAT_NOTCOMPUTE; - versionId = VERS__NOTCOMPUTE; - method.length = STAT_NOTCOMPUTE; - methodId = METH__NOTCOMPUTE; - uri.length = STAT_NOTCOMPUTE; - statusCode.length = STAT_NOTCOMPUTE; - statusCodeNum = STAT_NOTCOMPUTE; - reasonPhrase.length = STAT_NOTCOMPUTE; - headers.length = STAT_NOTCOMPUTE; - numHeaders = STAT_NOTCOMPUTE; - for(int k = 0; k < MAXHEADERS; k++) { - headerLine[k].length = STAT_NOTCOMPUTE; - headerName[k].length = STAT_NOTCOMPUTE; - headerNameId[k] = HEAD__NOTCOMPUTE; - headerValue[k].length = STAT_NOTCOMPUTE; - } - for (int k = 1; k < HEAD__MAXVALUE; k++) { - headerValueNorm[k].length = STAT_NOTCOMPUTE; - } -} - -// All the header processing that is done for every message (i.e. not just-in-time) is done here. -void NHttpMsgHeader::analyze() { - parseWhole(); - if (sourceId == SRC_CLIENT) { - parseRequestLine(); - deriveMethodId(); - } - else if (sourceId == SRC_SERVER) { - parseStatusLine(); - deriveStatusCodeNum(); - } - deriveVersionId(); - parseHeaderBlock(); - parseHeaderLines(); - for (int j=0; j < MAXHEADERS; j++) { - if (headerName[j].length <= 0) break; - deriveHeaderNameId(j); - } - for (int k=1; k <= numNorms; k++) { - headerNorms[k]->normalize(scratchPad, infractions, (HeaderId)k, headerNameId, headerValue, MAXHEADERS, headerValueNorm[k]); - } -} - -// All we do here is separate the start line from the header fields. -// It is so complicated because 1) there might not be any header fields and 2) the message may have been truncated by a TCP connection close. -// The asserts are very useful in test mode because they pick up bad test case data that we are not designed to handle. Otherwise they should -// never go off unless PAF is broken and feeding us bad stuff. -void NHttpMsgHeader::parseWhole() { - startLine.start = msgText; - startLine.length = findCrlf(startLine.start, length, false); - // findCrtl() guarentees that either the start line is the whole message or there must be at least two more characters and the first two are . - assert((length == startLine.length) || ((length >= startLine.length+2) && !memcmp(msgText + startLine.length, "\r\n", 2))); - // We trust PAF. !tcpClose guarentees that either there are exactly four more characters or there are at least seven more characters - // with the first two being and the last four being . - assert(tcpClose || - ((length == startLine.length+4) && !memcmp(msgText + startLine.length, "\r\n\r\n", 4)) || - ((length >= startLine.length+7) && !memcmp(msgText + startLine.length, "\r\n", 2) && !memcmp(msgText + length - 4, "\r\n\r\n", 4))); - - // The following if-else ladder puts the extremely common normal cases at the beginning and the rare pathological cases at the end - // Normal case with header fields - if (!tcpClose && (length >= startLine.length+7)) { - headers.start = msgText + startLine.length + 2; - headers.length = length - startLine.length - 6; - } - // Normal case no header fields (only a start line) - else if (!tcpClose) { - headers.length = STAT_NOTPRESENT; - } - // Normal case with header fields and TCP connection close - else if ((length >= startLine.length+7) && !memcmp(msgText+length-4, "\r\n\r\n", 4)) { - headers.start = msgText + startLine.length + 2; - headers.length = length - startLine.length - 6; - } - // Normal case no header fields and TCP connection close - else if ((length == startLine.length + 4) && !memcmp(msgText+length-2, "\r\n", 2)) { - headers.length = STAT_NOTPRESENT; - } - // Abnormal cases truncated by TCP connection close - else { - infractions |= INF_TRUNCATED; - // Either start line incomplete or start line complete but no leftover octets for anything else - if (length <= startLine.length+2) { - headers.length = STAT_NOTPRESENT; - } - // Start line complete followed by lone - else if ((length == startLine.length+3) && (msgText[length-1] == '\r')) { - headers.length = STAT_NOTPRESENT; - } - // Truncation occurred somewhere in the header fields - else { - headers.start = msgText + startLine.length + 2; - headers.length = length - startLine.length - 2; - // When present, remove partial sequence from the very end - if ((length > startLine.length+6) && !memcmp(msgText+length-3, "\r\n\r", 3)) headers.length -= 3; - else if ((length > startLine.length+5) && !memcmp(msgText+length-2, "\r\n", 2)) headers.length -= 2; - else if ((length > startLine.length+4) && (msgText[length-1] == '\r')) headers.length -= 1; - } - } -} - -void NHttpMsgHeader::parseRequestLine() { - // There should be exactly two spaces. One following the method and one before "HTTP/". - // Eventually we may need to cater to certain format errors, but for now exact match or treat as error. - // HTTP/X.Y - if (startLine.start[startLine.length-9] != ' ') { - // space before "HTTP" missing or in wrong place - infractions |= INF_BADREQLINE; - return; - } - - int space = -1; - for (int32_t k=0; k < startLine.length-9; k++) { - if (startLine.start[k] == ' ') { - if (space == -1) space = k; - else { - // too many spaces - infractions |= INF_BADREQLINE; - return; - } - } - } - if ((space <= 0)) { - // no first space or a leading space - infractions |= INF_BADREQLINE; - return; - } - - method.start = startLine.start; - method.length = space; - uri.start = startLine.start + method.length + 1; - uri.length = startLine.length - method.length - 10; - version.start = startLine.start + (startLine.length - 8); - version.length = 8; - assert (startLine.length == method.length + uri.length + version.length + 2); -} - -void NHttpMsgHeader::parseStatusLine() { - // Eventually we may need to cater to certain format errors, but for now exact match or treat as error. - // HTTP/X.Y### - if ((startLine.length < 13) || (startLine.start[8] != ' ') || (startLine.start[12] != ' ')) { - infractions |= INF_BADSTATLINE; - return; - } - version.start = startLine.start; - version.length = 8; - statusCode.start = startLine.start + 9; - statusCode.length = 3; - reasonPhrase.start = startLine.start + 13; - reasonPhrase.length = startLine.length - 13; - assert (startLine.length == version.length + statusCode.length + reasonPhrase.length + 2); -} - -// Divide up the block of header fields into individual header field lines. -void NHttpMsgHeader::parseHeaderBlock() { - if (headers.length <= 0) return; - int32_t bytesused = 0; - numHeaders = 0; - while (bytesused < headers.length) { - headerLine[numHeaders].start = headers.start + bytesused; - headerLine[numHeaders].length = findCrlf(headerLine[numHeaders].start, headers.length - bytesused, true); - bytesused += headerLine[numHeaders++].length + 2; - if (numHeaders >= MAXHEADERS) { - break; - } - } - if (bytesused < headers.length) { - infractions |= INF_TOOMANYHEADERS; - } -} - -// Divide header field lines into field name and field value -void NHttpMsgHeader::parseHeaderLines() { - int colon; - for (int k=0; k < numHeaders; k++) { - for (colon=0; colon < headerLine[k].length; colon++) { - if (headerLine[k].start[colon] == ':') break; - } - if (colon < headerLine[k].length) { - headerName[k].start = headerLine[k].start; - headerName[k].length = colon; - headerValue[k].start = headerLine[k].start + colon + 1; - headerValue[k].length = headerLine[k].length - colon - 1; - } - else { - infractions |= INF_BADHEADER; - } - } -} - -void NHttpMsgHeader::deriveStatusCodeNum() { - if (statusCode.length != 3) { - statusCodeNum = STAT_PROBLEMATIC; - return; - } - if ((statusCode.start[0] < '0') || (statusCode.start[0] > '9') || (statusCode.start[1] < '0') || (statusCode.start[1] > '9') || - (statusCode.start[2] < '0') || (statusCode.start[2] > '9')) { - infractions |= INF_BADSTATCODE; - statusCodeNum = STAT_PROBLEMATIC; - return; - } - statusCodeNum = (statusCode.start[0] - '0') * 100 + (statusCode.start[1] - '0') * 10 + (statusCode.start[2] - '0'); - if ((statusCodeNum < 100) || (statusCodeNum > 599)) { - infractions |= INF_BADSTATCODE; - } -} - -void NHttpMsgHeader::deriveVersionId() { - if (version.length != 8) { - versionId = VERS__PROBLEMATIC; - return; - } - if (memcmp(version.start, "HTTP/", 5) || (version.start[6] != '.')) { - versionId = VERS__PROBLEMATIC; - infractions |= INF_BADVERSION; - } - else if ((version.start[5] == '1') && (version.start[7] == '1')) { - versionId = VERS_1_1; - } - else if ((version.start[5] == '1') && (version.start[7] == '0')) { - versionId = VERS_1_0; - } - else if ((version.start[5] == '2') && (version.start[7] == '0')) { - versionId = VERS_2_0; - } - else if ((version.start[5] >= '0') && (version.start[5] <= '9') && (version.start[7] >= '0') && (version.start[7] <= '9')) { - versionId = VERS__OTHER; - infractions |= INF_UNKNOWNVERSION; - } - else { - versionId = VERS__PROBLEMATIC; - infractions |= INF_BADVERSION; - } -} - -void NHttpMsgHeader::deriveMethodId() { - methodId = (MethodId) strToCode(method.start, method.length, methodList); -} - -void NHttpMsgHeader::deriveHeaderNameId(int index) { - if (headerName[index].length <= 0) return; - // Normalize header field name to lower case for matching purposes - uint8_t *lowerName; - if ((lowerName = scratchPad.request(headerName[index].length)) == nullptr) { - infractions |= INF_NOSCRATCH; - headerNameId[index] = HEAD__INSUFMEMORY; - return; - } - int32_t lowerLength = norm2Lower(headerName[index].start, headerName[index].length, lowerName, infractions, nullptr); - headerNameId[index] = (HeaderId) strToCode(lowerName, lowerLength, headerList); -} - -void NHttpMsgHeader::genEvents() { - if (infractions != 0) SnortEventqAdd(GID_HTTP_CLIENT, 1); // I'm just an example event (HI_CLIENT_ASCII) -} - -void NHttpMsgHeader::printInterval(FILE *output, const char* name, const uint8_t *text, int32_t length, bool intVals) { - if ((length == STAT_NOTPRESENT) || (length == STAT_NOTCOMPUTE)) return; - fprintf(output, "%s, length = %d\n", name, length); - if (length <= 0) return; - if (text == nullptr) { - fprintf(output, "nullptr\n"); - return; - } - for (int k=0; k < length; k++) { - if ((text[k] >= 0x20) && (text[k] <= 0x7E)) fprintf(output, "%c", (char)text[k]); - else if (text[k] == 0x0) fprintf(output, "~"); - else if (text[k] == 0xD) fprintf(output, "`"); - else if (text[k] == 0xA) fprintf(output, "'"); - else fprintf(output, "*"); - if (k%200 == 199) fprintf(output, "\n"); - } - - if (intVals && (length%4 == 0)) { - fprintf(output, "\nInteger values ="); - for (int j=0; j < length; j+=4) { - fprintf(output, " %u", *((const uint32_t*)(text+j))); - } - } - fprintf(output, "\n"); -} - -void NHttpMsgHeader::printMessage(FILE *output) { - fprintf(output, "Printout of HTTP message structure.\n"); - printInterval(output, "Raw message", msgText, length); - printInterval(output, "Start Line", startLine.start, startLine.length); - if (sourceId != SRC__NOTCOMPUTE) fprintf(output, "Source Id: %d\n", sourceId); - printInterval(output, "Version", version.start, version.length); - if (versionId != VERS__NOTCOMPUTE) fprintf(output, "Version Id: %d\n", versionId); - printInterval(output, "Method", method.start, method.length); - if (methodId != METH__NOTCOMPUTE) fprintf(output, "Method Id: %d\n", methodId); - printInterval(output, "URI", uri.start, uri.length); - printInterval(output, "Status Code", statusCode.start, statusCode.length); - if (statusCodeNum != STAT_NOTCOMPUTE) fprintf(output, "Status Code Num: %d\n", statusCodeNum); - printInterval(output, "Reason Phrase", reasonPhrase.start, reasonPhrase.length); - printInterval(output, "Headers", headers.start, headers.length); - if (numHeaders != STAT_NOTCOMPUTE) fprintf(output, "Number of headers: %d\n", numHeaders); - for (int j=0; j < numHeaders && j < 200; j++) { - printInterval(output, "Header Line", headerLine[j].start, headerLine[j].length); - printInterval(output, "Header Name", headerName[j].start, headerName[j].length); - fprintf(output, "Header name Id: %d\n", headerNameId[j]); - printInterval(output, "Header Value", headerValue[j].start, headerValue[j].length); - } - for (int k=1; k <= numNorms; k++) { - if (headerValueNorm[k].length != STAT_NOTPRESENT) fprintf(output, "Header ID = %d\n", k); - printInterval(output, "Header Value Normalized", headerValueNorm[k].start, headerValueNorm[k].length, true); - } - fprintf(output, "Infractions: %lx\n", infractions); - fprintf(output, "TCP Close: %s\n", tcpClose ? "True" : "False"); - - fprintf(output, "Interface to old clients. http_mask = %x.\n", http_mask); - for (int i=0; i < HTTP_BUFFER_MAX; i++) { - if ((1 << i) & http_mask) printInterval(output, http_buffer_name[i], http_buffer[i].buf, http_buffer[i].length); - } -} - -// Legacy support function. Puts message fields into the buffers used by old Snort. This should go away. -void NHttpMsgHeader::oldClients() { - ClearHttpBuffers(); - - if (method.length > 0) SetHttpBuffer(HTTP_BUFFER_METHOD, method.start, (unsigned)method.length); - if (uri.length > 0) SetHttpBuffer(HTTP_BUFFER_RAW_URI, uri.start, (unsigned)uri.length); - if (uri.length > 0) SetHttpBuffer(HTTP_BUFFER_URI, uri.start, (unsigned)uri.length); - if (headers.length > 0) SetHttpBuffer(HTTP_BUFFER_RAW_HEADER, headers.start, (unsigned)headers.length); - if (headers.length > 0) SetHttpBuffer(HTTP_BUFFER_HEADER, headers.start, (unsigned)headers.length); - if (statusCode.length > 0) SetHttpBuffer(HTTP_BUFFER_STAT_CODE, statusCode.start, (unsigned)statusCode.length); - if (reasonPhrase.length > 0) SetHttpBuffer(HTTP_BUFFER_STAT_MSG, reasonPhrase.start, (unsigned)reasonPhrase.length); - - for (int k=0; (headerNameId[k] != HEAD__NOTCOMPUTE) && (k < MAXHEADERS); k++) { - if (((headerNameId[k] == HEAD_COOKIE) && (sourceId == SRC_CLIENT)) || ((headerNameId[k] == HEAD_SET_COOKIE) && (sourceId == SRC_SERVER))) { - if (headerValue[k].length > 0) SetHttpBuffer(HTTP_BUFFER_RAW_COOKIE, headerValue[k].start, (unsigned)headerValue[k].length); - break; - } - } - - if ((sourceId == SRC_CLIENT) && (headerValueNorm[HEAD_COOKIE].length > 0)) - SetHttpBuffer(HTTP_BUFFER_COOKIE, headerValueNorm[HEAD_COOKIE].start, (unsigned)headerValueNorm[HEAD_COOKIE].length); - else if ((sourceId == SRC_SERVER) && (headerValueNorm[HEAD_SET_COOKIE].length > 0)) - SetHttpBuffer(HTTP_BUFFER_COOKIE, headerValueNorm[HEAD_SET_COOKIE].start, (unsigned)headerValueNorm[HEAD_SET_COOKIE].length); -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msgheader.h b/src/service_inspectors/nhttp_inspect/nhttp_msgheader.h deleted file mode 100644 index adc859f0c..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_msgheader.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief NHttpMsgHeader class declaration -// - -#ifndef NHTTP_MSGHEADER_H -#define NHTTP_MSGHEADER_H - - -//------------------------------------------------------------------------- -// NHttpMsgHeader class -//------------------------------------------------------------------------- - -class NHttpMsgHeader { -public: - NHttpMsgHeader() {}; - void loadMessage(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_); - void analyze(); - void printMessage(FILE *output); - void genEvents(); - void oldClients(); // I'm a legacy support method and should go away eventually - static const uint32_t MAXOCTETS = 65535; - -private: - // Header normalization. There should be one of these for every different way we can process a header field value. - static const HeaderNormalizer NORMALIZER_NIL; - static const HeaderNormalizer NORMALIZER_BASIC; - static const HeaderNormalizer NORMALIZER_CAT; - static const HeaderNormalizer NORMALIZER_NOREPEAT; - static const HeaderNormalizer NORMALIZER_DECIMAL; - static const HeaderNormalizer NORMALIZER_TRANSCODE; - - // Master table of known header fields and their normalization strategies. - static const HeaderNormalizer* const headerNorms[]; - static const int32_t numNorms; - - // Code conversion tables are for turning token strings into enums. - static const StrCode methodList[]; - static const StrCode headerList[]; - static const StrCode transCodeList[]; - - // "Parse" methods cut things into pieces. "Derive" methods convert things into a new format such as an integer or enum token. "Normalize" methods convert - // things into a standard form without changing the underlying format. - void parseWhole(); - void deriveSourceId(); - void parseRequestLine(); - void parseStatusLine(); - void parseHeaderBlock(); - void parseHeaderLines(); - void deriveHeaderNameId(int index); - void deriveStatusCodeNum(); - void deriveVersionId(); - void deriveMethodId(); - - // Convenience methods - uint32_t findCrlf(const uint8_t* buffer, uint32_t length, bool wrappable); - void printInterval(FILE *output, const char* name, const uint8_t *text, int32_t length, bool intVals = false); - - // The current strategy is to copy the entire raw message headers into this object. Here it is. - uint32_t length; // Length of the original message headers in octets - uint8_t rawBuf[MAXOCTETS]; // The original HTTP message header octets - // This pointer is the handle for working with the original message data. It makes it simple to later replace rawBuf with some other form of storage - // such as the buffer in the packet structure or something dynamic. Const x 2 because this pointer should never change and people working with the - // original message should not be changing it. Only loading a completely new message into rawBuf should do that. - const uint8_t * const msgText = rawBuf; - - // Working space and storage for all the derived fields. See scratchPad.h for usage instructions. - // Allocation size may be complete overkill. Need to revisit this. - uint32_t derivedBuf[MAXOCTETS/4]; - NHttpFlowData* sessionData; - ScratchPad scratchPad {derivedBuf, MAXOCTETS/4}; - - // This is where all the derived values, extracted message parts, and normalized values are. - // Note that this is all scalars, buffer pointers, and buffer sizes. The actual buffers are in the original message buffer (raw pieces) or the - // scratchPad (normalized pieces). - uint64_t infractions; - bool tcpClose; - field startLine; - NHttpEnums::SourceId sourceId; - field version; - NHttpEnums::VersionId versionId; - field method; - NHttpEnums::MethodId methodId; - field uri; - field statusCode; - int32_t statusCodeNum; - field reasonPhrase; - field headers; - static const int MAXHEADERS = 200; // I'm an arbitrary number. Need to revisit. - int32_t numHeaders; - field headerLine[MAXHEADERS]; - field headerName[MAXHEADERS]; - NHttpEnums::HeaderId headerNameId[MAXHEADERS]; - field headerValue[MAXHEADERS]; - field headerValueNorm[NHttpEnums::HEAD__MAXVALUE]; -}; - -#endif - - - - - - - - - - - - - - - - - - - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_scratchpad.h b/src/service_inspectors/nhttp_inspect/nhttp_scratchpad.h deleted file mode 100644 index fd568f8fe..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_scratchpad.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief ScratchPad class declaration -// - -#ifndef NHTTP_SCRATCHPAD_H -#define NHTTP_SCRATCHPAD_H - - -//------------------------------------------------------------------------- -// ScratchPad class -// Memory management for NHttpMsgHeader class -//------------------------------------------------------------------------- - -// Working space and storage for all the derived fields -// Return value of request is 32-bit aligned and may be freely cast to uint32_t* -// 1. request the maximum number of bytes you might need -// 2. use what you need -// 3. commit() what you actually used if you want to keep it -// Anything you do not commit will be reused by the next request. - -class ScratchPad { -public: - ScratchPad(uint32_t *buff, uint32_t length) : buffer(buff), capacity(length*4), used(0) {}; // Careful: length must be number of uint32_ts provided, not octets. - void reinit() {used = 0;}; - uint8_t *request(uint32_t needed) const {return (needed <= capacity-used) ? (uint8_t*)(buffer+used) : nullptr;}; - void commit(uint32_t taken) { used += taken + (4-(taken%4))%4; }; // round up to multiple of 4 to preserve alignment - -private: - uint32_t *buffer; - uint32_t capacity; - uint32_t used; -}; - -#endif - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_strtocode.cc b/src/service_inspectors/nhttp_inspect/nhttp_strtocode.cc deleted file mode 100644 index 5ad95a40c..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_strtocode.cc +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Converts token strings to enum codes -// - - -#include -#include -#include -#include "snort.h" -#include "nhttp_enum.h" -#include "nhttp_strtocode.h" - -// Need to replace this simple algorithm for better performance -int32_t strToCode(const uint8_t *text, int32_t textLen, const StrCode table[]) { - if (textLen <= 0) return NHttpEnums::STAT_PROBLEMATIC; - for (int32_t k=0; table[k].name != nullptr; k++) { - if ((textLen == (int) strlen(table[k].name)) && (memcmp(text, table[k].name, textLen) == 0)) { - return table[k].code; - } - } - return NHttpEnums::STAT_OTHER; -} - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_strtocode.h b/src/service_inspectors/nhttp_inspect/nhttp_strtocode.h deleted file mode 100644 index 5aceece78..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_strtocode.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Converts protocol constant string to enum -// - -#ifndef NHTTP_STRTOCODE_H -#define NHTTP_STRTOCODE_H - -struct StrCode { - int32_t code; - const char *name; -}; - -int32_t strToCode(const uint8_t *text, int32_t textLen, const StrCode table[]); - -#endif - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_testinput.cc b/src/service_inspectors/nhttp_inspect/nhttp_testinput.cc deleted file mode 100644 index e264e7f7b..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_testinput.cc +++ /dev/null @@ -1,162 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Interface to file test messages -// - - -#include -#include -#include -#include -#include -#include "snort.h" -#include "flow/flow.h" -#include "nhttp_enum.h" -#include "nhttp_scratchpad.h" -#include "nhttp_strtocode.h" -#include "nhttp_headnorm.h" -#include "nhttp_flowdata.h" -#include "nhttp_msgheader.h" -#include "nhttp_testinput.h" - -NHttpTestInput::NHttpTestInput(const char *fileName) { - if ((msgFile = fopen(fileName, "r")) == nullptr) throw std::runtime_error("Cannot open test input file"); -} - -NHttpTestInput::~NHttpTestInput() { - fclose(msgFile); -} - -// Read the next message section from the test data file. -// In the process we may need to skip comments, execute simple commands, and handle simple escape sequences. -// The best way to understand this function is to read the comments at the top of the file of test cases. -int32_t NHttpTestInput::ntiGet(uint8_t **buffer, NHttpFlowData* sessionData, int64_t &testNumber) { - int32_t length = 0; - *buffer = msgBuf; - int newChar; - typedef enum { WAITING, COMMENT, COMMAND, SECTION, ESCAPE0, ESCAPE1, ESCAPE2 } State; - State state = WAITING; - bool ending; - char escapeNum[] = { 0, 0, '\0' }; - int commandLength = 0; - const int MaxCommand = 100; - char commandValue[MaxCommand]; - - sessionData->tcpClose = false; - sessionData->infractions = 0; - - while ((newChar = getc(msgFile)) != EOF) { - switch (state) { - case WAITING: - if (newChar == '#') state = COMMENT; - else if (newChar == '@') { - state = COMMAND; - commandLength = 0; - } - else if (newChar == '\\') { - state = ESCAPE0; - ending = false; - } - else if (newChar != '\n') { - state = SECTION; - ending = false; - msgBuf[length++] = (uint8_t) newChar; - } - break; - case COMMENT: - if (newChar == '\n') state = WAITING; - break; - case COMMAND: - if (newChar == '\n') { - state = WAITING; - if ((commandLength == strlen("request")) && !memcmp(commandValue, "request", strlen("request"))) sessionData->sourceId = NHttpEnums::SRC_CLIENT; - else if ((commandLength == strlen("response")) && !memcmp(commandValue, "response", strlen("response"))) sessionData->sourceId = NHttpEnums::SRC_SERVER; - else if ((commandLength == strlen("tcpclose")) && !memcmp(commandValue, "tcpclose", strlen("tcpclose"))) sessionData->tcpClose = true; - else if ((commandLength == strlen("break")) && !memcmp(commandValue, "break", strlen("break"))) { - // &&& signifies start of new session so wipe "session data" when we define some. See flowdata.h. - } - else if (commandLength > 0) { - // Look for a test number - bool isNumber = true; - for (int k=0; isNumber && (k < commandLength); k++) { - isNumber = (commandValue[k] >= '0') && (commandValue[k] <= '9'); - } - if (isNumber) { - testNumber = 0; - for (int j=0; j < commandLength; j++) { - testNumber = testNumber * 10 + (commandValue[j] - '0'); - } - } - } - } - else { - if (commandLength < MaxCommand) commandValue[commandLength++] = newChar; - } - break; - case SECTION: - if (newChar == '\\') { - state = ESCAPE0; - } - else if (newChar == '\n') { - if (ending) return length; // Found the blank line that ends the section. - ending = true; - } - else { - ending = false; - msgBuf[length++] = (uint8_t) newChar; - } - break; - case ESCAPE0: - if (newChar == 'n') { state = SECTION; ending = false; msgBuf[length++] = '\n'; } - else if (newChar == 'r') { state = SECTION; ending = false; msgBuf[length++] = '\r'; } - else if (newChar == 't') { state = SECTION; ending = false; msgBuf[length++] = '\t'; } - else if (newChar == '#') { state = SECTION; ending = false; msgBuf[length++] = '#'; } - else if (newChar == '@') { state = SECTION; ending = false; msgBuf[length++] = '@'; } - else if (newChar == '\\') { state = SECTION; ending = false; msgBuf[length++] = '\\'; } - else if ((newChar == 'x') || (newChar == 'X')) state = ESCAPE1; - else { state = SECTION; ending = false; } - break; - case ESCAPE1: - state = ESCAPE2; - escapeNum[0] = newChar; - break; - case ESCAPE2: - state = SECTION; - ending = false; - escapeNum[1] = newChar; - if (((escapeNum[0] < '0') || (escapeNum[0] > '9')) && ((escapeNum[0] < 'A') || (escapeNum[0] > 'Z')) && ((escapeNum[0] < 'a') || (escapeNum[0] > 'z'))) break; - if (((escapeNum[1] < '0') || (escapeNum[1] > '9')) && ((escapeNum[1] < 'A') || (escapeNum[1] > 'Z')) && ((escapeNum[1] < 'a') || (escapeNum[1] > 'z'))) break; - msgBuf[length++] = strtoul(escapeNum, nullptr, 16); - break; - } - // Return because the buffer is full. Not a feature just a safety precaution against bad input. - if (length >= sizeof(msgBuf)) return length; - } - // End-of-file. Return everything we have so far. - return length; -} - - diff --git a/src/service_inspectors/nhttp_inspect/nhttp_testinput.h b/src/service_inspectors/nhttp_inspect/nhttp_testinput.h deleted file mode 100644 index 2d578bd06..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttp_testinput.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** - * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. - * Copyright (C) 2003-2013 Sourcefire, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. You may not use, modify or - * distribute this program under any other version of the GNU General - * Public License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - ****************************************************************************/ - -// -// @author Tom Peters -// -// @brief Converts protocol constant string to enum -// - -#ifndef NHTTP_TESTINPUT_H -#define NHTTP_TESTINPUT_H - -// ntiGet() returns the same static buffer each time. -// Do not call it again before you are finished with the previous output. -class NHttpTestInput { -public: - NHttpTestInput(const char *fileName); - ~NHttpTestInput(); - int32_t ntiGet(uint8_t **buffer, NHttpFlowData* sessionData, int64_t &testNumber); -private: - FILE *msgFile; - uint8_t msgBuf[NHttpMsgHeader::MAXOCTETS]; -}; - -#endif - diff --git a/src/service_inspectors/nhttp_inspect/nhttptestmsgs.txt b/src/service_inspectors/nhttp_inspect/nhttptestmsgs.txt deleted file mode 100644 index 7595d4d97..000000000 --- a/src/service_inspectors/nhttp_inspect/nhttptestmsgs.txt +++ /dev/null @@ -1,66 +0,0 @@ -# A message section is the unit of data passed to the inspector and may by headers, body, a chunk, or trailing headers. -# Blank lines separate message sections. Extra blank lines don't have any effect. -# Lines beginning with '@' are control commands. -# You cannot put comments or control commands in the middle of a message section. -# If a message section begins with # or @ (presumably a very rare situation) you must escape it: \# or \@ -# Control commands: -# @request or @response sets the message direction. Applies to subsequent sections until changed. -# @tcpclose specifies that the section ends with a TCP close. Applies only to the very next section. -# @ sets the test number and hence the test output file name. Applies to subsequent sections until changed. Don't reuse numbers. -# Commands must be all lower case with no white space. -# The escape character is \ and it is used only within message sections. -# \# and \@ are only necessary for the very first character of a message section. \r, \n, \t, \x, \X, and \\ may appear anywhere in a section. -# \x and \X are identical and signify the beginning of an arbitrary two-digit hexadecimal escape value. Examples: 0x3A, 0X27, 0xeE. Case a-f or A-F -# does not matter. - -@1 -@response -HTTP/1.1 200 OK\r\n\r\n - -@2 -@response -HTTP/1.0 315 Redirection test with spaces\r\n\r\n - -@3 -@request -MKREDIRECTREF / HTTP/2.0\r\n\r\n - -@4 -@request -BIND 1234567890?abcdef HTTP/3.8\r\n\r\n - -@5 -@response -HTTP/2.0 600 Bogus-status-code\r\n\r\n - -@6 -@response -HTTP/1.9 26 Short?status++co\nde\r\n\r\n - -@7 -@response -HTTP/1.F 502 abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghij -klmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstu -vwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890\r\n\r\n - -@8 -@request -GET /test/hi-there.txt HTTP/1.0\r\n\r\n - -@9 -@request -GET /test/hi-there.htm HTTP/1.1\r\nAccept: text/*\r\nAccept-Language: en,fr\r\n\r\n - -@10 -@request -GET /test/trigger/hi-there.htm HTTP/1.1\r\nAccept: text/*\r\nAccept-Language: en,fr\r\n\r\n - -@11 -@request -@tcpclose -GET /test/trigger/hi-there.htm HTTP/1.1\r\nAccept: text/*\r\nAccept-Language: en,fr\r\n\r\n - -@12 -@response -HTTP/2.0 200 OK\r\nContent-type: \ttext/plain\t\r\nContent-LENGTH: 19\r\n\r\n -