nhttp_msg_status.h
nhttp_msg_head_shared.cc
nhttp_msg_head_shared.h
- nhttp_msg_head.cc
- nhttp_msg_head.h
+ nhttp_msg_header.cc
+ nhttp_msg_header.h
nhttp_msg_body.cc
nhttp_msg_body.h
nhttp_msg_chunk_head.cc
nhttp_msg_request.cc nhttp_msg_request.h \
nhttp_msg_status.cc nhttp_msg_status.h \
nhttp_msg_head_shared.cc nhttp_msg_head_shared.h \
-nhttp_msg_head.cc nhttp_msg_head.h \
+nhttp_msg_header.cc nhttp_msg_header.h \
nhttp_msg_body.cc nhttp_msg_body.h \
nhttp_msg_chunk_head.cc nhttp_msg_chunk_head.h \
nhttp_msg_chunk_body.cc nhttp_msg_chunk_body.h \
using namespace NHttpEnums;
+const Field Field::FIELD_NULL { STAT_NOSOURCE };
+
void Field::print(FILE *output, const char* name, bool intVals) const {
if ((length == STAT_NOTPRESENT) || (length == STAT_NOTCOMPUTE) || (length == STAT_NOSOURCE)) return;
int outCount = fprintf(output, "%s, length = %d, ", name, length);
#include <stdint.h>
#include <stdio.h>
+#include <assert.h>
// Individual pieces of the message found during parsing
// Length values <= 0 are StatusCode values and imply that the start pointer is meaningless.
int32_t length = NHttpEnums::STAT_NOTCOMPUTE;
const uint8_t* start = nullptr;
+ static const Field FIELD_NULL;
+
Field(int32_t length_, const uint8_t* start_) : length(length_), start(start_) {};
+ explicit Field(int32_t length_) : length(length_) { assert(length<=0); };
Field() = default;
void print(FILE *output, const char* name, bool intVals = false) const;
};
#include "nhttp_msg_section.h"
#include "nhttp_msg_request.h"
#include "nhttp_msg_status.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_header.h"
using namespace NHttpEnums;
NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) {}
NHttpFlowData::~NHttpFlowData() {
+ delete requestLine;
+ delete statusLine;
for(int k=0; k <= 1; k++) {
- delete startLine[k];
delete headers[k];
delete latestOther[k];
}
#include "stream/stream_api.h"
-class NHttpInspect;
-class NHttpMsgSection;
-class NHttpMsgStart;
-class NHttpMsgRequest;
-class NHttpMsgStatus;
-class NHttpMsgHeader;
-class NHttpMsgBody;
-class NHttpMsgChunkHead;
-class NHttpMsgChunkBody;
-class NHttpMsgTrailer;
-class NHttpTestInput;
-
class NHttpFlowData : public FlowData
{
public:
// Stored message sections from this session
// You must reset to nullptr after deleting a section
// Never put one section in two places. latestOther is only for things not otherwise listed
- NHttpMsgStart* startLine[2] = { nullptr, nullptr };
- NHttpMsgHeader* headers[2] = { nullptr, nullptr };
- NHttpMsgSection* latestOther[2] = { nullptr, nullptr };
+ class NHttpMsgRequest* requestLine = nullptr;
+ class NHttpMsgStatus* statusLine = nullptr;
+ class NHttpMsgHeader* headers[2] = { nullptr, nullptr };
+ class NHttpMsgSection* latestOther[2] = { nullptr, nullptr };
};
#endif
LogMessage("NHttpInspect\n");
}
-void NHttpInspect::eval(Packet* p)
+void NHttpInspect::eval(Packet*)
{
- // Only packets from the StreamSplitter can be processed
- if (!PacketHasPAFPayload(p)) return;
-
- process(p->data, p->dsize, p->flow, (p->packet_flags & PKT_FROM_CLIENT) ? SRC_CLIENT : SRC_SERVER);
+ printf("eval()\n"); fflush(nullptr); /* &&& */
+ return;
}
void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow, SourceId sourceId)
#include "framework/inspector.h"
#include "nhttp_msg_request.h"
#include "nhttp_msg_status.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_header.h"
#include "nhttp_msg_body.h"
#include "nhttp_msg_chunk_head.h"
#include "nhttp_msg_chunk_body.h"
bool enabled();
void pinit();
void pterm();
- NHttpStreamSplitter* get_splitter(bool isClientToServer) { return new NHttpStreamSplitter(isClientToServer); };
+ NHttpStreamSplitter* get_splitter(bool isClientToServer) { return new NHttpStreamSplitter(isClientToServer, this); };
private:
friend NHttpApi;
using namespace NHttpEnums;
NHttpMsgChunkBody::NHttpMsgChunkBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
- NHttpMsgBody(buffer, bufSize, sessionData_, sourceId_), numChunks(sessionData->numChunks[sourceId]),
+ NHttpMsgBody(buffer, bufSize, sessionData_, sourceId_), /* numChunks(sessionData->numChunks[sourceId]), &&& */
chunkSections(sessionData->chunkSections[sourceId]), chunkOctets(sessionData->chunkOctets[sourceId]) {}
void NHttpMsgChunkBody::analyze() {
void updateFlow();
private:
- int64_t numChunks;
+ // int64_t numChunks; // will be needed in future commented out to please compiler &&&
int64_t chunkSections;
int64_t chunkOctets;
};
#include "snort.h"
#include "nhttp_enum.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_header.h"
using namespace NHttpEnums;
// @brief NHttpMsgHeader class declaration
//
-#ifndef NHTTP_MSG_HEAD_H
-#define NHTTP_MSG_HEAD_H
+#ifndef NHTTP_MSG_HEADER_H
+#define NHTTP_MSG_HEADER_H
#include "nhttp_msg_head_shared.h"
#include "nhttp_enum.h"
#include "nhttp_normalizers.h"
#include "nhttp_msg_request.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_header.h"
using namespace NHttpEnums;
NHttpMsgRequest::NHttpMsgRequest(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) {
- delete sessionData->startLine[SRC_CLIENT];
- sessionData->startLine[SRC_CLIENT] = this;
+ delete sessionData->requestLine;
+ sessionData->requestLine = this;
delete sessionData->headers[SRC_CLIENT];
sessionData->headers[SRC_CLIENT] = nullptr;
delete sessionData->latestOther[SRC_CLIENT];
methodId = (MethodId) strToCode(method.start, method.length, methodList);
}
+const Field& NHttpMsgRequest::getUri() {
+ if (uri != nullptr) {
+ return uri->getUri();
+ }
+ return Field::FIELD_NULL;
+}
+
+const Field& NHttpMsgRequest::getUriNormLegacy() {
+ if (uri != nullptr) {
+ return uri->getNormLegacy();
+ }
+ return Field::FIELD_NULL;
+}
+
void NHttpMsgRequest::genEvents() {
if (methodId == METH__OTHER) createEvent(EVENT_UNKNOWN_METHOD);
void genEvents();
void updateFlow();
void legacyClients();
+ const Field& getMethod() { return method; };
+ const Field& getUri();
+ const Field& getUriNormLegacy();
private:
static const StrCode methodList[];
#include "snort.h"
#include "nhttp_enum.h"
#include "nhttp_msg_status.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_request.h"
+#include "nhttp_msg_header.h"
using namespace NHttpEnums;
NHttpMsgStatus::NHttpMsgStatus(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) :
- NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) {
- delete sessionData->startLine[SRC_SERVER];
- sessionData->startLine[SRC_SERVER] = this;
+ NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_), request(sessionData->requestLine) {
+ delete sessionData->statusLine;
+ sessionData->statusLine = this;
delete sessionData->headers[SRC_SERVER];
sessionData->headers[SRC_SERVER] = nullptr;
delete sessionData->latestOther[SRC_SERVER];
// Legacy support function. Puts message fields into the buffers used by old Snort.
void NHttpMsgStatus::legacyClients() {
ClearHttpBuffers();
- 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);
+ if ((request != nullptr) && (request->getMethod().length > 0)) {
+ SetHttpBuffer(HTTP_BUFFER_METHOD, request->getMethod().start, (unsigned)request->getMethod().length);
+ }
+ if ((request != nullptr) && (request->getUri().length > 0)) {
+ SetHttpBuffer(HTTP_BUFFER_RAW_URI, request->getUri().start, (unsigned)request->getUri().length);
+ }
+ if ((request != nullptr) && (request->getUriNormLegacy().length > 0)) {
+ SetHttpBuffer(HTTP_BUFFER_URI, request->getUriNormLegacy().start, (unsigned)request->getUriNormLegacy().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);
+ }
}
Field statusCode;
Field reasonPhrase;
+ NHttpMsgRequest* request;
};
#endif
#include <string.h>
#include <sys/types.h>
#include "snort.h"
+#include "protocols/packet.h"
#include "nhttp_enum.h"
#include "nhttp_test_input.h"
#include "nhttp_stream_splitter.h"
eventsGenerated |= 1 << (sid-1);
}
+const StreamBuffer* NHttpStreamSplitter::reassemble(unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) {
+ static THREAD_LOCAL StreamBuffer nhttp_buf;
+ if (flags & PKT_PDU_HEAD) {
+ sectionBuffer = new uint8_t[65536];
+ }
+ memcpy(sectionBuffer+offset, data, len);
+ copied = len;
+ if (flags & PKT_PDU_TAIL) {
+ process(sectionBuffer, offset + len, p->flow, to_server() ? SRC_CLIENT : SRC_SERVER);
+ nhttp_buf.data = sectionBuffer;
+ nhttp_buf.length = offset + len;
+ return &nhttp_buf;
+ }
+ return nullptr;
+}
+
PAF_Status NHttpStreamSplitter::scan (Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flushOffset) {
// When the system begins providing TCP connection close information this won't always be false. &&&
bool tcpClose = false;
#include "stream/stream_splitter.h"
#include "nhttp_flow_data.h"
+class NHttpInspect;
+
class NHttpStreamSplitter : public StreamSplitter {
public:
- NHttpStreamSplitter(bool isClientToServer) : StreamSplitter(isClientToServer) {};
+ NHttpStreamSplitter(bool isClientToServer, NHttpInspect* myInspector_) : StreamSplitter(isClientToServer), myInspector(myInspector_) {};
PAF_Status scan(Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flushOffset);
bool is_paf() { return true; };
uint32_t max() { return pafMax; };
+ const StreamBuffer* reassemble(unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied);
private:
void prepareFlush(NHttpFlowData* sessionData, uint32_t* flushOffset, NHttpEnums::SourceId sourceId, NHttpEnums::SectionType sectionType, bool tcpClose,
uint64_t infractions, uint32_t numOctets);
void createEvent(NHttpEnums::EventSid sid);
+ NHttpInspect* const myInspector;
+
+ uint8_t *sectionBuffer = nullptr;
uint64_t eventsGenerated = 0;
int64_t octetsSeen = 0;
int numCrlf = 0;
#include "nhttp_normalizers.h"
#include "nhttp_head_norm.h"
#include "nhttp_msg_request.h"
-#include "nhttp_msg_head.h"
+#include "nhttp_msg_header.h"
#include "nhttp_module.h"
#include "nhttp_uri_norm.h"
return schemeId;
}
-Field NHttpUri::getNormHost() {
+const Field& NHttpUri::getNormHost() {
if (hostNorm.length != STAT_NOTCOMPUTE) return hostNorm;
if (getHost().length < 0) {
hostNorm.length = STAT_NOSOURCE;
return hostNorm;
}
-Field NHttpUri::getNormPath() {
+const Field& NHttpUri::getNormPath() {
if (pathNorm.length != STAT_NOTCOMPUTE) return pathNorm;
if (getPath().length < 0) {
pathNorm.length = STAT_NOSOURCE;
return pathNorm;
}
-Field NHttpUri::getNormQuery() {
+const Field& NHttpUri::getNormQuery() {
if (queryNorm.length != STAT_NOTCOMPUTE) return queryNorm;
if (getQuery().length < 0) {
queryNorm.length = STAT_NOSOURCE;
return queryNorm;
}
-Field NHttpUri::getNormFragment() {
+const Field& NHttpUri::getNormFragment() {
if (fragmentNorm.length != STAT_NOTCOMPUTE) return fragmentNorm;
if (getFragment().length < 0) {
fragmentNorm.length = STAT_NOSOURCE;
}
// Glue normalized URI fields back together
-Field NHttpUri::getNormLegacy() {
+const Field& NHttpUri::getNormLegacy() {
if (legacyNorm.length != STAT_NOTCOMPUTE) return legacyNorm;
if (getPath().length >= 0) UriNormalizer::normalize(path, pathNorm, true, scratchPad, pathInfractions);
public:
NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method) : uri(length, start), methodId(method),
scratchPad(2*length+200) {};
- Field getUri() const { return uri; };
+ const Field& getUri() const { return uri; };
NHttpEnums::UriType getUriType() { parseUri(); return uriType; };
- Field getScheme() { parseUri(); return scheme; };
- Field getAuthority() { parseUri(); return authority; };
- Field getHost() { parseAuthority(); return host; };
- Field getPort() { parseAuthority(); return port; };
- Field getAbsPath() { parseUri(); return absPath; };
- Field getPath() { parseAbsPath(); return path; };
- Field getQuery() { parseAbsPath(); return query; };
- Field getFragment() { parseAbsPath(); return fragment; };
+ const Field& getScheme() { parseUri(); return scheme; };
+ const Field& getAuthority() { parseUri(); return authority; };
+ const Field& getHost() { parseAuthority(); return host; };
+ const Field& getPort() { parseAuthority(); return port; };
+ const Field& getAbsPath() { parseUri(); return absPath; };
+ const Field& getPath() { parseAbsPath(); return path; };
+ const Field& getQuery() { parseAbsPath(); return query; };
+ const Field& getFragment() { parseAbsPath(); return fragment; };
uint64_t getFormatInfractions() { parseUri(); return formatInfractions; };
uint64_t getSchemeInfractions() { getSchemeId(); return schemeInfractions; };
getPortInfractions() | getPathInfractions() | getQueryInfractions() | getFragmentInfractions(); };
NHttpEnums::SchemeId getSchemeId();
- Field getNormHost();
+ const Field& getNormHost();
int32_t getPortValue();
- Field getNormPath();
- Field getNormQuery();
- Field getNormFragment();
- Field getNormLegacy();
+ const Field& getNormPath();
+ const Field& getNormQuery();
+ const Field& getNormFragment();
+ const Field& getNormLegacy();
private:
static const StrCode schemeList[];