]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
just-in-time implementation and many refactorings
authorTom Peters <thopeter@cisco.com>
Mon, 14 Jul 2014 15:51:54 +0000 (11:51 -0400)
committerTom Peters <thopeter@cisco.com>
Mon, 14 Jul 2014 15:51:54 +0000 (11:51 -0400)
36 files changed:
src/service_inspectors/nhttp_inspect/nhttp_api.cc
src/service_inspectors/nhttp_inspect/nhttp_enum.h
src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc
src/service_inspectors/nhttp_inspect/nhttp_flow_data.h
src/service_inspectors/nhttp_inspect/nhttp_head_norm.cc
src/service_inspectors/nhttp_inspect/nhttp_head_norm.h
src/service_inspectors/nhttp_inspect/nhttp_inspect.cc
src/service_inspectors/nhttp_inspect/nhttp_inspect.h
src/service_inspectors/nhttp_inspect/nhttp_module.cc
src/service_inspectors/nhttp_inspect/nhttp_module.h
src/service_inspectors/nhttp_inspect/nhttp_msg_body.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_body.h
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.h
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_head.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_head.h
src/service_inspectors/nhttp_inspect/nhttp_msg_head.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_head.h
src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.h
src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_request.h
src/service_inspectors/nhttp_inspect/nhttp_msg_section.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_section.h
src/service_inspectors/nhttp_inspect/nhttp_msg_start.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_start.h
src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_status.h
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.cc
src/service_inspectors/nhttp_inspect/nhttp_msg_trailer.h
src/service_inspectors/nhttp_inspect/nhttp_scratch_pad.h
src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc
src/service_inspectors/nhttp_inspect/nhttp_tables.cc
src/service_inspectors/nhttp_inspect/nhttp_test_input.cc
src/service_inspectors/nhttp_inspect/nhttp_test_input.h
src/service_inspectors/nhttp_inspect/nhttp_uri.h

index 94bff69771c6f5e50a7e21a7b89636cacc123480..db9420bb68a2d64bc77efc020b1c71d57daba4d2 100644 (file)
@@ -50,7 +50,7 @@ void NHttpApi::nhttp_init()
 Inspector* NHttpApi::nhttp_ctor(Module* mod)
 {
     const NHttpModule* nhttpMod = (NHttpModule*) mod;
-    return new NHttpInspect(nhttpMod->get_test_input(), nhttpMod->get_test_output(), nhttpMod->get_test_inspect());
+    return new NHttpInspect(nhttpMod->get_test_input(), nhttpMod->get_test_output());
 }
 
 static const char* buffers[] =
index fa94fb34209f9974e690b79f8594cd2c82c65e36..fcc8d6f312df207fce3aba3619e9c8f8b915c4c4 100644 (file)
@@ -100,8 +100,11 @@ typedef enum { TRANSCODE__OTHER=1, TRANSCODE_CHUNKED, TRANSCODE_IDENTITY, TRANSC
 // Never use the start pointer without verifying that length > 0.
 struct field {
 public:
-    const uint8_t *start = nullptr;
     int32_t length = NHttpEnums::STAT_NOTCOMPUTE;
+    const uint8_t* start = nullptr;
+
+    field(int32_t length_, const uint8_t* start_) : length(length_), start(start_) {};
+    field() = default;
 };
 
 typedef enum 
index 818c229000c74686d61ca1d32f28b5820238a509..b1e99bc2801643e08c15dec6e829bff5c2737f0f 100644 (file)
@@ -41,17 +41,18 @@ NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) {}
 
 void NHttpFlowData::halfReset(SourceId sourceId) {
     assert((sourceId == SRC_CLIENT) || (sourceId == SRC_SERVER));
-    dataLength[sourceId] = STAT_NOTPRESENT;
     octetsExpected[sourceId] = STAT_NOTPRESENT;
+
+    versionId[sourceId] = VERS__NOTPRESENT;
+    methodId[sourceId] = METH__NOTPRESENT;
+    statusCodeNum[sourceId] = STAT_NOTPRESENT;
+
+    dataLength[sourceId] = STAT_NOTPRESENT;
     bodySections[sourceId] = STAT_NOTPRESENT;
     bodyOctets[sourceId] = STAT_NOTPRESENT;
     numChunks[sourceId] = STAT_NOTPRESENT;
     chunkSections[sourceId] = STAT_NOTPRESENT;
     chunkOctets[sourceId] = STAT_NOTPRESENT;
-
-    versionId[sourceId] = VERS__NOTPRESENT;
-    methodId[sourceId] = METH__NOTPRESENT;
-    statusCodeNum[sourceId] = STAT_NOTPRESENT;
 }
 
 
index c35ed00be58ef849f058cb7c53c3e85e74bc3e84..de787eb02d4a243f42d6c9083978895221737061 100644 (file)
@@ -58,19 +58,17 @@ public:
     friend class NHttpMsgChunkHead;
     friend class NHttpMsgChunkBody;
     friend class NHttpMsgTrailer;
-    friend class NHttpTestInput;
     friend class NHttpStreamSplitter;
 private:
     void halfReset(NHttpEnums::SourceId sourceId);
 
     // StreamSplitter => Inspector (facts about the most recent message section)
-    NHttpEnums::SourceId sourceId = NHttpEnums::SRC__NOTCOMPUTE;
-    NHttpEnums::SectionType sectionType = NHttpEnums::SEC__NOTCOMPUTE;
-    bool tcpClose = false;
-    uint64_t infractions = 0;
+    // 0 element refers to client request, 1 element refers to server response
+    NHttpEnums::SectionType sectionType[2] = { NHttpEnums::SEC__NOTCOMPUTE, NHttpEnums::SEC__NOTCOMPUTE };
+    bool tcpClose[2] = { false, false };
+    uint64_t infractions[2] = { 0, 0 };
 
     // Inspector => StreamSplitter (facts about the message section that is coming next)
-    // 0 element refers to client request, 1 element refers to server response
     NHttpEnums::SectionType typeExpected[2] = { NHttpEnums::SEC_REQUEST, NHttpEnums::SEC_STATUS };
     int64_t octetsExpected[2] = { NHttpEnums::STAT_NOTPRESENT, NHttpEnums::STAT_NOTPRESENT };    // expected size of the upcoming body or chunk body section      
 
index 9b3d6adc858f71c97673cb1c23d557bc5825da5c..da296d607cbbe74b37e3993d2cc5d2e3eb050621 100644 (file)
@@ -60,57 +60,46 @@ int32_t HeaderNormalizer::deriveHeaderContent(const uint8_t *value, int32_t leng
 }
 
 // This method normalizes the header field value for headId.
-int32_t HeaderNormalizer::normalize(HeaderId headId, ScratchPad &scratchPad, uint64_t &infractions, const HeaderId headerNameId[], const field headerValue[], int32_t numHeaders,
-        field &resultField) const {
-    // If the raw header is not present length will be STAT_NOSOURCE and normalization is skipped
+int32_t HeaderNormalizer::normalize(const HeaderId headId, const int count, ScratchPad &scratchPad, uint64_t &infractions,
+        const HeaderId headerNameId[], const field headerValue[], const int32_t numHeaders, field &resultField) const {
     if (resultField.length != STAT_NOTCOMPUTE) return resultField.length;
-    if (format == NORM_NULL) {
-        resultField.length = STAT_NOTCONFIGURED;
-        return resultField.length;
-    }
+    if (format == NORM_NULL) return resultField.length = STAT_NOTCONFIGURED;
+    if (count == 0) return resultField.length = STAT_NOSOURCE;
 
-    // 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.
+    // Search Header IDs from all the headers in this message. concatenateRepeats means the header can properly be
+    // present more than once. The standard normalization is to concatenate all the repeated field values into a
+    // comma-separated list. Otherwise only the first value will be normalized and the rest will be ignored.
 
     int numMatches = 0;
     int32_t bufferLength = 0;
-    int firstMatch = -1;
+    int currMatch;
     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 == 1) currMatch = k;    // remembering location of the first matching header
+            bufferLength += headerValue[k].length;
+            if (!concatenateRepeats || (numMatches >= count)) break;
         }
     }
-    if (numMatches == 0) {
-        resultField.length = STAT_NOSOURCE;
-        return resultField.length;
-    }
-    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
-    // Round up to multiple of eight so that both halves are 64-bit aligned.
-    // 200 is a "way too big" fudge factor to allow for modest expansion of field size during normalization. Needs improvement.
+    assert((!concatenateRepeats && (numMatches == 1)) || (concatenateRepeats && (numMatches == count)));
+    bufferLength += numMatches - 1;    // allow space for concatenation commas
+
+    // 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.
+
+    // Round up to multiple of eight so that both halves are 64-bit aligned. 200 is a "way too big" fudge factor to allow
+    // for modest expansion of field size during normalization.
     bufferLength += (8-bufferLength%8)%8 + 200;
-    uint8_t * const scratch = scratchPad.request(2*bufferLength);
-    if (scratch == nullptr) {
-        resultField.length = STAT_INSUFMEMORY;
-        return resultField.length;
-    }
+    uint8_t* const scratch = scratchPad.request(2*bufferLength);
+    if (scratch == nullptr) return resultField.length = STAT_INSUFMEMORY;
 
-    uint8_t * const frontHalf = scratch;
-    uint8_t * const backHalf = scratch + bufferLength;
-    uint8_t *working = (numNormalizers%2 == 0) ? frontHalf : backHalf;
-    int currMatch = firstMatch;
+    uint8_t* const frontHalf = scratch;
+    uint8_t* const backHalf = scratch + bufferLength;
+    uint8_t* working = (numNormalizers%2 == 0) ? frontHalf : backHalf;
     int32_t dataLength = 0;
     for (int j=0; j < numMatches; j++) {
         if (j >= 1) {
@@ -121,16 +110,12 @@ int32_t HeaderNormalizer::normalize(HeaderId headId, ScratchPad &scratchPad, uin
         int32_t 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.length;
-        }
+        if (dataLength <= 0) return resultField.length = dataLength;
     }
     resultField.start = scratch;
     resultField.length = dataLength;
@@ -139,3 +124,4 @@ int32_t HeaderNormalizer::normalize(HeaderId headId, ScratchPad &scratchPad, uin
 }
 
 
+
index 63b0d7e03d40508ac0abd882ac49245f7c93c244..46af08127dcf861b3fc64706de52588ca68750d3 100644 (file)
 
 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*),
+    constexpr HeaderNormalizer(NHttpEnums::NormFormat _format, bool _concatenateRepeats, 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)) {};
-    int32_t normalize(NHttpEnums::HeaderId headId, ScratchPad &scratchPad, uint64_t &infractions, const NHttpEnums::HeaderId headerNameId[], const field headerName[], int32_t numHeaders,
-       field &resultField) const;
+    int32_t normalize(const NHttpEnums::HeaderId headId, const int count, ScratchPad &scratchPad, uint64_t &infractions,
+       const NHttpEnums::HeaderId headerNameId[], const field headerValue[], const int32_t numHeaders, field &resultField) const;
     NHttpEnums::NormFormat getFormat() const {return format;};
 
 private:
@@ -61,7 +60,6 @@ private:
 
     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;
index 4bc2aec154bdf592136af188d9670656735ebf0e..ef99df94065295054daf2331dfd1b1c9adf63091 100644 (file)
@@ -42,7 +42,7 @@
 
 using namespace NHttpEnums;
 
-NHttpInspect::NHttpInspect(bool test_input, bool _test_output, bool _test_inspect) : test_output(_test_output), test_inspect(_test_inspect)
+NHttpInspect::NHttpInspect(bool test_input, bool _test_output) : test_output(_test_output)
 {
     NHttpTestInput::test_input = test_input;
     if (NHttpTestInput::test_input) {
@@ -104,10 +104,10 @@ void NHttpInspect::eval(Packet* p)
     // Only packets from the StreamSplitter can be processed
     if (!PacketHasPAFPayload(p)) return;
 
-    process(p->data, p->dsize, p->flow);
+    process(p->data, p->dsize, p->flow, (p->packet_flags & PKT_FROM_CLIENT) ? SRC_CLIENT : SRC_SERVER);
 }
 
-void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow)
+void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow, SourceId sourceId)
 {
     delete msgSection;
     msgSection = nullptr;
@@ -116,48 +116,44 @@ void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* cons
     assert(sessionData);
 
     if (!NHttpTestInput::test_input) {
-        switch (sessionData->sectionType) {
-          case SEC_REQUEST: msgSection = new NHttpMsgRequest; break;
-          case SEC_STATUS: msgSection = new NHttpMsgStatus; break;
-          case SEC_HEADER: msgSection = new NHttpMsgHeader; break;
-          case SEC_BODY: msgSection = new NHttpMsgBody; break;
-          case SEC_CHUNKHEAD: msgSection = new NHttpMsgChunkHead; break;
-          case SEC_CHUNKBODY: msgSection = new NHttpMsgChunkBody; break;
-          case SEC_TRAILER: msgSection = new NHttpMsgTrailer; break;
+        switch (sessionData->sectionType[sourceId]) {
+          case SEC_REQUEST: msgSection = new NHttpMsgRequest(data, dsize, sessionData, sourceId); break;
+          case SEC_STATUS: msgSection = new NHttpMsgStatus(data, dsize, sessionData, sourceId); break;
+          case SEC_HEADER: msgSection = new NHttpMsgHeader(data, dsize, sessionData, sourceId); break;
+          case SEC_BODY: msgSection = new NHttpMsgBody(data, dsize, sessionData, sourceId); break;
+          case SEC_CHUNKHEAD: msgSection = new NHttpMsgChunkHead(data, dsize, sessionData, sourceId); break;
+          case SEC_CHUNKBODY: msgSection = new NHttpMsgChunkBody(data, dsize, sessionData, sourceId); break;
+          case SEC_TRAILER: msgSection = new NHttpMsgTrailer(data, dsize, sessionData, sourceId); break;
           case SEC_DISCARD: return;
           default: assert(0); return;
         }
-        msgSection->loadSection(data, dsize, sessionData);
     }
     else {
         uint8_t *testBuffer;
         uint16_t testLength;
-        if ((testLength = NHttpTestInput::testInput->toEval(&testBuffer, testNumber)) > 0) {
-            switch (sessionData->sectionType) {
-              case SEC_REQUEST: msgSection = new NHttpMsgRequest; break;
-              case SEC_STATUS: msgSection = new NHttpMsgStatus; break;
-              case SEC_HEADER: msgSection = new NHttpMsgHeader; break;
-              case SEC_BODY: msgSection = new NHttpMsgBody; break;
-              case SEC_CHUNKHEAD: msgSection = new NHttpMsgChunkHead; break;
-              case SEC_CHUNKBODY: msgSection = new NHttpMsgChunkBody; break;
-              case SEC_TRAILER: msgSection = new NHttpMsgTrailer; break;
+        if ((testLength = NHttpTestInput::testInput->toEval(&testBuffer, testNumber, sourceId)) > 0) {
+            switch (sessionData->sectionType[sourceId]) {
+              case SEC_REQUEST: msgSection = new NHttpMsgRequest(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_STATUS: msgSection = new NHttpMsgStatus(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_HEADER: msgSection = new NHttpMsgHeader(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_BODY: msgSection = new NHttpMsgBody(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_CHUNKHEAD: msgSection = new NHttpMsgChunkHead(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_CHUNKBODY: msgSection = new NHttpMsgChunkBody(testBuffer, testLength, sessionData, sourceId); break;
+              case SEC_TRAILER: msgSection = new NHttpMsgTrailer(testBuffer, testLength, sessionData, sourceId); break;
               case SEC_DISCARD: return;
               default: assert(0); return;
             }
-            msgSection->loadSection(testBuffer, testLength, sessionData);
         }
         else {
             printf("Zero length test data.\n");
             return;
         }
     }
-    msgSection->initSection();
     msgSection->analyze();
     msgSection->updateFlow();
     msgSection->genEvents();
     msgSection->legacyClients();
 
-    if (test_inspect) msgSection->analyzeAll();
     if (test_output) {
         if (!NHttpTestInput::test_input) msgSection->printSection(stdout);
         else {
index e1db545f73fdf5ae17dd7e40ab8fa94b5946bd5d..1e70bf881af95d386e0123b9d9ca9241fb06f78e 100644 (file)
@@ -42,7 +42,7 @@ class NHttpApi;
 
 class NHttpInspect : public Inspector {
 public:
-    NHttpInspect(bool test_input, bool _test_output, bool _test_inspect);
+    NHttpInspect(bool test_input, bool _test_output);
     ~NHttpInspect();
 
     bool get_buf(unsigned, Packet*, InspectionBuffer&);
@@ -59,11 +59,10 @@ private:
     friend NHttpApi;
     NHttpMsgSection *msgSection = nullptr;
 
-    void process(const uint8_t* data, const uint16_t dsize, Flow* const flow);
+    void process(const uint8_t* data, const uint16_t dsize, Flow* const flow, NHttpEnums::SourceId sourceId_);
 
     // Test mode
     bool test_output;
-    bool test_inspect;
     const char *testInputFile = "nhttp_test_msgs.txt";
     const char *testOutputPrefix = "nhttpresults/testcase";
     FILE *testOut = nullptr;
index 691641f328ea368f46d5bce055e71c3639301c91..73b5670e1bc43298ecbf23b1c43f5de178842e30 100644 (file)
@@ -39,13 +39,11 @@ NHttpModule::NHttpModule() : Module("nhttp_inspect", nhttpParams, nhttpEvents) {
 const Parameter NHttpModule::nhttpParams[] =
     {{ "test_input", Parameter::PT_BOOL, nullptr, "false", "read HTTP messages from text file" },
      { "test_output", Parameter::PT_BOOL, nullptr, "false", "print out HTTP section data" },
-     { "test_inspect", Parameter::PT_BOOL, nullptr, "false", "force all possible inspections and normalizations" },
      { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }};
 
 bool NHttpModule::begin(const char*, int, SnortConfig*) {
     test_input = false;
     test_output = false;
-    test_inspect = false;
     return true;
 }
 
@@ -56,7 +54,6 @@ bool NHttpModule::end(const char*, int, SnortConfig*) {
 bool NHttpModule::set(const char*, Value &val, SnortConfig*) {
     if (val.is("test_input")) test_input = val.get_bool();
     else if (val.is("test_output")) test_output = val.get_bool();
-    else if (val.is("test_inspect")) test_inspect = val.get_bool();
     else return false;
 
     return true;
index 6b2b9a9939ea96a3c30ecd795cbbea2a0e1c2ebe..e1a9f566db607cab54b5a75b14db8a8ec1e3a24c 100644 (file)
@@ -41,13 +41,11 @@ public:
     unsigned get_gid() const;
     bool get_test_input() const { return test_input; };
     bool get_test_output() const { return test_output; };
-    bool get_test_inspect() const { return test_inspect; };
 private:
     static const Parameter nhttpParams[];
     static const RuleMap nhttpEvents[];
     bool test_input = false;
     bool test_output = false;
-    bool test_inspect = false;
 };
 
 #endif
index 20794737030e3accd6ae2f1d03c6a71bdd5dfbc4..b9adba53706f3956cb6a225589f81282529ef8cf 100644 (file)
 
 using namespace NHttpEnums;
 
-void NHttpMsgBody::loadSection(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_) {
-    NHttpMsgSection::loadSection(buffer, bufSize, sessionData_);
-
-    dataLength = sessionData->dataLength[sourceId];
-    bodySections = sessionData->bodySections[sourceId];
-    bodyOctets = sessionData->bodyOctets[sourceId];
-}
-
-void NHttpMsgBody::initSection() {
-    data.length = STAT_NOTCOMPUTE;
-}
+NHttpMsgBody::NHttpMsgBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
+   NHttpMsgSection(buffer, bufSize, sessionData_, sourceId_), dataLength(sessionData->dataLength[sourceId]),
+   bodySections(sessionData->bodySections[sourceId]), bodyOctets(sessionData->bodyOctets[sourceId]) {}
 
 void NHttpMsgBody::analyze() {
     bodySections++;
@@ -65,7 +57,7 @@ void NHttpMsgBody::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgBody::printSection(FILE *output) const {
+void NHttpMsgBody::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "body");
     fprintf(output, "Expected data length %" PRIi64 ", sections seen %" PRIi64 ", octets seen %" PRIi64 "\n", dataLength, bodySections, bodyOctets);
     printInterval(output, "Data", data.start, data.length);
index 97a3c5800473c4710e0c722b9aa0dce53d35e76c..73af41a9318ce7af7f38c939899e8f63b4271e45 100644 (file)
 
 class NHttpMsgBody : public NHttpMsgSection {
 public:
-    NHttpMsgBody() {};
-    void loadSection(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_);
-    void initSection();
+    NHttpMsgBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_);
     void analyze();
-    void printSection(FILE *output) const;
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
     void legacyClients();
index fddf73cc1ac0883e1ee1e00ea86f2bdfa8c54907..5197aaa3137a27e3f16af90d2edb3d7129f254ae 100644 (file)
 
 using namespace NHttpEnums;
 
-void NHttpMsgChunkBody::loadSection(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_) {
-    NHttpMsgBody::loadSection(buffer, bufSize, sessionData_);
-
-    numChunks = sessionData->numChunks[sourceId];
-    chunkSections = sessionData->chunkSections[sourceId];
-    chunkOctets = sessionData->chunkOctets[sourceId];
-}
-
-void NHttpMsgChunkBody::initSection() {
-    NHttpMsgBody::initSection();
-}
+NHttpMsgChunkBody::NHttpMsgChunkBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
+    NHttpMsgBody(buffer, bufSize, sessionData_, sourceId_), numChunks(sessionData->numChunks[sourceId]),
+    chunkSections(sessionData->chunkSections[sourceId]), chunkOctets(sessionData->chunkOctets[sourceId]) {}
 
 void NHttpMsgChunkBody::analyze() {
     bodySections++;
@@ -82,7 +74,7 @@ void NHttpMsgChunkBody::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgChunkBody::printSection(FILE *output) const {
+void NHttpMsgChunkBody::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "chunk body");
     fprintf(output, "Expected chunk length %" PRIi64 ", cumulative sections %" PRIi64 ", cumulative octets %" PRIi64 "\n", dataLength, bodySections, bodyOctets);
     fprintf(output, "cumulative chunk sections %" PRIi64 ", cumulative chunk octets %" PRIi64 "\n", chunkSections, chunkOctets);
index f18e6c2e45b43977a4f84a838ec66ee19f15e16f..0430affa462a9b859b3ad9ccbb24fc9359392e3f 100644 (file)
 
 class NHttpMsgChunkBody : public NHttpMsgBody {
 public:
-    NHttpMsgChunkBody() {};
-    void loadSection(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_);
-    void initSection();
+    NHttpMsgChunkBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_);
     void analyze();
-    void printSection(FILE *output) const;
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
 
index c15382e8512b0e7f53efa589497903352822c9bb..1a2598de7e017985f3e16931e562922d32ceed12 100644 (file)
 
 using namespace NHttpEnums;
 
+NHttpMsgChunkHead::NHttpMsgChunkHead(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
+   NHttpMsgSection(buffer, bufSize, sessionData_, sourceId_), bodySections(sessionData->bodySections[sourceId]),
+   numChunks(sessionData->numChunks[sourceId]) {}
+
 // Convert the hexadecimal chunk length.
 // RFC says that zero may be written with multiple digits "000000".
 // Arbitrary limit of 15 hex digits not including leading zeros ensures in a simple way against 64-bit overflow and should be
@@ -70,19 +74,6 @@ void NHttpMsgChunkHead::deriveChunkLength() {
     }
 }
 
-void NHttpMsgChunkHead::loadSection(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_) {
-    NHttpMsgSection::loadSection(buffer, bufSize, sessionData_);
-
-    bodySections = sessionData->bodySections[sourceId];
-    numChunks = sessionData->numChunks[sourceId];
-}
-
-void NHttpMsgChunkHead::initSection() {
-    startLine.length = STAT_NOTCOMPUTE;
-    chunkSize.length = STAT_NOTCOMPUTE;
-    chunkExtensions.length = STAT_NOTCOMPUTE;
-}
-
 void NHttpMsgChunkHead::analyze() {
     bodySections++;
     // First section in a new chunk is just the start line.
@@ -111,7 +102,7 @@ void NHttpMsgChunkHead::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgChunkHead::printSection(FILE *output) const {
+void NHttpMsgChunkHead::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "chunk header");
     fprintf(output, "Chunk size: %" PRIi64 "\n", dataLength);
     printInterval(output, "Chunk extensions", chunkExtensions.start, chunkExtensions.length);
index e99ca5e2472cb15d7683b2fb00f5349e81c48fb3..b32de8e9ad257caf6e53d69a53749c6d209ef8ca 100644 (file)
 
 class NHttpMsgChunkHead : public NHttpMsgSection {
 public:
-    NHttpMsgChunkHead() {};
-    void loadSection(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_);
-    void initSection();
+    NHttpMsgChunkHead(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_);
     void analyze();
-    void printSection(FILE *output) const;
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
     void legacyClients();
@@ -53,7 +51,7 @@ private:
     field chunkSize;
     field chunkExtensions;
 
-    int64_t dataLength;
+    int64_t dataLength = NHttpEnums::STAT_NOTCOMPUTE;
     int64_t bodySections;
     int64_t numChunks;
 };
index 997464a171f3ffc99fd13f359bb402d41d45cf00..a4acd6d1db63d301e96141f5012a471e7449456a 100644 (file)
@@ -42,7 +42,7 @@ void NHttpMsgHeader::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgHeader::printSection(FILE *output) const {
+void NHttpMsgHeader::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "header");
     NHttpMsgHeadShared::printHeaders(output);
     NHttpMsgSection::printMessageWrapup(output);
@@ -51,9 +51,6 @@ void NHttpMsgHeader::printSection(FILE *output) const {
 void NHttpMsgHeader::updateFlow() {
     const uint64_t disasterMask = 0;
 
-    ;
-    headerNorms[HEAD_CONTENT_LENGTH]->normalize(HEAD_CONTENT_LENGTH, scratchPad, infractions, headerNameId, headerValue, MAXHEADERS, headerValueNorm[HEAD_CONTENT_LENGTH]);
-
     // The following logic to determine body type is by no means the last word on this topic.
     if (tcpClose) {
         sessionData->typeExpected[sourceId] = SEC_CLOSED;
@@ -69,8 +66,8 @@ void NHttpMsgHeader::updateFlow() {
         sessionData->halfReset(sourceId);
     }
     // If there is a Transfer-Encoding header, see if the last of the encoded values is "chunked".
-    else if ( (headerNorms[HEAD_TRANSFER_ENCODING]->normalize(HEAD_TRANSFER_ENCODING, scratchPad, infractions,
-                  headerNameId, headerValue, MAXHEADERS, headerValueNorm[HEAD_TRANSFER_ENCODING]) > 0) &&
+    else if ( (headerNorms[HEAD_TRANSFER_ENCODING]->normalize(HEAD_TRANSFER_ENCODING, headerCount[HEAD_TRANSFER_ENCODING],
+                  scratchPad, infractions, headerNameId, headerValue, numHeaders, headerValueNorm[HEAD_TRANSFER_ENCODING]) > 0) &&
             ((*(int64_t *)(headerValueNorm[HEAD_TRANSFER_ENCODING].start + (headerValueNorm[HEAD_TRANSFER_ENCODING].length - 8))) == TRANSCODE_CHUNKED) ) {
         // Chunked body
         sessionData->typeExpected[sourceId] = SEC_CHUNKHEAD;
@@ -78,8 +75,8 @@ void NHttpMsgHeader::updateFlow() {
         sessionData->bodyOctets[sourceId] = 0;
         sessionData->numChunks[sourceId] = 0;
     }
-    else if ((headerNorms[HEAD_CONTENT_LENGTH]->normalize(HEAD_CONTENT_LENGTH, scratchPad, infractions,
-                 headerNameId, headerValue, MAXHEADERS, headerValueNorm[HEAD_CONTENT_LENGTH]) > 0) &&
+    else if ((headerNorms[HEAD_CONTENT_LENGTH]->normalize(HEAD_CONTENT_LENGTH, headerCount[HEAD_CONTENT_LENGTH],
+                 scratchPad, infractions, headerNameId, headerValue, numHeaders, headerValueNorm[HEAD_CONTENT_LENGTH]) > 0) &&
             (*(int64_t*)headerValueNorm[HEAD_CONTENT_LENGTH].start > 0)) {
         // Regular body
         sessionData->typeExpected[sourceId] = SEC_BODY;
index bb9898c3ed77936bfdeb9a362a0f8e06e2ab8650..5584c11f5a2cbff830dcd0a56b3968b11c0daaed 100644 (file)
@@ -37,8 +37,9 @@
 
 class NHttpMsgHeader: public NHttpMsgHeadShared {
 public:
-    NHttpMsgHeader() {};
-    void printSection(FILE *output) const;
+    NHttpMsgHeader(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgHeadShared(buffer, bufSize, sessionData_, sourceId_) {};
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
 };
index b22a1bdd3a39f27bf08348fe0aae6e9b2a3f993d..b5154dc18d2dfd0ce8bd38d23fbcf772e749e7f2 100644 (file)
 
 using namespace NHttpEnums;
 
-// Reinitialize everything derived in preparation for analyzing a new message
-void NHttpMsgHeadShared::initSection() {
-    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_NOSOURCE;
-    }
-}
-
 // All the header processing that is done for every message (i.e. not just-in-time) is done here.
 void NHttpMsgHeadShared::analyze() {
     parseWhole();
     parseHeaderBlock();
     parseHeaderLines();
-    for (int j=0; j < MAXHEADERS; j++) {
-        if (headerName[j].length <= 0) break;
+    for (int j=0; j < numHeaders; j++) {
         deriveHeaderNameId(j);
-        // Mark this header field as present and therefore eligible for normalization
-        if (headerNameId[j] > 0) headerValueNorm[headerNameId[j]].length = STAT_NOTCOMPUTE;
-    }
-}
-
-void NHttpMsgHeadShared::analyzeAll() {
-    for (int k=1; k <= numNorms; k++) {
-        headerNorms[k]->normalize((HeaderId)k, scratchPad, infractions, headerNameId, headerValue, MAXHEADERS, headerValueNorm[k]);
+        if (headerNameId[j] > 0) headerCount[headerNameId[j]]++;
     }
 }
 
@@ -176,7 +153,7 @@ void NHttpMsgHeadShared::legacyClients() {
     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);
  
-    for (int k=0; (headerNameId[k] != HEAD__NOTCOMPUTE) && (k < MAXHEADERS); k++) {
+    for (int k=0; k < numHeaders; 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;
@@ -184,26 +161,28 @@ void NHttpMsgHeadShared::legacyClients() {
     }
 
     if (sourceId == SRC_CLIENT) {
-       if (headerNorms[HEAD_COOKIE]->normalize(HEAD_COOKIE, scratchPad, infractions, headerNameId, headerValue, MAXHEADERS, headerValueNorm[HEAD_COOKIE]) > 0) {
+       if (headerNorms[HEAD_COOKIE]->normalize(HEAD_COOKIE, headerCount[HEAD_COOKIE], scratchPad, infractions,
+          headerNameId, headerValue, numHeaders, headerValueNorm[HEAD_COOKIE]) > 0) {
            SetHttpBuffer(HTTP_BUFFER_COOKIE, headerValueNorm[HEAD_COOKIE].start, (unsigned)headerValueNorm[HEAD_COOKIE].length);
        }
     }
     else {
-       if (headerNorms[HEAD_SET_COOKIE]->normalize(HEAD_SET_COOKIE, scratchPad, infractions, headerNameId, headerValue, MAXHEADERS, headerValueNorm[HEAD_SET_COOKIE]) > 0) {
+       if (headerNorms[HEAD_SET_COOKIE]->normalize(HEAD_SET_COOKIE, headerCount[HEAD_SET_COOKIE], scratchPad, infractions,
+          headerNameId, headerValue, numHeaders, headerValueNorm[HEAD_SET_COOKIE]) > 0) {
            SetHttpBuffer(HTTP_BUFFER_COOKIE, headerValueNorm[HEAD_SET_COOKIE].start, (unsigned)headerValueNorm[HEAD_SET_COOKIE].length);
        }
     }
 }
 
-void NHttpMsgHeadShared::printHeaders(FILE *output) const {
+void NHttpMsgHeadShared::printHeaders(FILE *output) {
     char titleBuf[100];
     if (numHeaders != STAT_NOSOURCE) fprintf(output, "Number of headers: %d\n", numHeaders);
-    for (int j=0; j < numHeaders && j < 200; j++) {
+    for (int j=0; j < numHeaders; j++) {
         snprintf(titleBuf, sizeof(titleBuf), "Header ID %d", headerNameId[j]);
         printInterval(output, titleBuf, headerValue[j].start, headerValue[j].length);
     }
     for (int k=1; k <= numNorms; k++) {
-        if (headerValueNorm[k].length != STAT_NOSOURCE) {
+        if (headerNorms[k]->normalize((HeaderId)k, headerCount[k], scratchPad, infractions, headerNameId, headerValue, numHeaders, headerValueNorm[k]) != STAT_NOSOURCE) {
             snprintf(titleBuf, sizeof(titleBuf), "Normalized header %d", k);
             printInterval(output, titleBuf, headerValueNorm[k].start, headerValueNorm[k].length, true);
         }
@@ -214,8 +193,3 @@ void NHttpMsgHeadShared::printHeaders(FILE *output) const {
 
 
 
-
-
-
-
-
index 155015e82e91ef41a2e20ee4de7ecff16bf87936..4271e7a33dd559b4b11007b4398f9840a1813bad 100644 (file)
 
 class NHttpMsgHeadShared: public NHttpMsgSection {
 public:
-    void initSection();
     void analyze();
-    void analyzeAll();
     void genEvents();
     void legacyClients();
 
 protected:
-    // Header normalization. There should be one of these for every different way we can process a header field value.
+    NHttpMsgHeadShared(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgSection(buffer, bufSize, sessionData_, sourceId_) {};
+
+    // Header normalization strategies. 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;
@@ -58,29 +59,29 @@ protected:
     static const HeaderNormalizer* const headerNorms[];
     static const int32_t numNorms;
 
-    // Code conversion tables are for turning token strings into enums.
+    // Tables of header field names and header value names
     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 parseHeaderBlock();
     void parseHeaderLines();
     void deriveHeaderNameId(int index);
 
-    void printHeaders(FILE *output) const;
+    void printHeaders(FILE *output);
 
-    // 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 message buffer (raw pieces) or the
-    // scratchPad (normalized pieces).
     field headers;
+
+    // All of these are indexed by the relative position of the header field in the message
     static const int MAXHEADERS = 200;  // I'm an arbitrary number. Need to revisit.
-    int32_t numHeaders;
+    int32_t numHeaders = NHttpEnums::STAT_NOTCOMPUTE;
     field headerLine[MAXHEADERS];
     field headerName[MAXHEADERS];
     NHttpEnums::HeaderId headerNameId[MAXHEADERS];
     field headerValue[MAXHEADERS];
+
+    // Normalized values are indexed by HeaderId
+    int headerCount[NHttpEnums::HEAD__MAXVALUE] = { };
     field headerValueNorm[NHttpEnums::HEAD__MAXVALUE];
 };
 
index df05d1093b046aed8298421adf005d5a1c653bfd..d7b630cf178cd7c415c51751b3e5b6356e331d2a 100644 (file)
 
 using namespace NHttpEnums;
 
-// Reinitialize everything derived in preparation for analyzing a new message
-void NHttpMsgRequest::initSection() {
-    NHttpMsgStart::initSection();
-    method.length = STAT_NOTCOMPUTE;
-    delete uri;
-    uri = nullptr;
-}
-
 void NHttpMsgRequest::parseStartLine() {
     // There should be exactly two spaces. One following the method and one before "HTTP/".
     // Additional spaces located within the URI are not allowed but we will tolerate it
@@ -88,7 +80,7 @@ void NHttpMsgRequest::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgRequest::printSection(FILE *output) const {
+void NHttpMsgRequest::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "request line");
     fprintf(output, "Version Id: %d\n", versionId);
     fprintf(output, "Method Id: %d\n", methodId);
index db39686220592a4a0cf8689b09bbf1455fe08449..6fda62a8764e94721ba0353058f494786a738509 100644 (file)
 
 class NHttpMsgRequest: public NHttpMsgStart {
 public:
-    NHttpMsgRequest() {};
+    NHttpMsgRequest(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) {};
     ~NHttpMsgRequest() { delete uri; };
-    void initSection();
-    void printSection(FILE *output) const;
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
     void legacyClients();
 
 private:
-    // Code conversion tables are for turning token strings into enums.
     static const StrCode methodList[];
 
-    // "Parse" methods cut things into pieces. "Extract" methods find the named item. "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 parseStartLine();
     void deriveMethodId();
 
-    // This is where all the derived values, extracted message parts, and normalized values are.
-    // Note that these are all scalars, buffer pointers, and buffer sizes. The actual buffers are in the message buffer (raw pieces) or the
-    // scratchPad (normalized pieces).
     field method;
     NHttpUri* uri = nullptr;
 };
index 7071aa6906e095da4eb8549b26e37a877ab3e2d7..c9019a4a6b149288b68cce507a5d4ef8fa283ebe 100644 (file)
 
 using namespace NHttpEnums;
 
+NHttpMsgSection::NHttpMsgSection(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
+   length(bufSize), sessionData(sessionData_), sourceId(sourceId_), tcpClose(sessionData->tcpClose[sourceId]),
+   scratchPad(2*length+500), infractions(sessionData->infractions[sourceId]), versionId(sessionData->versionId[sourceId]),
+   methodId(sessionData->methodId[sourceId]), statusCodeNum(sessionData->statusCodeNum[sourceId])
+{
+    rawBuf = new uint8_t[length];
+    memcpy(rawBuf, buffer, length);
+    msgText = rawBuf;
+}
+
 // 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 <SP> or <LF>. These whitespace characters
@@ -49,22 +59,6 @@ uint32_t NHttpMsgSection::findCrlf(const uint8_t* buffer, int32_t length, bool w
     return length;
 }
 
-// Load a new message section
-void NHttpMsgSection::loadSection(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_) {
-    length = bufsize;
-    memcpy(rawBuf, buffer, length);
-
-    sessionData = sessionData_;
-    infractions = sessionData->infractions;
-    sourceId = sessionData->sourceId;
-    tcpClose = sessionData->tcpClose;
-    versionId = sessionData->versionId[sourceId];
-    methodId = sessionData->methodId[sourceId];
-    statusCodeNum = sessionData->statusCodeNum[sourceId];
-
-    scratchPad.reinit();
-}
-
 void NHttpMsgSection::printInterval(FILE *output, const char* name, const uint8_t *text, int32_t length, bool intVals) {
     if ((length == STAT_NOTPRESENT) || (length == STAT_NOTCOMPUTE) || (length == STAT_NOSOURCE)) return;
     int outCount = fprintf(output, "%s, length = %d, ", name, length);
index 19c37825511ad95fbea3719f588bcb6dcd490472..2a3f47187b6df219d16307d1af63cfb6c955aa86 100644 (file)
 
 class NHttpMsgSection {
 public:
-    virtual void loadSection(const uint8_t *buffer, const uint16_t bufsize, NHttpFlowData *sessionData_);
-    virtual ~NHttpMsgSection() = default;
-    virtual void initSection() = 0;
+    virtual ~NHttpMsgSection() {delete[] rawBuf;};
     virtual void analyze() = 0;                           // Minimum necessary processing for every message
-    virtual void analyzeAll() {};                         // Force all just-in-time processing (testing method)
-    virtual void printSection(FILE *output) const = 0;
-    virtual void genEvents() = 0;
-    virtual void updateFlow() = 0;
-    virtual void legacyClients() = 0;
+    virtual void printSection(FILE *output) = 0;          // Test tool prints all derived message parts
+    virtual void genEvents() = 0;                         // Converts collected information into required preprocessor events
+    virtual void updateFlow() = 0;                        // Manages the splitter and communication between message sections
+    virtual void legacyClients() = 0;                     // Populates the raw and normalized buffer interface used by old Snort
 
 protected:
+    NHttpMsgSection(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_);
+
     // Convenience methods
     static uint32_t findCrlf(const uint8_t* buffer, int32_t length, bool wrappable);
     static void printInterval(FILE *output, const char* name, const uint8_t *text, int32_t length, bool intVals = false);
@@ -57,22 +56,20 @@ protected:
     void printMessageWrapup(FILE *output) const;
 
     // The current strategy is to copy the entire raw message section into this object. Here it is.
-    int32_t length;               // Length of the original message section in octets
-    uint8_t rawBuf[NHttpEnums::MAXOCTETS];    // The original HTTP message section 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;
+    int32_t length;
+    uint8_t* rawBuf;
+    // This pseudonym for rawBuf isolates details of how the raw message is stored from everything else.
+    const uint8_t* msgText;
 
     NHttpFlowData* sessionData;
-    ScratchPad scratchPad {NHttpEnums::MAXOCTETS*2};
+    NHttpEnums::SourceId sourceId;
+    bool tcpClose;
+    ScratchPad scratchPad;
 
     // This is where all the derived values, extracted message parts, and normalized values are.
-    // Note that these are all scalars, buffer pointers, and buffer sizes. The actual buffers are in message buffer (raw pieces) or the
+    // These are all scalars, buffer pointers, and buffer sizes. The actual buffers are in message buffer (raw pieces) or the
     // scratchPad (normalized pieces).
     uint64_t infractions;
-    bool tcpClose;
-    NHttpEnums::SourceId sourceId;
     NHttpEnums::VersionId versionId;
     NHttpEnums::MethodId methodId;
     int32_t statusCodeNum;
index cdcdf445a804ba92aaf205982f4f8174f76f4cac..bb16694bd7d78220ff5554300ae1e8ab3238b9e5 100644 (file)
@@ -23,7 +23,7 @@
 //
 //  @author     Tom Peters <thopeter@cisco.com>
 //
-//  @brief      NHttpMsgStart virtual class rolls up all the common elements of start line processing.
+//  @brief      NHttpMsgStart virtual class rolls up all the common elements of request and status line processing.
 //
 
 
 
 using namespace NHttpEnums;
 
-// Reinitialize everything derived in preparation for analyzing a new message
-void NHttpMsgStart::initSection() {
-    startLine.length = STAT_NOTCOMPUTE;
-    version.length = STAT_NOTCOMPUTE;
-}
-
-// Required message processing that is automatically done instead of being just-in-time
 void NHttpMsgStart::analyze() {
     startLine.start = msgText;
     startLine.length = findCrlf(startLine.start, length, false);
index 726602299d66474ac2c6218c1c8f5581c3eee7ec..b46eb4f2bd59ce29099da2c9bff442e9c036870a 100644 (file)
 
 class NHttpMsgStart: public NHttpMsgSection {
 public:
-    NHttpMsgStart() {};
-    void initSection();
     void analyze();
     void genEvents();
 
 protected:
-    // "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.
+    NHttpMsgStart(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgSection(buffer, bufSize, sessionData_, sourceId_) {};
     virtual void parseStartLine() = 0;
     void deriveVersionId();
 
-    // 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 message buffer (raw pieces) or the
-    // scratchPad (normalized pieces).
     field startLine;
     field version;
 };
index 48f3368e08dc360f1c96eb6e7a605785457ad9d6..ba390aae66e37716bfca79c3096b77658088f3db 100644 (file)
 
 using namespace NHttpEnums;
 
-// Reinitialize everything derived in preparation for analyzing a new message
-void NHttpMsgStatus::initSection() {
-    NHttpMsgStart::initSection();
-    statusCode.length = STAT_NOTCOMPUTE;
-    reasonPhrase.length = STAT_NOTCOMPUTE;
-}
-
 // All the header processing that is done for every message (i.e. not just-in-time) is done here.
 void NHttpMsgStatus::analyze() {
     NHttpMsgStart::analyze();
@@ -100,7 +93,7 @@ void NHttpMsgStatus::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgStatus::printSection(FILE *output) const {
+void NHttpMsgStatus::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "status line");
     fprintf(output, "Version Id: %d\n", versionId);
     fprintf(output, "Status Code Num: %d\n", statusCodeNum);
index 597332d725703aab9cf00f448576e14de59a3d5f..baf02883ee676c22bbee37cb9d0cde5131f171e6 100644 (file)
 
 class NHttpMsgStatus: public NHttpMsgStart {
 public:
-    NHttpMsgStatus() {};
-    void initSection();
+    NHttpMsgStatus(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) {};
     void analyze();
-    void printSection(FILE *output) const;
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
     void legacyClients();
 
 private:
-    // "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 parseStartLine();
     void deriveStatusCodeNum();
 
-    // 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 message buffer (raw pieces) or the
-    // scratchPad (normalized pieces).
     field statusCode;
     field reasonPhrase;
 };
index 049451a64937b6348eb4b81bfa238f6e3121d93b..409b5872a5fd538b6f781ed2ee28b6aa1d81c3d2 100644 (file)
@@ -41,7 +41,7 @@ void NHttpMsgTrailer::genEvents() {
     if (infractions != 0) SnortEventqAdd(NHTTP_GID, EVENT_ASCII); // I'm just an example event
 }
 
-void NHttpMsgTrailer::printSection(FILE *output) const {
+void NHttpMsgTrailer::printSection(FILE *output) {
     NHttpMsgSection::printMessageTitle(output, "trailer");
     NHttpMsgHeadShared::printHeaders(output);
     NHttpMsgSection::printMessageWrapup(output);
index 6c5101dd3433c30edef2644fb8bddf9de136e560..f74db659619b004a3b5af64c80f4fe498e3439fa 100644 (file)
@@ -37,8 +37,9 @@
 
 class NHttpMsgTrailer: public NHttpMsgHeadShared {
 public:
-    NHttpMsgTrailer() {};
-    void printSection(FILE *output) const;
+    NHttpMsgTrailer(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, NHttpEnums::SourceId sourceId_) :
+       NHttpMsgHeadShared(buffer, bufSize, sessionData_, sourceId_) {};
+    void printSection(FILE *output);
     void genEvents();
     void updateFlow();
 };
index 4ad6cb074c4793dccc9d3fa5911accdc512ed045..3501eebc3be999306397b52fbdc20273dff038bc 100644 (file)
@@ -46,7 +46,7 @@ class ScratchPad {
 public:
     ScratchPad(uint32_t _capacity) : capacity(_capacity), buffer(new uint64_t[_capacity/8+1]) {};
     ~ScratchPad() { delete[] buffer; };
-    void reinit() {used = 0;};
+    /* &&& not needed anymore I think */ 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 + (8-(taken%8))%8; };  // round up to multiple of 8 to preserve alignment
 
index cb61fd70f01c8f19016344ccc08ea2ca1ee3be7c..6bea3f9d2072d62ea72b2e83b838ca44aaf2e83e 100644 (file)
@@ -39,10 +39,9 @@ using namespace NHttpEnums;
 // Convenience function. All the housekeeping that must be done before we can return PAF_FLUSH to stream.
 void NHttpStreamSplitter::prepareFlush(NHttpFlowData* sessionData, uint32_t* flushOffset, SourceId sourceId, SectionType sectionType, bool tcpClose,
       uint64_t infractions, uint32_t numOctets) {
-    sessionData->sourceId = sourceId;
-    sessionData->sectionType = sectionType;
-    sessionData->tcpClose = tcpClose;
-    sessionData->infractions = infractions;
+    sessionData->sectionType[sourceId] = sectionType;
+    sessionData->tcpClose[sourceId] = tcpClose;
+    sessionData->infractions[sourceId] = infractions;
     if (tcpClose) sessionData->typeExpected[sourceId] = SEC_CLOSED;
     if (!NHttpTestInput::test_input) *flushOffset = numOctets;
     else NHttpTestInput::testInput->pafFlush(numOctets);
index fdad4c2d58f8001044f1725822a8766847600278..81917f9ecbcd9141ecdc6a5582102c4e9d16ad56 100644 (file)
@@ -167,12 +167,11 @@ const StrCode NHttpMsgHeadShared::transCodeList[] =
     { TRANSCODE_DEFLATE,         "deflate"},
     { 0,                         nullptr} };
 
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_NIL {NORM_NULL, false, false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_BASIC {NORM_FIELD, false, false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_CAT {NORM_FIELD, true, false, normRemoveLws, nullptr, nullptr, nullptr, nullptr, nullptr};
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_NOREPEAT {NORM_FIELD, false, true, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_DECIMAL {NORM_INT64, false, true, normDecimalInteger, nullptr, nullptr, nullptr, nullptr, nullptr};
-const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_TRANSCODE {NORM_ENUM64, true, false, normRemoveLws, nullptr, norm2Lower, nullptr, normSeqStrCode, NHttpMsgHeadShared::transCodeList};
+const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_NIL {NORM_NULL, false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
+const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_BASIC {NORM_FIELD, false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
+const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_CAT {NORM_FIELD, true, normRemoveLws, nullptr, nullptr, nullptr, nullptr, nullptr};
+const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_DECIMAL {NORM_INT64, false, normDecimalInteger, nullptr, nullptr, nullptr, nullptr, nullptr};
+const HeaderNormalizer NHttpMsgHeadShared::NORMALIZER_TRANSCODE {NORM_ENUM64, true, normRemoveLws, nullptr, norm2Lower, nullptr, normSeqStrCode, NHttpMsgHeadShared::transCodeList};
 
 const HeaderNormalizer* const NHttpMsgHeadShared::headerNorms[HEAD__MAXVALUE] = { [0] = &NORMALIZER_NIL,
     [HEAD__OTHER] = &NORMALIZER_BASIC,
index d2f246c9d653192572e1e0434d3994ac3c402f5f..70cbff4d3d0adb1c0024acb850916262b6f5649e 100644 (file)
@@ -253,9 +253,10 @@ void NHttpTestInput::pafFlush(uint32_t length) {
 }
 
 
-uint16_t NHttpTestInput::toEval(uint8_t **buffer, int64_t &testNumber_) {
+uint16_t NHttpTestInput::toEval(uint8_t **buffer, int64_t &testNumber_, SourceId &sourceId) {
     if (!flushed) return 0;
     testNumber_ = testNumber;
+    sourceId = lastSourceId;
     *buffer = msgBuf;
     if (fillOctets > 0) {
         uint32_t fillOut = (fillOctets <= 16384) ? fillOctets : 16384;
index 03e27a56998f2b48a84148ef062b221c6b882094..8344585598f5ae2717af906c2c3a12578225fae3 100644 (file)
@@ -35,7 +35,7 @@ public:
     ~NHttpTestInput();
     void toPaf(uint8_t*& data, uint32_t &length, NHttpEnums::SourceId &sourceId, bool &tcpClose, bool &needBreak);
     void pafFlush(uint32_t length);
-    uint16_t toEval(uint8_t **buffer, int64_t &testNumber);
+    uint16_t toEval(uint8_t **buffer, int64_t &testNumber, NHttpEnums::SourceId &sourceId);
 
     // Hard for NHttpInspect and PAF to share these without making them "global". This is as good a place as any for them to live.
     static bool test_input;
index 181ccd2f65e373c81a0bb33b4e93b58a1fc370e4..66911038600e639288c6493d32f112e776700ea9 100644 (file)
@@ -39,9 +39,7 @@
 
 class NHttpUri {
 public:
-    NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method) : methodId(method) {
-       uri.length = length; uri.start = start; };
-
+    NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method) : uri(length, start), methodId(method) {};
     field getUri() const { return uri; };
     NHttpEnums::UriType getUriType() { parseUri(); return uriType; };
     field getScheme() { parseUri(); return scheme; };