1 ############################################################################# 2 ## ## 3 ## http2.py --- HTTP/2 support for Scapy ## 4 ## see RFC7540 and RFC7541 ## 5 ## for more informations ## 6 ## ## 7 ## Copyright (C) 2016 Florian Maury <florian.maury (at] ssi.gouv.fr> ## 8 ## ## 9 ## This file is part of Scapy ## 10 ## Scapy is free software: you can redistribute it and/or modify it ## 11 ## under the terms of the GNU General Public License version 2 as ## 12 ## published by the Free Software Foundation. ## 13 ## ## 14 ## This program is distributed in the hope that it will be useful, but ## 15 ## WITHOUT ANY WARRANTY; without even the implied warranty of ## 16 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## 17 ## General Public License for more details. ## 18 ## ## 19 ############################################################################# 20 """http2 Module 21 Implements packets and fields required to encode/decode HTTP/2 Frames 22 and HPack encoded headers 23 24 scapy.contrib.status=loads 25 scapy.contrib.description=HTTP/2 (RFC 7540, RFC 7541) 26 """ 27 28 from __future__ import absolute_import 29 from __future__ import print_function 30 import abc 31 import types 32 import re 33 from io import BytesIO 34 import struct 35 import scapy.modules.six as six 36 from scapy.compat import * 37 from scapy.modules.six.moves import range 38 39 # Only required if using mypy-lang for static typing 40 # Most symbols are used in mypy-interpreted "comments". 41 # Sized must be one of the superclasses of a class implementing __len__ 42 try: 43 from typing import Optional, List, Union, Callable, Any, Tuple, Sized 44 except ImportError: 45 class Sized(object): pass 46 47 import scapy.fields as fields 48 import scapy.packet as packet 49 import scapy.config as config 50 import scapy.base_classes as base_classes 51 import scapy.volatile as volatile 52 import scapy.error as error 53 54 ######################################################################################################################## 55 ################################################ HPACK Integer Fields ################################################## 56 ######################################################################################################################## 57 58 class HPackMagicBitField(fields.BitField): 59 """ HPackMagicBitField is a BitField variant that cannot be assigned another 60 value than the default one. This field must not be used where there is 61 potential for fuzzing. OTOH, this field makes sense (for instance, if the 62 magic bits are used by a dispatcher to select the payload class) 63 """ 64 65 __slots__ = ['_magic'] 66 67 def __init__(self, name, default, size): 68 # type: (str, int, int) -> None 69 """ 70 @param str name: this field instance name. 71 @param int default: this field only valid value. 72 @param int size: this bitfield bitlength. 73 @return None 74 @raise AssertionError 75 """ 76 assert(default >= 0) 77 # size can be negative if encoding is little-endian (see rev property of bitfields) 78 assert(size != 0) 79 self._magic = default 80 super(HPackMagicBitField, self).__init__(name, default, size) 81 82 def addfield(self, pkt, s, val): 83 # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> Union[str, Tuple[str, int, int]] 84 """ 85 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 86 @param str|(str, int, long) s: either a str if 0 == size%8 or a tuple with the string to add this field to, the 87 number of bits already generated and the generated value so far. 88 @param int val: unused; must be equal to default value 89 @return str|(str, int, long): the s string extended with this field machine representation 90 @raise AssertionError 91 """ 92 assert val == self._magic, 'val parameter must value {}; received: {}'.format(self._magic, val) 93 return super(HPackMagicBitField, self).addfield(pkt, s, self._magic) 94 95 def getfield(self, pkt, s): 96 # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[Union[Tuple[str, int], str], int] 97 """ 98 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 99 @param str|(str, int) s: either a str if size%8==0 or a tuple with the string to parse from and the number of 100 bits already consumed by previous bitfield-compatible fields. 101 @return (str|(str, int), int): Returns the remaining string and the parsed value. May return a tuple if there 102 are remaining bits to parse in the first byte. Returned value is equal to default value 103 @raise AssertionError 104 """ 105 r = super(HPackMagicBitField, self).getfield(pkt, s) 106 assert ( 107 isinstance(r, tuple) 108 and len(r) == 2 109 and isinstance(r[1], six.integer_types) 110 ), 'Second element of BitField.getfield return value expected to be an int or a long; API change detected' 111 assert r[1] == self._magic, 'Invalid value parsed from s; error in class guessing detected!' 112 return r 113 114 def h2i(self, pkt, x): 115 # type: (Optional[packet.Packet], int) -> int 116 """ 117 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused 118 @param int x: unused; must be equal to default value 119 @return int; default value 120 @raise AssertionError 121 """ 122 assert x == self._magic, \ 123 'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic) 124 return super(HPackMagicBitField, self).h2i(pkt, self._magic) 125 126 def i2h(self, pkt, x): 127 # type: (Optional[packet.Packet], int) -> int 128 """ 129 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused 130 @param int x: unused; must be equal to default value 131 @return int; default value 132 @raise AssertionError 133 """ 134 assert x == self._magic, \ 135 'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic) 136 return super(HPackMagicBitField, self).i2h(pkt, self._magic) 137 138 def m2i(self, pkt, x): 139 # type: (Optional[packet.Packet], int) -> int 140 """ 141 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused 142 @param int x: must be the machine representatino of the default value 143 @return int; default value 144 @raise AssertionError 145 """ 146 r = super(HPackMagicBitField, self).m2i(pkt, x) 147 assert r == self._magic, 'Invalid value parsed from m2i; error in class guessing detected!' 148 return r 149 150 def i2m(self, pkt, x): 151 # type: (Optional[packet.Packet], int) -> int 152 """ 153 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused 154 @param int x: unused; must be equal to default value 155 @return int; default value 156 @raise AssertionError 157 """ 158 assert x == self._magic, \ 159 'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic) 160 return super(HPackMagicBitField, self).i2m(pkt, self._magic) 161 162 def any2i(self, pkt, x): 163 # type: (Optional[packet.Packet], int) -> int 164 """ 165 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused 166 @param int x: unused; must be equal to default value 167 @return int; default value 168 @raise AssertionError 169 """ 170 assert x == self._magic, \ 171 'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic) 172 return super(HPackMagicBitField, self).any2i(pkt, self._magic) 173 174 175 class AbstractUVarIntField(fields.Field): 176 """AbstractUVarIntField represents an integer as defined in RFC7541 177 """ 178 179 __slots__ = ['_max_value', 'size', 'rev'] 180 """ 181 :var int size: the bit length of the prefix of this AbstractUVarIntField. It 182 represents the complement of the number of MSB that are used in the 183 current byte for other purposes by some other BitFields 184 :var int _max_value: the maximum value that can be stored in the 185 sole prefix. If the integer equals or exceeds this value, the max prefix 186 value is assigned to the size first bits and the multibyte representation 187 is used 188 :var bool rev: is a fake property, also emulated for the sake of 189 compatibility with Bitfields 190 """ 191 192 def __init__(self, name, default, size): 193 # type: (str, Optional[int], int) -> None 194 """ 195 @param str name: the name of this field instance 196 @param int|None default: positive, null or None default value for this field instance. 197 @param int size: the number of bits to consider in the first byte. Valid range is ]0;8] 198 @return None 199 @raise AssertionError 200 """ 201 assert(default is None or (isinstance(default, six.integer_types) and default >= 0)) 202 assert(0 < size <= 8) 203 super(AbstractUVarIntField, self).__init__(name, default) 204 self.size = size 205 self._max_value = (1 << self.size) - 1 206 207 # Configuring the fake property that is useless for this class but that is 208 # expected from BitFields 209 self.rev = False 210 211 def h2i(self, pkt, x): 212 # type: (Optional[packet.Packet], Optional[int]) -> Optional[int] 213 """ 214 @param packet.Packet|None pkt: unused. 215 @param int|None x: the value to convert. 216 @return int|None: the converted value. 217 @raise AssertionError 218 """ 219 assert(not isinstance(x, six.integer_types) or x >= 0) 220 return x 221 222 def i2h(self, pkt, x): 223 # type: (Optional[packet.Packet], Optional[int]) -> Optional[int] 224 """ 225 @param packet.Packet|None pkt: unused. 226 @param int|None x: the value to convert. 227 @return: int|None: the converted value. 228 """ 229 return x 230 231 def _detect_multi_byte(self, fb): 232 # type: (str) -> bool 233 """ _detect_multi_byte returns whether the AbstractUVarIntField is represented on 234 multiple bytes or not. 235 236 A multibyte representation is indicated by all of the first size bits being set 237 238 @param str fb: first byte, as a character. 239 @return bool: True if multibyte repr detected, else False. 240 @raise AssertionError 241 """ 242 assert(isinstance(fb, int) or len(fb) == 1) 243 return (orb(fb) & self._max_value) == self._max_value 244 245 def _parse_multi_byte(self, s): 246 # type: (str) -> int 247 """ _parse_multi_byte parses x as a multibyte representation to get the 248 int value of this AbstractUVarIntField. 249 250 @param str s: the multibyte string to parse. 251 @return int: The parsed int value represented by this AbstractUVarIntField. 252 @raise: AssertionError 253 @raise: Scapy_Exception if the input value encodes an integer larger than 1<<64 254 """ 255 256 assert(len(s) >= 2) 257 258 l = len(s) 259 260 value = 0 261 i = 1 262 byte = orb(s[i]) 263 # For CPU sake, stops at an arbitrary large number! 264 max_value = 1 << 64 265 # As long as the MSG is set, an another byte must be read 266 while byte & 0x80: 267 value += (byte ^ 0x80) << (7 * (i - 1)) 268 if value > max_value: 269 raise error.Scapy_Exception( 270 'out-of-bound value: the string encodes a value that is too large (>2^{64}): {}'.format(value) 271 ) 272 i += 1 273 assert i < l, 'EINVAL: x: out-of-bound read: the string ends before the AbstractUVarIntField!' 274 byte = orb(s[i]) 275 value += byte << (7 * (i - 1)) 276 value += self._max_value 277 278 assert(value >= 0) 279 return value 280 281 def m2i(self, pkt, x): 282 # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> int 283 """ 284 A tuple is expected for the "x" param only if "size" is different than 8. If a tuple is received, some bits 285 were consumed by another field. This field consumes the remaining bits, therefore the int of the tuple must 286 equal "size". 287 288 @param packet.Packet|None pkt: unused. 289 @param str|(str, int) x: the string to convert. If bits were consumed by a previous bitfield-compatible field. 290 @raise AssertionError 291 """ 292 assert(isinstance(x, bytes) or (isinstance(x, tuple) and x[1] >= 0)) 293 294 if isinstance(x, tuple): 295 assert (8 - x[1]) == self.size, 'EINVAL: x: not enough bits remaining in current byte to read the prefix' 296 val = x[0] 297 else: 298 assert isinstance(x, bytes) and self.size == 8, 'EINVAL: x: tuple expected when prefix_len is not a full byte' 299 val = x 300 301 if self._detect_multi_byte(val[0]): 302 ret = self._parse_multi_byte(val) 303 else: 304 ret = orb(val[0]) & self._max_value 305 306 assert(ret >= 0) 307 return ret 308 309 def i2m(self, pkt, x): 310 # type: (Optional[packet.Packet], int) -> str 311 """ 312 @param packet.Packet|None pkt: unused. 313 @param int x: the value to convert. 314 @return str: the converted value. 315 @raise AssertionError 316 """ 317 assert(x >= 0) 318 319 if x < self._max_value: 320 return chb(x) 321 else: 322 # The sl list join is a performance trick, because string 323 # concatenation is not efficient with Python immutable strings 324 sl = [chb(self._max_value)] 325 x -= self._max_value 326 while x >= 0x80: 327 sl.append(chb(0x80 | (x & 0x7F))) 328 x >>= 7 329 sl.append(chb(x)) 330 return b''.join(sl) 331 332 def any2i(self, pkt, x): 333 # type: (Optional[packet.Packet], Union[None, str, int]) -> Optional[int] 334 """ 335 A "x" value as a string is parsed as a binary encoding of a UVarInt. An int is considered an internal value. 336 None is returned as is. 337 338 @param packet.Packet|None pkt: the packet containing this field; probably unused. 339 @param str|int|None x: the value to convert. 340 @return int|None: the converted value. 341 @raise AssertionError 342 """ 343 if isinstance(x, type(None)): 344 return x 345 if isinstance(x, six.integer_types): 346 assert(x >= 0) 347 ret = self.h2i(pkt, x) 348 assert(isinstance(ret, six.integer_types) and ret >= 0) 349 return ret 350 elif isinstance(x, bytes): 351 ret = self.m2i(pkt, x) 352 assert (isinstance(ret, six.integer_types) and ret >= 0) 353 return ret 354 assert False, 'EINVAL: x: No idea what the parameter format is' 355 356 def i2repr(self, pkt, x): 357 # type: (Optional[packet.Packet], Optional[int]) -> str 358 """ 359 @param packet.Packet|None pkt: probably unused. 360 @param x: int|None: the positive, null or none value to convert. 361 @return str: the representation of the value. 362 """ 363 return repr(self.i2h(pkt, x)) 364 365 def addfield(self, pkt, s, val): 366 # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> str 367 """ An AbstractUVarIntField prefix always consumes the remaining bits 368 of a BitField;if no current BitField is in use (no tuple in 369 entry) then the prefix length is 8 bits and the whole byte is to 370 be consumed 371 @param packet.Packet|None pkt: the packet containing this field. Probably unused. 372 @param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already 373 generated by another bitfield-compatible field. This MUST be the case if "size" is not 8. The int is the 374 number of bits already generated in the first byte of the str. The long is the value that was generated by the 375 previous bitfield-compatible fields. 376 @param int val: the positive or null value to be added. 377 @return str: s concatenated with the machine representation of this field. 378 @raise AssertionError 379 """ 380 assert(val >= 0) 381 if isinstance(s, bytes): 382 assert self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte' 383 return s + self.i2m(pkt, val) 384 385 # s is a tuple 386 #assert(s[1] >= 0) 387 #assert(s[2] >= 0) 388 #assert (8 - s[1]) == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix' 389 390 if val >= self._max_value: 391 return s[0] + chb((s[2] << self.size) + self._max_value) + self.i2m(pkt, val)[1:] 392 # This AbstractUVarIntField is only one byte long; setting the prefix value 393 # and appending the resulting byte to the string 394 return chb(s[0]) + chb((s[2] << self.size) + orb(self.i2m(pkt, val))) 395 396 @staticmethod 397 def _detect_bytelen_from_str(s): 398 # type: (str) -> int 399 """ _detect_bytelen_from_str returns the length of the machine 400 representation of an AbstractUVarIntField starting at the beginning 401 of s and which is assumed to expand over multiple bytes 402 (value > _max_prefix_value). 403 404 @param str s: the string to parse. It is assumed that it is a multibyte int. 405 @return The bytelength of the AbstractUVarIntField. 406 @raise AssertionError 407 """ 408 assert(len(s) >= 2) 409 l = len(s) 410 411 i = 1 412 while orb(s[i]) & 0x80 > 0: 413 i += 1 414 assert i < l, 'EINVAL: s: out-of-bound read: unfinished AbstractUVarIntField detected' 415 ret = i + 1 416 417 assert(ret >= 0) 418 return ret 419 420 def i2len(self, pkt, x): 421 # type: (Optional[packet.Packet], int) -> int 422 """ 423 @param packet.Packet|None pkt: unused. 424 @param int x: the positive or null value whose binary size if requested. 425 @raise AssertionError 426 """ 427 assert(x >= 0) 428 if x < self._max_value: 429 return 1 430 431 # x is expressed over multiple bytes 432 x -= self._max_value 433 i = 1 434 if x == 0: 435 i += 1 436 while x > 0: 437 x >>= 7 438 i += 1 439 440 ret = i 441 assert(ret >= 0) 442 return ret 443 444 def getfield(self, pkt, s): 445 # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[str, int] 446 """ 447 @param packet.Packet|None pkt: the packet instance containing this field; probably unused. 448 @param str|(str, int) s: the input value to get this field value from. If size is 8, s is a string, else 449 it is a tuple containing the value and an int indicating the number of bits already consumed in the first byte 450 of the str. The number of remaining bits to consume in the first byte must be equal to "size". 451 @return (str, int): the remaining bytes of s and the parsed value. 452 @raise AssertionError 453 """ 454 if isinstance(s, tuple): 455 assert(len(s) == 2) 456 temp = s # type: Tuple[str, int] 457 ts, ti = temp 458 assert(ti >= 0) 459 assert 8 - ti == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix' 460 val = ts 461 else: 462 assert isinstance(s, bytes) and self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte' 463 val = s 464 465 if self._detect_multi_byte(val[0]): 466 l = self._detect_bytelen_from_str(val) 467 else: 468 l = 1 469 470 ret = val[l:], self.m2i(pkt, s) 471 assert(ret[1] >= 0) 472 return ret 473 474 def randval(self): 475 # type: () -> volatile.VolatileValue 476 """ 477 @return volatile.VolatileValue: a volatile value for this field "long"-compatible internal value. 478 """ 479 return volatile.RandLong() 480 481 482 class UVarIntField(AbstractUVarIntField): 483 def __init__(self, name, default, size): 484 # type: (str, int, int) -> None 485 """ 486 @param str name: the name of this field instance. 487 @param default: the default value for this field instance. default must be positive or null. 488 @raise AssertionError 489 """ 490 assert(default >= 0) 491 assert(0 < size <= 8) 492 493 super(UVarIntField, self).__init__(name, default, size) 494 self.size = size 495 self._max_value = (1 << self.size) - 1 496 497 # Configuring the fake property that is useless for this class but that is 498 # expected from BitFields 499 self.rev = False 500 501 def h2i(self, pkt, x): 502 # type: (Optional[packet.Packet], int) -> int 503 """ h2i is overloaded to restrict the acceptable x values (not None) 504 505 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 506 @param int x: the value to convert. 507 @return int: the converted value. 508 @raise AssertionError 509 """ 510 ret = super(UVarIntField, self).h2i(pkt, x) 511 assert(not isinstance(ret, type(None)) and ret >= 0) 512 return ret 513 514 def i2h(self, pkt, x): 515 # type: (Optional[packet.Packet], int) -> int 516 """ i2h is overloaded to restrict the acceptable x values (not None) 517 518 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 519 @param int x: the value to convert. 520 @return int: the converted value. 521 @raise AssertionError 522 """ 523 ret = super(UVarIntField, self).i2h(pkt, x) 524 assert(not isinstance(ret, type(None)) and ret >= 0) 525 return ret 526 527 def any2i(self, pkt, x): 528 # type: (Optional[packet.Packet], Union[str, int]) -> int 529 """ any2i is overloaded to restrict the acceptable x values (not None) 530 531 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 532 @param str|int x: the value to convert. 533 @return int: the converted value. 534 @raise AssertionError 535 """ 536 ret = super(UVarIntField, self).any2i(pkt, x) 537 assert(not isinstance(ret, type(None)) and ret >= 0) 538 return ret 539 540 def i2repr(self, pkt, x): 541 # type: (Optional[packet.Packet], int) -> str 542 """ i2repr is overloaded to restrict the acceptable x values (not None) 543 544 @param packet.Packet|None pkt: the packet instance containing this field instance; probably unused. 545 @param int x: the value to convert. 546 @return str: the converted value. 547 """ 548 return super(UVarIntField, self).i2repr(pkt, x) 549 550 551 class FieldUVarLenField(AbstractUVarIntField): 552 __slots__ = ['_length_of', '_adjust'] 553 554 def __init__(self, name, default, size, length_of, adjust=lambda x: x): 555 # type: (str, Optional[int], int, str, Callable[[int], int]) -> None 556 """ Initializes a FieldUVarLenField 557 558 @param str name: The name of this field instance. 559 @param int|None default: the default value of this field instance. 560 @param int size: the number of bits that are occupied by this field in the first byte of a binary string. 561 size must be in the range ]0;8]. 562 @param str length_of: The name of the field this field value is measuring/representing. 563 @param callable adjust: A function that modifies the value computed from the "length_of" field. 564 565 adjust can be used for instance to add a constant to the length_of field 566 length. For instance, let's say that i2len of the length_of field 567 returns 2. If adjust is lambda x: x+1 In that case, this field will 568 value 3 at build time. 569 @return None 570 @raise AssertionError 571 """ 572 assert(default is None or default >= 0) 573 assert(0 < size <= 8) 574 575 super(FieldUVarLenField, self).__init__(name, default, size) 576 self._length_of = length_of 577 self._adjust = adjust 578 579 def addfield(self, pkt, s, val): 580 # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], Optional[int]) -> str 581 """ 582 @param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be 583 None if the val parameter is. 584 @param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already 585 generated by another bitfield-compatible field. This MUST be the case if "size" is not 8. The int is the 586 number of bits already generated in the first byte of the str. The long is the value that was generated by the 587 previous bitfield-compatible fields. 588 @param int|None val: the positive or null value to be added. If None, the value is computed from pkt. 589 @return str: s concatenated with the machine representation of this field. 590 @raise AssertionError 591 """ 592 if val is None: 593 assert isinstance(pkt, packet.Packet), \ 594 'EINVAL: pkt: Packet expected when val is None; received {}'.format(type(pkt)) 595 val = self._compute_value(pkt) 596 return super(FieldUVarLenField, self).addfield(pkt, s, val) 597 598 def i2m(self, pkt, x): 599 # type: (Optional[packet.Packet], Optional[int]) -> str 600 """ 601 @param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be 602 None if the x parameter is. 603 @param int|None x: the positive or null value to be added. If None, the value is computed from pkt. 604 @return str 605 @raise AssertionError 606 """ 607 if x is None: 608 assert isinstance(pkt, packet.Packet), \ 609 'EINVAL: pkt: Packet expected when x is None; received {}'.format(type(pkt)) 610 x = self._compute_value(pkt) 611 return super(FieldUVarLenField, self).i2m(pkt, x) 612 613 def _compute_value(self, pkt): 614 # type: (packet.Packet) -> int 615 """ Computes the value of this field based on the provided packet and 616 the length_of field and the adjust callback 617 618 @param packet.Packet pkt: the packet from which is computed this field value. 619 @return int: the computed value for this field. 620 @raise KeyError: the packet nor its payload do not contain an attribute 621 with the length_of name. 622 @raise AssertionError 623 @raise KeyError if _length_of is not one of pkt fields 624 """ 625 fld, fval = pkt.getfield_and_val(self._length_of) 626 val = fld.i2len(pkt, fval) 627 ret = self._adjust(val) 628 assert(ret >= 0) 629 return ret 630 631 ######################################################################################################################## 632 ################################################ HPACK String Fields ################################################### 633 ######################################################################################################################## 634 635 class HPackStringsInterface(six.with_metaclass(abc.ABCMeta, Sized)): 636 @abc.abstractmethod 637 def __str__(self): pass 638 639 def __bytes__(self): 640 r = self.__str__() 641 return r if isinstance(r, bytes) else raw(r) 642 643 @abc.abstractmethod 644 def origin(self): pass 645 646 @abc.abstractmethod 647 def __len__(self): pass 648 649 650 class HPackLiteralString(HPackStringsInterface): 651 """ HPackLiteralString is a string. This class is used as a marker and 652 implements an interface in common with HPackZString 653 """ 654 __slots__ = ['_s'] 655 656 def __init__(self, s): 657 # type: (str) -> None 658 self._s = s 659 660 def __str__(self): 661 # type: () -> str 662 return self._s 663 664 def origin(self): 665 # type: () -> str 666 return plain_str(self._s) 667 668 def __len__(self): 669 # type: () -> int 670 return len(self._s) 671 672 673 class EOS(object): 674 """ Simple "marker" to designate the End Of String symbol in the huffman table 675 """ 676 677 678 class HuffmanNode(object): 679 """ HuffmanNode is an entry of the binary tree used for encoding/decoding 680 HPack compressed HTTP/2 headers 681 """ 682 683 __slots__ = ['l', 'r'] 684 """@var l: the left branch of this node 685 @var r: the right branch of this Node 686 687 These variables can value None (leaf node), another HuffmanNode, or a 688 symbol. Symbols are either a character or the End Of String symbol (class 689 EOS) 690 """ 691 692 def __init__(self, l, r): 693 # type: (Union[None, HuffmanNode, EOS, str], Union[None, HuffmanNode, EOS, str]) -> None 694 self.l = l 695 self.r = r 696 697 def __getitem__(self, b): 698 # type: (int) -> Union[None, HuffmanNode, EOS, str] 699 return self.r if b else self.l 700 701 def __setitem__(self, b, val): 702 # type: (int, Union[None, HuffmanNode, EOS, str]) -> None 703 if b: 704 self.r = val 705 else: 706 self.l = val 707 708 def __str__(self): 709 # type: () -> str 710 return self.__repr__() 711 712 def __repr__(self): 713 # type: () -> str 714 return '({}, {})'.format(self.l, self.r) 715 716 717 class InvalidEncodingException(Exception): 718 """ InvalidEncodingException is raised when a supposedly huffman-encoded 719 string is decoded and a decoding error arises 720 """ 721 722 723 class HPackZString(HPackStringsInterface): 724 __slots__ = ['_s', '_encoded'] 725 726 # From RFC 7541 727 # Tuple is (code,code bitlength) 728 # The bitlength is required to know how long the left padding 729 # (implicit 0's) there are 730 static_huffman_code = [ 731 (0x1ff8, 13), 732 (0x7fffd8, 23), 733 (0xfffffe2, 28), 734 (0xfffffe3, 28), 735 (0xfffffe4, 28), 736 (0xfffffe5, 28), 737 (0xfffffe6, 28), 738 (0xfffffe7, 28), 739 (0xfffffe8, 28), 740 (0xffffea, 24), 741 (0x3ffffffc, 30), 742 (0xfffffe9, 28), 743 (0xfffffea, 28), 744 (0x3ffffffd, 30), 745 (0xfffffeb, 28), 746 (0xfffffec, 28), 747 (0xfffffed, 28), 748 (0xfffffee, 28), 749 (0xfffffef, 28), 750 (0xffffff0, 28), 751 (0xffffff1, 28), 752 (0xffffff2, 28), 753 (0x3ffffffe, 30), 754 (0xffffff3, 28), 755 (0xffffff4, 28), 756 (0xffffff5, 28), 757 (0xffffff6, 28), 758 (0xffffff7, 28), 759 (0xffffff8, 28), 760 (0xffffff9, 28), 761 (0xffffffa, 28), 762 (0xffffffb, 28), 763 (0x14, 6), 764 (0x3f8, 10), 765 (0x3f9, 10), 766 (0xffa, 12), 767 (0x1ff9, 13), 768 (0x15, 6), 769 (0xf8, 8), 770 (0x7fa, 11), 771 (0x3fa, 10), 772 (0x3fb, 10), 773 (0xf9, 8), 774 (0x7fb, 11), 775 (0xfa, 8), 776 (0x16, 6), 777 (0x17, 6), 778 (0x18, 6), 779 (0x0, 5), 780 (0x1, 5), 781 (0x2, 5), 782 (0x19, 6), 783 (0x1a, 6), 784 (0x1b, 6), 785 (0x1c, 6), 786 (0x1d, 6), 787 (0x1e, 6), 788 (0x1f, 6), 789 (0x5c, 7), 790 (0xfb, 8), 791 (0x7ffc, 15), 792 (0x20, 6), 793 (0xffb, 12), 794 (0x3fc, 10), 795 (0x1ffa, 13), 796 (0x21, 6), 797 (0x5d, 7), 798 (0x5e, 7), 799 (0x5f, 7), 800 (0x60, 7), 801 (0x61, 7), 802 (0x62, 7), 803 (0x63, 7), 804 (0x64, 7), 805 (0x65, 7), 806 (0x66, 7), 807 (0x67, 7), 808 (0x68, 7), 809 (0x69, 7), 810 (0x6a, 7), 811 (0x6b, 7), 812 (0x6c, 7), 813 (0x6d, 7), 814 (0x6e, 7), 815 (0x6f, 7), 816 (0x70, 7), 817 (0x71, 7), 818 (0x72, 7), 819 (0xfc, 8), 820 (0x73, 7), 821 (0xfd, 8), 822 (0x1ffb, 13), 823 (0x7fff0, 19), 824 (0x1ffc, 13), 825 (0x3ffc, 14), 826 (0x22, 6), 827 (0x7ffd, 15), 828 (0x3, 5), 829 (0x23, 6), 830 (0x4, 5), 831 (0x24, 6), 832 (0x5, 5), 833 (0x25, 6), 834 (0x26, 6), 835 (0x27, 6), 836 (0x6, 5), 837 (0x74, 7), 838 (0x75, 7), 839 (0x28, 6), 840 (0x29, 6), 841 (0x2a, 6), 842 (0x7, 5), 843 (0x2b, 6), 844 (0x76, 7), 845 (0x2c, 6), 846 (0x8, 5), 847 (0x9, 5), 848 (0x2d, 6), 849 (0x77, 7), 850 (0x78, 7), 851 (0x79, 7), 852 (0x7a, 7), 853 (0x7b, 7), 854 (0x7ffe, 15), 855 (0x7fc, 11), 856 (0x3ffd, 14), 857 (0x1ffd, 13), 858 (0xffffffc, 28), 859 (0xfffe6, 20), 860 (0x3fffd2, 22), 861 (0xfffe7, 20), 862 (0xfffe8, 20), 863 (0x3fffd3, 22), 864 (0x3fffd4, 22), 865 (0x3fffd5, 22), 866 (0x7fffd9, 23), 867 (0x3fffd6, 22), 868 (0x7fffda, 23), 869 (0x7fffdb, 23), 870 (0x7fffdc, 23), 871 (0x7fffdd, 23), 872 (0x7fffde, 23), 873 (0xffffeb, 24), 874 (0x7fffdf, 23), 875 (0xffffec, 24), 876 (0xffffed, 24), 877 (0x3fffd7, 22), 878 (0x7fffe0, 23), 879 (0xffffee, 24), 880 (0x7fffe1, 23), 881 (0x7fffe2, 23), 882 (0x7fffe3, 23), 883 (0x7fffe4, 23), 884 (0x1fffdc, 21), 885 (0x3fffd8, 22), 886 (0x7fffe5, 23), 887 (0x3fffd9, 22), 888 (0x7fffe6, 23), 889 (0x7fffe7, 23), 890 (0xffffef, 24), 891 (0x3fffda, 22), 892 (0x1fffdd, 21), 893 (0xfffe9, 20), 894 (0x3fffdb, 22), 895 (0x3fffdc, 22), 896 (0x7fffe8, 23), 897 (0x7fffe9, 23), 898 (0x1fffde, 21), 899 (0x7fffea, 23), 900 (0x3fffdd, 22), 901 (0x3fffde, 22), 902 (0xfffff0, 24), 903 (0x1fffdf, 21), 904 (0x3fffdf, 22), 905 (0x7fffeb, 23), 906 (0x7fffec, 23), 907 (0x1fffe0, 21), 908 (0x1fffe1, 21), 909 (0x3fffe0, 22), 910 (0x1fffe2, 21), 911 (0x7fffed, 23), 912 (0x3fffe1, 22), 913 (0x7fffee, 23), 914 (0x7fffef, 23), 915 (0xfffea, 20), 916 (0x3fffe2, 22), 917 (0x3fffe3, 22), 918 (0x3fffe4, 22), 919 (0x7ffff0, 23), 920 (0x3fffe5, 22), 921 (0x3fffe6, 22), 922 (0x7ffff1, 23), 923 (0x3ffffe0, 26), 924 (0x3ffffe1, 26), 925 (0xfffeb, 20), 926 (0x7fff1, 19), 927 (0x3fffe7, 22), 928 (0x7ffff2, 23), 929 (0x3fffe8, 22), 930 (0x1ffffec, 25), 931 (0x3ffffe2, 26), 932 (0x3ffffe3, 26), 933 (0x3ffffe4, 26), 934 (0x7ffffde, 27), 935 (0x7ffffdf, 27), 936 (0x3ffffe5, 26), 937 (0xfffff1, 24), 938 (0x1ffffed, 25), 939 (0x7fff2, 19), 940 (0x1fffe3, 21), 941 (0x3ffffe6, 26), 942 (0x7ffffe0, 27), 943 (0x7ffffe1, 27), 944 (0x3ffffe7, 26), 945 (0x7ffffe2, 27), 946 (0xfffff2, 24), 947 (0x1fffe4, 21), 948 (0x1fffe5, 21), 949 (0x3ffffe8, 26), 950 (0x3ffffe9, 26), 951 (0xffffffd, 28), 952 (0x7ffffe3, 27), 953 (0x7ffffe4, 27), 954 (0x7ffffe5, 27), 955 (0xfffec, 20), 956 (0xfffff3, 24), 957 (0xfffed, 20), 958 (0x1fffe6, 21), 959 (0x3fffe9, 22), 960 (0x1fffe7, 21), 961 (0x1fffe8, 21), 962 (0x7ffff3, 23), 963 (0x3fffea, 22), 964 (0x3fffeb, 22), 965 (0x1ffffee, 25), 966 (0x1ffffef, 25), 967 (0xfffff4, 24), 968 (0xfffff5, 24), 969 (0x3ffffea, 26), 970 (0x7ffff4, 23), 971 (0x3ffffeb, 26), 972 (0x7ffffe6, 27), 973 (0x3ffffec, 26), 974 (0x3ffffed, 26), 975 (0x7ffffe7, 27), 976 (0x7ffffe8, 27), 977 (0x7ffffe9, 27), 978 (0x7ffffea, 27), 979 (0x7ffffeb, 27), 980 (0xffffffe, 28), 981 (0x7ffffec, 27), 982 (0x7ffffed, 27), 983 (0x7ffffee, 27), 984 (0x7ffffef, 27), 985 (0x7fffff0, 27), 986 (0x3ffffee, 26), 987 (0x3fffffff, 30) 988 ] 989 990 static_huffman_tree = None 991 992 @classmethod 993 def _huffman_encode_char(cls, c): 994 # type: (Union[str, EOS]) -> Tuple[int, int] 995 """ huffman_encode_char assumes that the static_huffman_tree was 996 previously initialized 997 998 @param str|EOS c: a symbol to encode 999 @return (int, int): the bitstring of the symbol and its bitlength 1000 @raise AssertionError 1001 """ 1002 if isinstance(c, EOS): 1003 return cls.static_huffman_code[-1] 1004 else: 1005 assert(isinstance(c, int) or len(c) == 1) 1006 return cls.static_huffman_code[orb(c)] 1007 1008 @classmethod 1009 def huffman_encode(cls, s): 1010 # type: (str) -> Tuple[int, int] 1011 """ huffman_encode returns the bitstring and the bitlength of the 1012 bitstring representing the string provided as a parameter 1013 1014 @param str s: the string to encode 1015 @return (int, int): the bitstring of s and its bitlength 1016 @raise AssertionError 1017 """ 1018 i = 0 1019 ibl = 0 1020 for c in s: 1021 val, bl = cls._huffman_encode_char(c) 1022 i = (i << bl) + val 1023 ibl += bl 1024 1025 padlen = 8 - (ibl % 8) 1026 if padlen != 8: 1027 val, bl = cls._huffman_encode_char(EOS()) 1028 i = (i << padlen) + (val >> (bl - padlen)) 1029 ibl += padlen 1030 1031 ret = i, ibl 1032 assert(ret[0] >= 0) 1033 assert (ret[1] >= 0) 1034 return ret 1035 1036 @classmethod 1037 def huffman_decode(cls, i, ibl): 1038 # type: (int, int) -> str 1039 """ huffman_decode decodes the bitstring provided as parameters. 1040 1041 @param int i: the bitstring to decode 1042 @param int ibl: the bitlength of i 1043 @return str: the string decoded from the bitstring 1044 @raise AssertionError, InvalidEncodingException 1045 """ 1046 assert(i >= 0) 1047 assert(ibl >= 0) 1048 1049 if isinstance(cls.static_huffman_tree, type(None)): 1050 cls.huffman_compute_decode_tree() 1051 assert(not isinstance(cls.static_huffman_tree, type(None))) 1052 1053 s = [] 1054 j = 0 1055 interrupted = False 1056 cur = cls.static_huffman_tree 1057 cur_sym = 0 1058 cur_sym_bl = 0 1059 while j < ibl: 1060 b = (i >> (ibl - j - 1)) & 1 1061 cur_sym = (cur_sym << 1) + b 1062 cur_sym_bl += 1 1063 elmt = cur[b] 1064 1065 if isinstance(elmt, HuffmanNode): 1066 interrupted = True 1067 cur = elmt 1068 if isinstance(cur, type(None)): 1069 raise AssertionError() 1070 elif isinstance(elmt, EOS): 1071 raise InvalidEncodingException('Huffman decoder met the full EOS symbol') 1072 elif isinstance(elmt, bytes): 1073 interrupted = False 1074 s.append(elmt) 1075 cur = cls.static_huffman_tree 1076 cur_sym = 0 1077 cur_sym_bl = 0 1078 else: 1079 raise InvalidEncodingException('Should never happen, so incidentally it will') 1080 j += 1 1081 1082 if interrupted: 1083 # Interrupted values true if the bitstring ends in the middle of a 1084 # symbol; this symbol must be, according to RFC7541 par5.2 the MSB 1085 # of the EOS symbol 1086 if cur_sym_bl > 7: 1087 raise InvalidEncodingException('Huffman decoder is detecting padding longer than 7 bits') 1088 eos_symbol = cls.static_huffman_code[-1] 1089 eos_msb = eos_symbol[0] >> (eos_symbol[1] - cur_sym_bl) 1090 if eos_msb != cur_sym: 1091 raise InvalidEncodingException('Huffman decoder is detecting unexpected padding format') 1092 return b''.join(s) 1093 1094 @classmethod 1095 def huffman_conv2str(cls, bit_str, bit_len): 1096 # type: (int, int) -> str 1097 """ huffman_conv2str converts a bitstring of bit_len bitlength into a 1098 binary string. It DOES NOT compress/decompress the bitstring! 1099 1100 @param int bit_str: the bitstring to convert. 1101 @param int bit_len: the bitlength of bit_str. 1102 @return str: the converted bitstring as a bytestring. 1103 @raise AssertionError 1104 """ 1105 assert(bit_str >= 0) 1106 assert(bit_len >= 0) 1107 1108 byte_len = bit_len // 8 1109 rem_bit = bit_len % 8 1110 if rem_bit != 0: 1111 bit_str <<= 8 - rem_bit 1112 byte_len += 1 1113 1114 # As usual the list/join tricks is a performance trick to build 1115 # efficiently a Python string 1116 s = [] # type: List[str] 1117 i = 0 1118 while i < byte_len: 1119 s.insert(0, chb((bit_str >> (i*8)) & 0xFF)) 1120 i += 1 1121 return b''.join(s) 1122 1123 @classmethod 1124 def huffman_conv2bitstring(cls, s): 1125 # type: (str) -> Tuple[int, int] 1126 """ huffman_conv2bitstring converts a string into its bitstring 1127 representation. It returns a tuple: the bitstring and its bitlength. 1128 This function DOES NOT compress/decompress the string! 1129 1130 @param str s: the bytestring to convert. 1131 @return (int, int): the bitstring of s, and its bitlength. 1132 @raise AssertionError 1133 """ 1134 i = 0 1135 ibl = len(s) * 8 1136 for c in s: 1137 i = (i << 8) + orb(c) 1138 1139 ret = i, ibl 1140 assert(ret[0] >= 0) 1141 assert(ret[1] >= 0) 1142 return ret 1143 1144 @classmethod 1145 def huffman_compute_decode_tree(cls): 1146 # type: () -> None 1147 """ huffman_compute_decode_tree initializes/builds the static_huffman_tree 1148 1149 @return None 1150 @raise InvalidEncodingException if there is an encoding problem 1151 """ 1152 cls.static_huffman_tree = HuffmanNode(None, None) 1153 i = 0 1154 for entry in cls.static_huffman_code: 1155 parent = cls.static_huffman_tree 1156 for idx in range(entry[1] - 1, -1, -1): 1157 b = (entry[0] >> idx) & 1 1158 if isinstance(parent[b], bytes): 1159 raise InvalidEncodingException('Huffman unique prefix violation :/') 1160 if idx == 0: 1161 parent[b] = chb(i) if i < 256 else EOS() 1162 elif parent[b] is None: 1163 parent[b] = HuffmanNode(None, None) 1164 parent = parent[b] 1165 i += 1 1166 1167 def __init__(self, s): 1168 # type: (str) -> None 1169 self._s = s 1170 i, ibl = type(self).huffman_encode(s) 1171 self._encoded = type(self).huffman_conv2str(i, ibl) 1172 1173 def __str__(self): 1174 # type: () -> str 1175 return self._encoded 1176 1177 def origin(self): 1178 # type: () -> str 1179 return plain_str(self._s) 1180 1181 def __len__(self): 1182 # type: () -> int 1183 return len(self._encoded) 1184 1185 1186 class HPackStrLenField(fields.Field): 1187 """ HPackStrLenField is a StrLenField variant specialized for HTTP/2 HPack 1188 1189 This variant uses an internal representation that implements HPackStringsInterface. 1190 """ 1191 __slots__ = ['_length_from', '_type_from'] 1192 1193 def __init__(self, name, default, length_from, type_from): 1194 # type: (str, HPackStringsInterface, Callable[[packet.Packet], int], str) -> None 1195 super(HPackStrLenField, self).__init__(name, default) 1196 self._length_from = length_from 1197 self._type_from = type_from 1198 1199 def addfield(self, pkt, s, val): 1200 # type: (Optional[packet.Packet], str, HPackStringsInterface) -> str 1201 return s + self.i2m(pkt, val) 1202 1203 @staticmethod 1204 def _parse(t, s): 1205 # type: (bool, str) -> HPackStringsInterface 1206 """ 1207 @param bool t: whether this string is a huffman compressed string. 1208 @param str s: the string to parse. 1209 @return HPackStringsInterface: either a HPackLiteralString or HPackZString, depending on t. 1210 @raise InvalidEncodingException 1211 """ 1212 if t: 1213 i, ibl = HPackZString.huffman_conv2bitstring(s) 1214 return HPackZString(HPackZString.huffman_decode(i, ibl)) 1215 return HPackLiteralString(s) 1216 1217 def getfield(self, pkt, s): 1218 # type: (packet.Packet, str) -> Tuple[str, HPackStringsInterface] 1219 """ 1220 @param packet.Packet pkt: the packet instance containing this field instance. 1221 @param str s: the string to parse this field from. 1222 @return (str, HPackStringsInterface): the remaining string after this field was carved out & the extracted 1223 value. 1224 @raise KeyError if "type_from" is not a field of pkt or its payloads. 1225 @raise InvalidEncodingException 1226 """ 1227 l = self._length_from(pkt) 1228 t = pkt.getfieldval(self._type_from) == 1 1229 return s[l:], self._parse(t, s[:l]) 1230 1231 def i2h(self, pkt, x): 1232 # type: (Optional[packet.Packet], HPackStringsInterface) -> str 1233 fmt = '' 1234 if isinstance(x, HPackLiteralString): 1235 fmt = "HPackLiteralString({})" 1236 elif isinstance(x, HPackZString): 1237 fmt = "HPackZString({})" 1238 return fmt.format(x.origin()) 1239 1240 def h2i(self, pkt, x): 1241 # type: (packet.Packet, str) -> HPackStringsInterface 1242 return HPackLiteralString(x) 1243 1244 def m2i(self, pkt, x): 1245 # type: (packet.Packet, str) -> HPackStringsInterface 1246 """ 1247 @param packet.Packet pkt: the packet instance containing this field instance. 1248 @param str x: the string to parse. 1249 @return HPackStringsInterface: the internal type of the value parsed from x. 1250 @raise AssertionError 1251 @raise InvalidEncodingException 1252 @raise KeyError if _type_from is not one of pkt fields. 1253 """ 1254 t = pkt.getfieldval(self._type_from) 1255 l = self._length_from(pkt) 1256 1257 assert t is not None and l is not None, 'Conversion from string impossible: no type or length specified' 1258 1259 return self._parse(t == 1, x[:l]) 1260 1261 def any2i(self, pkt, x): 1262 # type: (Optional[packet.Packet], Union[str, HPackStringsInterface]) -> HPackStringsInterface 1263 """ 1264 @param packet.Packet|None pkt: the packet instance containing this field instance. 1265 @param str|HPackStringsInterface x: the value to convert 1266 @return HPackStringsInterface: the Scapy internal value for this field 1267 @raise AssertionError, InvalidEncodingException 1268 """ 1269 if isinstance(x, bytes): 1270 assert(isinstance(pkt, packet.Packet)) 1271 return self.m2i(pkt, x) 1272 assert(isinstance(x, HPackStringsInterface)) 1273 return x 1274 1275 def i2m(self, pkt, x): 1276 # type: (Optional[packet.Packet], HPackStringsInterface) -> str 1277 return raw(x) 1278 1279 def i2len(self, pkt, x): 1280 # type: (Optional[packet.Packet], HPackStringsInterface) -> int 1281 return len(x) 1282 1283 def i2repr(self, pkt, x): 1284 # type: (Optional[packet.Packet], HPackStringsInterface) -> str 1285 return repr(self.i2h(pkt, x)) 1286 1287 ######################################################################################################################## 1288 ################################################ HPACK Packets ######################################################### 1289 ######################################################################################################################## 1290 1291 class HPackHdrString(packet.Packet): 1292 """ HPackHdrString is a packet that that is serialized into a RFC7541 par5.2 1293 string literal repr. 1294 """ 1295 name = 'HPack Header String' 1296 fields_desc = [ 1297 fields.BitEnumField('type', None, 1, {0: 'Literal', 1: 'Compressed'}), 1298 FieldUVarLenField('len', None, 7, length_of='data'), 1299 HPackStrLenField( 1300 'data', HPackLiteralString(''), 1301 length_from=lambda pkt: pkt.getfieldval('len'), 1302 type_from='type' 1303 ) 1304 ] 1305 1306 def guess_payload_class(self, payload): 1307 # type: (str) -> base_classes.Packet_metaclass 1308 # Trick to tell scapy that the remaining bytes of the currently 1309 # dissected string is not a payload of this packet but of some other 1310 # underlayer packet 1311 return config.conf.padding_layer 1312 1313 def self_build(self, field_pos_list=None): 1314 # type: (Any) -> str 1315 """self_build is overridden because type and len are determined at 1316 build time, based on the "data" field internal type 1317 """ 1318 if self.getfieldval('type') is None: 1319 self.type = 1 if isinstance(self.getfieldval('data'), HPackZString) else 0 1320 return super(HPackHdrString, self).self_build(field_pos_list) 1321 1322 1323 class HPackHeaders(packet.Packet): 1324 """HPackHeaders uses the "dispatch_hook" trick of Packet_metaclass to select 1325 the correct HPack header packet type. For this, the first byte of the string 1326 to dissect is snooped on. 1327 """ 1328 @classmethod 1329 def dispatch_hook(cls, s=None, *_args, **_kwds): 1330 # type: (Optional[str], *Any, **Any) -> base_classes.Packet_metaclass 1331 """dispatch_hook returns the subclass of HPackHeaders that must be used 1332 to dissect the string. 1333 """ 1334 if s is None: 1335 return config.conf.raw_layer 1336 fb = orb(s[0]) 1337 if fb & 0x80 != 0: 1338 return HPackIndexedHdr 1339 if fb & 0x40 != 0: 1340 return HPackLitHdrFldWithIncrIndexing 1341 if fb & 0x20 != 0: 1342 return HPackDynamicSizeUpdate 1343 return HPackLitHdrFldWithoutIndexing 1344 1345 def guess_payload_class(self, payload): 1346 # type: (str) -> base_classes.Packet_metaclass 1347 return config.conf.padding_layer 1348 1349 1350 class HPackIndexedHdr(HPackHeaders): 1351 """ HPackIndexedHdr implements RFC 7541 par6.1 1352 """ 1353 name = 'HPack Indexed Header Field' 1354 fields_desc = [ 1355 HPackMagicBitField('magic', 1, 1), 1356 UVarIntField('index', 2, 7) # Default "2" is ":method GET" 1357 ] 1358 1359 1360 class HPackLitHdrFldWithIncrIndexing(HPackHeaders): 1361 """ HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.1 1362 """ 1363 name = 'HPack Literal Header With Incremental Indexing' 1364 fields_desc = [ 1365 HPackMagicBitField('magic', 1, 2), 1366 UVarIntField('index', 0, 6), # Default is New Name 1367 fields.ConditionalField( 1368 fields.PacketField('hdr_name', None, HPackHdrString), 1369 lambda pkt: pkt.getfieldval('index') == 0 1370 ), 1371 fields.PacketField('hdr_value', None, HPackHdrString) 1372 ] 1373 1374 1375 class HPackLitHdrFldWithoutIndexing(HPackHeaders): 1376 """ HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.2 1377 and par6.2.3 1378 """ 1379 name = 'HPack Literal Header Without Indexing (or Never Indexing)' 1380 fields_desc = [ 1381 HPackMagicBitField('magic', 0, 3), 1382 fields.BitEnumField( 1383 'never_index', 0, 1, 1384 {0: "Don't Index", 1: 'Never Index'} 1385 ), 1386 UVarIntField('index', 0, 4), # Default is New Name 1387 fields.ConditionalField( 1388 fields.PacketField('hdr_name', None, HPackHdrString), 1389 lambda pkt: pkt.getfieldval('index') == 0 1390 ), 1391 fields.PacketField('hdr_value', None, HPackHdrString) 1392 ] 1393 1394 1395 class HPackDynamicSizeUpdate(HPackHeaders): 1396 """ HPackDynamicSizeUpdate implements RFC 7541 par6.3 1397 """ 1398 name = 'HPack Dynamic Size Update' 1399 fields_desc = [ 1400 HPackMagicBitField('magic', 1, 3), 1401 UVarIntField('max_size', 0, 5) 1402 ] 1403 1404 ######################################################################################################################## 1405 ############################################# HTTP/2 Frames ############################################################ 1406 ######################################################################################################################## 1407 1408 class H2FramePayload(packet.Packet): 1409 """ H2FramePayload is an empty class that is a super class of all Scapy 1410 HTTP/2 Frame Packets 1411 """ 1412 1413 ############################################# HTTP/2 Data Frame Packets ################################################ 1414 1415 class H2DataFrame(H2FramePayload): 1416 """ H2DataFrame implements RFC7540 par6.1 1417 This packet is the Data Frame to use when there is no padding. 1418 """ 1419 type_id = 0 1420 END_STREAM_FLAG = 0 # 0x1 1421 PADDED_FLAG = 3 # 0x8 1422 flags = { 1423 END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'), 1424 PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded') 1425 } 1426 1427 name = 'HTTP/2 Data Frame' 1428 fields_desc = [ 1429 fields.StrField('data', '') 1430 ] 1431 1432 1433 class H2PaddedDataFrame(H2DataFrame): 1434 """ H2DataFrame implements RFC7540 par6.1 1435 This packet is the Data Frame to use when there is padding. 1436 """ 1437 __slots__ = ['s_len'] 1438 1439 name = 'HTTP/2 Padded Data Frame' 1440 fields_desc = [ 1441 fields.FieldLenField('padlen', None, length_of='padding', fmt="B"), 1442 fields.StrLenField('data', '', 1443 length_from=lambda pkt: pkt.get_data_len() 1444 ), 1445 fields.StrLenField('padding', '', 1446 length_from=lambda pkt: pkt.getfieldval('padlen') 1447 ) 1448 ] 1449 1450 def get_data_len(self): 1451 # type: () -> int 1452 """ get_data_len computes the length of the data field 1453 1454 To do this computation, the length of the padlen field and the actual 1455 padding is subtracted to the string that was provided to the pre_dissect 1456 fun of the pkt parameter 1457 @return int; length of the data part of the HTTP/2 frame packet provided as parameter 1458 @raise AssertionError 1459 """ 1460 padding_len = self.getfieldval('padlen') 1461 fld, fval = self.getfield_and_val('padlen') 1462 padding_len_len = fld.i2len(self, fval) 1463 1464 ret = self.s_len - padding_len_len - padding_len 1465 assert(ret >= 0) 1466 return ret 1467 1468 def pre_dissect(self, s): 1469 # type: (str) -> str 1470 """pre_dissect is filling the s_len property of this instance. This 1471 property is later used during the getfield call of the "data" field when 1472 trying to evaluate the length of the StrLenField! This "trick" works 1473 because the underlayer packet (H2Frame) is assumed to override the 1474 "extract_padding" method and to only provide to this packet the data 1475 necessary for this packet. Tricky, tricky, will break some day probably! 1476 """ 1477 self.s_len = len(s) 1478 return s 1479 1480 1481 ############################################# HTTP/2 Header Frame Packets ############################################## 1482 1483 class H2AbstractHeadersFrame(H2FramePayload): 1484 """Superclass of all variants of HTTP/2 Header Frame Packets. 1485 May be used for type checking. 1486 """ 1487 1488 class H2HeadersFrame(H2AbstractHeadersFrame): 1489 """ H2HeadersFrame implements RFC 7540 par6.2 Headers Frame 1490 when there is no padding and no priority informations 1491 1492 The choice of decomposing into four classes is probably preferable to having 1493 numerous conditional fields based on the underlayer :/ 1494 """ 1495 type_id = 1 1496 END_STREAM_FLAG = 0 # 0x1 1497 END_HEADERS_FLAG = 2 # 0x4 1498 PADDED_FLAG = 3 # 0x8 1499 PRIORITY_FLAG = 5 # 0x20 1500 flags = { 1501 END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'), 1502 END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'), 1503 PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded'), 1504 PRIORITY_FLAG: fields.MultiFlagsEntry('+', 'Priority') 1505 } 1506 1507 name = 'HTTP/2 Headers Frame' 1508 fields_desc = [ 1509 fields.PacketListField('hdrs', [], HPackHeaders) 1510 ] 1511 1512 1513 class H2PaddedHeadersFrame(H2AbstractHeadersFrame): 1514 """ H2PaddedHeadersFrame is the variant of H2HeadersFrame where padding flag 1515 is set and priority flag is cleared 1516 """ 1517 __slots__ = ['s_len'] 1518 1519 name = 'HTTP/2 Headers Frame with Padding' 1520 fields_desc = [ 1521 fields.FieldLenField('padlen', None, length_of='padding', fmt='B'), 1522 fields.PacketListField('hdrs', [], HPackHeaders, 1523 length_from=lambda pkt: pkt.get_hdrs_len() 1524 ), 1525 fields.StrLenField('padding', '', 1526 length_from=lambda pkt: pkt.getfieldval('padlen') 1527 ) 1528 ] 1529 1530 def get_hdrs_len(self): 1531 # type: () -> int 1532 """ get_hdrs_len computes the length of the hdrs field 1533 1534 To do this computation, the length of the padlen field and the actual 1535 padding is subtracted to the string that was provided to the pre_dissect 1536 fun of the pkt parameter. 1537 @return int; length of the data part of the HTTP/2 frame packet provided as parameter 1538 @raise AssertionError 1539 """ 1540 padding_len = self.getfieldval('padlen') 1541 fld, fval = self.getfield_and_val('padlen') 1542 padding_len_len = fld.i2len(self, fval) 1543 1544 ret = self.s_len - padding_len_len - padding_len 1545 assert(ret >= 0) 1546 return ret 1547 1548 def pre_dissect(self, s): 1549 # type: (str) -> str 1550 """pre_dissect is filling the s_len property of this instance. This 1551 property is later used during the parsing of the hdrs PacketListField 1552 when trying to evaluate the length of the PacketListField! This "trick" 1553 works because the underlayer packet (H2Frame) is assumed to override the 1554 "extract_padding" method and to only provide to this packet the data 1555 necessary for this packet. Tricky, tricky, will break some day probably! 1556 """ 1557 self.s_len = len(s) 1558 return s 1559 1560 1561 class H2PriorityHeadersFrame(H2AbstractHeadersFrame): 1562 """ H2PriorityHeadersFrame is the variant of H2HeadersFrame where priority flag 1563 is set and padding flag is cleared 1564 """ 1565 __slots__ = ['s_len'] 1566 1567 name = 'HTTP/2 Headers Frame with Priority' 1568 fields_desc = [ 1569 fields.BitField('exclusive', 0, 1), 1570 fields.BitField('stream_dependency', 0, 31), 1571 fields.ByteField('weight', 0), 1572 # This PacketListField will consume all remaining bytes; not a problem 1573 # because the underlayer (H2Frame) overrides "extract_padding" so that 1574 # this Packet only get to parser what it needs to 1575 fields.PacketListField('hdrs', [], HPackHeaders), 1576 ] 1577 1578 1579 class H2PaddedPriorityHeadersFrame(H2AbstractHeadersFrame): 1580 """ H2PaddedPriorityHeadersFrame is the variant of H2HeadersFrame where 1581 both priority and padding flags are set 1582 """ 1583 __slots__ = ['s_len'] 1584 1585 name = 'HTTP/2 Headers Frame with Padding and Priority' 1586 fields_desc = [ 1587 fields.FieldLenField('padlen', None, length_of='padding', fmt='B'), 1588 fields.BitField('exclusive', 0, 1), 1589 fields.BitField('stream_dependency', 0, 31), 1590 fields.ByteField('weight', 0), 1591 fields.PacketListField('hdrs', [], HPackHeaders, 1592 length_from=lambda pkt: pkt.get_hdrs_len() 1593 ), 1594 fields.StrLenField('padding', '', 1595 length_from=lambda pkt: pkt.getfieldval('padlen') 1596 ) 1597 ] 1598 1599 def get_hdrs_len(self): 1600 # type: () -> int 1601 """ get_hdrs_len computes the length of the hdrs field 1602 1603 To do this computation, the length of the padlen field, the priority 1604 information fields and the actual padding is subtracted to the string 1605 that was provided to the pre_dissect fun of the pkt parameter. 1606 @return int: the length of the hdrs field 1607 @raise AssertionError 1608 """ 1609 1610 padding_len = self.getfieldval('padlen') 1611 fld, fval = self.getfield_and_val('padlen') 1612 padding_len_len = fld.i2len(self, fval) 1613 bit_cnt = self.get_field('exclusive').size 1614 bit_cnt += self.get_field('stream_dependency').size 1615 fld, fval = self.getfield_and_val('weight') 1616 weight_len = fld.i2len(self, fval) 1617 ret = int(self.s_len 1618 - padding_len_len 1619 - padding_len 1620 - (bit_cnt / 8) 1621 - weight_len 1622 ) 1623 assert(ret >= 0) 1624 return ret 1625 1626 def pre_dissect(self, s): 1627 # type: (str) -> str 1628 """pre_dissect is filling the s_len property of this instance. This 1629 property is later used during the parsing of the hdrs PacketListField 1630 when trying to evaluate the length of the PacketListField! This "trick" 1631 works because the underlayer packet (H2Frame) is assumed to override the 1632 "extract_padding" method and to only provide to this packet the data 1633 necessary for this packet. Tricky, tricky, will break some day probably! 1634 """ 1635 self.s_len = len(s) 1636 return s 1637 1638 ########################################### HTTP/2 Priority Frame Packets ############################################## 1639 1640 class H2PriorityFrame(H2FramePayload): 1641 """ H2PriorityFrame implements RFC 7540 par6.3 1642 """ 1643 type_id = 2 1644 name = 'HTTP/2 Priority Frame' 1645 fields_desc = [ 1646 fields.BitField('exclusive', 0, 1), 1647 fields.BitField('stream_dependency', 0, 31), 1648 fields.ByteField('weight', 0) 1649 ] 1650 1651 ################################################# HTTP/2 Errors ######################################################## 1652 1653 class H2ErrorCodes(object): 1654 """ H2ErrorCodes is an enumeration of the error codes defined in 1655 RFC7540 par7. 1656 This enumeration is not part of any frame because the error codes are in 1657 common with H2ResetFrame and H2GoAwayFrame. 1658 """ 1659 1660 NO_ERROR = 0x0 1661 PROTOCOL_ERROR = 0x1 1662 INTERNAL_ERROR = 0x2 1663 FLOW_CONTROL_ERROR = 0x3 1664 SETTINGS_TIMEOUT = 0x4 1665 STREAM_CLOSED = 0x5 1666 FRAME_SIZE_ERROR = 0x6 1667 REFUSED_STREAM = 0x7 1668 CANCEL = 0x8 1669 COMPRESSION_ERROR = 0x9 1670 CONNECT_ERROR = 0xa 1671 ENHANCE_YOUR_CALM = 0xb 1672 INADEQUATE_SECURITY = 0xc 1673 HTTP_1_1_REQUIRED = 0xd 1674 1675 literal = { 1676 NO_ERROR: 'No error', 1677 PROTOCOL_ERROR: 'Protocol error', 1678 INTERNAL_ERROR: 'Internal error', 1679 FLOW_CONTROL_ERROR: 'Flow control error', 1680 SETTINGS_TIMEOUT: 'Settings timeout', 1681 STREAM_CLOSED: 'Stream closed', 1682 FRAME_SIZE_ERROR: 'Frame size error', 1683 REFUSED_STREAM: 'Refused stream', 1684 CANCEL: 'Cancel', 1685 COMPRESSION_ERROR: 'Compression error', 1686 CONNECT_ERROR: 'Control error', 1687 ENHANCE_YOUR_CALM: 'Enhance your calm', 1688 INADEQUATE_SECURITY: 'Inadequate security', 1689 HTTP_1_1_REQUIRED: 'HTTP/1.1 required' 1690 } 1691 1692 1693 ########################################### HTTP/2 Reset Frame Packets ################################################# 1694 1695 class H2ResetFrame(H2FramePayload): 1696 """ H2ResetFrame implements RFC 7540 par6.4 1697 """ 1698 type_id = 3 1699 name = 'HTTP/2 Reset Frame' 1700 fields_desc = [ 1701 fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I') 1702 ] 1703 1704 1705 ########################################### HTTP/2 Settings Frame Packets ############################################## 1706 1707 class H2Setting(packet.Packet): 1708 """ H2Setting implements a setting, as defined in RFC7540 par6.5.1 1709 """ 1710 SETTINGS_HEADER_TABLE_SIZE = 0x1 1711 SETTINGS_ENABLE_PUSH = 0x2 1712 SETTINGS_MAX_CONCURRENT_STREAMS = 0x3 1713 SETTINGS_INITIAL_WINDOW_SIZE = 0x4 1714 SETTINGS_MAX_FRAME_SIZE = 0x5 1715 SETTINGS_MAX_HEADER_LIST_SIZE = 0x6 1716 1717 name = 'HTTP/2 Setting' 1718 fields_desc = [ 1719 fields.EnumField('id', 0, { 1720 SETTINGS_HEADER_TABLE_SIZE: 'Header table size', 1721 SETTINGS_ENABLE_PUSH: 'Enable push', 1722 SETTINGS_MAX_CONCURRENT_STREAMS: 'Max concurrent streams', 1723 SETTINGS_INITIAL_WINDOW_SIZE: 'Initial window size', 1724 SETTINGS_MAX_FRAME_SIZE: 'Max frame size', 1725 SETTINGS_MAX_HEADER_LIST_SIZE: 'Max header list size' 1726 }, fmt='!H'), 1727 fields.IntField('value', 0) 1728 ] 1729 1730 def guess_payload_class(self, payload): 1731 # type: (str) -> base_classes.Packet_metaclass 1732 return config.conf.padding_layer 1733 1734 1735 class H2SettingsFrame(H2FramePayload): 1736 """ H2SettingsFrame implements RFC7540 par6.5 1737 """ 1738 type_id = 4 1739 ACK_FLAG = 0 # 0x1 1740 flags = { 1741 ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK') 1742 } 1743 1744 name = 'HTTP/2 Settings Frame' 1745 fields_desc = [ 1746 fields.PacketListField('settings', [], H2Setting) 1747 ] 1748 1749 def __init__(self, *args, **kwargs): 1750 """__init__ initializes this H2SettingsFrame 1751 1752 If a _pkt arg is provided (by keyword), then this is an initialization 1753 from a string to dissect and therefore the length of the string to 1754 dissect have distinctive characteristics that we might want to check. 1755 This is possible because the underlayer packet (H2Frame) overrides 1756 extract_padding method to provided only the string that must be parsed 1757 by this packet! 1758 @raise AssertionError 1759 """ 1760 1761 # RFC7540 par6.5 p36 1762 assert( 1763 len(args) == 0 or ( 1764 isinstance(args[0], bytes) 1765 and len(args[0]) % 6 == 0 1766 ) 1767 ), 'Invalid settings frame; length is not a multiple of 6' 1768 super(H2SettingsFrame, self).__init__(*args, **kwargs) 1769 1770 ######################################## HTTP/2 Push Promise Frame Packets ############################################# 1771 1772 class H2PushPromiseFrame(H2FramePayload): 1773 """ H2PushPromiseFrame implements RFC7540 par6.6. This packet 1774 is the variant to use when the underlayer padding flag is cleared 1775 """ 1776 type_id = 5 1777 END_HEADERS_FLAG = 2 # 0x4 1778 PADDED_FLAG = 3 # 0x8 1779 flags = { 1780 END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'), 1781 PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded') 1782 } 1783 1784 name = 'HTTP/2 Push Promise Frame' 1785 fields_desc = [ 1786 fields.BitField('reserved', 0, 1), 1787 fields.BitField('stream_id', 0, 31), 1788 fields.PacketListField('hdrs', [], HPackHeaders) 1789 ] 1790 1791 1792 class H2PaddedPushPromiseFrame(H2PushPromiseFrame): 1793 """ H2PaddedPushPromiseFrame implements RFC7540 par6.6. This 1794 packet is the variant to use when the underlayer padding flag is set 1795 """ 1796 __slots__ = ['s_len'] 1797 1798 name = 'HTTP/2 Padded Push Promise Frame' 1799 fields_desc = [ 1800 fields.FieldLenField('padlen', None, length_of='padding', fmt='B'), 1801 fields.BitField('reserved', 0, 1), 1802 fields.BitField('stream_id', 0, 31), 1803 fields.PacketListField('hdrs', [], HPackHeaders, 1804 length_from=lambda pkt: pkt.get_hdrs_len() 1805 ), 1806 fields.StrLenField('padding', '', 1807 length_from=lambda pkt: pkt.getfieldval('padlen') 1808 ) 1809 ] 1810 1811 def get_hdrs_len(self): 1812 # type: () -> int 1813 """ get_hdrs_len computes the length of the hdrs field 1814 1815 To do this computation, the length of the padlen field, reserved, 1816 stream_id and the actual padding is subtracted to the string that was 1817 provided to the pre_dissect fun of the pkt parameter. 1818 @return int: the length of the hdrs field 1819 @raise AssertionError 1820 """ 1821 fld, padding_len = self.getfield_and_val('padlen') 1822 padding_len_len = fld.i2len(self, padding_len) 1823 bit_len = self.get_field('reserved').size 1824 bit_len += self.get_field('stream_id').size 1825 1826 ret = int(self.s_len 1827 - padding_len_len 1828 - padding_len 1829 - (bit_len / 8) 1830 ) 1831 assert(ret >= 0) 1832 return ret 1833 1834 def pre_dissect(self, s): 1835 # type: (str) -> str 1836 """pre_dissect is filling the s_len property of this instance. This 1837 property is later used during the parsing of the hdrs PacketListField 1838 when trying to evaluate the length of the PacketListField! This "trick" 1839 works because the underlayer packet (H2Frame) is assumed to override the 1840 "extract_padding" method and to only provide to this packet the data 1841 necessary for this packet. Tricky, tricky, will break some day probably! 1842 """ 1843 self.s_len = len(s) 1844 return s 1845 1846 ############################################### HTTP/2 Ping Frame Packets ############################################## 1847 1848 class H2PingFrame(H2FramePayload): 1849 """ H2PingFrame implements the RFC 7540 par6.7 1850 """ 1851 type_id = 6 1852 ACK_FLAG = 0 # 0x1 1853 flags = { 1854 ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK') 1855 } 1856 1857 name = 'HTTP/2 Ping Frame' 1858 fields_desc = [ 1859 fields.LongField('opaque', 0) 1860 ] 1861 1862 def __init__(self, *args, **kwargs): 1863 """ 1864 @raise AssertionError 1865 """ 1866 # RFC7540 par6.7 p42 1867 assert( 1868 len(args) == 0 or ( 1869 (isinstance(args[0], bytes) or 1870 isinstance(args[0], str)) 1871 and len(args[0]) == 8 1872 ) 1873 ), 'Invalid ping frame; length is not 8' 1874 super(H2PingFrame, self).__init__(*args, **kwargs) 1875 1876 1877 ############################################# HTTP/2 GoAway Frame Packets ############################################## 1878 1879 class H2GoAwayFrame(H2FramePayload): 1880 """ H2GoAwayFrame implements the RFC 7540 par6.8 1881 """ 1882 type_id = 7 1883 1884 name = 'HTTP/2 Go Away Frame' 1885 fields_desc = [ 1886 fields.BitField('reserved', 0, 1), 1887 fields.BitField('last_stream_id', 0, 31), 1888 fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I'), 1889 fields.StrField('additional_data', '') 1890 ] 1891 1892 ###################################### HTTP/2 Window Update Frame Packets ############################################## 1893 1894 class H2WindowUpdateFrame(H2FramePayload): 1895 """ H2WindowUpdateFrame implements the RFC 7540 par6.9 1896 """ 1897 type_id = 8 1898 1899 name = 'HTTP/2 Window Update Frame' 1900 fields_desc = [ 1901 fields.BitField('reserved', 0, 1), 1902 fields.BitField('win_size_incr', 0, 31) 1903 ] 1904 1905 def __init__(self, *args, **kwargs): 1906 """ 1907 @raise AssertionError 1908 """ 1909 # RFC7540 par6.9 p46 1910 assert( 1911 len(args) == 0 or ( 1912 (isinstance(args[0], bytes) or 1913 isinstance(args[0], str)) 1914 and len(args[0]) == 4 1915 ) 1916 ), 'Invalid window update frame; length is not 4' 1917 super(H2WindowUpdateFrame, self).__init__(*args, **kwargs) 1918 1919 ####################################### HTTP/2 Continuation Frame Packets ############################################## 1920 1921 class H2ContinuationFrame(H2FramePayload): 1922 """ H2ContinuationFrame implements the RFC 7540 par6.10 1923 """ 1924 type_id = 9 1925 END_HEADERS_FLAG = 2 # Ox4 1926 flags = { 1927 END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers') 1928 } 1929 1930 name = 'HTTP/2 Continuation Frame' 1931 fields_desc = [ 1932 fields.PacketListField('hdrs', [], HPackHeaders) 1933 ] 1934 1935 ########################################## HTTP/2 Base Frame Packets ################################################### 1936 1937 class H2Frame(packet.Packet): 1938 """ H2Frame implements the frame structure as defined in RFC 7540 par4.1 1939 1940 This packet may have a payload (one of the H2FramePayload) or none, in some 1941 rare cases such as settings acknowledgement) 1942 """ 1943 name = 'HTTP/2 Frame' 1944 fields_desc = [ 1945 fields.X3BytesField('len', None), 1946 fields.EnumField('type', None, { 1947 0: 'DataFrm', 1948 1: 'HdrsFrm', 1949 2: 'PrioFrm', 1950 3: 'RstFrm', 1951 4: 'SetFrm', 1952 5: 'PushFrm', 1953 6: 'PingFrm', 1954 7: 'GoawayFrm', 1955 8: 'WinFrm', 1956 9: 'ContFrm' 1957 }, "b"), 1958 fields.MultiFlagsField('flags', set(), 8, { 1959 H2DataFrame.type_id: H2DataFrame.flags, 1960 H2HeadersFrame.type_id: H2HeadersFrame.flags, 1961 H2PushPromiseFrame.type_id: H2PushPromiseFrame.flags, 1962 H2SettingsFrame.type_id: H2SettingsFrame.flags, 1963 H2PingFrame.type_id: H2PingFrame.flags, 1964 H2ContinuationFrame.type_id: H2ContinuationFrame.flags, 1965 }, 1966 depends_on=lambda pkt: pkt.getfieldval('type') 1967 ), 1968 fields.BitField('reserved', 0, 1), 1969 fields.BitField('stream_id', 0, 31) 1970 ] 1971 1972 def guess_payload_class(self, payload): 1973 # type: (str) -> base_classes.Packet_metaclass 1974 """ guess_payload_class returns the Class object to use for parsing a payload 1975 This function uses the H2Frame.type field value to decide which payload to parse. The implement cannot be 1976 performed using the simple bind_layers helper because sometimes the selection of which Class object to return 1977 also depends on the H2Frame.flags value. 1978 1979 @param payload: 1980 @return: 1981 """ 1982 if len(payload) == 0: 1983 return packet.NoPayload 1984 1985 t = self.getfieldval('type') 1986 if t == H2DataFrame.type_id: 1987 if H2DataFrame.flags[H2DataFrame.PADDED_FLAG].short in self.getfieldval('flags'): 1988 return H2PaddedDataFrame 1989 return H2DataFrame 1990 1991 if t == H2HeadersFrame.type_id: 1992 if H2HeadersFrame.flags[H2HeadersFrame.PADDED_FLAG].short in self.getfieldval('flags'): 1993 if H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'): 1994 return H2PaddedPriorityHeadersFrame 1995 else: 1996 return H2PaddedHeadersFrame 1997 elif H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'): 1998 return H2PriorityHeadersFrame 1999 return H2HeadersFrame 2000 2001 if t == H2PriorityFrame.type_id: 2002 return H2PriorityFrame 2003 2004 if t == H2ResetFrame.type_id: 2005 return H2ResetFrame 2006 2007 if t == H2SettingsFrame.type_id: 2008 return H2SettingsFrame 2009 2010 if t == H2PushPromiseFrame.type_id: 2011 if H2PushPromiseFrame.flags[H2PushPromiseFrame.PADDED_FLAG].short in self.getfieldval('flags'): 2012 return H2PaddedPushPromiseFrame 2013 return H2PushPromiseFrame 2014 2015 if t == H2PingFrame.type_id: 2016 return H2PingFrame 2017 2018 if t == H2GoAwayFrame.type_id: 2019 return H2GoAwayFrame 2020 2021 if t == H2WindowUpdateFrame.type_id: 2022 return H2WindowUpdateFrame 2023 2024 if t == H2ContinuationFrame.type_id: 2025 return H2ContinuationFrame 2026 2027 return config.conf.padding_layer 2028 2029 def extract_padding(self, s): 2030 # type: (str) -> Tuple[str, str] 2031 """ 2032 @param str s: the string from which to tell the padding and the payload data apart 2033 @return (str, str): the padding and the payload data strings 2034 @raise AssertionError 2035 """ 2036 assert isinstance(self.len, six.integer_types) and self.len >= 0, 'Invalid length: negative len?' 2037 assert len(s) >= self.len, 'Invalid length: string too short for this length' 2038 return s[:self.len], s[self.len:] 2039 2040 def post_build(self, p, pay): 2041 # type: (str, str) -> str 2042 """ 2043 @param str p: the stringified packet 2044 @param str pay: the stringified payload 2045 @return str: the stringified packet and payload, with the packet length field "patched" 2046 @raise AssertionError 2047 """ 2048 # This logic, while awkward in the post_build and more reasonable in 2049 # a self_build is implemented here for performance tricks reason 2050 if self.getfieldval('len') is None: 2051 assert(len(pay) < (1 << 24)), 'Invalid length: payload is too long' 2052 p = struct.pack('!L', len(pay))[1:] + p[3:] 2053 return super(H2Frame, self).post_build(p, pay) 2054 2055 class H2Seq(packet.Packet): 2056 """ H2Seq is a helper packet that contains several H2Frames and their 2057 payload. This packet can be used, for instance, while reading manually from 2058 a TCP socket. 2059 """ 2060 name = 'HTTP/2 Frame Sequence' 2061 fields_desc = [ 2062 fields.PacketListField('frames', [], H2Frame) 2063 ] 2064 2065 def guess_payload_class(self, payload): 2066 # type: (str) -> base_classes.Packet_metaclass 2067 return config.conf.padding_layer 2068 2069 2070 packet.bind_layers(H2Frame, H2DataFrame, {'type': H2DataFrame.type_id}) 2071 packet.bind_layers(H2Frame, H2PaddedDataFrame, {'type': H2DataFrame.type_id}) 2072 packet.bind_layers(H2Frame, H2HeadersFrame, {'type': H2HeadersFrame.type_id}) 2073 packet.bind_layers(H2Frame, H2PaddedHeadersFrame, {'type': H2HeadersFrame.type_id}) 2074 packet.bind_layers(H2Frame, H2PriorityHeadersFrame, {'type': H2HeadersFrame.type_id}) 2075 packet.bind_layers(H2Frame, H2PaddedPriorityHeadersFrame, {'type': H2HeadersFrame.type_id}) 2076 packet.bind_layers(H2Frame, H2PriorityFrame, {'type': H2PriorityFrame.type_id}) 2077 packet.bind_layers(H2Frame, H2ResetFrame, {'type': H2ResetFrame.type_id}) 2078 packet.bind_layers(H2Frame, H2SettingsFrame, {'type': H2SettingsFrame.type_id}) 2079 packet.bind_layers(H2Frame, H2PingFrame, {'type': H2PingFrame.type_id}) 2080 packet.bind_layers(H2Frame, H2PushPromiseFrame, {'type': H2PushPromiseFrame.type_id}) 2081 packet.bind_layers(H2Frame, H2PaddedPushPromiseFrame, {'type': H2PaddedPushPromiseFrame.type_id}) 2082 packet.bind_layers(H2Frame, H2GoAwayFrame, {'type': H2GoAwayFrame.type_id}) 2083 packet.bind_layers(H2Frame, H2WindowUpdateFrame, {'type': H2WindowUpdateFrame.type_id}) 2084 packet.bind_layers(H2Frame, H2ContinuationFrame, {'type': H2ContinuationFrame.type_id}) 2085 2086 2087 ########################################## HTTP/2 Connection Preface ################################################### 2088 # From RFC 7540 par3.5 2089 H2_CLIENT_CONNECTION_PREFACE = bytes_hex('505249202a20485454502f322e300d0a0d0a534d0d0a0d0a') 2090 2091 2092 ######################################################################################################################## 2093 ################################################### HTTP/2 Helpers ##################################################### 2094 ######################################################################################################################## 2095 2096 class HPackHdrEntry(Sized): 2097 """ HPackHdrEntry is an entry of the HPackHdrTable helper 2098 2099 Each HPackHdrEntry instance is a header line (name and value). Names are 2100 normalized (lowercased), according to RFC 7540 par8.1.2 2101 """ 2102 __slots__ = ['_name', '_len', '_value'] 2103 2104 def __init__(self, name, value): 2105 # type: (str, str) -> None 2106 """ 2107 @raise AssertionError 2108 """ 2109 assert(len(name) > 0) 2110 2111 self._name = name.lower() 2112 self._value = value 2113 2114 # 32 bytes is an RFC-hardcoded value: see RFC 7541 par4.1 2115 self._len = (32 + len(self._name) + len(self._value)) 2116 2117 def name(self): 2118 # type: () -> str 2119 return self._name 2120 2121 def value(self): 2122 # type: () -> str 2123 return self._value 2124 2125 def size(self): 2126 # type: () -> int 2127 """ size returns the "length" of the header entry, as defined in 2128 RFC 7541 par4.1. 2129 """ 2130 return self._len 2131 2132 __len__ = size 2133 2134 def __str__(self): 2135 # type: () -> str 2136 """ __str__ returns the header as it would be formated in textual format 2137 """ 2138 if self._name.startswith(':'): 2139 return "{} {}".format(self._name, self._value) 2140 else: 2141 return "{}: {}".format(self._name, self._value) 2142 def __bytes__(self): 2143 return raw(self.__str__()) 2144 2145 2146 class HPackHdrTable(Sized): 2147 """ HPackHdrTable is a helper class that implements some of the logic 2148 associated with indexing of headers (read and write operations in this 2149 "registry". THe HPackHdrTable also implements convenience functions to easily 2150 convert to and from textual representation and binary representation of 2151 a HTTP/2 requests 2152 """ 2153 __slots__ = [ 2154 '_dynamic_table', 2155 '_dynamic_table_max_size', 2156 '_dynamic_table_cap_size', 2157 '_regexp' 2158 ] 2159 """:var _dynamic_table: the list containing entries requested to be added by 2160 the peer and registered with a register() call 2161 :var _dynamic_table_max_size: the current maximum size of the dynamic table 2162 in bytes. This value is updated with the Dynamic Table Size Update messages 2163 defined in RFC 7541 par6.3 2164 :var _dynamic_table_cap_size: the maximum size of the dynamic table in 2165 bytes. This value is updated with the SETTINGS_HEADER_TABLE_SIZE HTTP/2 2166 setting. 2167 """ 2168 2169 # Manually imported from RFC 7541 Appendix A 2170 _static_entries = { 2171 1: HPackHdrEntry(':authority', ''), 2172 2: HPackHdrEntry(':method', 'GET'), 2173 3: HPackHdrEntry(':method', 'POST'), 2174 4: HPackHdrEntry(':path', '/'), 2175 5: HPackHdrEntry(':path', '/index.html'), 2176 6: HPackHdrEntry(':scheme', 'http'), 2177 7: HPackHdrEntry(':scheme', 'https'), 2178 8: HPackHdrEntry(':status', '200'), 2179 9: HPackHdrEntry(':status', '204'), 2180 10: HPackHdrEntry(':status', '206'), 2181 11: HPackHdrEntry(':status', '304'), 2182 12: HPackHdrEntry(':status', '400'), 2183 13: HPackHdrEntry(':status', '404'), 2184 14: HPackHdrEntry(':status', '500'), 2185 15: HPackHdrEntry('accept-charset', ''), 2186 16: HPackHdrEntry('accept-encoding', 'gzip, deflate'), 2187 17: HPackHdrEntry('accept-language', ''), 2188 18: HPackHdrEntry('accept-ranges', ''), 2189 19: HPackHdrEntry('accept', ''), 2190 20: HPackHdrEntry('access-control-allow-origin', ''), 2191 21: HPackHdrEntry('age', ''), 2192 22: HPackHdrEntry('allow', ''), 2193 23: HPackHdrEntry('authorization', ''), 2194 24: HPackHdrEntry('cache-control', ''), 2195 25: HPackHdrEntry('content-disposition', ''), 2196 26: HPackHdrEntry('content-encoding', ''), 2197 27: HPackHdrEntry('content-language', ''), 2198 28: HPackHdrEntry('content-length', ''), 2199 29: HPackHdrEntry('content-location', ''), 2200 30: HPackHdrEntry('content-range', ''), 2201 31: HPackHdrEntry('content-type', ''), 2202 32: HPackHdrEntry('cookie', ''), 2203 33: HPackHdrEntry('date', ''), 2204 34: HPackHdrEntry('etag', ''), 2205 35: HPackHdrEntry('expect', ''), 2206 36: HPackHdrEntry('expires', ''), 2207 37: HPackHdrEntry('from', ''), 2208 38: HPackHdrEntry('host', ''), 2209 39: HPackHdrEntry('if-match', ''), 2210 40: HPackHdrEntry('if-modified-since', ''), 2211 41: HPackHdrEntry('if-none-match', ''), 2212 42: HPackHdrEntry('if-range', ''), 2213 43: HPackHdrEntry('if-unmodified-since', ''), 2214 44: HPackHdrEntry('last-modified', ''), 2215 45: HPackHdrEntry('link', ''), 2216 46: HPackHdrEntry('location', ''), 2217 47: HPackHdrEntry('max-forwards', ''), 2218 48: HPackHdrEntry('proxy-authenticate', ''), 2219 49: HPackHdrEntry('proxy-authorization', ''), 2220 50: HPackHdrEntry('range', ''), 2221 51: HPackHdrEntry('referer', ''), 2222 52: HPackHdrEntry('refresh', ''), 2223 53: HPackHdrEntry('retry-after', ''), 2224 54: HPackHdrEntry('server', ''), 2225 55: HPackHdrEntry('set-cookie', ''), 2226 56: HPackHdrEntry('strict-transport-security', ''), 2227 57: HPackHdrEntry('transfer-encoding', ''), 2228 58: HPackHdrEntry('user-agent', ''), 2229 59: HPackHdrEntry('vary', ''), 2230 60: HPackHdrEntry('via', ''), 2231 61: HPackHdrEntry('www-authenticate', ''), 2232 } 2233 2234 # The value of this variable cannot be determined at declaration time. It is 2235 # initialized by an init_static_table call 2236 _static_entries_last_idx = None 2237 2238 @classmethod 2239 def init_static_table(cls): 2240 # type: () -> None 2241 cls._static_entries_last_idx = max(cls._static_entries) 2242 2243 def __init__(self, dynamic_table_max_size=4096, dynamic_table_cap_size=4096): 2244 # type: (int, int) -> None 2245 """ 2246 @param int dynamic_table_max_size: the current maximum size of the dynamic entry table in bytes 2247 @param int dynamic_table_cap_size: the maximum-maximum size of the dynamic entry table in bytes 2248 @raises AssertionError 2249 """ 2250 self._regexp = None 2251 if isinstance(type(self)._static_entries_last_idx, type(None)): 2252 type(self).init_static_table() 2253 2254 assert dynamic_table_max_size <= dynamic_table_cap_size, \ 2255 'EINVAL: dynamic_table_max_size too large; expected value is less or equal to dynamic_table_cap_size' 2256 2257 self._dynamic_table = [] # type: List[HPackHdrEntry] 2258 self._dynamic_table_max_size = dynamic_table_max_size 2259 self._dynamic_table_cap_size = dynamic_table_cap_size 2260 2261 def __getitem__(self, idx): 2262 # type: (int) -> HPackHdrEntry 2263 """Gets an element from the header tables (static or dynamic indifferently) 2264 2265 @param int idx: the index number of the entry to retrieve. If the index 2266 value is superior to the last index of the static entry table, then the 2267 dynamic entry type is requested, following the procedure described in 2268 RFC 7541 par2.3.3 2269 @return HPackHdrEntry: the entry defined at this requested index. If the entry does not exist, KeyError is 2270 raised 2271 @raise KeyError, AssertionError 2272 """ 2273 assert(idx >= 0) 2274 if idx > type(self)._static_entries_last_idx: 2275 idx -= type(self)._static_entries_last_idx + 1 2276 if idx >= len(self._dynamic_table): 2277 raise KeyError( 2278 'EINVAL: idx: out-of-bound read: {}; maximum index: {}'.format(idx, len(self._dynamic_table)) 2279 ) 2280 return self._dynamic_table[idx] 2281 return type(self)._static_entries[idx] 2282 2283 def resize(self, ns): 2284 # type: (int) -> None 2285 """Resize the dynamic table. If the new size (ns) must be between 0 and 2286 the cap size. If the new size is lower than the current size of the 2287 dynamic table, entries are evicted. 2288 @param int ns: the new size of the dynamic table 2289 @raise AssertionError 2290 """ 2291 assert 0 <= ns <= self._dynamic_table_cap_size, \ 2292 'EINVAL: ns: out-of-range value; expected value is in the range [0;{}['.format(self._dynamic_table_cap_size) 2293 2294 old_size = self._dynamic_table_max_size 2295 self._dynamic_table_max_size = ns 2296 if old_size > self._dynamic_table_max_size: 2297 self._reduce_dynamic_table() 2298 2299 def recap(self, nc): 2300 # type: (int) -> None 2301 """recap changes the maximum size limit of the dynamic table. It also 2302 proceeds to a resize(), if the new size is lower than the previous one. 2303 @param int nc: the new cap of the dynamic table (that is the maximum-maximum size) 2304 @raise AssertionError 2305 """ 2306 assert(nc >= 0) 2307 t = self._dynamic_table_cap_size > nc 2308 self._dynamic_table_cap_size = nc 2309 2310 if t: 2311 # The RFC is not clear about whether this resize should happen; 2312 # we do it anyway 2313 self.resize(nc) 2314 2315 def _reduce_dynamic_table(self, new_entry_size=0): 2316 # type: (int) -> None 2317 """_reduce_dynamic_table evicts entries from the dynamic table until it 2318 fits in less than the current size limit. The optional parameter, 2319 new_entry_size, allows the resize to happen so that a new entry of this 2320 size fits in. 2321 @param int new_entry_size: if called before adding a new entry, the size of the new entry in bytes (following 2322 the RFC7541 definition of the size of an entry) 2323 @raise AssertionError 2324 """ 2325 assert(new_entry_size >= 0) 2326 cur_sz = len(self) 2327 dyn_tbl_sz = len(self._dynamic_table) 2328 while dyn_tbl_sz > 0 and cur_sz + new_entry_size > self._dynamic_table_max_size: 2329 last_elmt_sz = len(self._dynamic_table[-1]) 2330 self._dynamic_table.pop() 2331 dyn_tbl_sz -= 1 2332 cur_sz -= last_elmt_sz 2333 2334 def register(self, hdrs): 2335 # type: (Union[HPackLitHdrFldWithIncrIndexing, H2Frame, List[HPackHeaders]]) -> None 2336 """register adds to this table the instances of 2337 HPackLitHdrFldWithIncrIndexing provided as parameters. 2338 2339 A H2Frame with a H2HeadersFrame payload can be provided, as much as a 2340 python list of HPackHeaders or a single HPackLitHdrFldWithIncrIndexing 2341 instance. 2342 @param HPackLitHdrFldWithIncrIndexing|H2Frame|list of HPackHeaders hdrs: the header(s) to register 2343 @raise AssertionError 2344 """ 2345 if isinstance(hdrs, H2Frame): 2346 hdrs = [hdr for hdr in hdrs.payload.hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)] 2347 elif isinstance(hdrs, HPackLitHdrFldWithIncrIndexing): 2348 hdrs = [hdrs] 2349 else: 2350 hdrs = [hdr for hdr in hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)] 2351 2352 for hdr in hdrs: 2353 if hdr.index == 0: 2354 hdr_name = hdr.hdr_name.getfieldval('data').origin() 2355 else: 2356 idx = int(hdr.index) 2357 hdr_name = self[idx].name() 2358 hdr_value = hdr.hdr_value.getfieldval('data').origin() 2359 2360 # Note: we do not delete any existing hdrentry with the same names 2361 # and values, as dictated by RFC 7541 par2.3.2 2362 2363 entry = HPackHdrEntry(hdr_name, hdr_value) 2364 # According to RFC7541 par4.4, "Before a new entry is added to 2365 # the dynamic table, entries are evicted 2366 # from the end of the dynamic table until the size of the dynamic 2367 # table is less than or equal to (maximum size - new entry size) 2368 # or until the table is empty" 2369 # Also, "It is not an error to attempt to add an entry that is 2370 # larger than the maximum size; an attempt to add an entry larger 2371 # than the maximum size causes the table to be emptied of all 2372 # existing entries and results in an empty table" 2373 # For this reason, we first call the _reduce_dynamic_table and 2374 # then throw an assertion error if the new entry does not fit in 2375 new_entry_len = len(entry) 2376 self._reduce_dynamic_table(new_entry_len) 2377 assert(new_entry_len <= self._dynamic_table_max_size) 2378 self._dynamic_table.insert(0, entry) 2379 2380 def get_idx_by_name(self, name): 2381 # type: (str) -> Optional[int] 2382 """ get_idx_by_name returns the index of a matching registered header 2383 2384 This implementation will prefer returning a static entry index whenever 2385 possible. If multiple matching header name are found in the static 2386 table, there is insurance that the first entry (lowest index number) 2387 will be returned. 2388 If no matching header is found, this method returns None. 2389 """ 2390 name = name.lower() 2391 for key, val in six.iteritems(type(self)._static_entries): 2392 if val.name() == name: 2393 return key 2394 for idx, val in enumerate(self._dynamic_table): 2395 if val.name() == name: 2396 return type(self)._static_entries_last_idx + idx + 1 2397 return None 2398 2399 def get_idx_by_name_and_value(self, name, value): 2400 # type: (str, str) -> Optional[int] 2401 """ get_idx_by_name_and_value returns the index of a matching registered 2402 header 2403 2404 This implementation will prefer returning a static entry index whenever 2405 possible. If multiple matching headers are found in the dynamic table, 2406 the lowest index is returned 2407 If no matching header is found, this method returns None. 2408 """ 2409 name = name.lower() 2410 for key, val in six.iteritems(type(self)._static_entries): 2411 if val.name() == name and val.value() == value: 2412 return key 2413 for idx, val in enumerate(self._dynamic_table): 2414 if val.name() == name and val.value() == value: 2415 return type(self)._static_entries_last_idx + idx + 1 2416 return None 2417 2418 def __len__(self): 2419 # type: () -> int 2420 """ __len__ returns the summed length of all dynamic entries 2421 """ 2422 return sum(len(x) for x in self._dynamic_table) 2423 2424 def gen_txt_repr(self, hdrs, register=True): 2425 # type: (Union[H2Frame, List[HPackHeaders]], Optional[bool]) -> str 2426 """ gen_txt_repr returns a "textual" representation of the provided 2427 headers. 2428 2429 The output of this function is compatible with the input of 2430 parse_txt_hdrs. 2431 @param H2Frame|list of HPackHeaders hdrs: the list of headers to convert to textual representation 2432 @param bool: whether incremental headers should be added to the dynamic table as we generate the text 2433 representation 2434 @return str: the textual representation of the provided headers 2435 @raise AssertionError 2436 """ 2437 l = [] 2438 if isinstance(hdrs, H2Frame): 2439 hdrs = hdrs.payload.hdrs 2440 2441 for hdr in hdrs: 2442 try: 2443 if isinstance(hdr, HPackIndexedHdr): 2444 l.append('{}'.format(self[hdr.index])) 2445 elif isinstance(hdr, ( 2446 HPackLitHdrFldWithIncrIndexing, 2447 HPackLitHdrFldWithoutIndexing 2448 )): 2449 if hdr.index != 0: 2450 name = self[hdr.index].name() 2451 else: 2452 name = hdr.hdr_name.getfieldval('data').origin() 2453 if name.startswith(':'): 2454 l.append( 2455 '{} {}'.format( 2456 name, 2457 hdr.hdr_value.getfieldval('data').origin() 2458 ) 2459 ) 2460 else: 2461 l.append( 2462 '{}: {}'.format( 2463 name, 2464 hdr.hdr_value.getfieldval('data').origin() 2465 ) 2466 ) 2467 if register and isinstance(hdr, HPackLitHdrFldWithIncrIndexing): 2468 self.register(hdr) 2469 except KeyError as e: # raised when an index is out-of-bound 2470 print(e) 2471 continue 2472 return '\n'.join(l) 2473 2474 @staticmethod 2475 def _optimize_header_length_and_packetify(s): 2476 # type: (str) -> HPackHdrString 2477 # type: (str) -> HPackHdrString 2478 zs = HPackZString(s) 2479 if len(zs) >= len(s): 2480 return HPackHdrString(data=HPackLiteralString(s)) 2481 return HPackHdrString(data=zs) 2482 2483 def _convert_a_header_to_a_h2_header(self, hdr_name, hdr_value, is_sensitive, should_index): 2484 # type: (str, str, Callable[[str, str], bool], Callable[[str], bool]) -> Tuple[HPackHeaders, int] 2485 """ _convert_a_header_to_a_h2_header builds a HPackHeaders from a header 2486 name and a value. It returns a HPackIndexedHdr whenever possible. If not, 2487 it returns a HPackLitHdrFldWithoutIndexing or a 2488 HPackLitHdrFldWithIncrIndexing, based on the should_index callback. 2489 HPackLitHdrFldWithoutIndexing is forced if the is_sensitive callback 2490 returns True and its never_index bit is set. 2491 """ 2492 2493 # If both name and value are already indexed 2494 idx = self.get_idx_by_name_and_value(hdr_name, hdr_value) 2495 if idx is not None: 2496 return HPackIndexedHdr(index=idx), len(self[idx]) 2497 2498 # The value is not indexed for this headers 2499 2500 hdr_value = self._optimize_header_length_and_packetify(hdr_value) 2501 2502 # Searching if the header name is indexed 2503 idx = self.get_idx_by_name(hdr_name) 2504 if idx is not None: 2505 if is_sensitive( 2506 hdr_name, 2507 hdr_value.getfieldval('data').origin() 2508 ): 2509 return HPackLitHdrFldWithoutIndexing( 2510 never_index=1, 2511 index=idx, 2512 hdr_value=hdr_value 2513 ), len( 2514 HPackHdrEntry( 2515 self[idx].name(), 2516 hdr_value.getfieldval('data').origin() 2517 ) 2518 ) 2519 if should_index(hdr_name): 2520 return HPackLitHdrFldWithIncrIndexing( 2521 index=idx, 2522 hdr_value=hdr_value 2523 ), len( 2524 HPackHdrEntry( 2525 self[idx].name(), 2526 hdr_value.getfieldval('data').origin() 2527 ) 2528 ) 2529 return HPackLitHdrFldWithoutIndexing( 2530 index=idx, 2531 hdr_value=hdr_value 2532 ), len( 2533 HPackHdrEntry( 2534 self[idx].name(), 2535 hdr_value.getfieldval('data').origin() 2536 ) 2537 ) 2538 2539 hdr_name = self._optimize_header_length_and_packetify(hdr_name) 2540 2541 if is_sensitive( 2542 hdr_name.getfieldval('data').origin(), 2543 hdr_value.getfieldval('data').origin() 2544 ): 2545 return HPackLitHdrFldWithoutIndexing( 2546 never_index=1, 2547 index=0, 2548 hdr_name=hdr_name, 2549 hdr_value=hdr_value 2550 ), len( 2551 HPackHdrEntry( 2552 hdr_name.getfieldval('data').origin(), 2553 hdr_value.getfieldval('data').origin() 2554 ) 2555 ) 2556 if should_index(hdr_name.getfieldval('data').origin()): 2557 return HPackLitHdrFldWithIncrIndexing( 2558 index=0, 2559 hdr_name=hdr_name, 2560 hdr_value=hdr_value 2561 ), len( 2562 HPackHdrEntry( 2563 hdr_name.getfieldval('data').origin(), 2564 hdr_value.getfieldval('data').origin() 2565 ) 2566 ) 2567 return HPackLitHdrFldWithoutIndexing( 2568 index=0, 2569 hdr_name=hdr_name, 2570 hdr_value=hdr_value 2571 ), len( 2572 HPackHdrEntry( 2573 hdr_name.getfieldval('data').origin(), 2574 hdr_value.getfieldval('data').origin() 2575 ) 2576 ) 2577 2578 def _parse_header_line(self, l): 2579 # type: (str) -> Union[Tuple[None, None], Tuple[str, str]] 2580 2581 if self._regexp is None: 2582 self._regexp = re.compile(b'^(?::([a-z\-0-9]+)|([a-z\-0-9]+):)\s+(.+)$') 2583 2584 hdr_line = l.rstrip() 2585 grp = self._regexp.match(hdr_line) 2586 2587 if grp is None or len(grp.groups()) != 3: 2588 return None, None 2589 2590 if grp.group(1) is not None: 2591 hdr_name = b':'+grp.group(1) 2592 else: 2593 hdr_name = grp.group(2) 2594 return plain_str(hdr_name.lower()), plain_str(grp.group(3)) 2595 2596 def parse_txt_hdrs(self, 2597 s, # type: str 2598 stream_id=1, # type: int 2599 body=None, # type: Optional[str] 2600 max_frm_sz=4096, # type: int 2601 max_hdr_lst_sz=0, # type: int 2602 is_sensitive=lambda n, v: False, # type: Callable[[str, str], bool] 2603 should_index=lambda x: False, # type: Callable[[str], bool] 2604 register=True, # type: bool 2605 ): 2606 # type: (...) -> H2Seq 2607 """ parse_txt_hdrs parses headers expressed in text and converts them 2608 into a series of H2Frames with the "correct" flags. A body can be provided 2609 in which case, the data frames are added, bearing the End Stream flag, 2610 instead of the H2HeadersFrame/H2ContinuationFrame. The generated frames 2611 may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE) and 2612 max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided. The headers 2613 are split into multiple headers fragment (and H2Frames) to respect these 2614 limits. Also, a callback can be provided to tell if a header should be 2615 never indexed (sensitive headers, such as cookies), and another callback 2616 say if the header should be registered into the index table at all. 2617 For an header to be registered, the is_sensitive callback must return 2618 False AND the should_index callback should return True. This is the 2619 default behavior. 2620 2621 @param str s: the string to parse for headers 2622 @param int stream_id: the stream id to use in the generated H2Frames 2623 @param str|None body: the eventual body of the request, that is added to the generated frames 2624 @param int max_frm_sz: the maximum frame size. This is used to split the headers and data frames according to 2625 the maximum frame size negociated for this connection 2626 @param int max_hdr_lst_sz: the maximum size of a "header fragment" as defined in RFC7540 2627 @param callable is_sensitive: callback that returns True if the provided header is sensible and must be stored 2628 in a header packet requesting this header never to be indexed 2629 @param callable should_index: callback that returns True if the provided header should be stored in a header 2630 packet requesting indexation in the dynamic header table. 2631 @param bool register: whether to register new headers with incremental indexing as we parse them 2632 @raise Exception 2633 """ 2634 2635 sio = BytesIO(s) 2636 2637 base_frm_len = len(raw(H2Frame())) 2638 2639 ret = H2Seq() 2640 cur_frm = H2HeadersFrame() # type: Union[H2HeadersFrame, H2ContinuationFrame] 2641 cur_hdr_sz = 0 2642 2643 # For each line in the headers str to parse 2644 for hdr_line in sio: 2645 hdr_name, hdr_value = self._parse_header_line(hdr_line) 2646 if hdr_name is None: 2647 continue 2648 2649 new_hdr, new_hdr_len = self._convert_a_header_to_a_h2_header( 2650 hdr_name, hdr_value, is_sensitive, should_index 2651 ) 2652 new_hdr_bin_len = len(raw(new_hdr)) 2653 2654 if register and isinstance(new_hdr, HPackLitHdrFldWithIncrIndexing): 2655 self.register(new_hdr) 2656 2657 # The new header binary length (+ base frame size) must not exceed 2658 # the maximum frame size or it will just never fit. Also, the 2659 # header entry length (as specified in RFC7540 par6.5.2) must not 2660 # exceed the maximum length of a header fragment or it will just 2661 # never fit 2662 if (new_hdr_bin_len + base_frm_len > max_frm_sz 2663 or (max_hdr_lst_sz != 0 and new_hdr_len > max_hdr_lst_sz) 2664 ): 2665 raise Exception('Header too long: {}'.format(hdr_name)) 2666 2667 if (max_frm_sz < len(raw(cur_frm)) + base_frm_len + new_hdr_len 2668 or ( 2669 max_hdr_lst_sz != 0 2670 and max_hdr_lst_sz < cur_hdr_sz + new_hdr_len 2671 ) 2672 ): 2673 flags = set() 2674 if isinstance(cur_frm, H2HeadersFrame) and not body: 2675 flags.add('ES') 2676 ret.frames.append(H2Frame(stream_id=stream_id, flags=flags)/cur_frm) 2677 cur_frm = H2ContinuationFrame() 2678 cur_hdr_sz = 0 2679 2680 hdr_list = cur_frm.hdrs 2681 hdr_list += new_hdr 2682 cur_hdr_sz += new_hdr_len 2683 2684 flags = {'EH'} 2685 if isinstance(cur_frm, H2HeadersFrame) and not body: 2686 flags.add('ES') 2687 ret.frames.append(H2Frame(stream_id=stream_id, flags=flags)/cur_frm) 2688 2689 if body: 2690 base_data_frm_len = len(raw(H2DataFrame())) 2691 sio = BytesIO(body) 2692 frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len) 2693 while frgmt: 2694 nxt_frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len) 2695 flags = set() 2696 if len(nxt_frgmt) == 0: 2697 flags.add('ES') 2698 ret.frames.append( 2699 H2Frame(stream_id=stream_id, flags=flags)/H2DataFrame(data=frgmt) 2700 ) 2701 frgmt = nxt_frgmt 2702 return ret 2703