TLS: Fix TLS tunneled within TLS
In order to retrieve the correct set of TLS information, previously pinfo->curr_layer_num was used. However, this is not a stable identifier between the first and later passes, as subdissectors that couldn't dissect data due to fragmentation on the first pass aren't called on later passes. To fix issue #16109, the layer number wasn't used at all, which did break TLS over TLS. We now have pinfo->curr_proto_layer_num which specifically counts the number of layers of the current protocol instead of the total number of layers; using that instead fixes TLS within TLS (in most situations; some very rare cases, e.g. DVB baseband frames with multiple TCP PDUs, which might be from the same or from different TCP connections, might not work, but those don't work currently either) while not reopening #16109. Add tests for both cases, the one fixed by the other workaround and for TLS over TLS. As noted in the comments to #16109, there are other dissectors that use curr_layer_num that might break in some cases because it's not stable. Fix #17977.
This commit is contained in:
parent
001930e1e5
commit
e0f1f8dbf3
|
@ -601,16 +601,9 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|||
* - TLS within a different encrypted TLS tunnel.
|
||||
*
|
||||
* To support the second case, 'curr_layer_num_ssl' is used as identifier
|
||||
* for the current TLS layer. It is however not a stable identifier for the
|
||||
* second pass (Bug 16109). If the first decrypted record requests
|
||||
* reassembly for HTTP, then the second pass will skip calling the dissector
|
||||
* for the first record. That means that 'pinfo->curr_layer_num' will
|
||||
* actually be lower the second time.
|
||||
*
|
||||
* Since this cannot be easily fixed, we will just break the (hopefully less
|
||||
* common) case of TLS tunneled within TLS.
|
||||
* for the current TLS layer.
|
||||
*/
|
||||
guint8 curr_layer_num_ssl = 0; // pinfo->curr_layer_num;
|
||||
guint8 curr_layer_num_ssl = pinfo->curr_proto_layer_num;
|
||||
|
||||
ti = NULL;
|
||||
ssl_tree = NULL;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAuIpwxT/BdUhlQNwpm11Wrz6oEV5glXDeFBSp3CUd7SX+2O1z
|
||||
iXxe6cW0p2ljPQjnvVFe/NTkDcGhgaXVH+8/sk1N1s101L98ZxjLaMaMKhj+yf6Q
|
||||
IOvN1weaMt9qnl8JRrk5f6aNGWTr+dqLU2veE6zX1oT/lFtDTafopyAFGpEJnDRz
|
||||
NudARQpt1CnakRu2zkKsQ/ApMjRa9Zm4w2Kf+M23IeU+j/gi5wAU9/D39ke67tKO
|
||||
GDNXYfMfFcgsmDrH+a2xrU3Zf9KtXiPI5lw2dXs3UG19Sr+HRoydCrIPPJBMzUKw
|
||||
9M3Hc7i0aMO2vn94GJKC6mqpOeeQIWo5Y4GMnwIDAQABAoIBAE6eLAzcbH6aqQhI
|
||||
wzD9QsDF4LQFkQAZZYMIipTO+0DcvwWLo30fDxBoud3Yd/64nIF6+QydZcq2gyfI
|
||||
jlNcibZcWJz6SpuYOFdzqLSqYWxN2b4URTLBQqApDPg/VhzCQCFxJ53KRrJa3G1F
|
||||
PbX8bk/TguBRKND7UGD095i7e3ElPmmTEe4RSpzqYqCsUQ9e1ndhAVRKYSMXHdbY
|
||||
N4wtM+P2bIJghWQjyo2P4Jb7gXF47ghBett4krduvxv96m3dIuGAM0Y7V9okclQT
|
||||
7cv/8iDUXBhbWzIsB3bXG0lm9QttQ3T0doSlqg0q2DgLiYBHEhK9SiUAVt+dQftP
|
||||
kRYa+gECgYEA9c1tNXM2u4SOgMUyiFkU8Slr7MbywMq2jnalbea63Q8JxNWNW9VX
|
||||
wQOBZvKK/BEGEP9kOeS1aMQ5dUZOxzI6SN9eCfEDFzIA5VknaZcJdBW+X3kyy/wF
|
||||
7awEWcZ6B9HrtRZ+vA2rQ4LyfJd2M1eGuK6+0WJa0hGjglbFBrHJNLECgYEAwDJg
|
||||
ls3IWhPEQXWFwXXv1SM63hnbUpGFICLqLz26+qZ64hR52ZcvuZsS3l7slO+5YSim
|
||||
fQNXXYZiwQm+SdtL5V5anUKvtaMWw9VlZVNOFPYyh1RyaGr5CO0j5aoC76DnD2ee
|
||||
cRQPv8Uodf50FR5Y9uyxijGOfA3SMj4WfLppak8CgYAnDg3VGUpP/x7ZTPvbeDQA
|
||||
oXE5fN7jTRI2jpl4XdnA9/u4X6oHNl2sGE9+OPlmVZoeJ0YYgMNmMw9iF9q6gbuL
|
||||
CpqZf8ba76H+zuyZNVtWK4JFDy/IA3I5skQ6s3N+PJdz/XADlzRoFK1MqJAqVjTc
|
||||
sT82a6c8i3rsYbcKekMa8QKBgBPjorc4aGlZ7k9P2B2jFMSbtrXROy8aPAqNUmq9
|
||||
GqJhpAnNUKbBzICKmbNFY3ouLKLvT/tT4zCcfY+4cGa4OOxtjTcE9aX4UJzHcoy/
|
||||
yC7HI4d5p7VCjK7ty28y3sbpgb/IW08cYlzYDE3ZnS2qTE6RQ/YnFrWjwILOhgk2
|
||||
ST5lAoGAIYpxE2Qcz9nHHfx2Fn70Ysg8XUoyk61QBSeZEmVBPp1XhVEz7idJc4PZ
|
||||
tozarw3mo9aqY/sX2f+mwLhL0E5wxy6kcVICkYhE9y45bESAeWk9YIlOMUzTW84C
|
||||
bVJUJiciDPuTJks6XVrRzc0GayaxpblhKHeR7w+6V22+lS7wgTg=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -562,6 +562,22 @@ class TestDecryptTLS:
|
|||
), encoding='utf-8', env=test_env)
|
||||
assert 'example.com\t\n\t200\nexample.net\t\n\t200\n' == output
|
||||
|
||||
def test_tls_over_tls(self, cmd_tshark, dirs, capture_file, features, test_env):
|
||||
'''TLS using the server's private key with p < q
|
||||
(test whether libgcrypt is correctly called)'''
|
||||
if not features.have_gnutls:
|
||||
pytest.skip('Requires GnuTLS.')
|
||||
key_file = os.path.join(dirs.key_dir, 'tls-over-tls.key')
|
||||
output = subprocess.check_output((cmd_tshark,
|
||||
'-r', capture_file('tls-over-tls.pcapng.gz'),
|
||||
'-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file),
|
||||
'-z', 'expert,tls.handshake.certificates',
|
||||
'-Tfields',
|
||||
'-e', 'tls.handshake.certificate_length',
|
||||
'-Y', 'tls.handshake.certificates',
|
||||
), encoding='utf-8', env=test_env)
|
||||
assert '1152,1115,1352\n1152\n1412,1434,1382\n' == output
|
||||
|
||||
|
||||
class TestDecryptZigbee:
|
||||
def test_zigbee(self, cmd_tshark, capture_file, test_env):
|
||||
|
|
|
@ -718,6 +718,18 @@ class TestDissectTls:
|
|||
expected = ''.join('%04x\n' % i for i in range(1, 1001))
|
||||
assert stdout == expected
|
||||
|
||||
@staticmethod
|
||||
def check_tls_reassembly_over_tcp_reassembly(cmd_tshark, capture_file, test_env,
|
||||
extraArgs=[]):
|
||||
stdout = subprocess.check_output([cmd_tshark,
|
||||
'-r', capture_file('tls-fragmented-over-tcp-segmented.pcapng.gz'),
|
||||
'-zexpert,note',
|
||||
'-Yhttp.host',
|
||||
'-Tfields', '-ehttp.host'] + extraArgs,
|
||||
encoding='utf-8', env=test_env)
|
||||
stdout = stdout.replace(',', '\n')
|
||||
assert stdout == 'reports.crashlytics.com\n'
|
||||
|
||||
def test_tls_handshake_reassembly(self, cmd_tshark, capture_file, test_env):
|
||||
'''Verify that TCP and TLS handshake reassembly works.'''
|
||||
self.check_tls_handshake_reassembly(cmd_tshark, capture_file, test_env)
|
||||
|
@ -727,6 +739,22 @@ class TestDissectTls:
|
|||
self.check_tls_handshake_reassembly(
|
||||
cmd_tshark, capture_file, test_env, extraArgs=['-2'])
|
||||
|
||||
def test_tls_reassembly_over_tcp_reassembly(self, cmd_tshark, capture_file, features, test_env):
|
||||
'''Verify that TLS reassembly over TCP reassembly works.'''
|
||||
if not features.have_gnutls:
|
||||
pytest.skip('Requires GnuTLS.')
|
||||
self.check_tls_reassembly_over_tcp_reassembly(cmd_tshark, capture_file, test_env)
|
||||
|
||||
def test_tls_reassembly_over_tcp_reassembly_2(self, cmd_tshark, capture_file, features, test_env):
|
||||
'''Verify that TLS reassembly over TCP reassembly works (second pass).'''
|
||||
# pinfo->curr_layer_num can be different on the second pass than the
|
||||
# first pass, because the HTTP dissector isn't called for the first
|
||||
# TLS record on the second pass.
|
||||
if not features.have_gnutls:
|
||||
pytest.skip('Requires GnuTLS.')
|
||||
self.check_tls_reassembly_over_tcp_reassembly(cmd_tshark, capture_file,
|
||||
test_env, extraArgs=['-2'])
|
||||
|
||||
class TestDissectQuic:
|
||||
@staticmethod
|
||||
def check_quic_tls_handshake_reassembly(cmd_tshark, capture_file, test_env,
|
||||
|
|
Loading…
Reference in New Issue