aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-06-01 15:11:47 +0200
committerAnders Broman <a.broman58@gmail.com>2018-06-28 06:10:35 +0000
commitca423314373b0a4ce7d6bc1cf94c4995e1263ea2 (patch)
tree9a39a7a9f4f9a06bc51e77f115fb597349f29bf9 /test
parente6935f96354574699379009d7f55857ba69c55b1 (diff)
tcp: add support for reassembling out-of-order segments
Currently out-of-order segments will result in cutting a stream into two pieces while the out-of-order segment itself is ignored. For example, a stream of segments "ABDCE" is interpreted as "AB", "DE" with "C" ignored. This behavior breaks TLS decryption or prevent application layer PDUs (such as HTTP requests/responses) from being reconstructed. To fix this, buffer segments when a gap is detected. The proposed approach extends the "multi-segment PDU" (MSP) mechanism which is normally used for linking multiple, sequential TCP segments into a single PDU. When a gap is detected between segments, it is assumed that the segments within this gap are out-of-order and will be received (or retransmitted) later. The current implementation has a limitation though, if multiple gaps exist, then the subdissector will only be called when all gaps are filled (the subdissector will receive segments later than necessary). For example with "ACEBD", "ABC" can already be processed after "B" is received (with "E" still buffered), but due to how MSP are extended, it must receive "D" too before it reassembles "ABCDE". In practice this could mean that the request/response times between HTTP requests and responses are slightly off, but at least the stream is correct now. (These limitations are documented in the User's Guide.) As the feature fails at least the 802.11 decryption test where packets are missing (instead of OoO), hide this feature behind a preference. Tested with captures containing out-of-order TCP segments from the linked bug reports, comparing the effect of toggling the preference on the summary output of tshark, the verbose output (-V) and the two-pass output (-2 or -2V). Captures marked with "ok" just needed "simple" out-of-order handling. Captures marked with "ok2" additionally required the reassembly API change to set the correct reassembled length. This change does "regress" on bug 10289 though when the preference is enabled as retransmitted single-segment PDUs are now passed to subdissectors. I added a TODO comment for this unrelated cosmetic issue. Bug: 3389 # capture 2907 (HTTP) ok Bug: 4727 # capture 4590 (HTTP) ok Bug: 9461 # capture 12130 (TLS/HTTP/RPC-over-HTTP +key 12131) ok Bug: 12006 # capture 14236 (HTTP) ok2; capture 15261 (HTTP) ok Bug: 13517 # capture 15370 (HTTP) ok; capture 16059 (MQ) ok Bug: 13754 # capture 15593 (MySQL) ok2 Bug: 14649 # capture 16305 (WebSocket) ok Change-Id: If3938c5c1c96db8f7f50e39ea779f623ce657d56 Reviewed-on: https://code.wireshark.org/review/27943 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'test')
-rw-r--r--test/captures/http-ooo.pcapbin0 -> 1209 bytes
-rw-r--r--test/suite_dissection.py50
2 files changed, 50 insertions, 0 deletions
diff --git a/test/captures/http-ooo.pcap b/test/captures/http-ooo.pcap
new file mode 100644
index 0000000000..be0b5d2f88
--- /dev/null
+++ b/test/captures/http-ooo.pcap
Binary files differ
diff --git a/test/suite_dissection.py b/test/suite_dissection.py
index b81d048b53..cfec7c4c66 100644
--- a/test/suite_dissection.py
+++ b/test/suite_dissection.py
@@ -29,3 +29,53 @@ class case_dissect_http2(subprocesstest.SubprocessTestCase):
),
env=config.test_env)
self.assertTrue(self.grepOutput('DATA'))
+
+class case_dissect_tcp(subprocesstest.SubprocessTestCase):
+ def check_tcp_out_of_order(self, extraArgs=[]):
+ capture_file = os.path.join(config.capture_dir, 'http-ooo.pcap')
+ self.runProcess([config.cmd_tshark,
+ '-r', capture_file,
+ '-otcp.reassemble_out_of_order:TRUE',
+ '-Y', 'http',
+ ] + extraArgs,
+ env=config.test_env)
+ self.assertEqual(self.countOutput('HTTP'), 5)
+ # TODO PDU /1 (segments in frames 1, 2, 4) should be reassembled in
+ # frame 4, but it is currently done in frame 6 because the current
+ # implementation reassembles only contiguous segments and PDU /2 has
+ # segments in frames 6, 3, 7.
+ self.assertTrue(self.grepOutput(r'^\s*6\s.*PUT /1 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*7\s.*GET /2 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*10\s.*PUT /3 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*11\s.*PUT /4 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*15\s.*PUT /5 HTTP/1.1'))
+
+ def test_tcp_out_of_order_onepass(self):
+ self.check_tcp_out_of_order()
+
+ @unittest.skip("MSP splitting is not implemented yet")
+ def test_tcp_out_of_order_twopass(self):
+ self.check_tcp_out_of_order(extraArgs=['-2'])
+
+ def test_tcp_out_of_order_twopass_with_bug(self):
+ # TODO fix the issue below, remove this and enable
+ # "test_tcp_out_of_order_twopass"
+ capture_file = os.path.join(config.capture_dir, 'http-ooo.pcap')
+ self.runProcess((config.cmd_tshark,
+ '-r', capture_file,
+ '-otcp.reassemble_out_of_order:TRUE',
+ '-Y', 'http',
+ '-2',
+ ),
+ env=config.test_env)
+ self.assertEqual(self.countOutput('HTTP'), 3)
+ self.assertTrue(self.grepOutput(r'^\s*7\s.*PUT /1 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*7\s.*GET /2 HTTP/1.1'))
+ # TODO ideally this should not be concatenated.
+ # Normally a multi-segment PDU (MSP) covers only a single PDU, but OoO
+ # segments can extend MSP such that it covers two (or even more) PDUs.
+ # Until MSP splitting is implemented, two PDUs are shown in a single
+ # packet (and in case of -2, they are only shown in the last packet).
+ self.assertTrue(self.grepOutput(r'^\s*11\s.*PUT /3 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*11\s.*PUT /4 HTTP/1.1'))
+ self.assertTrue(self.grepOutput(r'^\s*15\s.*PUT /5 HTTP/1.1'))