summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-07-06 01:08:22 +0200
committerPeter Wu <peter@lekensteyn.nl>2018-07-06 01:35:00 +0200
commit4ecf9d858b49e76d8a9c29df01ce1bd523ae6704 (patch)
treece6ae94e876a873daacd7c4b160def781b8c1c70
parent8f85e795ef1f9045b353cf063c12f7dab463f74a (diff)
downloadwireshark-notes-4ecf9d858b49e76d8a9c29df01ce1bd523ae6704.tar.gz
crafted-pkt/badsegments.py: test Follow TCP Stream edge cases
For testing various issues such as https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=14944 Code coverage checked with Clang 6.0.0 by building packet-tcp.c with options from https://clang.llvm.org/docs/SourceBasedCodeCoverage.html # link.sh is the command to link libwireshark.so with the two profiling options eval $(jq -r '.[] | select(.file | contains("packet-tcp.c")) | .command' compile_commands.json | sed 's/^[^ ]\+/clang -fprofile-instr-generate -fcoverage-mapping/') && time bash link.sh llvm-profdata merge -sparse tcp.profraw -o tcp.profdata && llvm-cov show epan/dissectors/CMakeFiles/dissectors.dir/packet-tcp.c.o -instr-profile=tcp.profdata /tmp/wireshark/epan/dissectors/packet-tcp.c -name-regex='check_follow_fragments|follow_tcp_tap_listener' Tested against https://code.wireshark.org/review/#/c/28614/4 with log: 1c6dc6d31f (master) Some fixes. 777dac163a Follow Stream: ensure linear performance with many packets b853858e84 tcp: remove repetitive "follow_record->is_server" 98c33f532e tcp: fix Follow TCP Stream with missing (but ACKed) segments 8f4abb0346 tcp: fix Follow TCP Stream for overlapping data 9219c4b1b6 tcp: ignore zero-length payloads for Follow TCP Stream 9499a15a4a Qt: fix wrong Follow Stream text position after changing mode All cases are covered, except for one: 1122| 1| data_offset = follow_info->seq[is_server] - sequence; 1123| 1| if (data_length <= data_offset) { 1124| 0| data_length = 0; 1125| 1| } else { To reach that situation, the IP header probably needs to be modified, or the pcap snaplen/caplen fields. Too much work for now and a visual inspection shows that the case does not hurt, so just go for it.
-rwxr-xr-xcrafted-pkt/badsegments.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/crafted-pkt/badsegments.py b/crafted-pkt/badsegments.py
new file mode 100755
index 0000000..73f26f3
--- /dev/null
+++ b/crafted-pkt/badsegments.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+# Create a crafted TCP stream with overlapping and retransmitted segments
+# Usage: badsegments.py [output.pcap]
+
+import sys
+from scapy.all import *
+
+
+def make_tcp(server=None, flags=None, data=b'', datalen=0, **kwargs):
+ assert type(server) == bool
+ assert len(data) == datalen
+ if not flags:
+ flags = 'A'
+ kwargs['seq' if server else 'ack'] += 0x44332211
+ kwargs['ack' if server else 'seq'] += 0x88776655
+ if 'A' not in flags:
+ kwargs['ack'] = 0
+ if server:
+ tcp = TCP(flags=flags, sport=80, dport=32323, **kwargs)
+ tcpip = IP(dst='10.0.0.1', src='10.0.0.2') / tcp
+ else:
+ tcp = TCP(flags=flags, sport=32323, dport=80, **kwargs)
+ tcpip = IP(dst='10.0.0.2', src='10.0.0.1') / tcp
+ return tcpip / data
+
+s = lambda **kwargs: make_tcp(server=True, **kwargs)
+c = lambda **kwargs: make_tcp(server=False, **kwargs)
+
+pkts = []
+# Cases:
+# 1. two sequential segments
+# 2. out-of-order (swapped two sequential segments)
+# 3. Bad overlap (second overlap with different data should be ignored)
+# 4. Ignore bad retransmitted data, but extend with remaining data.
+# 5. Check handling of overlapping data while fragments are incomplete
+# (out-of-order - cannot add fragments to stream)
+# 6. lost but acked segments
+# 7. lost 3/5 fragments, but acked
+# TODO lost and not acked (currently truncated, is that OK?)
+
+bad = len(sys.argv) <= 2 or sys.argv[2] != 'ok'
+
+pkts += [
+c(seq=0, ack=0, flags='S'),
+s(seq=0, ack=1, flags='SA'),
+c(seq=1, ack=1, flags='A'),
+
+# 1. two sequential segments
+c(seq=1, ack=1, data=b'GET / HTTP/1.1\r\n', datalen=16),
+c(seq=17, ack=1, data=b'Host:localhost\r\n', datalen=16),
+]
+
+pkts += [
+# 2. out-of-order (swapped two sequential segments)
+c(seq=33, ack=1, data=b'X-Swapped: 1st\r\n', datalen=16),
+c(seq=49, ack=1, data=b'X-Swapped: 2nd\r\n', datalen=16),
+][::-1 if bad else 1]
+pkts += [
+s(seq=1, ack=65),
+]
+
+pkts += [
+# 3. Bad overlap (second overlap with different data should be ignored)
+c(seq=65, ack=1, data=b'X-Overlap-Packet', datalen=16),
+c(seq=65, ack=1, data=b'X-Overlap-IGNORE', datalen=16),
+][:2 if bad else 1]
+
+pkts += [
+# 4. Ignore bad retransmitted data, but extend with remaining data.
+c(seq=65, ack=1, data=b'X-BADOVERLAPHEAD: extra data--\r\n', datalen=32),
+s(seq=1, ack=97),
+]
+
+# 5. Check handling of overlapping data while fragments are incomplete
+# (out-of-order - cannot add fragments to stream)
+pkts += [
+c(seq=113, ack=1, data=b'his is delayed\r\n', datalen=16),
+c(seq=161, ack=1, data=b'X-OoO-Overlap3:e', datalen=16),
+c(seq=161, ack=1, data=b'X-OoO-Overlap3:extend fragment\r\n', datalen=32),
+c(seq=97, ack=1, data=b'X-OoO-Overlap: t', datalen=16),
+c(seq=129, ack=1, data=b'X-OoO-Overlap2: second delayed\r\n', datalen=32),
+]
+
+pkts += [
+# 6. lost but acked segments
+c(seq=193, ack=1, data=b'Cookie: value=1234567890abcdef\r\n', datalen=32),
+c(seq=225, ack=1, data=b'X-Missing-But-Acked-Previous:1\r\n', datalen=32),
+s(seq=1, ack=257),
+][1 if bad else 0:]
+
+pkts += [
+# 7. lost 3/5 fragments, but acked
+c(seq=257, ack=1, data=b'X-IGNORED-ANYWAY: wjedgfjrsfdg\r\n', datalen=32),
+c(seq=287, ack=1, data=b'\r', datalen=1),
+c(seq=273, ack=1, data=b':', datalen=1),
+c(seq=289, ack=1, data=b'X-Missing-3-Out-Of-5-But-ACK:Y\r\n', datalen=32),
+s(seq=1, ack=321),
+][1 if bad else 0:]
+
+pkts += [
+c(seq=321, ack=1, data=b'\r\n', datalen=2),
+s(seq=1, ack=323),
+]
+
+# Show packets and write to file
+for i, pkt in enumerate(pkts):
+ pkt.time = i * 0.000001
+ print(pkt.summary())
+if len(sys.argv) > 1:
+ wrpcap(sys.argv[1], pkts)