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