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