]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output: fix logging wrong direction in tls upgrade 3353/head
authorVictor Julien <victor@inliniac.net>
Fri, 2 Mar 2018 12:44:43 +0000 (13:44 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 6 Apr 2018 07:05:54 +0000 (09:05 +0200)
When upgrading to TLS from HTTP logging of the final HTTP tx could
have the wrong direction. This was due to the original packet triggering/
finalizing the upgrade would be used as the base for both the toserver
and toclient pseudo packet meaning it was wrong in one direction.

This patch creates a pseudo packet in the same way as the flow timeout
code does, so it no longer takes the raw original packet in.

Bug #2430

src/stream-tcp.c

index e5b70f5eacc710b1a3727914673b5a0c11857f36..2b5d8693cfcbb1f5563d80b65b433610fc09a182 100644 (file)
@@ -5855,68 +5855,186 @@ void StreamTcpPseudoPacketCreateStreamEndPacket(ThreadVars *tv, StreamTcpThread
 /** \brief Create a pseudo packet injected into the engine to signal the
  *         opposing direction of this stream trigger detection/logging.
  *
- *  \param p real packet
+ *  \param parent real packet
  *  \param pq packet queue to store the new pseudo packet in
  *  \param dir 0 ts 1 tc
  */
 static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
-        StreamTcpThread *stt, Packet *p, TcpSession *ssn, PacketQueue *pq, bool dir)
+        StreamTcpThread *stt, Packet *parent,
+        TcpSession *ssn, PacketQueue *pq, int dir)
 {
     SCEnter();
+    Flow *f = parent->flow;
 
-    if (p->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
+    if (parent->flags & PKT_PSEUDO_DETECTLOG_FLUSH) {
         SCReturn;
     }
 
-    Packet *np = StreamTcpPseudoSetup(p, GET_PKT_DATA(p), GET_PKT_LEN(p));
+    Packet *np = PacketPoolGetPacket();
     if (np == NULL) {
-        SCLogDebug("The packet received from packet allocation is NULL");
-        StatsIncr(tv, stt->counter_tcp_pseudo_failed);
         SCReturn;
     }
     PKT_SET_SRC(np, PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH);
 
-    /* Setup the IP and TCP headers */
-    StreamTcpPseudoPacketSetupHeader(np,p);
-
-    np->tenant_id = p->flow->tenant_id;
-    np->flowflags = p->flowflags;
-
+    np->tenant_id = f->tenant_id;
+    np->datalink = DLT_RAW;
+    np->proto = IPPROTO_TCP;
+    FlowReference(&np->flow, f);
     np->flags |= PKT_STREAM_EST;
     np->flags |= PKT_HAS_FLOW;
     np->flags |= PKT_IGNORE_CHECKSUM;
     np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
 
-    if (p->flags & PKT_NOPACKET_INSPECTION) {
+    if (f->flags & FLOW_NOPACKET_INSPECTION) {
         DecodeSetNoPacketInspectionFlag(np);
     }
-    if (p->flags & PKT_NOPAYLOAD_INSPECTION) {
+    if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
         DecodeSetNoPayloadInspectionFlag(np);
     }
 
-    if (dir == false) {
+    if (dir == 0) {
+        SCLogDebug("pseudo is to_server");
+        np->flowflags |= FLOW_PKT_TOSERVER;
+    } else {
         SCLogDebug("pseudo is to_client");
-        np->flowflags &= ~(FLOW_PKT_TOSERVER|FLOW_PKT_TOCLIENT);
         np->flowflags |= FLOW_PKT_TOCLIENT;
-#ifdef DEBUG
-        BUG_ON(!(PKT_IS_TOCLIENT(np)));
-        BUG_ON((PKT_IS_TOSERVER(np)));
-#endif
+    }
+    np->flowflags |= FLOW_PKT_ESTABLISHED;
+    np->payload = NULL;
+    np->payload_len = 0;
+
+    if (FLOW_IS_IPV4(f)) {
+        if (dir == 0) {
+            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->src);
+            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->dst);
+            np->sp = f->sp;
+            np->dp = f->dp;
+        } else {
+            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->src, &np->dst);
+            FLOW_COPY_IPV4_ADDR_TO_PACKET(&f->dst, &np->src);
+            np->sp = f->dp;
+            np->dp = f->sp;
+        }
+
+        /* Check if we have enough room in direct data. We need ipv4 hdr + tcp hdr.
+         * Force an allocation if it is not the case.
+         */
+        if (GET_PKT_DIRECT_MAX_SIZE(np) <  40) {
+            if (PacketCallocExtPkt(np, 40) == -1) {
+                goto error;
+            }
+        }
+        /* set the ip header */
+        np->ip4h = (IPV4Hdr *)GET_PKT_DATA(np);
+        /* version 4 and length 20 bytes for the tcp header */
+        np->ip4h->ip_verhl = 0x45;
+        np->ip4h->ip_tos = 0;
+        np->ip4h->ip_len = htons(40);
+        np->ip4h->ip_id = 0;
+        np->ip4h->ip_off = 0;
+        np->ip4h->ip_ttl = 64;
+        np->ip4h->ip_proto = IPPROTO_TCP;
+        if (dir == 0) {
+            np->ip4h->s_ip_src.s_addr = f->src.addr_data32[0];
+            np->ip4h->s_ip_dst.s_addr = f->dst.addr_data32[0];
+        } else {
+            np->ip4h->s_ip_src.s_addr = f->dst.addr_data32[0];
+            np->ip4h->s_ip_dst.s_addr = f->src.addr_data32[0];
+        }
+
+        /* set the tcp header */
+        np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 20);
+
+        SET_PKT_LEN(np, 40); /* ipv4 hdr + tcp hdr */
+
+    } else if (FLOW_IS_IPV6(f)) {
+        if (dir == 0) {
+            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->src);
+            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->dst);
+            np->sp = f->sp;
+            np->dp = f->dp;
+        } else {
+            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->src, &np->dst);
+            FLOW_COPY_IPV6_ADDR_TO_PACKET(&f->dst, &np->src);
+            np->sp = f->dp;
+            np->dp = f->sp;
+        }
+
+        /* Check if we have enough room in direct data. We need ipv6 hdr + tcp hdr.
+         * Force an allocation if it is not the case.
+         */
+        if (GET_PKT_DIRECT_MAX_SIZE(np) <  60) {
+            if (PacketCallocExtPkt(np, 60) == -1) {
+                goto error;
+            }
+        }
+        /* set the ip header */
+        np->ip6h = (IPV6Hdr *)GET_PKT_DATA(np);
+        /* version 6 */
+        np->ip6h->s_ip6_vfc = 0x60;
+        np->ip6h->s_ip6_flow = 0;
+        np->ip6h->s_ip6_nxt = IPPROTO_TCP;
+        np->ip6h->s_ip6_plen = htons(20);
+        np->ip6h->s_ip6_hlim = 64;
+        if (dir == 0) {
+            np->ip6h->s_ip6_src[0] = f->src.addr_data32[0];
+            np->ip6h->s_ip6_src[1] = f->src.addr_data32[1];
+            np->ip6h->s_ip6_src[2] = f->src.addr_data32[2];
+            np->ip6h->s_ip6_src[3] = f->src.addr_data32[3];
+            np->ip6h->s_ip6_dst[0] = f->dst.addr_data32[0];
+            np->ip6h->s_ip6_dst[1] = f->dst.addr_data32[1];
+            np->ip6h->s_ip6_dst[2] = f->dst.addr_data32[2];
+            np->ip6h->s_ip6_dst[3] = f->dst.addr_data32[3];
+        } else {
+            np->ip6h->s_ip6_src[0] = f->dst.addr_data32[0];
+            np->ip6h->s_ip6_src[1] = f->dst.addr_data32[1];
+            np->ip6h->s_ip6_src[2] = f->dst.addr_data32[2];
+            np->ip6h->s_ip6_src[3] = f->dst.addr_data32[3];
+            np->ip6h->s_ip6_dst[0] = f->src.addr_data32[0];
+            np->ip6h->s_ip6_dst[1] = f->src.addr_data32[1];
+            np->ip6h->s_ip6_dst[2] = f->src.addr_data32[2];
+            np->ip6h->s_ip6_dst[3] = f->src.addr_data32[3];
+        }
+
+        /* set the tcp header */
+        np->tcph = (TCPHdr *)((uint8_t *)GET_PKT_DATA(np) + 40);
+
+        SET_PKT_LEN(np, 60); /* ipv6 hdr + tcp hdr */
+    }
+
+    np->tcph->th_offx2 = 0x50;
+    np->tcph->th_flags |= TH_ACK;
+    np->tcph->th_win = 10;
+    np->tcph->th_urp = 0;
+
+    /* to server */
+    if (dir == 0) {
+        np->tcph->th_sport = htons(f->sp);
+        np->tcph->th_dport = htons(f->dp);
+
+        np->tcph->th_seq = htonl(ssn->client.next_seq);
+        np->tcph->th_ack = htonl(ssn->server.last_ack);
+
+    /* to client */
     } else {
-        SCLogDebug("pseudo is to_server");
-        np->flowflags &= ~(FLOW_PKT_TOCLIENT|FLOW_PKT_TOSERVER);
-        np->flowflags |= FLOW_PKT_TOSERVER;
-#ifdef DEBUG
-        BUG_ON(!(PKT_IS_TOSERVER(np)));
-        BUG_ON((PKT_IS_TOCLIENT(np)));
-#endif
+        np->tcph->th_sport = htons(f->dp);
+        np->tcph->th_dport = htons(f->sp);
+
+        np->tcph->th_seq = htonl(ssn->server.next_seq);
+        np->tcph->th_ack = htonl(ssn->client.last_ack);
     }
 
+    /* use parent time stamp */
+    memcpy(&np->ts, &parent->ts, sizeof(struct timeval));
+
     SCLogDebug("np %p", np);
     PacketEnqueue(pq, np);
 
     StatsIncr(tv, stt->counter_tcp_pseudo);
     SCReturn;
+error:
+    FlowDeReference(&np->flow);
+    SCReturn;
 }
 
 /** \brief create packets in both directions to flush out logging