diff --git a/scapy/layers/ntp.py b/scapy/layers/ntp.py index e8739006f14..ac0b403a1d9 100644 --- a/scapy/layers/ntp.py +++ b/scapy/layers/ntp.py @@ -40,6 +40,7 @@ StrFixedLenField, StrLenField, XByteField, + XStrField, XStrFixedLenField, ) from scapy.layers.inet import UDP @@ -235,24 +236,6 @@ def mysummary(self): ) -class _NTPAuthenticatorPaddingField(StrField): - """ - StrField handling the padding that may be found before the - "authenticator" field. - """ - - def getfield(self, pkt, s): - ret = None - remain = s - length = len(s) - - if length > _NTP_AUTH_MD5_TAIL_SIZE: - start = length - _NTP_AUTH_MD5_TAIL_SIZE - ret = s[:start] - remain = s[start:] - return remain, ret - - class NTPAuthenticator(Packet): """ Packet handling the "authenticator" part of a NTP packet, as @@ -261,9 +244,8 @@ class NTPAuthenticator(Packet): name = "Authenticator" fields_desc = [ - _NTPAuthenticatorPaddingField("padding", ""), IntField("key_id", 0), - XStrFixedLenField("dgst", "", length_from=lambda x: 16) + XStrField("dgst", "") ] def extract_padding(self, s): @@ -476,7 +458,8 @@ def guess_payload_class(self, payload): """ plen = len(payload) - if plen - 4 in [16, 20, 32, 64]: # length of MD5, SHA1, SHA256, SHA512 + # length of MD5, SHA1, SHA256, SHA384, SHA512 + if plen - 4 in [16, 20, 32, 48, 64]: return NTPAuthenticator elif plen > _NTP_AUTH_MD5_TAIL_SIZE: return NTPExtensions diff --git a/test/scapy/layers/ntp.uts b/test/scapy/layers/ntp.uts index 120e841200d..00b3bbf6e28 100644 --- a/test/scapy/layers/ntp.uts +++ b/test/scapy/layers/ntp.uts @@ -103,11 +103,50 @@ assert p.version == 4 assert p.mode == 3 assert p.stratum == 2 -= NTPAuthenticator += NTPAuthenticator - MD5 with padding (old test, updated for correct parsing) s = hex_bytes("000c2962f268d094666d23750800450000640db640004011a519c0a80364c0a80305a51e007b0050731a2300072000000000000000000000000000000000000000000000000000000000000000000000000052c7bc1dda64b97d0000000bcdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1") p = Ether(s) -assert NTPAuthenticator in p and p[NTPAuthenticator].key_id == 3452142173 +assert NTPAuthenticator in p +assert p[NTPAuthenticator].key_id == 11 +assert len(p[NTPAuthenticator].dgst) == 20 +assert bytes_hex(p[NTPAuthenticator].dgst) == b'cdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1' + += NTPAuthenticator - SHA1 (24 bytes: 4 key_id + 20 digest) +# Create an NTP packet with SHA1 authenticator +ntp_header = b"!\x0b\x06\xea\x00\x00\x00\x00\x00\x00\xf2\xc1\x7f\x7f\x01\x00\xdb9\xe8\xa21\x02\xe6\xbc\xdb9\xe8\x81\x02U8\xef\xdb9\xe8\x80\xdcl+\x06\xdb9\xe8\xa91\xcbI\xbf" +sha1_key_id = b"\x00\x00\x00\x02" # key_id = 2 +sha1_digest = b"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x00\x01\x02\x03\x04" # 20 bytes +s = ntp_header + sha1_key_id + sha1_digest +p = NTP(s) +assert isinstance(p, NTPHeader) +assert NTPAuthenticator in p +assert p[NTPAuthenticator].key_id == 2 +assert len(p[NTPAuthenticator].dgst) == 20 +assert bytes_hex(p[NTPAuthenticator].dgst) == b'112233445566778899aabbccddeeff0001020304' +# Test round-trip (build and parse) +rebuilt = NTP(raw(p)) +assert rebuilt[NTPAuthenticator].key_id == 2 +assert len(rebuilt[NTPAuthenticator].dgst) == 20 +assert bytes_hex(rebuilt[NTPAuthenticator].dgst) == b'112233445566778899aabbccddeeff0001020304' + += NTPAuthenticator - SHA256 (36 bytes: 4 key_id + 32 digest) +# Create an NTP packet with SHA256 authenticator +ntp_header = b"!\x0b\x06\xea\x00\x00\x00\x00\x00\x00\xf2\xc1\x7f\x7f\x01\x00\xdb9\xe8\xa21\x02\xe6\xbc\xdb9\xe8\x81\x02U8\xef\xdb9\xe8\x80\xdcl+\x06\xdb9\xe8\xa91\xcbI\xbf" +sha256_key_id = b"\x00\x00\x00\x03" # key_id = 3 +sha256_digest = b"\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x00" # 32 bytes +s = ntp_header + sha256_key_id + sha256_digest +p = NTP(s) +assert isinstance(p, NTPHeader) +assert NTPAuthenticator in p +assert p[NTPAuthenticator].key_id == 3 +assert len(p[NTPAuthenticator].dgst) == 32 +assert bytes_hex(p[NTPAuthenticator].dgst) == b'aabbccddeeff00112233445566778899112233445566778899aabbccddeeff00' +# Test round-trip (build and parse) +rebuilt = NTP(raw(p)) +assert rebuilt[NTPAuthenticator].key_id == 3 +assert len(rebuilt[NTPAuthenticator].dgst) == 32 +assert bytes_hex(rebuilt[NTPAuthenticator].dgst) == b'aabbccddeeff00112233445566778899112233445566778899aabbccddeeff00' ############ @@ -343,8 +382,9 @@ assert p.more == 0 assert p.op_code == 9 assert p.count == 15 assert p.data == b'ntp.test.2.conf' -assert p.authenticator.key_id == 1 -assert bytes_hex(p.authenticator.dgst) == b'c9fb8abe3c605ffa36d218c3b7648923' +assert p.authenticator.key_id == 0 +assert len(p.authenticator.dgst) == 20 +assert bytes_hex(p.authenticator.dgst) == b'00000001c9fb8abe3c605ffa36d218c3b7648923' = NTP Control (mode 6) - CTL_OP_SAVECONFIG (2) - response