def __init__(self, server_end, client_end): self.server_end = server_end self.client_end = client_end self.trans_frame = { FRAME_DIR_REQUEST: h2frame.ClientPreface(), FRAME_DIR_RESPONSE: h2frame.ServerPreface() } # self.conn_settings = SettingManager() self.all_stream = {} self.open_status = True # connection's hpack decoder. self._req_hpack_decoder = hpack.Decoder() self._resp_hpack_decoder = hpack.Decoder()
def read_headers(self): if self.frame_type == Http2FrameDefs.HEADERS_FRAME: try: decoder = hpack.Decoder() decoded_data = decoder.decode(self.payload) output_str = '' for header in decoded_data: output_str += '\n' for each in header: output_str += each + ' ' except hpack.exceptions.InvalidTableIndex: output_str = self.payload.hex() output_str += '\nWarning: Decode failed: Invalid table index (not too important)' return output_str else: return '\nError: Frame type mismatch: {0}'.format( Http2FrameDefs.FRAME_TYPES[self.frame_type])
#!/usr/bin/python import hpack if __name__ == '__main__': data = '' with open('./fragment2.pcap', 'rb') as f: data = f.read() idx = data.find("\x00\x02\x06\x2a") + 4 data = data[idx:] for i in xrange(len(data)): for j in xrange(i, len(data)): try: d = hpack.Decoder() print("DECODED : %s" % d.decode(data[i:j])) except Exception as e: print(e)
import textwrap import hpack PREFACE = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" PREFACE_PRETTY = r"""Client Connection Preface = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' Hexdump (Client Connection Preface) = 50 52 49 20 2a 20 48 54 54 50 2f 32 2e 30 0d 0a 0d 0a 53 4d 0d 0a 0d 0a""" MISSING_PREFACE = ( "Expected TCP packet data to begin with client connection preface") HEADER = "=" * 60 FOOTER = "-" * 40 STRUCT_H = struct.Struct(">H") STRUCT_L = struct.Struct(">L") HPACK_DECODER = hpack.Decoder() # See: https://http2.github.io/http2-spec/#iana-frames FRAME_TYPES = { 0x0: "DATA", 0x1: "HEADERS", 0x2: "PRIORITY", 0x3: "RST_STREAM", 0x4: "SETTINGS", 0x5: "PUSH_PROMISE", 0x6: "PING", 0x7: "GOAWAY", 0x8: "WINDOW_UPDATE", 0x9: "CONTINUATION", } # The following bit flags are defined "globally" (i.e. across all types), but # some flags apply to only certain frame types (e.g. END_STREAM only applies
async def http2(reader, writer): addr = writer.get_extra_info("peername") print("OPEN:", addr) stream = await http2_StreamWrapper(reader, writer) if (PREFACE != await stream.read(preface_length)): stream.conn.Close() return hpack_decoder = hpack.Decoder() hpack_encoder = hpack.Encoder() # Length(24) Type(8) flags(8) [R(1) StreamIdentifier(31)] FramePayload(Length) while (True): Length = int.from_bytes(await stream.read(3), "big") if (Length == 0): stream.conn.Close() return Type = await stream.read(1) flags = int.from_bytes(await stream.read(1), "big") RnS = await stream.read(4) #print(http2_frame.bytes_frame_name[Type]) FramePayload = await stream.read(Length) Payload = http2_parser.frame_payload_parsers[Type](FramePayload, flags) frame_type = http2_frame.bytes_frame_name[Type] stream_identifire = int.from_bytes(RnS, "big") if (frame_type is "HEADERS"): content, content_type, status = b"", "", 404 request = {} for p in hpack_decoder.decode(Payload[-1]): request[p[0]] = p[1] if (request[":method"] == "GET"): if (request[":path"].find("?") != -1): print("GEPT...>>> ", request[":path"]) pfg = request[":path"].split("?") content, content_type, status = gept.gept( pfg[0], pfg[1].encode("utf-8"), message_dir + "/412.html") else: print("GET...>>> ", request[":path"]) content, content_type, status = get.get( req=request[":path"], root_dir=root_dir, message_dir=message_dir) elif (request[":method"] == "POST"): print("POST--->:", request[":path"]) post_data = b"" print("reading ...") if (not (flags & 0x01)): while True: Length = int.from_bytes(await stream.read(3), "big") Type = await stream.read(1) flags = int.from_bytes(await stream.read(1), "big") RnS = await stream.read(4) FramePayload = await stream.read(Length) if (Type == b"\x00"): Payload = http2_parser.frame_payload_parsers[Type]( FramePayload, flags) post_data += Payload[0] if (flags & 0x01): break print(len(post_data)) content, content_type, status = post.post( request[":path"], post_data, message_dir) rh = [(":status", status), ("server", SERVER_NAME), ("content-type", content_type), ("content-length", len(content)), ("x-frame-options", "SAMEORIGIN"), ("x-xss-protection", "1; mode=block"), ("cache-control", "no-cache")] res_header_frame = Http2Frame() res_header_frame.SetFrameType( http2_frame.frame_type_name["HEADERS"]) res_header_frame.SetStreamIdentifire(stream_identifire) res_header_frame.SetFramePayload(hpack_encoder.encode(rh)) res_header_frame.SetFlags([http2_frame.frame_flag["END_HEADERS"]]) await stream.conn.Send(res_header_frame.Gen()) res_data = parser.bytes_parseq(content, default_max_frame_size) res_header_frame.SetFlags([http2_frame.frame_flag["NONE"]]) res_data_frame = res_header_frame res_data_frame.SetFrameType(http2_frame.frame_type_name["DATA"]) if (len(res_data) == 1): res_data_frame.SetFramePayload(res_data[0]) res_data_frame.SetFlags([http2_frame.frame_flag["END_STREAM"]]) await stream.conn.Send(res_data_frame.Gen()) for d in res_data[:-1]: res_data_frame.SetFramePayload(d) await stream.conn.Send(res_data_frame.Gen()) res_data_frame.SetFramePayload(res_data[-1]) res_data_frame.SetFlags([http2_frame.frame_flag["END_STREAM"]]) await stream.conn.Send(res_data_frame.Gen()) elif (frame_type is "SETTINGS"): print(Payload) if (flags == b"\x01"): break hpack_encoder.header_table_size = int.from_bytes( Payload[0][1], "big") res_settings_frame = Http2Frame() res_settings_frame.SetFrameType( http2_frame.frame_type_name["SETTINGS"]) res_settings_frame.SetStreamIdentifire(stream_identifire) res_settings_frame.SetFlags([http2_frame.frame_flag["NONE"]]) res_settings_frame.SetFramePayload( b"\x00\x01\x00\x02\x00\x00\x00\x03\x00\x00\x03\xe8\x00\x04\x00\xff\xff\xff\x00\x05\x00\xff\xff\xff" ) await stream.conn.Send(res_settings_frame.Gen()) wuf = Http2Frame() wuf.SetFrameType(http2_frame.frame_type_name["WINDOW_UPDATE"]) wuf.SetStreamIdentifire(0) wuf.SetFramePayload(b"\x00\xff\xff\xff") wuf.SetFlags([http2_frame.frame_flag["NONE"]]) await stream.conn.Send(wuf.Gen()) elif (frame_type is "WINDOW_UPDATE"): print(Payload) elif (frame_type is "RST_STREAM"): print(Payload) stream.conn.Close() elif (frame_type is "DATA"): #print(Payload) pass elif (frame_type is "PING"): print("PING") ping_frame = Http2Frame() ping_frame.SetFrameType(http2_frame.frame_type_name["PING"]) ping_frame.SetStreamIdentifire(stream_identifire) ping_frame.SetFramePayload(Payload) ping_frame.SetFlags([http2_frame.frame_flag["ACK"]]) await stream.conn.Send(ping_frame.Gen())
def read_frame(sock): '''Read exactly 1 h2 frame from socket ''' data = read_bytes(sock, 9) frame, payload_len = hyperframe.frame.Frame.parse_frame_header(data) if payload_len: data = read_bytes(sock, payload_len) frame.parse_body(memoryview(data)) return frame if __name__ == '__main__': # connect hostname = 'www.google.com' hpack_enc = hpack.Encoder() hpack_dec = hpack.Decoder() sock = connect(hostname) # send connection preface write(sock, MAGIC) write(sock, hyperframe.frame.SettingsFrame()) # send request headers = hyperframe.frame.HeadersFrame(3) headers.data = hpack_enc.encode([ (b':method', b'GET'), (b':scheme', b'https'), (b':authority', b'www.google.com'), (b':path', b'/'), ]) headers.flags.add('END_HEADERS')
def __init__(self, options, is_request, params): BaseProcessor.__init__(self, options, is_request, params) self.compressor = hpack.Encoder() self.decompressor = hpack.Decoder() self.sensitive = []