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