#include "packet_tracer/packet_tracer.h"
#include "parser/parse_rule.h"
#include "profiler/profiler.h"
+#include "protocols/tcp.h"
#include "pub_sub/opportunistic_tls_event.h"
#include "stream/stream.h"
#include "utils/util.h"
}
}
+void FtpDataFlowData::handle_retransmit(Packet* p)
+{
+ FTP_DATA_SESSION* data_ssn = &session;
+
+ if ((data_ssn->eof_seq > 0) and (data_ssn->eof_seq == p->ptrs.tcph->seq() + p->dsize))
+ {
+ // only process the final data segment
+ initFilePosition(&data_ssn->position, get_file_processed_size(p->flow));
+ finalFilePosition(&data_ssn->position);
+
+ FileFlows* file_flows = FileFlows::get_file_flows(p->flow);
+ if (file_flows)
+ {
+ file_flows->file_process(DetectionEngine::get_current_packet(),
+ p->data, 0, SNORT_FILE_END, data_ssn->direction, data_ssn->path_hash);
+
+ eof_handled = true;
+ }
+ }
+}
+
void FtpDataFlowData::handle_eof(Packet* p)
{
FTP_DATA_SESSION* data_ssn = &session;
+ data_ssn->eof_seq = 0;
if (!PROTO_IS_FTP_DATA(data_ssn) || !FTPDataDirection(p, data_ssn))
return;
- initFilePosition(&data_ssn->position, get_file_processed_size(p->flow));
- finalFilePosition(&data_ssn->position);
- eof_handled = true;
+ if (p->dsize != 0)
+ {
+ initFilePosition(&data_ssn->position, get_file_processed_size(p->flow));
+ finalFilePosition(&data_ssn->position);
+ eof_handled = true;
+ }
+ else
+ {
+ Active* act = p->active;
+ act->set_delayed_action(Active::ACT_RETRY, true);
+ data_ssn->eof_seq = p->ptrs.tcph->seq();
+ }
+
+ if (data_ssn->mss_changed)
+ ftstats.total_sessions_mss_changed++;
}
//-------------------------------------------------------------------------
{ CountType::SUM, "start_tls", "total STARTTLS events generated" },
{ CountType::SUM, "ssl_search_abandoned", "total SSL search abandoned" },
{ CountType::SUM, "ssl_srch_abandoned_early", "total SSL search abandoned too soon" },
-
+ { CountType::SUM, "pkt_segment_size_changed", "total number of FTP data packets with segment size change" },
+ { CountType::SUM, "flow_segment_size_changed", "total number of FTP sessions with segment size change" },
{ CountType::END, nullptr, nullptr }
};
#include "detection/detection_engine.h"
#include "file_api/file_flows.h"
#include "flow/session.h"
+#include "packet_io/active.h"
+#include "protocols/tcp.h"
#include "stream/stream.h"
#include "ftpp_si.h"
{
Flow* flow = pkt->flow;
assert(flow);
+ FtpDataFlowData* fdfd = (FtpDataFlowData*)flow->get_flow_data(FtpDataFlowData::inspector_id);
+ if (!fdfd)
+ return SEARCH;
if ( len )
{
if(expected_seg_size == 0)
if ( len != expected_seg_size )
{
- // Treat this as the last packet of the FTP data transfer.
- set_ftp_flush_flag(flow);
+ ftstats.total_packets_mss_changed++;
+ fdfd->session.mss_changed = true;
+ if (fdfd->session.bytes_seen == 0)
+ {
+ // Segmented pkt is smaller than expected_seg_size
+ set_ftp_flush_flag(flow);
+ }
+ else if (pkt->ptrs.tcph and !pkt->ptrs.tcph->is_fin())
+ {
+ Active* act = pkt->active;
+ // add packet to retry queue to consider this is not end of ftp flow
+ if (!(pkt->flow->flags.trigger_detained_packet_event))
+ act->set_delayed_action(Active::ACT_RETRY, true);
+ }
expected_seg_size = len;
restart_scan();
*fp = len;
+ fdfd->session.bytes_seen += len;
return FLUSH;
}
else
segs++;
bytes += len;
}
+ fdfd->session.bytes_seen += len;
- if ( segs >= 2 && bytes >= min )
+ if ((segs >= 2 and bytes >= min) or (pkt->ptrs.tcph and pkt->ptrs.tcph->is_fin()))
{
+ // Either FIN or smaller size do FLUSH to continue inspection
restart_scan();
*fp = len;
return FLUSH;
FTP_TELNET_SESSION ft_ssn;
snort::FlowKey ftp_key;
char* filename;
+ uint32_t eof_seq;
size_t path_hash;
int data_chan;
int file_xfer_info;
FilePosition position;
- bool direction;
+ uint32_t bytes_seen;
unsigned char mode;
unsigned char packet_flags;
+ bool direction;
+ bool mss_changed;
};
class FtpDataFlowData : public snort::FlowData
void handle_expected(snort::Packet*) override;
void handle_eof(snort::Packet*) override;
-
+ void handle_retransmit(snort::Packet*) override;
size_t size_of() override
{ return sizeof(*this); }
PegCount starttls;
PegCount ssl_search_abandoned;
PegCount ssl_search_abandoned_too_soon;
+ PegCount total_packets_mss_changed;
+ PegCount total_sessions_mss_changed;
};
struct TelnetStats