1# This file is part of Scapy 2# See http://www.secdev.org/projects/scapy for more informations 3# Copyright (C) Philippe Biondi <phil@secdev.org> 4# This program is published under a GPLv2 license 5 6""" 7NTP (Network Time Protocol). 8References : RFC 5905, RC 1305, ntpd source code 9""" 10 11from __future__ import absolute_import 12import struct 13import time 14import datetime 15 16from scapy.packet import Packet, bind_layers 17from scapy.fields import (BitField, BitEnumField, ByteField, ByteEnumField, \ 18XByteField, SignedByteField, FlagsField, ShortField, LEShortField, IntField,\ 19LEIntField, FixedPointField, IPField, StrField, StrFixedLenField,\ 20StrFixedLenEnumField, XStrFixedLenField, PacketField, PacketLenField,\ 21PacketListField, FieldListField, ConditionalField, PadField) 22from scapy.layers.inet6 import IP6Field 23from scapy.layers.inet import UDP 24from scapy.utils import lhex 25from scapy.compat import * 26from scapy.config import conf 27import scapy.modules.six as six 28from scapy.modules.six.moves import range 29 30 31 32############################################################################# 33##### Constants 34############################################################################# 35 36_NTP_AUTH_MD5_MIN_SIZE = 68 37_NTP_EXT_MIN_SIZE = 16 38_NTP_HDR_WITH_EXT_MIN_SIZE = _NTP_AUTH_MD5_MIN_SIZE + _NTP_EXT_MIN_SIZE 39_NTP_AUTH_MD5_TAIL_SIZE = 20 40_NTP_AUTH_MD5_DGST_SIZE = 16 41_NTP_PRIVATE_PACKET_MIN_SIZE = 8 42 43# ntpd "Private" messages are the shortest 44_NTP_PACKET_MIN_SIZE = _NTP_PRIVATE_PACKET_MIN_SIZE 45 46_NTP_PRIVATE_REQ_PKT_TAIL_LEN = 28 47 48# seconds between 01-01-1900 and 01-01-1970 49_NTP_BASETIME = 2208988800 50 51# include/ntp.h 52_NTP_SHIFT = 8 53_NTP_HASH_SIZE = 128 54 55 56############################################################################# 57##### Fields and utilities 58############################################################################# 59 60class XLEShortField(LEShortField): 61 """ 62 XShortField which value is encoded in little endian. 63 """ 64 65 def i2repr(self, pkt, x): 66 return lhex(self.i2h(pkt, x)) 67 68 69class TimeStampField(FixedPointField): 70 """ 71 This field handles the timestamp fields in the NTP header. 72 """ 73 74 def __init__(self, name, default): 75 FixedPointField.__init__(self, name, default, 64, 32) 76 77 def i2repr(self, pkt, val): 78 if val is None: 79 return "--" 80 val = self.i2h(pkt, val) 81 if val < _NTP_BASETIME: 82 return val 83 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(val - _NTP_BASETIME)) 84 85 def any2i(self, pkt, val): 86 if isinstance(val, six.string_types): 87 val = int(time.mktime(time.strptime(val))) + _NTP_BASETIME 88 elif isinstance(val, datetime.datetime): 89 val = int(val.strftime("%s")) + _NTP_BASETIME 90 return FixedPointField.any2i(self, pkt, val) 91 92 def i2m(self, pkt, val): 93 if val is None: 94 val = FixedPointField.any2i(self, pkt, time.time() + _NTP_BASETIME) 95 return FixedPointField.i2m(self, pkt, val) 96 97 98############################################################################# 99##### NTP 100############################################################################# 101 102# RFC 5905 / Section 7.3 103_leap_indicator = { 104 0: "no warning", 105 1: "last minute of the day has 61 seconds", 106 2: "last minute of the day has 59 seconds", 107 3: "unknown (clock unsynchronized)" 108} 109 110 111# RFC 5905 / Section 7.3 112_ntp_modes = { 113 0: "reserved", 114 1: "symmetric active", 115 2: "symmetric passive", 116 3: "client", 117 4: "server", 118 5: "broadcast", 119 6: "NTP control message", 120 7: "reserved for private use" 121} 122 123 124# RFC 5905 / Section 7.3 125_reference_identifiers = { 126 "GOES": "Geosynchronous Orbit Environment Satellite", 127 "GPS ": "Global Position System", 128 "GAL ": "Galileo Positioning System", 129 "PPS ": "Generic pulse-per-second", 130 "IRIG": "Inter-Range Instrumentation Group", 131 "WWVB": "LF Radio WWVB Ft. Collins, CO 60 kHz", 132 "DCF ": "LF Radio DCF77 Mainflingen, DE 77.5 kHz", 133 "HBG ": "LF Radio HBG Prangins, HB 75 kHz", 134 "MSF ": "LF Radio MSF Anthorn, UK 60 kHz", 135 "JJY ": "LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz", 136 "LORC": "MF Radio LORAN C station, 100 kHz", 137 "TDF ": "MF Radio Allouis, FR 162 kHz", 138 "CHU ": "HF Radio CHU Ottawa, Ontario", 139 "WWV ": "HF Radio WWV Ft. Collins, CO", 140 "WWVH": "HF Radio WWVH Kauai, HI", 141 "NIST": "NIST telephone modem", 142 "ACTS": "NIST telephone modem", 143 "USNO": "USNO telephone modem", 144 "PTB ": "European telephone modem", 145} 146 147 148# RFC 5905 / Section 7.4 149_kiss_codes = { 150 "ACST": "The association belongs to a unicast server.", 151 "AUTH": "Server authentication failed.", 152 "AUTO": "Autokey sequence failed.", 153 "BCST": "The association belongs to a broadcast server.", 154 "CRYP": "Cryptographic authentication or identification failed.", 155 "DENY": "Access denied by remote server.", 156 "DROP": "Lost peer in symmetric mode.", 157 "RSTR": "Access denied due to local policy.", 158 "INIT": "The association has not yet synchronized for the first time.", 159 "MCST": "The association belongs to a dynamically discovered server.", 160 "NKEY": "No key found.", 161 "RATE": "Rate exceeded.", 162 "RMOT": "Alteration of association from a remote host running ntpdc." 163} 164 165 166# Used by _ntp_dispatcher to instantiate the appropriate class 167def _ntp_dispatcher(payload): 168 """ 169 Returns the right class for a given NTP packet. 170 """ 171 # By default, calling NTP() will build a NTP packet as defined in RFC 5905 172 # (see the code of NTPHeader). Use NTPHeader for extension fields and MAC. 173 if payload is None: 174 return NTPHeader 175 else: 176 length = len(payload) 177 if length >= _NTP_PACKET_MIN_SIZE: 178 first_byte = orb(payload[0]) 179 # Extract NTP mode 180 mode = first_byte & 7 181 return {6: NTPControl, 7: NTPPrivate}.get(mode, NTPHeader) 182 return conf.raw_layer 183 184 185class NTP(Packet): 186 """ 187 Base class that allows easier instantiation of a NTP packet from binary 188 data. 189 """ 190 191 @classmethod 192 def dispatch_hook(cls, _pkt=None, *args, **kargs): 193 """ 194 Returns the right class for the given data. 195 """ 196 197 return _ntp_dispatcher(_pkt) 198 199 def pre_dissect(self, s): 200 """ 201 Check that the payload is long enough to build a NTP packet. 202 """ 203 length = len(s) 204 if length < _NTP_PACKET_MIN_SIZE: 205 err = " ({}".format(length) + " is < _NTP_PACKET_MIN_SIZE " 206 err += "({})).".format(_NTP_PACKET_MIN_SIZE) 207 raise _NTPInvalidDataException(err) 208 return s 209 210 # NTPHeader, NTPControl and NTPPrivate are NTP packets. 211 # This might help, for example when reading a pcap file. 212 def haslayer(self, cls): 213 """Specific: NTPHeader().haslayer(NTP) should return True.""" 214 if cls == "NTP": 215 if isinstance(self, NTP): 216 return True 217 elif issubclass(cls, NTP): 218 if isinstance(self, cls): 219 return True 220 return super(NTP, self).haslayer(cls) 221 222 def getlayer(self, cls, nb=1, _track=None, _subclass=True, **flt): 223 return super(NTP, self).getlayer(cls, nb=nb, _track=_track, 224 _subclass=True, **flt) 225 226 def mysummary(self): 227 return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%") 228 229 230class _NTPAuthenticatorPaddingField(StrField): 231 """ 232 StrField handling the padding that may be found before the 233 "authenticator" field. 234 """ 235 236 def getfield(self, pkt, s): 237 ret = None 238 remain = s 239 length = len(s) 240 241 if length > _NTP_AUTH_MD5_TAIL_SIZE: 242 start = length - _NTP_AUTH_MD5_TAIL_SIZE 243 ret = s[:start] 244 remain = s[start:] 245 return remain, ret 246 247 248class NTPAuthenticator(Packet): 249 """ 250 Packet handling the "authenticator" part of a NTP packet, as 251 defined in RFC 5905. 252 """ 253 254 name = "Authenticator" 255 fields_desc = [ 256 _NTPAuthenticatorPaddingField("padding", ""), 257 IntField("key_id", 0), 258 XStrFixedLenField("dgst", "", length_from=lambda x: 16) 259 ] 260 261 def extract_padding(self, s): 262 return b"", s 263 264 265class NTPExtension(Packet): 266 """ 267 Packet handling a NTPv4 extension. 268 """ 269 270 #________________________________________________________________________ 271 # 272 # RFC 7822 273 #________________________________________________________________________ 274 # 275 # 7.5. NTP Extension Field Format 276 # 277 # In NTPv3, one or more extension fields can be inserted after the 278 # header and before the MAC, if a MAC is present. 279 # 280 # Other than defining the field format, this document makes no use 281 # of the field contents. An extension field contains a request or 282 # response message in the format shown in Figure 14. 283 # 284 # 0 1 2 3 285 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 286 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 287 # | Field Type | Length | 288 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 289 # . . 290 # . Value . 291 # . . 292 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 293 # | Padding (as needed) | 294 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 295 # 296 # Figure 14: Extension Field Format 297 # 298 # 299 # All extension fields are zero-padded to a word (four octets) 300 # boundary. 301 #________________________________________________________________________ 302 # 303 304 name = "extension" 305 fields_desc = [ 306 ShortField("type", 0), 307 ShortField("len", 0), 308 PadField(PacketField("value", "", Packet), align=4, padwith=b"\x00") 309 ] 310 311 312class NTPExtPacketListField(PacketListField): 313 314 """ 315 PacketListField handling NTPv4 extensions (NTPExtension list). 316 """ 317 318 def m2i(self, pkt, m): 319 ret = None 320 if len(m) >= 16: 321 ret = NTPExtension(m) 322 else: 323 ret = conf.raw_layer(m) 324 return ret 325 326 def getfield(self, pkt, s): 327 lst = [] 328 remain = s 329 length = len(s) 330 if length > _NTP_AUTH_MD5_TAIL_SIZE: 331 end = length - _NTP_AUTH_MD5_TAIL_SIZE 332 extensions = s[:end] 333 remain = s[end:] 334 335 extensions_len = len(extensions) 336 while extensions_len >= 16: 337 ext_len = struct.unpack("!H", extensions[2:4])[0] 338 ext_len = min(ext_len, extensions_len) 339 if ext_len < 1: 340 ext_len = extensions_len 341 current = extensions[:ext_len] 342 extensions = extensions[ext_len:] 343 current_packet = self.m2i(pkt, current) 344 lst.append(current_packet) 345 extensions_len = len(extensions) 346 347 if extensions_len > 0: 348 lst.append(self.m2i(pkt, extensions)) 349 350 return remain, lst 351 352 353class NTPExtensions(Packet): 354 """ 355 Packet handling the NTPv4 extensions and the "MAC part" of the packet. 356 """ 357 358 #________________________________________________________________________ 359 # 360 # RFC 5905 / RFC 7822 361 #________________________________________________________________________ 362 # 363 # 7.5. NTP Extension Field Format 364 # 365 # In NTPv4, one or more extension fields can be inserted after the 366 # header and before the MAC, if a MAC is present. 367 #________________________________________________________________________ 368 # 369 370 name = "NTPv4 extensions" 371 fields_desc = [ 372 NTPExtPacketListField("extensions", [], Packet), 373 PacketField("mac", NTPAuthenticator(), NTPAuthenticator) 374 ] 375 376 377class NTPHeader(NTP): 378 379 """ 380 Packet handling the RFC 5905 NTP packet. 381 """ 382 383 #________________________________________________________________________ 384 # 385 # RFC 5905 386 #________________________________________________________________________ 387 # 388 # 0 1 2 3 389 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 390 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 391 # |LI | VN |Mode | Stratum | Poll | Precision | 392 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 393 # | Root Delay | 394 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 395 # | Root Dispersion | 396 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 397 # | Reference ID | 398 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 399 # | | 400 # + Reference Timestamp (64) + 401 # | | 402 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 403 # | | 404 # + Origin Timestamp (64) + 405 # | | 406 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 407 # | | 408 # + Receive Timestamp (64) + 409 # | | 410 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 411 # | | 412 # + Transmit Timestamp (64) + 413 # | | 414 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 415 # | | 416 # . . 417 # . Extension Field 1 (variable) . 418 # . . 419 # | | 420 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 421 # | | 422 # . . 423 # . Extension Field 2 (variable) . 424 # . . 425 # | | 426 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 427 # | Key Identifier | 428 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 429 # | | 430 # | dgst (128) | 431 # | | 432 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 433 # 434 # Figure 8: Packet Header Format 435 #________________________________________________________________________ 436 # 437 438 name = "NTPHeader" 439 fields_desc = [ 440 BitEnumField("leap", 0, 2, _leap_indicator), 441 BitField("version", 4, 3), 442 BitEnumField("mode", 3, 3, _ntp_modes), 443 BitField("stratum", 2, 8), 444 BitField("poll", 0xa, 8), 445 BitField("precision", 0, 8), 446 FixedPointField("delay", 0, size=32, frac_bits=16), 447 FixedPointField("dispersion", 0, size=32, frac_bits=16), 448 ConditionalField(IPField("id", "127.0.0.1"), lambda p: p.stratum > 1), 449 ConditionalField( 450 StrFixedLenEnumField( 451 "ref_id", 452 "", 453 length=4, 454 enum=_reference_identifiers 455 ), 456 lambda p: p.stratum < 2 457 ), 458 TimeStampField("ref", 0), 459 TimeStampField("orig", None), 460 TimeStampField("recv", 0), 461 TimeStampField("sent", None), 462 ] 463 464 def guess_payload_class(self, payload): 465 """ 466 Handles NTPv4 extensions and MAC part (when authentication is used.) 467 """ 468 plen = len(payload) 469 470 if plen > _NTP_AUTH_MD5_TAIL_SIZE: 471 return NTPExtensions 472 elif plen == _NTP_AUTH_MD5_TAIL_SIZE: 473 return NTPAuthenticator 474 475 return Packet.guess_payload_class(self, payload) 476 477 478class _NTPInvalidDataException(Exception): 479 """ 480 Raised when it is not possible to instantiate a NTP packet with the 481 given data. 482 """ 483 484 def __init__(self, details): 485 Exception.__init__( 486 self, 487 "Data does not seem to be a valid NTP message" + details 488 ) 489 490 491############################################################################## 492##### Private (mode 7) 493############################################################################## 494 495# Operation codes 496_op_codes = { 497 0: "CTL_OP_UNSPEC", 498 1: "CTL_OP_READSTAT", 499 2: "CTL_OP_READVAR", 500 3: "CTL_OP_WRITEVAR", 501 4: "CTL_OP_READCLOCK", 502 5: "CTL_OP_WRITECLOCK", 503 6: "CTL_OP_SETTRAP", 504 7: "CTL_OP_ASYNCMSG", 505 8: "CTL_OP_CONFIGURE", 506 9: "CTL_OP_SAVECONFIG", 507 10: "CTL_OP_READ_MRU", 508 11: "CTL_OP_READ_ORDLIST_A", 509 12: "CTL_OP_REQ_NONCE", 510 31: "CTL_OP_UNSETTRAP" 511} 512 513 514# System status words 515_system_statuses = { 516 0: "no warning", 517 1: "last minute was 61 seconds", 518 2: "last minute was 59 seconds", 519 3: "alarm condition (clock not synchronized)" 520} 521 522 523_clock_sources = { 524 0: "unspecified or unknown", 525 1: " Calibrated atomic clock", 526 2: "VLF (band 4) or LF (band 5) radio", 527 3: "HF (band 7) radio", 528 4: "UHF (band 9) satellite", 529 5: "local net", 530 6: "UDP/NTP", 531 7: "UDP/TIME", 532 8: "eyeball-and-wristwatch", 533 9: "telephone modem" 534} 535 536 537_system_event_codes = { 538 0: "unspecified", 539 1: "system restart", 540 2: "system or hardware fault", 541 3: "system new status word (leap bits or synchronization change)", 542 4: "system new synchronization source or stratum (sys.peer or sys.stratum change)", 543 5: "system clock reset (offset correction exceeds CLOCK.MAX)", 544 6: "system invalid time or date", 545 7: "system clock exception", 546} 547 548 549# Peer status words 550_peer_statuses = { 551 0: "configured", 552 1: "authentication enabled", 553 2: "authentication okay", 554 3: "reachability okay", 555 4: "reserved" 556} 557 558 559_peer_selection = { 560 0: "rejected", 561 1: "passed sanity checks", 562 2: "passed correctness checks", 563 3: "passed candidate checks", 564 4: "passed outlyer checks", 565 5: "current synchronization source; max distance exceeded", 566 6: "current synchronization source; max distance okay", 567 7: "reserved" 568} 569 570 571_peer_event_codes = { 572 0: "unspecified", 573 1: "peer IP error", 574 2: "peer authentication failure", 575 3: "peer unreachable", 576 4: "peer reachable", 577 5: "peer clock exception", 578} 579 580 581# Clock status words 582_clock_statuses = { 583 0: "clock operating within nominals", 584 1: "reply timeout", 585 2: "bad reply format", 586 3: "hardware or software fault", 587 4: "propagation failure", 588 5: "bad date format or value", 589 6: "bad time format or value" 590} 591 592 593# Error status words 594_error_statuses = { 595 0: "unspecified", 596 1: "authentication failure", 597 2: "invalid message length or format", 598 3: "invalid opcode", 599 4: "unknown association identifier", 600 5: "unknown variable name", 601 6: "invalid variable value", 602 7: "administratively prohibited" 603} 604 605 606class NTPStatusPacket(Packet): 607 """ 608 Packet handling a non specific status word. 609 """ 610 611 name = "status" 612 fields_desc = [ShortField("status", 0)] 613 614 def extract_padding(self, s): 615 return b"", s 616 617 618class NTPSystemStatusPacket(Packet): 619 620 """ 621 Packet handling the system status fields. 622 """ 623 624 name = "system status" 625 fields_desc = [ 626 BitEnumField("leap_indicator", 0, 2, _system_statuses), 627 BitEnumField("clock_source", 0, 6, _clock_sources), 628 BitField("system_event_counter", 0, 4), 629 BitEnumField("system_event_code", 0, 4, _system_event_codes), 630 ] 631 632 def extract_padding(self, s): 633 return b"", s 634 635 636class NTPPeerStatusPacket(Packet): 637 """ 638 Packet handling the peer status fields. 639 """ 640 641 name = "peer status" 642 fields_desc = [ 643 BitField("configured", 0, 1), 644 BitField("auth_enabled", 0, 1), 645 BitField("authentic", 0, 1), 646 BitField("reachability", 0, 1), 647 BitField("reserved", 0, 1), 648 BitEnumField("peer_sel", 0, 3, _peer_selection), 649 BitField("peer_event_counter", 0, 4), 650 BitEnumField("peer_event_code", 0, 4, _peer_event_codes), 651 ] 652 653 def extract_padding(self, s): 654 return b"", s 655 656 657class NTPClockStatusPacket(Packet): 658 """ 659 Packet handling the clock status fields. 660 """ 661 662 name = "clock status" 663 fields_desc = [ 664 BitEnumField("clock_status", 0, 8, _clock_statuses), 665 BitField("code", 0, 8) 666 ] 667 668 def extract_padding(self, s): 669 return b"", s 670 671 672class NTPErrorStatusPacket(Packet): 673 """ 674 Packet handling the error status fields. 675 """ 676 677 name = "error status" 678 fields_desc = [ 679 BitEnumField("error_code", 0, 8, _error_statuses), 680 BitField("reserved", 0, 8) 681 ] 682 683 def extract_padding(self, s): 684 return b"", s 685 686 687class NTPControlStatusField(PacketField): 688 """ 689 This field provides better readability for the "status" field. 690 """ 691 692 #________________________________________________________________________ 693 # 694 # RFC 1305 695 #________________________________________________________________________ 696 # 697 # Appendix B.3. Commands // ntpd source code: ntp_control.h 698 #________________________________________________________________________ 699 # 700 701 def m2i(self, pkt, m): 702 ret = None 703 association_id = struct.unpack("!H", m[2:4])[0] 704 705 if pkt.err == 1: 706 ret = NTPErrorStatusPacket(m) 707 708 # op_code == CTL_OP_READSTAT 709 elif pkt.op_code == 1: 710 if association_id != 0: 711 ret = NTPPeerStatusPacket(m) 712 else: 713 ret = NTPSystemStatusPacket(m) 714 715 # op_code == CTL_OP_READVAR 716 elif pkt.op_code == 2: 717 if association_id != 0: 718 ret = NTPPeerStatusPacket(m) 719 else: 720 ret = NTPSystemStatusPacket(m) 721 722 # op_code == CTL_OP_WRITEVAR 723 elif pkt.op_code == 3: 724 ret = NTPStatusPacket(m) 725 726 # op_code == CTL_OP_READCLOCK or op_code == CTL_OP_WRITECLOCK 727 elif pkt.op_code == 4 or pkt.op_code == 5: 728 ret = NTPClockStatusPacket(m) 729 730 else: 731 ret = NTPStatusPacket(m) 732 733 return ret 734 735 736class NTPPeerStatusDataPacket(Packet): 737 """ 738 Packet handling the data field when op_code is CTL_OP_READSTAT 739 and the association_id field is null. 740 """ 741 742 name = "data / peer status" 743 fields_desc = [ 744 ShortField("association_id", 0), 745 PacketField("peer_status", NTPPeerStatusPacket(), NTPPeerStatusPacket), 746 ] 747 748 749class NTPControlDataPacketLenField(PacketLenField): 750 751 """ 752 PacketField handling the "data" field of NTP control messages. 753 """ 754 755 def m2i(self, pkt, m): 756 ret = None 757 758 # op_code == CTL_OP_READSTAT 759 if pkt.op_code == 1: 760 if pkt.association_id == 0: 761 # Data contains association ID and peer status 762 ret = NTPPeerStatusDataPacket(m) 763 else: 764 ret = conf.raw_layer(m) 765 else: 766 ret = conf.raw_layer(m) 767 768 return ret 769 770 def getfield(self, pkt, s): 771 length = self.length_from(pkt) 772 i = None 773 if length > 0: 774 # RFC 1305 775 # The maximum number of data octets is 468. 776 # 777 # include/ntp_control.h 778 # u_char data[480 + MAX_MAC_LEN]; /* data + auth */ 779 # 780 # Set the minimum length to 480 - 468 781 length = max(12, length) 782 if length % 4: 783 length += (4 - length % 4) 784 try: 785 i = self.m2i(pkt, s[:length]) 786 except Exception: 787 if conf.debug_dissector: 788 raise 789 i = conf.raw_layer(load=s[:length]) 790 return s[length:], i 791 792 793class NTPControl(NTP): 794 """ 795 Packet handling NTP mode 6 / "Control" messages. 796 """ 797 798 #________________________________________________________________________ 799 # 800 # RFC 1305 801 #________________________________________________________________________ 802 # 803 # Appendix B.3. Commands // ntpd source code: ntp_control.h 804 #________________________________________________________________________ 805 # 806 807 name = "Control message" 808 fields_desc = [ 809 BitField("zeros", 0, 2), 810 BitField("version", 2, 3), 811 BitField("mode", 6, 3), 812 BitField("response", 0, 1), 813 BitField("err", 0, 1), 814 BitField("more", 0, 1), 815 BitEnumField("op_code", 0, 5, _op_codes), 816 ShortField("sequence", 0), 817 ConditionalField(NTPControlStatusField( 818 "status_word", "", Packet), lambda p: p.response == 1), 819 ConditionalField(ShortField("status", 0), lambda p: p.response == 0), 820 ShortField("association_id", 0), 821 ShortField("offset", 0), 822 ShortField("count", None), 823 NTPControlDataPacketLenField( 824 "data", "", Packet, length_from=lambda p: p.count), 825 PacketField("authenticator", "", NTPAuthenticator), 826 ] 827 828 def post_build(self, p, pay): 829 if self.count is None: 830 length = 0 831 if self.data: 832 length = len(self.data) 833 p = p[:11] + struct.pack("!H", length) + p[13:] 834 return p + pay 835 836 837############################################################################## 838##### Private (mode 7) 839############################################################################## 840 841_information_error_codes = { 842 0: "INFO_OKAY", 843 1: "INFO_ERR_IMPL", 844 2: "INFO_ERR_REQ", 845 3: "INFO_ERR_FMT", 846 4: "INFO_ERR_NODATA", 847 7: "INFO_ERR_AUTH" 848} 849 850 851_implementations = { 852 0: "IMPL_UNIV", 853 2: "IMPL_XNTPD_OLD", 854 3: "XNTPD" 855} 856 857 858_request_codes = { 859 0: "REQ_PEER_LIST", 860 1: "REQ_PEER_LIST_SUM", 861 2: "REQ_PEER_INFO", 862 3: "REQ_PEER_STATS", 863 4: "REQ_SYS_INFO", 864 5: "REQ_SYS_STATS", 865 6: "REQ_IO_STATS", 866 7: "REQ_MEM_STATS", 867 8: "REQ_LOOP_INFO", 868 9: "REQ_TIMER_STATS", 869 10: "REQ_CONFIG", 870 11: "REQ_UNCONFIG", 871 12: "REQ_SET_SYS_FLAG", 872 13: "REQ_CLR_SYS_FLAG", 873 14: "REQ_MONITOR", 874 15: "REQ_NOMONITOR", 875 16: "REQ_GET_RESTRICT", 876 17: "REQ_RESADDFLAGS", 877 18: "REQ_RESSUBFLAGS", 878 19: "REQ_UNRESTRICT", 879 20: "REQ_MON_GETLIST", 880 21: "REQ_RESET_STATS", 881 22: "REQ_RESET_PEER", 882 23: "REQ_REREAD_KEYS", 883 24: "REQ_DO_DIRTY_HACK", 884 25: "REQ_DONT_DIRTY_HACK", 885 26: "REQ_TRUSTKEY", 886 27: "REQ_UNTRUSTKEY", 887 28: "REQ_AUTHINFO", 888 29: "REQ_TRAPS", 889 30: "REQ_ADD_TRAP", 890 31: "REQ_CLR_TRAP", 891 32: "REQ_REQUEST_KEY", 892 33: "REQ_CONTROL_KEY", 893 34: "REQ_GET_CTLSTATS", 894 35: "REQ_GET_LEAPINFO", 895 36: "REQ_GET_CLOCKINFO", 896 37: "REQ_SET_CLKFUDGE", 897 38: "REQ_GET_KERNEL", 898 39: "REQ_GET_CLKBUGINFO", 899 41: "REQ_SET_PRECISION", 900 42: "REQ_MON_GETLIST_1", 901 43: "REQ_HOSTNAME_ASSOCID", 902 44: "REQ_IF_STATS", 903 45: "REQ_IF_RELOAD" 904} 905 906 907# Flags in the peer information returns 908_peer_flags = [ 909 "INFO_FLAG_CONFIG", 910 "INFO_FLAG_SYSPEER", 911 "INFO_FLAG_BURST", 912 "INFO_FLAG_REFCLOCK", 913 "INFO_FLAG_PREFER", 914 "INFO_FLAG_AUTHENABLE", 915 "INFO_FLAG_SEL_CANDIDATE", 916 "INFO_FLAG_SHORTLIST", 917 "INFO_FLAG_IBURST" 918] 919 920 921# Flags in the system information returns 922_sys_info_flags = [ 923 "INFO_FLAG_BCLIENT", 924 "INFO_FLAG_AUTHENTICATE", 925 "INFO_FLAG_NTP", 926 "INFO_FLAG_KERNEL", 927 "INFO_FLAG_CAL", 928 "INFO_FLAG_PPS_SYNC", 929 "INFO_FLAG_MONITOR", 930 "INFO_FLAG_FILEGEN", 931] 932 933 934class NTPInfoPeerList(Packet): 935 936 """ 937 Used to return raw lists of peers. 938 """ 939 name = "info_peer_list" 940 fields_desc = [ 941 IPField("addr", "0.0.0.0"), 942 ShortField("port", 0), 943 ByteEnumField("hmode", 0, _ntp_modes), 944 FlagsField("flags", 0, 8, _peer_flags), 945 IntField("v6_flag", 0), 946 IntField("unused1", 0), 947 IP6Field("addr6", "::") 948 ] 949 950 951class NTPInfoPeerSummary(Packet): 952 """ 953 Sort of the info that ntpdc returns by default. 954 """ 955 name = "info_peer_summary" 956 fields_desc = [ 957 IPField("dstaddr", "0.0.0.0"), 958 IPField("srcaddr", "0.0.0.0"), 959 ShortField("srcport", 0), 960 ByteField("stratum", 0), 961 ByteField("hpoll", 0), 962 ByteField("ppoll", 0), 963 ByteField("reach", 0), 964 FlagsField("flags", 0, 8, _peer_flags), 965 ByteField("hmode", _ntp_modes), 966 FixedPointField("delay", 0, size=32, frac_bits=16), 967 TimeStampField("offset", 0), 968 FixedPointField("dispersion", 0, size=32, frac_bits=16), 969 IntField("v6_flag", 0), 970 IntField("unused1", 0), 971 IP6Field("dstaddr6", "::"), 972 IP6Field("srcaddr6", "::") 973 ] 974 975 976class NTPInfoPeer(Packet): 977 """ 978 Peer information structure. 979 """ 980 981 name = "info_peer" 982 fields_desc = [ 983 IPField("dstaddr", "0.0.0.0"), 984 IPField("srcaddr", "0.0.0.0"), 985 ShortField("srcport", 0), 986 FlagsField("flags", 0, 8, _peer_flags), 987 ByteField("leap", 0), 988 ByteEnumField("hmode", 0, _ntp_modes), 989 ByteField("pmode", 0), 990 ByteField("stratum", 0), 991 ByteField("ppoll", 0), 992 ByteField("hpoll", 0), 993 SignedByteField("precision", 0), 994 ByteField("version", 0), 995 ByteField("unused8", 0), 996 ByteField("reach", 0), 997 ByteField("unreach", 0), 998 XByteField("flash", 0), 999 ByteField("ttl", 0), 1000 XLEShortField("flash2", 0), 1001 ShortField("associd", 0), 1002 LEIntField("keyid", 0), 1003 IntField("pkeyid", 0), 1004 IPField("refid", 0), 1005 IntField("timer", 0), 1006 FixedPointField("rootdelay", 0, size=32, frac_bits=16), 1007 FixedPointField("rootdispersion", 0, size=32, frac_bits=16), 1008 TimeStampField("reftime", 0), 1009 TimeStampField("org", 0), 1010 TimeStampField("rec", 0), 1011 TimeStampField("xmt", 0), 1012 FieldListField( 1013 "filtdelay", 1014 [0.0 for i in range(0, _NTP_SHIFT)], 1015 FixedPointField("", 0, size=32, frac_bits=16), 1016 count_from=lambda p: _NTP_SHIFT 1017 ), 1018 FieldListField( 1019 "filtoffset", 1020 [0.0 for i in range(0, _NTP_SHIFT)], 1021 TimeStampField("", 0), 1022 count_from=lambda p: _NTP_SHIFT 1023 ), 1024 FieldListField( 1025 "order", 1026 [0 for i in range(0, _NTP_SHIFT)], 1027 ByteField("", 0), 1028 count_from=lambda p: _NTP_SHIFT 1029 ), 1030 FixedPointField("delay", 0, size=32, frac_bits=16), 1031 FixedPointField("dispersion", 0, size=32, frac_bits=16), 1032 TimeStampField("offset", 0), 1033 FixedPointField("selectdisp", 0, size=32, frac_bits=16), 1034 IntField("unused1", 0), 1035 IntField("unused2", 0), 1036 IntField("unused3", 0), 1037 IntField("unused4", 0), 1038 IntField("unused5", 0), 1039 IntField("unused6", 0), 1040 IntField("unused7", 0), 1041 FixedPointField("estbdelay", 0, size=32, frac_bits=16), 1042 IntField("v6_flag", 0), 1043 IntField("unused9", 0), 1044 IP6Field("dstaddr6", "::"), 1045 IP6Field("srcaddr6", "::"), 1046 ] 1047 1048 1049class NTPInfoPeerStats(Packet): 1050 """ 1051 Peer statistics structure. 1052 """ 1053 1054 name = "info_peer_stats" 1055 fields_desc = [ 1056 IPField("dstaddr", "0.0.0.0"), 1057 IPField("srcaddr", "0.0.0.0"), 1058 ShortField("srcport", 0), 1059 FlagsField("flags", 0, 16, _peer_flags), 1060 IntField("timereset", 0), 1061 IntField("timereceived", 0), 1062 IntField("timetosend", 0), 1063 IntField("timereachable", 0), 1064 IntField("sent", 0), 1065 IntField("unused1", 0), 1066 IntField("processed", 0), 1067 IntField("unused2", 0), 1068 IntField("badauth", 0), 1069 IntField("bogusorg", 0), 1070 IntField("oldpkt", 0), 1071 IntField("unused3", 0), 1072 IntField("unused4", 0), 1073 IntField("seldisp", 0), 1074 IntField("selbroken", 0), 1075 IntField("unused5", 0), 1076 ByteField("candidate", 0), 1077 ByteField("unused6", 0), 1078 ByteField("unused7", 0), 1079 ByteField("unused8", 0), 1080 IntField("v6_flag", 0), 1081 IntField("unused9", 0), 1082 IP6Field("dstaddr6", "::"), 1083 IP6Field("srcaddr6", "::"), 1084 ] 1085 1086 1087class NTPInfoLoop(Packet): 1088 """ 1089 Loop filter variables. 1090 """ 1091 1092 name = "info_loop" 1093 fields_desc = [ 1094 TimeStampField("last_offset", 0), 1095 TimeStampField("drift_comp", 0), 1096 IntField("compliance", 0), 1097 IntField("watchdog_timer", 0) 1098 ] 1099 1100 1101class NTPInfoSys(Packet): 1102 """ 1103 System info. Mostly the sys.* variables, plus a few unique to 1104 the implementation. 1105 """ 1106 1107 name = "info_sys" 1108 fields_desc = [ 1109 IPField("peer", "0.0.0.0"), 1110 ByteField("peer_mode", 0), 1111 ByteField("leap", 0), 1112 ByteField("stratum", 0), 1113 ByteField("precision", 0), 1114 FixedPointField("rootdelay", 0, size=32, frac_bits=16), 1115 FixedPointField("rootdispersion", 0, size=32, frac_bits=16), 1116 IPField("refid", 0), 1117 TimeStampField("reftime", 0), 1118 IntField("poll", 0), 1119 FlagsField("flags", 0, 8, _sys_info_flags), 1120 ByteField("unused1", 0), 1121 ByteField("unused2", 0), 1122 ByteField("unused3", 0), 1123 FixedPointField("bdelay", 0, size=32, frac_bits=16), 1124 FixedPointField("frequency", 0, size=32, frac_bits=16), 1125 TimeStampField("authdelay", 0), 1126 FixedPointField("stability", 0, size=32, frac_bits=16), 1127 IntField("v6_flag", 0), 1128 IntField("unused4", 0), 1129 IP6Field("peer6", "::") 1130 ] 1131 1132 1133class NTPInfoSysStats(Packet): 1134 """ 1135 System stats. These are collected in the protocol module. 1136 """ 1137 1138 name = "info_sys_stats" 1139 fields_desc = [ 1140 IntField("timeup", 0), 1141 IntField("timereset", 0), 1142 IntField("denied", 0), 1143 IntField("oldversionpkt", 0), 1144 IntField("newversionpkt", 0), 1145 IntField("unknownversion", 0), 1146 IntField("badlength", 0), 1147 IntField("processed", 0), 1148 IntField("badauth", 0), 1149 IntField("received", 0), 1150 IntField("limitrejected", 0) 1151 ] 1152 1153 1154class NTPInfoMemStats(Packet): 1155 """ 1156 Peer memory statistics. 1157 """ 1158 1159 name = "info_mem_stats" 1160 fields_desc = [ 1161 IntField("timereset", 0), 1162 ShortField("totalpeermem", 0), 1163 ShortField("freepeermem", 0), 1164 IntField("findpeer_calls", 0), 1165 IntField("allocations", 0), 1166 IntField("demobilizations", 0), 1167 FieldListField( 1168 "hashcount", 1169 [0.0 for i in range(0, _NTP_HASH_SIZE)], 1170 ByteField("", 0), 1171 count_from=lambda p: _NTP_HASH_SIZE 1172 ) 1173 ] 1174 1175 1176class NTPInfoIOStats(Packet): 1177 """ 1178 I/O statistics. 1179 """ 1180 1181 name = "info_io_stats" 1182 fields_desc = [ 1183 IntField("timereset", 0), 1184 ShortField("totalrecvbufs", 0), 1185 ShortField("freerecvbufs", 0), 1186 ShortField("fullrecvbufs", 0), 1187 ShortField("lowwater", 0), 1188 IntField("dropped", 0), 1189 IntField("ignored", 0), 1190 IntField("received", 0), 1191 IntField("sent", 0), 1192 IntField("notsent", 0), 1193 IntField("interrupts", 0), 1194 IntField("int_received", 0) 1195 ] 1196 1197 1198class NTPInfoTimerStats(Packet): 1199 """ 1200 Timer stats. 1201 """ 1202 1203 name = "info_timer_stats" 1204 fields_desc = [ 1205 IntField("timereset", 0), 1206 IntField("alarms", 0), 1207 IntField("overflows", 0), 1208 IntField("xmtcalls", 0), 1209 ] 1210 1211 1212_conf_peer_flags = [ 1213 "CONF_FLAG_AUTHENABLE", 1214 "CONF_FLAG_PREFER", 1215 "CONF_FLAG_BURST", 1216 "CONF_FLAG_IBURST", 1217 "CONF_FLAG_NOSELECT", 1218 "CONF_FLAG_SKEY" 1219] 1220 1221 1222class NTPConfPeer(Packet): 1223 """ 1224 Structure for passing peer configuration information. 1225 """ 1226 1227 name = "conf_peer" 1228 fields_desc = [ 1229 IPField("peeraddr", "0.0.0.0"), 1230 ByteField("hmode", 0), 1231 ByteField("version", 0), 1232 ByteField("minpoll", 0), 1233 ByteField("maxpoll", 0), 1234 FlagsField("flags", 0, 8, _conf_peer_flags), 1235 ByteField("ttl", 0), 1236 ShortField("unused1", 0), 1237 IntField("keyid", 0), 1238 StrFixedLenField("keystr", "", length=128), 1239 IntField("v6_flag", 0), 1240 IntField("unused2", 0), 1241 IP6Field("peeraddr6", "::") 1242 ] 1243 1244 1245class NTPConfUnpeer(Packet): 1246 """ 1247 Structure for passing peer deletion information. 1248 """ 1249 1250 name = "conf_unpeer" 1251 fields_desc = [ 1252 IPField("peeraddr", "0.0.0.0"), 1253 IntField("v6_flag", 0), 1254 IP6Field("peeraddr6", "::") 1255 ] 1256 1257 1258_restrict_flags = [ 1259 "RES_IGNORE", 1260 "RES_DONTSERVE", 1261 "RES_DONTTRUST", 1262 "RES_VERSION", 1263 "RES_NOPEER", 1264 "RES_LIMITED", 1265 "RES_NOQUERY", 1266 "RES_NOMODIFY", 1267 "RES_NOTRAP", 1268 "RES_LPTRAP", 1269 "RES_KOD", 1270 "RES_MSSNTP", 1271 "RES_FLAKE", 1272 "RES_NOMRULIST", 1273] 1274 1275 1276class NTPConfRestrict(Packet): 1277 """ 1278 Structure used for specifying restrict entries. 1279 """ 1280 1281 name = "conf_restrict" 1282 fields_desc = [ 1283 IPField("addr", "0.0.0.0"), 1284 IPField("mask", "0.0.0.0"), 1285 FlagsField("flags", 0, 16, _restrict_flags), 1286 ShortField("m_flags", 0), 1287 IntField("v6_flag", 0), 1288 IP6Field("addr6", "::"), 1289 IP6Field("mask6", "::") 1290 ] 1291 1292 1293class NTPInfoKernel(Packet): 1294 """ 1295 Structure used for returning kernel pll/PPS information 1296 """ 1297 1298 name = "info_kernel" 1299 fields_desc = [ 1300 IntField("offset", 0), 1301 IntField("freq", 0), 1302 IntField("maxerror", 0), 1303 IntField("esterror", 0), 1304 ShortField("status", 0), 1305 ShortField("shift", 0), 1306 IntField("constant", 0), 1307 IntField("precision", 0), 1308 IntField("tolerance", 0), 1309 IntField("ppsfreq", 0), 1310 IntField("jitter", 0), 1311 IntField("stabil", 0), 1312 IntField("jitcnt", 0), 1313 IntField("calcnt", 0), 1314 IntField("errcnt", 0), 1315 IntField("stbcnt", 0), 1316 ] 1317 1318 1319class NTPInfoIfStatsIPv4(Packet): 1320 """ 1321 Interface statistics. 1322 """ 1323 1324 name = "info_if_stats" 1325 fields_desc = [ 1326 PadField(IPField("unaddr", "0.0.0.0"), 16, padwith=b"\x00"), 1327 PadField(IPField("unbcast", "0.0.0.0"), 16, padwith=b"\x00"), 1328 PadField(IPField("unmask", "0.0.0.0"), 16, padwith=b"\x00"), 1329 IntField("v6_flag", 0), 1330 StrFixedLenField("ifname", "", length=32), 1331 IntField("flags", 0), 1332 IntField("last_ttl", 0), 1333 IntField("num_mcast", 0), 1334 IntField("received", 0), 1335 IntField("sent", 0), 1336 IntField("notsent", 0), 1337 IntField("uptime", 0), 1338 IntField("scopeid", 0), 1339 IntField("ifindex", 0), 1340 IntField("ifnum", 0), 1341 IntField("peercnt", 0), 1342 ShortField("family", 0), 1343 ByteField("ignore_packets", 0), 1344 ByteField("action", 0), 1345 IntField("_filler0", 0) 1346 ] 1347 1348 1349class NTPInfoIfStatsIPv6(Packet): 1350 """ 1351 Interface statistics. 1352 """ 1353 1354 name = "info_if_stats" 1355 fields_desc = [ 1356 IP6Field("unaddr", "::"), 1357 IP6Field("unbcast", "::"), 1358 IP6Field("unmask", "::"), 1359 IntField("v6_flag", 0), 1360 StrFixedLenField("ifname", "", length=32), 1361 IntField("flags", 0), 1362 IntField("last_ttl", 0), 1363 IntField("num_mcast", 0), 1364 IntField("received", 0), 1365 IntField("sent", 0), 1366 IntField("notsent", 0), 1367 IntField("uptime", 0), 1368 IntField("scopeid", 0), 1369 IntField("ifindex", 0), 1370 IntField("ifnum", 0), 1371 IntField("peercnt", 0), 1372 ShortField("family", 0), 1373 ByteField("ignore_packets", 0), 1374 ByteField("action", 0), 1375 IntField("_filler0", 0) 1376 ] 1377 1378 1379class NTPInfoMonitor1(Packet): 1380 """ 1381 Structure used for returning monitor data. 1382 """ 1383 1384 name = "InfoMonitor1" 1385 fields_desc = [ 1386 IntField("lasttime", 0), 1387 IntField("firsttime", 0), 1388 IntField("lastdrop", 0), 1389 IntField("count", 0), 1390 IPField("addr", "0.0.0.0"), 1391 IPField("daddr", "0.0.0.0"), 1392 IntField("flags", 0), 1393 ShortField("port", 0), 1394 ByteField("mode", 0), 1395 ByteField("version", 0), 1396 IntField("v6_flag", 0), 1397 IntField("unused1", 0), 1398 IP6Field("addr6", "::"), 1399 IP6Field("daddr6", "::") 1400 ] 1401 1402 1403class NTPInfoAuth(Packet): 1404 """ 1405 Structure used to return information concerning the authentication module. 1406 """ 1407 1408 name = "info_auth" 1409 fields_desc = [ 1410 IntField("timereset", 0), 1411 IntField("numkeys", 0), 1412 IntField("numfreekeys", 0), 1413 IntField("keylookups", 0), 1414 IntField("keynotfound", 0), 1415 IntField("encryptions", 0), 1416 IntField("decryptions", 0), 1417 IntField("expired", 0), 1418 IntField("keyuncached", 0), 1419 ] 1420 1421 1422class NTPConfTrap(Packet): 1423 """ 1424 Structure used to pass add/clear trap information to the client 1425 """ 1426 1427 name = "conf_trap" 1428 fields_desc = [ 1429 IPField("local_address", "0.0.0.0"), 1430 IPField("trap_address", "0.0.0.0"), 1431 ShortField("trap_port", 0), 1432 ShortField("unused", 0), 1433 IntField("v6_flag", 0), 1434 IP6Field("local_address6", "::"), 1435 IP6Field("trap_address6", "::"), 1436 ] 1437 1438 1439class NTPInfoControl(Packet): 1440 """ 1441 Structure used to return statistics from the control module. 1442 """ 1443 1444 name = "info_control" 1445 fields_desc = [ 1446 IntField("ctltimereset", 0), 1447 IntField("numctlreq", 0), 1448 IntField("numctlbadpkts", 0), 1449 IntField("numctlresponses", 0), 1450 IntField("numctlfrags", 0), 1451 IntField("numctlerrors", 0), 1452 IntField("numctltooshort", 0), 1453 IntField("numctlinputresp", 0), 1454 IntField("numctlinputfrag", 0), 1455 IntField("numctlinputerr", 0), 1456 IntField("numctlbadoffset", 0), 1457 IntField("numctlbadversion", 0), 1458 IntField("numctldatatooshort", 0), 1459 IntField("numctlbadop", 0), 1460 IntField("numasyncmsgs", 0), 1461 ] 1462 1463 1464# ntp_request.h 1465_ntpd_private_errors = { 1466 0: "no error", 1467 1: "incompatible implementation number", 1468 2: "unimplemented request code", 1469 3: "format error (wrong data items, data size, packet size etc.)", 1470 4: "no data available (e.g. request for details on unknown peer)", 1471 5: "I don\"t know", 1472 6: "I don\"t know", 1473 7: "authentication failure (i.e. permission denied)", 1474} 1475 1476 1477# dict mapping request codes to the right response data class 1478_private_data_objects = { 1479 0: NTPInfoPeerList, # "REQ_PEER_LIST", 1480 1: NTPInfoPeerSummary, # "REQ_PEER_LIST_SUM", 1481 2: NTPInfoPeer, # "REQ_PEER_INFO", 1482 3: NTPInfoPeerStats, # "REQ_PEER_STATS", 1483 4: NTPInfoSys, # "REQ_SYS_INFO", 1484 5: NTPInfoSysStats, # "REQ_SYS_STATS", 1485 6: NTPInfoIOStats, # "REQ_IO_STATS", 1486 7: NTPInfoMemStats, # "REQ_MEM_STATS", 1487 8: NTPInfoLoop, # "REQ_LOOP_INFO", 1488 9: NTPInfoTimerStats, # "REQ_TIMER_STATS", 1489 10: NTPConfPeer, # "REQ_CONFIG", 1490 11: NTPConfUnpeer, # "REQ_UNCONFIG", 1491 28: NTPInfoAuth, # "REQ_AUTHINFO", 1492 30: NTPConfTrap, # "REQ_ADD_TRAP", 1493 34: NTPInfoControl, # "REQ_GET_CTLSTATS", 1494 38: NTPInfoKernel, # "REQ_GET_KERNEL", 1495 42: NTPInfoMonitor1, # "REQ_MON_GETLIST_1", 1496} 1497 1498 1499class NTPPrivateRespPacketListField(PacketListField): 1500 """ 1501 PacketListField handling the response data. 1502 """ 1503 1504 def m2i(self, pkt, s): 1505 ret = None 1506 1507 # info_if_stats 1508 if pkt.request_code == 44 or pkt.request_code == 45: 1509 is_v6 = struct.unpack("!I", s[48:52])[0] 1510 ret = NTPInfoIfStatsIPv6(s) if is_v6 else NTPInfoIfStatsIPv4(s) 1511 else: 1512 ret = _private_data_objects.get(pkt.request_code, conf.raw_layer)(s) 1513 1514 return ret 1515 1516 def getfield(self, pkt, s): 1517 lst = [] 1518 remain = s 1519 length = pkt.data_item_size 1520 if length > 0: 1521 item_counter = 0 1522 # Response payloads can be placed in several packets 1523 while len(remain) >= pkt.data_item_size and item_counter < pkt.nb_items: 1524 current = remain[:length] 1525 remain = remain[length:] 1526 current_packet = self.m2i(pkt, current) 1527 lst.append(current_packet) 1528 item_counter += 1 1529 1530 return remain, lst 1531 1532 1533class NTPPrivateReqPacket(Packet): 1534 """ 1535 Packet handling request data. 1536 """ 1537 1538 name = "request data" 1539 fields_desc = [StrField("req_data", "")] 1540 1541 1542_request_codes = { 1543 0: "REQ_PEER_LIST", 1544 1: "REQ_PEER_LIST_SUM", 1545 2: "REQ_PEER_INFO", 1546 3: "REQ_PEER_STATS", 1547 4: "REQ_SYS_INFO", 1548 5: "REQ_SYS_STATS", 1549 6: "REQ_IO_STATS", 1550 7: "REQ_MEM_STATS", 1551 8: "REQ_LOOP_INFO", 1552 9: "REQ_TIMER_STATS", 1553 10: "REQ_CONFIG", 1554 11: "REQ_UNCONFIG", 1555 12: "REQ_SET_SYS_FLAG", 1556 13: "REQ_CLR_SYS_FLAG", 1557 14: "REQ_MONITOR", 1558 15: "REQ_NOMONITOR", 1559 16: "REQ_GET_RESTRICT", 1560 17: "REQ_RESADDFLAGS", 1561 18: "REQ_RESSUBFLAGS", 1562 19: "REQ_UNRESTRICT", 1563 20: "REQ_MON_GETLIST", 1564 21: "REQ_RESET_STATS", 1565 22: "REQ_RESET_PEER", 1566 23: "REQ_REREAD_KEYS", 1567 24: "REQ_DO_DIRTY_HACK", 1568 25: "REQ_DONT_DIRTY_HACK", 1569 26: "REQ_TRUSTKEY", 1570 27: "REQ_UNTRUSTKEY", 1571 28: "REQ_AUTHINFO", 1572 29: "REQ_TRAPS", 1573 30: "REQ_ADD_TRAP", 1574 31: "REQ_CLR_TRAP", 1575 32: "REQ_REQUEST_KEY", 1576 33: "REQ_CONTROL_KEY", 1577 34: "REQ_GET_CTLSTATS", 1578 35: "REQ_GET_LEAPINFO", 1579 36: "REQ_GET_CLOCKINFO", 1580 37: "REQ_SET_CLKFUDGE", 1581 38: "REQ_GET_KERNEL", 1582 39: "REQ_GET_CLKBUGINFO", 1583 41: "REQ_SET_PRECISION", 1584 42: "REQ_MON_GETLIST_1", 1585 43: "REQ_HOSTNAME_ASSOCID", 1586 44: "REQ_IF_STATS", 1587 45: "REQ_IF_RELOAD" 1588} 1589 1590 1591class NTPPrivateReqPacketListField(PacketListField): 1592 """ 1593 Handles specific request packets. 1594 """ 1595 1596 # See ntpdc/ntpdc.c and ntpdc/ntpdc_ops.c 1597 1598 def m2i(self, pkt, s): 1599 ret = None 1600 1601 if pkt.request_code == 2 or pkt.request_code == 3: 1602 # REQ_PEER_INFO (see ntpdc/ntpdc_ops.c: showpeer()) 1603 # REQ_PEER_STATS (for request only) 1604 ret = NTPInfoPeerList(s) 1605 1606 elif pkt.request_code == 10: 1607 # REQ_CONFIG 1608 ret = NTPConfPeer(s) 1609 1610 elif pkt.request_code == 11: 1611 # REQ_CONFIG 1612 ret = NTPConfUnpeer(s) 1613 1614 elif pkt.request_code == 17: 1615 # REQ_RESADDFLAGS 1616 ret = NTPConfRestrict(s) 1617 1618 elif pkt.request_code == 18: 1619 # REQ_RESSUBFLAGS 1620 ret = NTPConfRestrict(s) 1621 1622 elif pkt.request_code == 22: 1623 # REQ_RESET_PEER 1624 ret = NTPConfUnpeer(s) 1625 1626 elif pkt.request_code == 30 or pkt.request_code == 31: 1627 # REQ_ADD_TRAP 1628 ret = NTPConfTrap(s) 1629 1630 else: 1631 ret = NTPPrivateReqPacket(s) 1632 1633 return ret 1634 1635 def getfield(self, pkt, s): 1636 lst = [] 1637 remain = s 1638 length = pkt.data_item_size 1639 if length > 0: 1640 item_counter = 0 1641 while len(remain) >= pkt.data_item_size * pkt.nb_items and item_counter < pkt.nb_items: 1642 current = remain[:length] 1643 remain = remain[length:] 1644 current_packet = self.m2i(pkt, current) 1645 lst.append(current_packet) 1646 item_counter += 1 1647 1648 # If "auth" bit is set, don't forget the padding bytes 1649 if pkt.auth: 1650 padding_end = len(remain) - _NTP_PRIVATE_REQ_PKT_TAIL_LEN 1651 current_packet = conf.raw_layer(remain[:padding_end]) 1652 lst.append(current_packet) 1653 remain = remain[padding_end:] 1654 1655 return remain, lst 1656 1657 1658class NTPPrivatePktTail(Packet): 1659 """ 1660 include/ntp_request.h 1661 The req_pkt_tail structure is used by ntpd to adjust for different 1662 packet sizes that may arrive. 1663 """ 1664 1665 name = "req_pkt_tail" 1666 fields_desc = [ 1667 TimeStampField("tstamp", 0), 1668 IntField("key_id", 0), 1669 XStrFixedLenField( 1670 "dgst", "", length_from=lambda x: _NTP_AUTH_MD5_DGST_SIZE) 1671 ] 1672 1673 1674class NTPPrivate(NTP): 1675 """ 1676 Packet handling the private (mode 7) messages. 1677 """ 1678 1679 #________________________________________________________________________ 1680 # 1681 # ntpd source code: ntp_request.h 1682 #________________________________________________________________________ 1683 # 1684 # A mode 7 packet is used exchanging data between an NTP server 1685 # and a client for purposes other than time synchronization, e.g. 1686 # monitoring, statistics gathering and configuration. A mode 7 1687 # packet has the following format: 1688 # 1689 # 0 1 2 3 1690 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1691 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1692 # |R|M| VN | Mode|A| Sequence | Implementation| Req Code | 1693 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1694 # | Err | Number of data items | MBZ | Size of data item | 1695 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1696 # | | 1697 # | Data (Minimum 0 octets, maximum 500 octets) | 1698 # | | 1699 # [...] | 1700 # | | 1701 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1702 # | Encryption Keyid (when A bit set) | 1703 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1704 # | | 1705 # | Message Authentication Code (when A bit set) | 1706 # | | 1707 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1708 # 1709 # where the fields are (note that the client sends requests, the server 1710 # responses): 1711 # 1712 # Response Bit: This packet is a response (if clear, packet is a request). 1713 # 1714 # More Bit: Set for all packets but the last in a response which 1715 # requires more than one packet. 1716 # 1717 # Version Number: 2 for current version 1718 # 1719 # Mode: Always 7 1720 # 1721 # Authenticated bit: If set, this packet is authenticated. 1722 # 1723 # Sequence number: For a multipacket response, contains the sequence 1724 # number of this packet. 0 is the first in the sequence, 1725 # 127 (or less) is the last. The More Bit must be set in 1726 # all packets but the last. 1727 # 1728 # Implementation number: The number of the implementation this request code 1729 # is defined by. An implementation number of zero is used 1730 # for request codes/data formats which all implementations 1731 # agree on. Implementation number 255 is reserved (for 1732 # extensions, in case we run out). 1733 # 1734 # Request code: An implementation-specific code which specifies the 1735 # operation to be (which has been) performed and/or the 1736 # format and semantics of the data included in the packet. 1737 # 1738 # Err: Must be 0 for a request. For a response, holds an error 1739 # code relating to the request. If nonzero, the operation 1740 # requested wasn"t performed. 1741 # 1742 # 0 - no error 1743 # 1 - incompatible implementation number 1744 # 2 - unimplemented request code 1745 # 3 - format error (wrong data items, data size, packet size etc.) 1746 # 4 - no data available (e.g. request for details on unknown peer) 1747 # 5-6 I don"t know 1748 # 7 - authentication failure (i.e. permission denied) 1749 # 1750 # Number of data items: number of data items in packet. 0 to 500 1751 # 1752 # MBZ: A reserved data field, must be zero in requests and responses. 1753 # 1754 # Size of data item: size of each data item in packet. 0 to 500 1755 # 1756 # Data: Variable sized area containing request/response data. For 1757 # requests and responses the size in octets must be greater 1758 # than or equal to the product of the number of data items 1759 # and the size of a data item. For requests the data area 1760 # must be exactly 40 octets in length. For responses the 1761 # data area may be any length between 0 and 500 octets 1762 # inclusive. 1763 # 1764 # Message Authentication Code: Same as NTP spec, in definition and function. 1765 # May optionally be included in requests which require 1766 # authentication, is never included in responses. 1767 # 1768 # The version number, mode and keyid have the same function and are 1769 # in the same location as a standard NTP packet. The request packet 1770 # is the same size as a standard NTP packet to ease receive buffer 1771 # management, and to allow the same encryption procedure to be used 1772 # both on mode 7 and standard NTP packets. The mac is included when 1773 # it is required that a request be authenticated, the keyid should be 1774 # zero in requests in which the mac is not included. 1775 # 1776 # The data format depends on the implementation number/request code pair 1777 # and whether the packet is a request or a response. The only requirement 1778 # is that data items start in the octet immediately following the size 1779 # word and that data items be concatenated without padding between (i.e. 1780 # if the data area is larger than data_items*size, all padding is at 1781 # the end). Padding is ignored, other than for encryption purposes. 1782 # Implementations using encryption might want to include a time stamp 1783 # or other data in the request packet padding. The key used for requests 1784 # is implementation defined, but key 15 is suggested as a default. 1785 #________________________________________________________________________ 1786 # 1787 1788 name = "Private (mode 7)" 1789 fields_desc = [ 1790 BitField("response", 0, 1), 1791 BitField("more", 0, 1), 1792 BitField("version", 2, 3), 1793 BitField("mode", 0, 3), 1794 BitField("auth", 0, 1), 1795 BitField("seq", 0, 7), 1796 ByteEnumField("implementation", 0, _implementations), 1797 ByteEnumField("request_code", 0, _request_codes), 1798 BitEnumField("err", 0, 4, _ntpd_private_errors), 1799 BitField("nb_items", 0, 12), 1800 BitField("mbz", 0, 4), 1801 BitField("data_item_size", 0, 12), 1802 ConditionalField( 1803 NTPPrivateReqPacketListField( 1804 "req_data", 1805 [], 1806 Packet, 1807 length_from=lambda p: p.data_item_size, 1808 count_from=lambda p: p.nb_items 1809 ), 1810 lambda p: p.response == 0 1811 ), 1812 # Responses 1813 ConditionalField( 1814 NTPPrivateRespPacketListField( 1815 "data", 1816 [], 1817 Packet, 1818 length_from=lambda p: p.data_item_size, 1819 count_from=lambda p: p.nb_items 1820 ), 1821 lambda p: p.response == 1 1822 ), 1823 # Responses are not supposed to be authenticated 1824 ConditionalField(PacketField("authenticator", "", NTPPrivatePktTail), 1825 lambda p: p.response == 0 and p.auth == 1), 1826 ] 1827 1828 1829############################################################################## 1830##### Layer bindings 1831############################################################################## 1832 1833bind_layers(UDP, NTP, {"sport": 123}) 1834bind_layers(UDP, NTP, {"dport": 123}) 1835bind_layers(UDP, NTP, {"sport": 123, "dport": 123}) 1836 1837 1838