Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

detect/file-data: Improved support for shared buffers #5549

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 89 additions & 16 deletions src/detect-file-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ static void DetectFiledataSetupCallback(const DetectEngineCtx *de_ctx,
Signature *s);
static int g_file_data_buffer_id = 0;

static inline HtpBody *GetResponseBody(htp_tx_t *tx);

/* HTTP */
static InspectionBuffer *HttpServerBodyGetDataCallback(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms,
Expand All @@ -75,6 +77,10 @@ int PrefilterMpmFiledataRegister(DetectEngineCtx *de_ctx,
SigGroupHead *sgh, MpmCtx *mpm_ctx,
const DetectBufferMpmRegistery *mpm_reg, int list_id);

static int DetectEngineInspectBufferHttpBody(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);

/**
* \brief Registration function for keyword: file_data
*/
Expand Down Expand Up @@ -110,9 +116,8 @@ void DetectFiledataRegister(void)
PrefilterMpmFiledataRegister, NULL,
ALPROTO_HTTP2, HTTP2StateDataServer);

DetectAppLayerInspectEngineRegister2("file_data",
ALPROTO_HTTP, SIG_FLAG_TOCLIENT, HTP_RESPONSE_BODY,
DetectEngineInspectBufferGeneric, HttpServerBodyGetDataCallback);
DetectAppLayerInspectEngineRegister2("file_data", ALPROTO_HTTP, SIG_FLAG_TOCLIENT,
HTP_RESPONSE_BODY, DetectEngineInspectBufferHttpBody, HttpServerBodyGetDataCallback);
DetectAppLayerInspectEngineRegister2("file_data",
ALPROTO_SMTP, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectFiledata, NULL);
Expand Down Expand Up @@ -162,6 +167,73 @@ static void SetupDetectEngineConfig(DetectEngineCtx *de_ctx) {
de_ctx->filedata_config_initialized = true;
}

static int DetectEngineInspectBufferHttpBody(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine,
const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
{
const int list_id = engine->sm_list;
const InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
bool eof = false;
if (buffer->inspect == NULL) {
SCLogDebug("running inspect on %d", list_id);

eof = (AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags) > engine->progress);

SCLogDebug("list %d mpm? %s transforms %p", engine->sm_list, engine->mpm ? "true" : "false",
engine->v2.transforms);

/* if prefilter didn't already run, we need to consider transformations */
const DetectEngineTransforms *transforms = NULL;
if (!engine->mpm) {
transforms = engine->v2.transforms;
}

buffer = engine->v2.GetData(det_ctx, transforms, f, flags, txv, list_id);
if (unlikely(buffer == NULL)) {
return eof ? DETECT_ENGINE_INSPECT_SIG_CANT_MATCH : DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
}

const uint32_t data_len = buffer->inspect_len;
const uint8_t *data = buffer->inspect;
const uint64_t offset = buffer->inspect_offset;

uint8_t ci_flags = eof ? DETECT_CI_FLAGS_END : 0;
ci_flags |= (offset == 0 ? DETECT_CI_FLAGS_START : 0);
ci_flags |= buffer->flags;

det_ctx->discontinue_matching = 0;
det_ctx->buffer_offset = 0;
det_ctx->inspection_recursion_counter = 0;

/* Inspect all the uricontents fetched on each
* transaction at the app layer */
int r = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, (uint8_t *)data,
data_len, offset, ci_flags, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);

/* move inspected tracker to end of the data. HtpBodyPrune will consider
* the window sizes when freeing data */
htp_tx_t *tx = txv;
HtpBody *body = GetResponseBody(tx);
body->body_inspected = body->content_len_so_far;
SCLogDebug("body->body_inspected now: %"PRIu64, body->body_inspected);

if (r == 1) {
return DETECT_ENGINE_INSPECT_SIG_MATCH;
}

if (flags & STREAM_TOSERVER) {
if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) >
HTP_REQUEST_BODY)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
} else {
if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) >
HTP_RESPONSE_BODY)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}

/**
* \brief this function is used to parse filedata options
* \brief into the current signature
Expand Down Expand Up @@ -336,11 +408,6 @@ static InspectionBuffer *HttpServerBodyGetDataCallback(DetectEngineThreadCtx *de

InspectionBufferApplyTransforms(buffer, transforms);

/* move inspected tracker to end of the data. HtpBodyPrune will consider
* the window sizes when freeing data */
body->body_inspected = body->content_len_so_far;
SCLogDebug("body->body_inspected now: %"PRIu64, body->body_inspected);

SCReturnPtr(buffer, "InspectionBuffer");
}

Expand All @@ -367,10 +434,11 @@ static InspectionBuffer *FiledataGetDataCallback(DetectEngineThreadCtx *det_ctx,
// TODO this is unused, is that right?
//const uint32_t content_inspect_window = de_ctx->filedata_config[f->alproto].content_inspect_window;

SCLogDebug("content_limit %u, content_inspect_min_size %u",
content_limit, content_inspect_min_size);
SCLogDebug("[list %d] first: %d, content_limit %u, content_inspect_min_size %u", list_id,
first ? 1 : 0, content_limit, content_inspect_min_size);

SCLogDebug("file %p size %"PRIu64", state %d", cur_file, file_size, cur_file->state);
SCLogDebug("[list %d] file %p size %"PRIu64 ", state %d", list_id, cur_file, file_size,
cur_file->state);

/* no new data */
if (cur_file->content_inspected == file_size) {
Expand Down Expand Up @@ -399,15 +467,18 @@ static InspectionBuffer *FiledataGetDataCallback(DetectEngineThreadCtx *det_ctx,
&data, &data_len,
cur_file->content_inspected);
InspectionBufferSetup(buffer, data, data_len);
SCLogDebug("[list %d] [before] buffer offset %"PRIu64 "; buffer len %"PRIu32
"; data_len %"PRIu32 "; file_size %"PRIu64,
list_id, buffer->inspect_offset, buffer->inspect_len, data_len, file_size);
buffer->inspect_offset = cur_file->content_inspected;
InspectionBufferApplyTransforms(buffer, transforms);
SCLogDebug("[list %d] [after] buffer offset %"PRIu64 "; buffer len %"PRIu32, list_id,
buffer->inspect_offset, buffer->inspect_len);

/* update inspected tracker */
cur_file->content_inspected = file_size;
SCLogDebug("content_inspected %"PRIu64, cur_file->content_inspected);
SCLogDebug("[list %d] content_inspected %"PRIu64, list_id, cur_file->content_inspected);

SCLogDebug("file_data buffer %p, data %p len %u offset %"PRIu64,
buffer, buffer->inspect, buffer->inspect_len, buffer->inspect_offset);
SCLogDebug("[list %d] file_data buffer %p, data %p len %u offset %"PRIu64, list_id, buffer,
buffer->inspect, buffer->inspect_len, buffer->inspect_offset);

SCReturnPtr(buffer, "InspectionBuffer");
}
Expand Down Expand Up @@ -456,6 +527,8 @@ static int DetectEngineInspectFiledata(
buffer->inspect_len,
buffer->inspect_offset, ciflags,
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
/* update inspected tracker */
file->content_inspected = buffer->inspect_len + buffer->inspect_offset;
if (match == 1) {
r = 1;
break;
Expand Down