ENGINE_SET_EVENT(p,TCP_OPT_INVALID_LEN);
}
break;
+ /* RFC 2385 MD5 option */
+ case TCP_OPT_MD5:
+ SCLogDebug("MD5 option, len %u", olen);
+ if (olen != 18) {
+ ENGINE_SET_INVALID_EVENT(p,TCP_OPT_INVALID_LEN);
+ } else {
+ /* we can't validate the option as the key is out of band */
+ p->tcpvars.md5_option_present = true;
+ }
+ break;
+ /* RFC 5925 AO option */
+ case TCP_OPT_AO:
+ SCLogDebug("AU option, len %u", olen);
+ if (olen < 4) {
+ ENGINE_SET_INVALID_EVENT(p,TCP_OPT_INVALID_LEN);
+ } else {
+ /* we can't validate the option as the key is out of band */
+ p->tcpvars.ao_option_present = true;
+ }
+ break;
}
pkt += olen;
#define TCP_OPT_TFO 0x22 /* TCP Fast Open */
#define TCP_OPT_EXP1 0xfd /* Experimental, could be TFO */
#define TCP_OPT_EXP2 0xfe /* Experimental, could be TFO */
+#define TCP_OPT_MD5 0x13 /* 19: RFC 2385 TCP MD5 option */
+#define TCP_OPT_AO 0x1d /* 29: RFC 5925 TCP AO option */
#define TCP_OPT_SACKOK_LEN 2
#define TCP_OPT_WS_LEN 3
typedef struct TCPVars_
{
/* commonly used and needed opts */
+ bool md5_option_present;
+ bool ao_option_present;
bool ts_set;
uint32_t ts_val; /* host-order */
uint32_t ts_ecr; /* host-order */
if (ostream->flags & STREAMTCP_STREAM_FLAG_RST_RECV) {
if (StreamTcpStateDispatch(tv, p, stt, ssn, &stt->pseudo_queue, ssn->pstate) < 0)
return -1;
+ /* if state is still "closed", it wasn't updated by our dispatch. */
+ if (ssn->state == TCP_CLOSED)
+ ssn->state = ssn->pstate;
}
}
return 0;
static int StreamTcpValidateRst(TcpSession *ssn, Packet *p)
{
-
uint8_t os_policy;
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
}
}
+ /* RFC 2385 md5 signature header or RFC 5925 TCP AO headerpresent. Since we can't
+ * validate these (requires key that is set/transfered out of band), we can't know
+ * if the RST will be accepted or rejected by the end host. We accept it, but keep
+ * tracking if the sender of it ignores it, which would be a sign of injection. */
+ if (p->tcpvars.md5_option_present || p->tcpvars.ao_option_present) {
+ TcpStream *receiver_stream;
+ if (PKT_IS_TOSERVER(p)) {
+ receiver_stream = &ssn->server;
+ } else {
+ receiver_stream = &ssn->client;
+ }
+ SCLogDebug("ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
+ receiver_stream->flags |= STREAMTCP_STREAM_FLAG_RST_RECV;
+ }
+
if (ssn->flags & STREAMTCP_FLAG_ASYNC) {
if (PKT_IS_TOSERVER(p)) {
if (SEQ_GEQ(TCP_GET_SEQ(p), ssn->client.next_seq)) {