Repository: secdev/scapy

Issue:
NTP Authenticator parsing broken for SHA MAC
#### Brief description

Parsing of NTP packet Authenticator, that uses SHA-based MAC, incorrectly identifies key id and message digest.

#### Environment

-   Scapy version: 2.4.3
-   Python version: 3.8
-   Operating System: Ubuntu/Windows

#### How to reproduce

Use NTP packet capture with NTP Version 4 packets using SHA1, SHA256, SHA512 message authentication (produced by chrony or ntpd NTP server.)
Use show() command to parse packet.

#### Actual result

###[ UDP ]###
        sport     = 42270
        dport     = ntp
        len       = 80
        chksum    = 0x731a
###[ NTPHeader ]###
           leap      = no warning
           version   = 4
           mode      = client
           stratum   = 0
           poll      = 7
           precision = 32
           delay     = 0.0
           dispersion= 0.0
           ref_id    = b''
           ref       = 0.0
           orig      = 0.0
           recv      = 0.0
           sent      = 1388821533.8530993
###[ NTPv4 extensions ]###
              \extensions\
               |###[ Raw ]###
               |  load      = '\x00\x00\x00\x0b'
              \mac       \
               |###[ Authenticator ]###
               |  padding   = None
               |  key_id    = 3452142173
               |  dgst      = bf6b7ad02886ff45aa8b2eaf7ac78bc1


#### Expected result
Key ID should be 0x0000000b (11)
Digest should be 
cdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1
This also corresponds with RFC description, Wireshark output, performed server setup, actual message digest if calculated based on RFC.

#### Related resources
Hex stream of example packets for easier import:
1. client
000c2962f268d094666d23750800450000640db640004011a519c0a80364c0a80305a51e007b0050731a2300072000000000000000000000000000000000000000000000000000000000000000000000000052c7bc1dda64b97d0000000bcdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1
2. server
d094666d2375000c29a9635908004500006428ab400040118a27c0a80302c0a80364007ba51e00508818240407e70000000700000002c0a80301e2c27398f95cc96a52c7bc1dda64b97de2c273a7eb366588e2c273a7eb391be50000000b9a6178d82b4408adfd9cab87f04ad1c92b280171




Discussion:
Thanks for reporting the issue. The problem occurs in https://github.com/secdev/scapy/blob/master/scapy/layers/ntp.py#L449

Here is howto decode the packet correctly by forcing the usage of NTPAuthenticator:
```
>>> packet = Ether(hex_bytes("000c2962f268d094666d23750800450000640db640004011a519c0a80364c0a80305a51e007b
...:0050731a2300072000000000000000000000000000000000000000000000000000000000000000000000000052c7bc1dda64b9
...:7d0000000bcdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1"))
>>> packet[NTPHeader].decode_payload_as(NTPAuthenticator)
>>> packet[NTPHeader]
<NTPHeader  leap=no warning version=4 mode=client stratum=0 poll=7 precision=32 delay=0.0 dispersion=0.0 ref_id=b'' ref=0.0 orig=0.0 recv=0.0 sent=1388821533.8530993 |<NTPAuthenticator  padding='\x00\x00\x00\x0b' key_id=3452142173 dgst=bf6b7ad02886ff45aa8b2eaf7ac78bc1 |>>
``` 

Resolving patch:
diff --git a/scapy/layers/ntp.py b/scapy/layers/ntp.py
--- a/scapy/layers/ntp.py
+++ b/scapy/layers/ntp.py
@@ -452,10 +452,10 @@ def guess_payload_class(self, payload):
         """
         plen = len(payload)
 
-        if plen > _NTP_AUTH_MD5_TAIL_SIZE:
-            return NTPExtensions
-        elif plen == _NTP_AUTH_MD5_TAIL_SIZE:
+        if plen - 4 in [16, 20, 32, 64]:  # length of MD5, SHA1, SHA256, SHA512
             return NTPAuthenticator
+        elif plen > _NTP_AUTH_MD5_TAIL_SIZE:
+            return NTPExtensions
 
         return Packet.guess_payload_class(self, payload)
 


Test patch:
diff --git a/test/regression.uts b/test/regression.uts
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -9579,6 +9579,12 @@ assert(p.version == 4)
 assert(p.mode == 3)
 assert(p.stratum == 2)
 
+= NTPAuthenticator
+
+s = hex_bytes("000c2962f268d094666d23750800450000640db640004011a519c0a80364c0a80305a51e007b0050731a2300072000000000000000000000000000000000000000000000000000000000000000000000000052c7bc1dda64b97d0000000bcdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1")
+p = Ether(s)
+assert NTPAuthenticator in p and p[NTPAuthenticator].key_id == 3452142173
+
 
 ############
 ############