#define PKT_PDU_TAIL 0x00000200 /* end of PDU */
#define PKT_DETECT_LIMIT 0x00000400 /* alt_dsize is valid */
-#define PKT_ALLOW_MULTIPLE_DETECT 0x00000800 /* packet has either pipelined mime attachments
- or pipeline http requests */
+#define PKT_ALLOW_MULTIPLE_DETECT 0x00000800 /* packet has multiple PDUs */
#define PKT_PAYLOAD_OBFUSCATE 0x00001000
#define PKT_STATELESS 0x00002000 /* Packet has matched a stateless rule */
const SourceId source_id = p->is_from_client() ? SRC_CLIENT : SRC_SERVER;
HttpFlowData* session_data = http_get_flow_data(p->flow);
+ if (session_data == nullptr)
+ {
+ assert(false);
+ return;
+ }
if (!session_data->for_http2)
HttpModule::increment_peg_counts(PEG_TOTAL_BYTES, p->dsize);
- // FIXIT-E Workaround for unexpected eval() calls. Convert to asserts when possible.
+ // FIXIT-M Workaround for unexpected eval() calls. Convert to asserts when possible.
if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) ||
(session_data->type_expected[source_id] == SEC_ABORT) ||
(session_data->octets_reassembled[source_id] != p->dsize))
{
+ // assert(session_data->type_expected[source_id] != SEC_ABORT);
+ // assert(session_data->section_type[source_id] != SEC__NOT_COMPUTE);
+ // assert(session_data->octets_reassembled[source_id] == p->dsize);
session_data->type_expected[source_id] = SEC_ABORT;
return;
}
HttpFlowData* const session_data = http_get_flow_data(p->flow);
- if ( session_data == nullptr )
+ if (session_data == nullptr)
+ {
+ // assert(false); // FIXIT-M something wrong with H2I Push Promise triggers this.
return;
+ }
Http2FlowData* h2i_flow_data = nullptr;
if (Http2FlowData::inspector_id != 0)
else
current_section = HttpContextData::clear_snapshot(p->context);
- // FIXIT-M This test is necessary because sometimes we get extra clears
- // Convert to assert when that gets fixed.
if ( current_section == nullptr )
+ {
+ // assert(false); // FIXIT-M this happens a lot
return;
+ }
current_section->clear();
HttpTransaction* current_transaction = current_section->get_transaction();
const SourceId source_id = current_section->get_source_id();
- //FIXIT-M This check may not apply to the transaction attached to the packet
- //in case of offload.
+ // FIXIT-M This check may not apply to the transaction attached to the packet
+ // in case of offload.
if (session_data->detection_status[source_id] == DET_DEACTIVATING)
{
if (source_id == SRC_CLIENT)
const snort::StreamBuffer reassemble(snort::Flow* flow, unsigned total, unsigned, const
uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) override;
bool finish(snort::Flow* flow) override;
- bool prep_partial_flush(snort::Flow* flow, uint32_t num_flush);
+ void prep_partial_flush(snort::Flow* flow, uint32_t num_flush);
bool is_paf() override { return true; }
static StreamSplitter::Status status_value(StreamSplitter::Status ret_val, bool http2 = false);
HttpFlowData* session_data = HttpInspect::http_get_flow_data(flow);
if (!session_data)
+ {
+ // assert(false); // FIXIT-M this should not be possible but currently it is
return false;
+ }
#ifdef REG_TEST
if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
return false;
}
+ if (session_data->tcp_close[source_id])
+ {
+ // assert(false); // FIXIT-M this should not happen but it does
+ session_data->type_expected[source_id] = SEC_ABORT;
+ return false;
+ }
+
session_data->tcp_close[source_id] = true;
if (session_data->section_type[source_id] != SEC__NOT_COMPUTE)
return true;
return false;
}
-bool HttpStreamSplitter::prep_partial_flush(Flow* flow, uint32_t num_flush)
+void HttpStreamSplitter::prep_partial_flush(Flow* flow, uint32_t num_flush)
{
Profile profile(HttpModule::get_profile_stats());
HttpFlowData* session_data = HttpInspect::http_get_flow_data(flow);
+ assert(session_data != nullptr);
#ifdef REG_TEST
if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) &&
session_data->cutter[source_id]->get_num_good_chunks(),
session_data->cutter[source_id]->get_octets_seen() - num_flush);
session_data->partial_flush[source_id] = true;
- return true;
}
{
Profile profile(HttpModule::get_profile_stats());
- StreamBuffer http_buf { nullptr, 0 };
-
copied = len;
HttpFlowData* session_data = HttpInspect::http_get_flow_data(flow);
- assert(session_data != nullptr);
+ if (session_data == nullptr)
+ {
+ assert(false);
+ return { nullptr, 0 };
+ }
#ifdef REG_TEST
if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP))
{
if (!(flags & PKT_PDU_TAIL))
{
- return http_buf;
+ return { nullptr, 0 };
}
bool tcp_close;
uint8_t* test_buffer;
{
// Source ID does not match test data, no test data was flushed, preparing for a
// TCP connection close, or there is no more test data
- return http_buf;
+ return { nullptr, 0 };
}
data = test_buffer;
}
}
#endif
- assert(session_data->type_expected[source_id] != SEC_ABORT);
- if (session_data->section_type[source_id] == SEC__NOT_COMPUTE)
+ if ((session_data->type_expected[source_id] == SEC_ABORT) ||
+ (session_data->section_type[source_id] == SEC__NOT_COMPUTE))
{
+ assert(session_data->type_expected[source_id] != SEC_ABORT);
+ // assert(session_data->section_type[source_id] != SEC__NOT_COMPUTE); // FIXIT-M H2I
+ session_data->type_expected[source_id] = SEC_ABORT;
return { nullptr, 0 };
}
// Sometimes it is necessary to reassemble zero bytes when a connection is closing to trigger
// proper clean up. But even a zero-length buffer cannot be processed with a nullptr lest we
// get in trouble with memcpy() (undefined behavior) or some library.
- assert((data != nullptr) || (len == 0));
if (data == nullptr)
+ {
+ if (len != 0)
+ {
+ assert(false);
+ session_data->type_expected[source_id] = SEC_ABORT;
+ return { nullptr, 0 };
+ }
data = (const uint8_t*)"";
+ }
uint8_t*& partial_buffer = session_data->partial_buffer[source_id];
uint32_t& partial_buffer_length = session_data->partial_buffer_length[source_id];
uint32_t& partial_raw_bytes = session_data->partial_raw_bytes[source_id];
assert(partial_raw_bytes + total <= MAX_OCTETS);
- // FIXIT-E this is a precaution/workaround for stream issues. When they are fixed replace this
- // block with an assert.
if ((session_data->section_offset[source_id] == 0) &&
(session_data->octets_expected[source_id] != partial_raw_bytes + total))
{
assert(!session_data->for_http2);
-
- if (session_data->octets_expected[source_id] == 0)
- {
- // FIXIT-E This is a known problem. No data was scanned and yet somehow stream can
- // give us data when we ask for an empty message section. Dropping the unexpected data
- // enables us to send the HTTP headers through detection as originally planned.
- total = 0;
- len = 0;
- }
- else
- {
-#ifdef REG_TEST
- // FIXIT-M: known case: if session clears w/o a flush point,
- // stream_tcp will flush to paf max which could be well below what
- // has been scanned so far. since no flush point was specified,
- // NHI should just deal with what it gets.
- //assert(false);
-#endif
- return http_buf;
- }
+ assert(total == 0); // FIXIT-L this special exception for total of zero is needed for now
+ session_data->type_expected[source_id] = SEC_ABORT;
+ return { nullptr, 0 };
}
session_data->running_total[source_id] += len;
- assert(session_data->running_total[source_id] <= total);
+ if (session_data->running_total[source_id] > total)
+ {
+ assert(false);
+ session_data->type_expected[source_id] = SEC_ABORT;
+ return { nullptr, 0 };
+ }
// FIXIT-P stream should be enhanced to do discarding for us. For now flush-then-discard here
// is how scan() handles things we don't need to examine.
}
}
}
- return http_buf;
+ return { nullptr, 0 };
}
HttpModule::increment_peg_counts(PEG_REASSEMBLE);
chunk_spray(session_data, buffer, data, len);
}
+ StreamBuffer http_buf { nullptr, 0 };
+
if (flags & PKT_PDU_TAIL)
{
uint32_t& running_total = session_data->running_total[source_id];
- assert(running_total == total);
+ if (running_total != total)
+ {
+ assert(false);
+ session_data->type_expected[source_id] = SEC_ABORT;
+ return { nullptr, 0 };
+ }
running_total = 0;
const uint32_t buf_size =
session_data->section_offset[source_id] - session_data->num_excess[source_id];
{
Profile profile(HttpModule::get_profile_stats());
- assert(length <= MAX_OCTETS);
-
- Flow* flow = pkt->flow;
+ Flow* const flow = pkt->flow;
// This is the session state information we share with HttpInspect and store with stream. A
// session is defined by a TCP connection. Since scan() is the first to see a new TCP
HttpModule::increment_peg_counts(PEG_FLOW);
}
- SectionType type = session_data->type_expected[source_id];
-
#ifdef REG_TEST
if (HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
{
}
#endif
+ SectionType& type = session_data->type_expected[source_id];
+
if (type == SEC_ABORT)
return status_value(StreamSplitter::ABORT);
+ if (length > MAX_OCTETS)
+ {
+ assert(false);
+ type = SEC_ABORT;
+ return status_value(StreamSplitter::ABORT);
+ }
+
#ifdef REG_TEST
if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) &&
!HttpTestManager::use_test_input(HttpTestManager::IN_HTTP))
}
#endif
+ if (session_data->tcp_close[source_id])
+ {
+ // assert(false); // FIXIT-L This currently happens. Add assert back when problem resolved.
+ type = SEC_ABORT;
+ return status_value(StreamSplitter::ABORT);
+ }
+
// If the last request was a CONNECT and we have not yet seen the response, this is early C2S
// traffic. If there has been a pipeline overflow or underflow we cannot match requests to
// responses, so there is no attempt to track early C2S traffic.
session_data->last_request_was_connect = false;
}
- assert(!session_data->tcp_close[source_id]);
-
HttpModule::increment_peg_counts(PEG_SCAN);
if (session_data->detection_status[source_id] == DET_REACTIVATING)
// 0.9 response is a body that runs to connection end with no headers. HttpInspect does
// not support no headers. Processing this imaginary status line and empty headers allows
// us to overcome this limitation and reuse the entire HTTP infrastructure.
- type = SEC_BODY_OLD;
prepare_flush(session_data, nullptr, SEC_STATUS, 14, 0, 0, false, 0, 14);
my_inspector->process((const uint8_t*)"HTTP/0.9 200 .", 14, flow, SRC_SERVER, false);
session_data->transaction[SRC_SERVER]->clear_section();
// should be an unconditional EVENT_LOSS_OF_SYNC.
session_data->events[source_id]->generate_misformatted_http(data, length);
// FIXIT-E need to process this data not just discard it.
- session_data->type_expected[source_id] = SEC_ABORT;
+ type = SEC_ABORT;
delete cutter;
cutter = nullptr;
return status_value(StreamSplitter::ABORT);
// Wait patiently for more data
return status_value(StreamSplitter::SEARCH);
case SCAN_ABORT:
- session_data->type_expected[source_id] = SEC_ABORT;
+ type = SEC_ABORT;
delete cutter;
cutter = nullptr;
return status_value(StreamSplitter::ABORT);