1 ## This file is part of Scapy 2 ## Copyright (C) 2017 Maxence Tury 3 ## This program is published under a GPLv2 license 4 5 """ 6 TLS handshake extensions. 7 """ 8 9 from __future__ import print_function 10 11 from scapy.fields import * 12 from scapy.packet import Packet, Raw, Padding 13 from scapy.layers.x509 import X509_Extensions 14 from scapy.layers.tls.basefields import _tls_version 15 from scapy.layers.tls.keyexchange import (SigAndHashAlgsLenField, 16 SigAndHashAlgsField, _tls_hash_sig) 17 from scapy.layers.tls.session import _GenericTLSSessionInheritance 18 from scapy.layers.tls.crypto.groups import _tls_named_groups 19 20 21 _tls_ext = { 0: "server_name", # RFC 4366 22 1: "max_fragment_length", # RFC 4366 23 2: "client_certificate_url", # RFC 4366 24 3: "trusted_ca_keys", # RFC 4366 25 4: "truncated_hmac", # RFC 4366 26 5: "status_request", # RFC 4366 27 6: "user_mapping", # RFC 4681 28 7: "client_authz", # RFC 5878 29 8: "server_authz", # RFC 5878 30 9: "cert_type", # RFC 6091 31 #10: "elliptic_curves", # RFC 4492 32 10: "supported_groups", 33 11: "ec_point_formats", # RFC 4492 34 13: "signature_algorithms", # RFC 5246 35 0x0f: "heartbeat", # RFC 6520 36 0x10: "alpn", # RFC 7301 37 0x12: "signed_certificate_timestamp", # RFC 6962 38 0x15: "padding", # RFC 7685 39 0x16: "encrypt_then_mac", # RFC 7366 40 0x17: "extended_master_secret",# RFC 7627 41 0x23: "session_ticket", # RFC 5077 42 0x28: "key_share", 43 0x29: "pre_shared_key", 44 0x2a: "early_data", 45 0x2b: "supported_versions", 46 0x2c: "cookie", 47 0x2d: "psk_key_exchange_modes", 48 0x2e: "ticket_early_data_info", 49 0x2f: "certificate_authorities", 50 0x30: "oid_filters", 51 0x3374: "next_protocol_negotiation", 52 # RFC-draft-agl-tls-nextprotoneg-03 53 0xff01: "renegotiation_info" # RFC 5746 54 } 55 56 57 class TLS_Ext_Unknown(_GenericTLSSessionInheritance): 58 """ 59 We put this here rather than in extensions.py in order to avoid 60 circular imports... 61 """ 62 name = "TLS Extension - Scapy Unknown" 63 fields_desc = [ShortEnumField("type", None, _tls_ext), 64 FieldLenField("len", None, fmt="!H", length_of="val"), 65 StrLenField("val", "", 66 length_from=lambda pkt: pkt.len) ] 67 68 def post_build(self, p, pay): 69 if self.len is None: 70 l = len(p) - 4 71 p = p[:2] + struct.pack("!H", l) + p[4:] 72 return p+pay 73 74 75 ############################################################################### 76 ### ClientHello/ServerHello extensions ### 77 ############################################################################### 78 79 # We provide these extensions mostly for packet manipulation purposes. 80 # For now, most of them are not considered by our automaton. 81 82 class TLS_Ext_PrettyPacketList(TLS_Ext_Unknown): 83 """ 84 Dummy extension used for server_name/ALPN/NPN for a lighter representation: 85 the final field is showed as a 1-line list rather than as lots of packets. 86 XXX Define a new condition for packet lists in Packet._show_or_dump? 87 """ 88 def _show_or_dump(self, dump=False, indent=3, 89 lvl="", label_lvl="", first_call=True): 90 """ Reproduced from packet.py """ 91 ct = AnsiColorTheme() if dump else conf.color_theme 92 s = "%s%s %s %s \n" % (label_lvl, ct.punct("###["), 93 ct.layer_name(self.name), ct.punct("]###")) 94 for f in self.fields_desc[:-1]: 95 ncol = ct.field_name 96 vcol = ct.field_value 97 fvalue = self.getfieldval(f.name) 98 begn = "%s %-10s%s " % (label_lvl+lvl, ncol(f.name), 99 ct.punct("="),) 100 reprval = f.i2repr(self,fvalue) 101 if isinstance(reprval, str): 102 reprval = reprval.replace("\n", "\n"+" "*(len(label_lvl) 103 +len(lvl) 104 +len(f.name) 105 +4)) 106 s += "%s%s\n" % (begn,vcol(reprval)) 107 f = self.fields_desc[-1] 108 ncol = ct.field_name 109 vcol = ct.field_value 110 fvalue = self.getfieldval(f.name) 111 begn = "%s %-10s%s " % (label_lvl+lvl, ncol(f.name), ct.punct("="),) 112 reprval = f.i2repr(self,fvalue) 113 if isinstance(reprval, str): 114 reprval = reprval.replace("\n", "\n"+" "*(len(label_lvl) 115 +len(lvl) 116 +len(f.name) 117 +4)) 118 s += "%s%s\n" % (begn,vcol(reprval)) 119 if self.payload: 120 s += self.payload._show_or_dump(dump=dump, indent=indent, 121 lvl=lvl+(" "*indent*self.show_indent), 122 label_lvl=label_lvl, first_call=False) 123 124 if first_call and not dump: 125 print(s) 126 else: 127 return s 128 129 130 _tls_server_name_types = { 0: "host_name" } 131 132 class ServerName(Packet): 133 name = "HostName" 134 fields_desc = [ ByteEnumField("nametype", 0, _tls_server_name_types), 135 FieldLenField("namelen", None, length_of="servername"), 136 StrLenField("servername", "", 137 length_from=lambda pkt: pkt.namelen) ] 138 def guess_payload_class(self, p): 139 return Padding 140 141 class ServerListField(PacketListField): 142 def i2repr(self, pkt, x): 143 res = [p.servername for p in x] 144 return "[%s]" % b", ".join(res) 145 146 class ServerLenField(FieldLenField): 147 """ 148 There is no length when there are no servernames (as in a ServerHello). 149 """ 150 def addfield(self, pkt, s, val): 151 if not val: 152 if not pkt.servernames: 153 return s 154 return super(ServerLenField, self).addfield(pkt, s, val) 155 156 class TLS_Ext_ServerName(TLS_Ext_PrettyPacketList): # RFC 4366 157 name = "TLS Extension - Server Name" 158 fields_desc = [ShortEnumField("type", 0, _tls_ext), 159 FieldLenField("len", None, length_of="servernames", 160 adjust=lambda pkt,x: x+2), 161 ServerLenField("servernameslen", None, 162 length_of="servernames"), 163 ServerListField("servernames", [], ServerName, 164 length_from=lambda pkt: pkt.servernameslen)] 165 166 167 class TLS_Ext_MaxFragLen(TLS_Ext_Unknown): # RFC 4366 168 name = "TLS Extension - Max Fragment Length" 169 fields_desc = [ShortEnumField("type", 1, _tls_ext), 170 ShortField("len", None), 171 ByteEnumField("maxfraglen", 4, { 1: "2^9", 172 2: "2^10", 173 3: "2^11", 174 4: "2^12" }) ] 175 176 177 class TLS_Ext_ClientCertURL(TLS_Ext_Unknown): # RFC 4366 178 name = "TLS Extension - Client Certificate URL" 179 fields_desc = [ShortEnumField("type", 2, _tls_ext), 180 ShortField("len", None) ] 181 182 183 _tls_trusted_authority_types = {0: "pre_agreed", 184 1: "key_sha1_hash", 185 2: "x509_name", 186 3: "cert_sha1_hash" } 187 188 class TAPreAgreed(Packet): 189 name = "Trusted authority - pre_agreed" 190 fields_desc = [ ByteEnumField("idtype", 0, _tls_trusted_authority_types) ] 191 def guess_payload_class(self, p): 192 return Padding 193 194 class TAKeySHA1Hash(Packet): 195 name = "Trusted authority - key_sha1_hash" 196 fields_desc = [ ByteEnumField("idtype", 1, _tls_trusted_authority_types), 197 StrFixedLenField("id", None, 20) ] 198 def guess_payload_class(self, p): 199 return Padding 200 201 class TAX509Name(Packet): 202 """ 203 XXX Section 3.4 of RFC 4366. Implement a more specific DNField 204 rather than current StrLenField. 205 """ 206 name = "Trusted authority - x509_name" 207 fields_desc = [ ByteEnumField("idtype", 2, _tls_trusted_authority_types), 208 FieldLenField("dnlen", None, length_of="dn"), 209 StrLenField("dn", "", length_from=lambda pkt: pkt.dnlen) ] 210 def guess_payload_class(self, p): 211 return Padding 212 213 class TACertSHA1Hash(Packet): 214 name = "Trusted authority - cert_sha1_hash" 215 fields_desc = [ ByteEnumField("idtype", 3, _tls_trusted_authority_types), 216 StrFixedLenField("id", None, 20) ] 217 def guess_payload_class(self, p): 218 return Padding 219 220 _tls_trusted_authority_cls = {0: TAPreAgreed, 221 1: TAKeySHA1Hash, 222 2: TAX509Name, 223 3: TACertSHA1Hash } 224 225 class _TAListField(PacketListField): 226 """ 227 Specific version that selects the right Trusted Authority (previous TA*) 228 class to be used for dissection based on idtype. 229 """ 230 def m2i(self, pkt, m): 231 idtype = ord(m[0]) 232 cls = self.cls 233 if idtype in _tls_trusted_authority_cls: 234 cls = _tls_trusted_authority_cls[idtype] 235 return cls(m) 236 237 class TLS_Ext_TrustedCAInd(TLS_Ext_Unknown): # RFC 4366 238 name = "TLS Extension - Trusted CA Indication" 239 fields_desc = [ShortEnumField("type", 3, _tls_ext), 240 ShortField("len", None), 241 FieldLenField("talen", None, length_of="ta"), 242 _TAListField("ta", [], Raw, 243 length_from=lambda pkt: pkt.talen) ] 244 245 246 class TLS_Ext_TruncatedHMAC(TLS_Ext_Unknown): # RFC 4366 247 name = "TLS Extension - Truncated HMAC" 248 fields_desc = [ShortEnumField("type", 4, _tls_ext), 249 ShortField("len", None) ] 250 251 252 class ResponderID(Packet): 253 name = "Responder ID structure" 254 fields_desc = [ FieldLenField("respidlen", None, length_of="respid"), 255 StrLenField("respid", "", 256 length_from=lambda pkt: pkt.respidlen)] 257 def guess_payload_class(self, p): 258 return Padding 259 260 class OCSPStatusRequest(Packet): 261 """ 262 This is the structure defined in RFC 6066, not in RFC 6960! 263 """ 264 name = "OCSPStatusRequest structure" 265 fields_desc = [ FieldLenField("respidlen", None, length_of="respid"), 266 PacketListField("respid", [], ResponderID, 267 length_from=lambda pkt: pkt.respidlen), 268 FieldLenField("reqextlen", None, length_of="reqext"), 269 PacketField("reqext", "", X509_Extensions) ] 270 def guess_payload_class(self, p): 271 return Padding 272 273 _cert_status_type = { 1: "ocsp" } 274 _cert_status_req_cls = { 1: OCSPStatusRequest } 275 276 class _StatusReqField(PacketListField): 277 def m2i(self, pkt, m): 278 idtype = pkt.stype 279 cls = self.cls 280 if idtype in _cert_status_req_cls: 281 cls = _cert_status_req_cls[idtype] 282 return cls(m) 283 284 class TLS_Ext_CSR(TLS_Ext_Unknown): # RFC 4366 285 name = "TLS Extension - Certificate Status Request" 286 fields_desc = [ShortEnumField("type", 5, _tls_ext), 287 ShortField("len", None), 288 ByteEnumField("stype", None, _cert_status_type), 289 _StatusReqField("req", [], Raw, 290 length_from=lambda pkt: pkt.len - 1) ] 291 292 293 class TLS_Ext_UserMapping(TLS_Ext_Unknown): # RFC 4681 294 name = "TLS Extension - User Mapping" 295 fields_desc = [ShortEnumField("type", 6, _tls_ext), 296 ShortField("len", None), 297 FieldLenField("umlen", None, fmt="B", length_of="um"), 298 FieldListField("um", [], 299 ByteField("umtype", 0), 300 length_from=lambda pkt: pkt.umlen) ] 301 302 303 class TLS_Ext_ClientAuthz(TLS_Ext_Unknown): # RFC 5878 304 """ XXX Unsupported """ 305 name = "TLS Extension - Client Authz" 306 fields_desc = [ShortEnumField("type", 7, _tls_ext), 307 ShortField("len", None), 308 ] 309 310 class TLS_Ext_ServerAuthz(TLS_Ext_Unknown): # RFC 5878 311 """ XXX Unsupported """ 312 name = "TLS Extension - Server Authz" 313 fields_desc = [ShortEnumField("type", 8, _tls_ext), 314 ShortField("len", None), 315 ] 316 317 318 _tls_cert_types = { 0: "X.509", 1: "OpenPGP" } 319 320 class TLS_Ext_ClientCertType(TLS_Ext_Unknown): # RFC 5081 321 name = "TLS Extension - Certificate Type (client version)" 322 fields_desc = [ShortEnumField("type", 9, _tls_ext), 323 ShortField("len", None), 324 FieldLenField("ctypeslen", None, length_of="ctypes"), 325 FieldListField("ctypes", [0, 1], 326 ByteEnumField("certtypes", None, 327 _tls_cert_types), 328 length_from=lambda pkt: pkt.ctypeslen) ] 329 330 class TLS_Ext_ServerCertType(TLS_Ext_Unknown): # RFC 5081 331 name = "TLS Extension - Certificate Type (server version)" 332 fields_desc = [ShortEnumField("type", 9, _tls_ext), 333 ShortField("len", None), 334 ByteEnumField("ctype", None, _tls_cert_types) ] 335 336 def _TLS_Ext_CertTypeDispatcher(m, *args, **kargs): 337 """ 338 We need to select the correct one on dissection. We use the length for 339 that, as 1 for client version would emply an empty list. 340 """ 341 l = struct.unpack("!H", m[2:4])[0] 342 if l == 1: 343 cls = TLS_Ext_ServerCertType 344 else: 345 cls = TLS_Ext_ClientCertType 346 return cls(m, *args, **kargs) 347 348 349 class TLS_Ext_SupportedGroups(TLS_Ext_Unknown): 350 """ 351 This extension was known as 'Supported Elliptic Curves' before TLS 1.3 352 merged both group selection mechanisms for ECDH and FFDH. 353 """ 354 name = "TLS Extension - Supported Groups" 355 fields_desc = [ShortEnumField("type", 10, _tls_ext), 356 ShortField("len", None), 357 FieldLenField("groupslen", None, length_of="groups"), 358 FieldListField("groups", [], 359 ShortEnumField("ng", None, 360 _tls_named_groups), 361 length_from=lambda pkt: pkt.groupslen) ] 362 363 class TLS_Ext_SupportedEllipticCurves(TLS_Ext_SupportedGroups): # RFC 4492 364 pass 365 366 367 _tls_ecpoint_format = { 0: "uncompressed", 368 1: "ansiX962_compressed_prime", 369 2: "ansiX962_compressed_char2" } 370 371 class TLS_Ext_SupportedPointFormat(TLS_Ext_Unknown): # RFC 4492 372 name = "TLS Extension - Supported Point Format" 373 fields_desc = [ShortEnumField("type", 11, _tls_ext), 374 ShortField("len", None), 375 FieldLenField("ecpllen", None, fmt="B", length_of="ecpl"), 376 FieldListField("ecpl", [0], 377 ByteEnumField("nc", None, 378 _tls_ecpoint_format), 379 length_from=lambda pkt: pkt.ecpllen) ] 380 381 382 class TLS_Ext_SignatureAlgorithms(TLS_Ext_Unknown): # RFC 5246 383 name = "TLS Extension - Signature Algorithms" 384 fields_desc = [ShortEnumField("type", 13, _tls_ext), 385 ShortField("len", None), 386 SigAndHashAlgsLenField("sig_algs_len", None, 387 length_of="sig_algs"), 388 SigAndHashAlgsField("sig_algs", [], 389 EnumField("hash_sig", None, 390 _tls_hash_sig), 391 length_from= 392 lambda pkt: pkt.sig_algs_len) ] 393 394 395 class TLS_Ext_Heartbeat(TLS_Ext_Unknown): # RFC 6520 396 name = "TLS Extension - Heartbeat" 397 fields_desc = [ShortEnumField("type", 0x0f, _tls_ext), 398 ShortField("len", None), 399 ByteEnumField("heartbeat_mode", 2, 400 { 1: "peer_allowed_to_send", 401 2: "peer_not_allowed_to_send" }) ] 402 403 404 class ProtocolName(Packet): 405 name = "Protocol Name" 406 fields_desc = [ FieldLenField("len", None, fmt='B', length_of="protocol"), 407 StrLenField("protocol", "", 408 length_from=lambda pkt: pkt.len)] 409 def guess_payload_class(self, p): 410 return Padding 411 412 class ProtocolListField(PacketListField): 413 def i2repr(self, pkt, x): 414 res = [p.protocol for p in x] 415 return "[%s]" % b", ".join(res) 416 417 class TLS_Ext_ALPN(TLS_Ext_PrettyPacketList): # RFC 7301 418 name = "TLS Extension - Application Layer Protocol Negotiation" 419 fields_desc = [ShortEnumField("type", 0x10, _tls_ext), 420 ShortField("len", None), 421 FieldLenField("protocolslen", None, length_of="protocols"), 422 ProtocolListField("protocols", [], ProtocolName, 423 length_from=lambda pkt:pkt.protocolslen) ] 424 425 426 class TLS_Ext_Padding(TLS_Ext_Unknown): # RFC 7685 427 name = "TLS Extension - Padding" 428 fields_desc = [ShortEnumField("type", 0x15, _tls_ext), 429 FieldLenField("len", None, length_of="padding"), 430 StrLenField("padding", "", 431 length_from=lambda pkt: pkt.len) ] 432 433 434 class TLS_Ext_EncryptThenMAC(TLS_Ext_Unknown): # RFC 7366 435 name = "TLS Extension - Encrypt-then-MAC" 436 fields_desc = [ShortEnumField("type", 0x16, _tls_ext), 437 ShortField("len", None) ] 438 439 440 class TLS_Ext_ExtendedMasterSecret(TLS_Ext_Unknown): # RFC 7627 441 name = "TLS Extension - Extended Master Secret" 442 fields_desc = [ShortEnumField("type", 0x17, _tls_ext), 443 ShortField("len", None) ] 444 445 446 class TLS_Ext_SessionTicket(TLS_Ext_Unknown): # RFC 5077 447 """ 448 RFC 5077 updates RFC 4507 according to most implementations, which do not 449 use another (useless) 'ticketlen' field after the global 'len' field. 450 """ 451 name = "TLS Extension - Session Ticket" 452 fields_desc = [ShortEnumField("type", 0x23, _tls_ext), 453 FieldLenField("len", None, length_of="ticket"), 454 StrLenField("ticket", "", 455 length_from=lambda pkt: pkt.len) ] 456 457 458 class TLS_Ext_KeyShare(TLS_Ext_Unknown): 459 name = "TLS Extension - Key Share (dummy class)" 460 fields_desc = [ShortEnumField("type", 0x28, _tls_ext), 461 ShortField("len", None) ] 462 463 464 class TLS_Ext_PreSharedKey(TLS_Ext_Unknown): 465 name = "TLS Extension - Pre Shared Key (dummy class)" 466 fields_desc = [ShortEnumField("type", 0x29, _tls_ext), 467 ShortField("len", None) ] 468 469 470 class TLS_Ext_EarlyData(TLS_Ext_Unknown): 471 name = "TLS Extension - Early Data" 472 fields_desc = [ShortEnumField("type", 0x2a, _tls_ext), 473 ShortField("len", None) ] 474 475 476 class TLS_Ext_SupportedVersions(TLS_Ext_Unknown): 477 name = "TLS Extension - Supported Versions" 478 fields_desc = [ShortEnumField("type", 0x2b, _tls_ext), 479 ShortField("len", None), 480 FieldLenField("versionslen", None, fmt='B', 481 length_of="versions"), 482 FieldListField("versions", [], 483 ShortEnumField("version", None, 484 _tls_version), 485 length_from=lambda pkt: pkt.versionslen) ] 486 487 488 class TLS_Ext_Cookie(TLS_Ext_Unknown): 489 name = "TLS Extension - Cookie" 490 fields_desc = [ShortEnumField("type", 0x2c, _tls_ext), 491 ShortField("len", None), 492 FieldLenField("cookielen", None, length_of="cookie"), 493 XStrLenField("cookie", "", 494 length_from=lambda pkt: pkt.cookielen) ] 495 496 497 _tls_psk_kx_modes = { 0: "psk_ke", 1: "psk_dhe_ke" } 498 499 class TLS_Ext_PSKKeyExchangeModes(TLS_Ext_Unknown): 500 name = "TLS Extension - PSK Key Exchange Modes" 501 fields_desc = [ShortEnumField("type", 0x2d, _tls_ext), 502 ShortField("len", None), 503 FieldLenField("kxmodeslen", None, fmt='B', 504 length_of="kxmodes"), 505 FieldListField("kxmodes", [], 506 ByteEnumField("kxmode", None, 507 _tls_psk_kx_modes), 508 length_from=lambda pkt: pkt.kxmodeslen) ] 509 510 511 class TLS_Ext_TicketEarlyDataInfo(TLS_Ext_Unknown): 512 name = "TLS Extension - Ticket Early Data Info" 513 fields_desc = [ShortEnumField("type", 0x2e, _tls_ext), 514 ShortField("len", None), 515 IntField("max_early_data_size", 0) ] 516 517 518 class TLS_Ext_NPN(TLS_Ext_PrettyPacketList): 519 """ 520 Defined in RFC-draft-agl-tls-nextprotoneg-03. Deprecated in favour of ALPN. 521 """ 522 name = "TLS Extension - Next Protocol Negotiation" 523 fields_desc = [ShortEnumField("type", 0x3374, _tls_ext), 524 FieldLenField("len", None, length_of="protocols"), 525 ProtocolListField("protocols", [], ProtocolName, 526 length_from=lambda pkt:pkt.len) ] 527 528 529 class TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown): # RFC 5746 530 name = "TLS Extension - Renegotiation Indication" 531 fields_desc = [ShortEnumField("type", 0xff01, _tls_ext), 532 ShortField("len", None), 533 FieldLenField("reneg_conn_len", None, fmt='B', 534 length_of="renegotiated_connection"), 535 StrLenField("renegotiated_connection", "", 536 length_from=lambda pkt: pkt.reneg_conn_len) ] 537 538 539 _tls_ext_cls = { 0: TLS_Ext_ServerName, 540 1: TLS_Ext_MaxFragLen, 541 2: TLS_Ext_ClientCertURL, 542 3: TLS_Ext_TrustedCAInd, 543 4: TLS_Ext_TruncatedHMAC, 544 5: TLS_Ext_CSR, 545 6: TLS_Ext_UserMapping, 546 7: TLS_Ext_ClientAuthz, 547 8: TLS_Ext_ServerAuthz, 548 9: _TLS_Ext_CertTypeDispatcher, 549 #10: TLS_Ext_SupportedEllipticCurves, 550 10: TLS_Ext_SupportedGroups, 551 11: TLS_Ext_SupportedPointFormat, 552 13: TLS_Ext_SignatureAlgorithms, 553 0x0f: TLS_Ext_Heartbeat, 554 0x10: TLS_Ext_ALPN, 555 0x15: TLS_Ext_Padding, 556 0x16: TLS_Ext_EncryptThenMAC, 557 0x17: TLS_Ext_ExtendedMasterSecret, 558 0x23: TLS_Ext_SessionTicket, 559 0x28: TLS_Ext_KeyShare, 560 0x29: TLS_Ext_PreSharedKey, 561 0x2a: TLS_Ext_EarlyData, 562 0x2b: TLS_Ext_SupportedVersions, 563 0x2c: TLS_Ext_Cookie, 564 0x2d: TLS_Ext_PSKKeyExchangeModes, 565 0x2e: TLS_Ext_TicketEarlyDataInfo, 566 #0x2f: TLS_Ext_CertificateAuthorities, #XXX 567 #0x30: TLS_Ext_OIDFilters, #XXX 568 0x3374: TLS_Ext_NPN, 569 0xff01: TLS_Ext_RenegotiationInfo 570 } 571 572 573 class _ExtensionsLenField(FieldLenField): 574 def getfield(self, pkt, s): 575 """ 576 We try to compute a length, usually from a msglen parsed earlier. 577 If this length is 0, we consider 'selection_present' (from RFC 5246) 578 to be False. This means that there should not be any length field. 579 However, with TLS 1.3, zero lengths are always explicit. 580 """ 581 ext = pkt.get_field(self.length_of) 582 l = ext.length_from(pkt) 583 if l is None or l <= 0: 584 v = pkt.tls_session.tls_version 585 if v is None or v < 0x0304: 586 return s, None 587 return super(_ExtensionsLenField, self).getfield(pkt, s) 588 589 def addfield(self, pkt, s, i): 590 """ 591 There is a hack with the _ExtensionsField.i2len. It works only because 592 we expect _ExtensionsField.i2m to return a string of the same size (if 593 not of the same value) upon successive calls (e.g. through i2len here, 594 then i2m when directly building the _ExtensionsField). 595 596 XXX A proper way to do this would be to keep the extensions built from 597 the i2len call here, instead of rebuilding them later on. 598 """ 599 if i is None: 600 if self.length_of is not None: 601 fld,fval = pkt.getfield_and_val(self.length_of) 602 603 tmp = pkt.tls_session.frozen 604 pkt.tls_session.frozen = True 605 f = fld.i2len(pkt, fval) 606 pkt.tls_session.frozen = tmp 607 608 i = self.adjust(pkt, f) 609 if i == 0: # for correct build if no ext and not explicitly 0 610 return s 611 return s + struct.pack(self.fmt, i) 612 613 class _ExtensionsField(StrLenField): 614 islist=1 615 holds_packets=1 616 617 def i2len(self, pkt, i): 618 if i is None: 619 return 0 620 return len(self.i2m(pkt, i)) 621 622 def getfield(self, pkt, s): 623 l = self.length_from(pkt) 624 if l is None: 625 return s, [] 626 return s[l:], self.m2i(pkt, s[:l]) 627 628 def i2m(self, pkt, i): 629 if i is None: 630 return b"" 631 if isinstance(pkt, _GenericTLSSessionInheritance): 632 if not pkt.tls_session.frozen: 633 s = b"" 634 for ext in i: 635 if isinstance(ext, _GenericTLSSessionInheritance): 636 ext.tls_session = pkt.tls_session 637 s += ext.raw_stateful() 638 else: 639 s += raw(ext) 640 return s 641 return b"".join(map(raw, i)) 642 643 def m2i(self, pkt, m): 644 res = [] 645 while m: 646 t = struct.unpack("!H", m[:2])[0] 647 l = struct.unpack("!H", m[2:4])[0] 648 cls = _tls_ext_cls.get(t, TLS_Ext_Unknown) 649 if cls is TLS_Ext_KeyShare: 650 from scapy.layers.tls.keyexchange_tls13 import _tls_ext_keyshare_cls 651 cls = _tls_ext_keyshare_cls.get(pkt.msgtype, TLS_Ext_Unknown) 652 elif cls is TLS_Ext_PreSharedKey: 653 from scapy.layers.tls.keyexchange_tls13 import _tls_ext_presharedkey_cls 654 cls = _tls_ext_presharedkey_cls.get(pkt.msgtype, TLS_Ext_Unknown) 655 res.append(cls(m[:l+4], tls_session=pkt.tls_session)) 656 m = m[l+4:] 657 return res 658 659 660