diff options
-rwxr-xr-x | mitmproxy/contrib/kaitaistruct/make.sh | 1 | ||||
-rw-r--r-- | mitmproxy/contrib/kaitaistruct/tls_client_hello.py | 146 | ||||
-rw-r--r-- | mitmproxy/contrib/tls_client_hello.ksy | 139 | ||||
-rw-r--r-- | mitmproxy/contrib/tls_parser.py | 208 | ||||
-rw-r--r-- | mitmproxy/flowfilter.py | 2 | ||||
-rw-r--r-- | mitmproxy/net/tcp.py | 2 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/http2.py | 17 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/tls.py | 26 | ||||
-rw-r--r-- | pathod/language/generators.py | 22 | ||||
-rw-r--r-- | pathod/pathod_cmdline.py | 3 | ||||
-rw-r--r-- | release/setup.py | 4 | ||||
-rw-r--r-- | requirements.txt | 2 | ||||
-rw-r--r-- | setup.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/contrib/test_tls_parser.py | 38 | ||||
-rw-r--r-- | test/mitmproxy/net/test_tcp.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_tls.py | 3 | ||||
-rw-r--r-- | test/pathod/language/test_generators.py | 12 | ||||
-rw-r--r-- | test/pathod/test_test.py | 40 | ||||
-rw-r--r-- | test/pathod/tservers.py | 4 |
19 files changed, 348 insertions, 324 deletions
diff --git a/mitmproxy/contrib/kaitaistruct/make.sh b/mitmproxy/contrib/kaitaistruct/make.sh index 218d5198..9ef68886 100755 --- a/mitmproxy/contrib/kaitaistruct/make.sh +++ b/mitmproxy/contrib/kaitaistruct/make.sh @@ -6,5 +6,6 @@ wget -N https://raw.githubusercontent.com/kaitai-io/kaitai_struct_formats/master wget -N https://raw.githubusercontent.com/kaitai-io/kaitai_struct_formats/master/image/gif.ksy wget -N https://raw.githubusercontent.com/kaitai-io/kaitai_struct_formats/master/image/jpeg.ksy wget -N https://raw.githubusercontent.com/kaitai-io/kaitai_struct_formats/master/image/png.ksy +wget -N https://raw.githubusercontent.com/mitmproxy/mitmproxy/master/mitmproxy/contrib/tls_client_hello.py kaitai-struct-compiler --target python --opaque-types=true *.ksy diff --git a/mitmproxy/contrib/kaitaistruct/tls_client_hello.py b/mitmproxy/contrib/kaitaistruct/tls_client_hello.py new file mode 100644 index 00000000..6aff9b14 --- /dev/null +++ b/mitmproxy/contrib/kaitaistruct/tls_client_hello.py @@ -0,0 +1,146 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import array +import struct +import zlib +from enum import Enum +from pkg_resources import parse_version + +from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO + +if parse_version(ks_version) < parse_version('0.7'): + raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version)) + + +class TlsClientHello(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.version = self._root.Version(self._io, self, self._root) + self.random = self._root.Random(self._io, self, self._root) + self.session_id = self._root.SessionId(self._io, self, self._root) + self.cipher_suites = self._root.CipherSuites(self._io, self, self._root) + self.compression_methods = self._root.CompressionMethods(self._io, self, self._root) + if self._io.is_eof() == True: + self.extensions = [None] * (0) + for i in range(0): + self.extensions[i] = self._io.read_bytes(0) + + if self._io.is_eof() == False: + self.extensions = self._root.Extensions(self._io, self, self._root) + + class ServerName(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.name_type = self._io.read_u1() + self.length = self._io.read_u2be() + self.host_name = self._io.read_bytes(self.length) + + class Random(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.gmt_unix_time = self._io.read_u4be() + self.random = self._io.read_bytes(28) + + class SessionId(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.len = self._io.read_u1() + self.sid = self._io.read_bytes(self.len) + + class Sni(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.list_length = self._io.read_u2be() + self.server_names = [] + while not self._io.is_eof(): + self.server_names.append(self._root.ServerName(self._io, self, self._root)) + + class CipherSuites(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.len = self._io.read_u2be() + self.cipher_suites = [None] * (self.len // 2) + for i in range(self.len // 2): + self.cipher_suites[i] = self._root.CipherSuite(self._io, self, self._root) + + class CompressionMethods(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.len = self._io.read_u1() + self.compression_methods = self._io.read_bytes(self.len) + + class Alpn(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.ext_len = self._io.read_u2be() + self.alpn_protocols = [] + while not self._io.is_eof(): + self.alpn_protocols.append(self._root.Protocol(self._io, self, self._root)) + + class Extensions(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.len = self._io.read_u2be() + self.extensions = [] + while not self._io.is_eof(): + self.extensions.append(self._root.Extension(self._io, self, self._root)) + + class Version(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.major = self._io.read_u1() + self.minor = self._io.read_u1() + + class CipherSuite(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.cipher_suite = self._io.read_u2be() + + class Protocol(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.strlen = self._io.read_u1() + self.name = self._io.read_bytes(self.strlen) + + class Extension(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.type = self._io.read_u2be() + self.len = self._io.read_u2be() + _on = self.type + if _on == 0: + self._raw_body = self._io.read_bytes(self.len) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.Sni(io, self, self._root) + elif _on == 16: + self._raw_body = self._io.read_bytes(self.len) + io = KaitaiStream(BytesIO(self._raw_body)) + self.body = self._root.Alpn(io, self, self._root) + else: + self.body = self._io.read_bytes(self.len) diff --git a/mitmproxy/contrib/tls_client_hello.ksy b/mitmproxy/contrib/tls_client_hello.ksy new file mode 100644 index 00000000..5b6eb0fb --- /dev/null +++ b/mitmproxy/contrib/tls_client_hello.ksy @@ -0,0 +1,139 @@ +meta: + id: tls_client_hello + endian: be + +seq: + - id: version + type: version + + - id: random + type: random + + - id: session_id + type: session_id + + - id: cipher_suites + type: cipher_suites + + - id: compression_methods + type: compression_methods + + - id: extensions + size: 0 + repeat: expr + repeat-expr: 0 + if: _io.eof == true + + - id: extensions + type: extensions + if: _io.eof == false + +types: + version: + seq: + - id: major + type: u1 + + - id: minor + type: u1 + + random: + seq: + - id: gmt_unix_time + type: u4 + + - id: random + size: 28 + + session_id: + seq: + - id: len + type: u1 + + - id: sid + size: len + + cipher_suites: + seq: + - id: len + type: u2 + + - id: cipher_suites + type: cipher_suite + repeat: expr + repeat-expr: len/2 + + cipher_suite: + seq: + - id: cipher_suite + type: u2 + + compression_methods: + seq: + - id: len + type: u1 + + - id: compression_methods + size: len + + extensions: + seq: + - id: len + type: u2 + + - id: extensions + type: extension + repeat: eos + + extension: + seq: + - id: type + type: u2 + + - id: len + type: u2 + + - id: body + size: len + type: + switch-on: type + cases: + 0: sni + 16: alpn + + sni: + seq: + - id: list_length + type: u2 + + - id: server_names + type: server_name + repeat: eos + + server_name: + seq: + - id: name_type + type: u1 + + - id: length + type: u2 + + - id: host_name + size: length + + alpn: + seq: + - id: ext_len + type: u2 + + - id: alpn_protocols + type: protocol + repeat: eos + + protocol: + seq: + - id: strlen + type: u1 + + - id: name + size: strlen diff --git a/mitmproxy/contrib/tls_parser.py b/mitmproxy/contrib/tls_parser.py deleted file mode 100644 index 61fb3e3e..00000000 --- a/mitmproxy/contrib/tls_parser.py +++ /dev/null @@ -1,208 +0,0 @@ -# This file originally comes from https://github.com/pyca/tls/blob/master/tls/_constructs.py. -# Modified by the mitmproxy team. - -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - - -from construct import ( - Array, - Bytes, - Struct, - VarInt, - Int8ub, - Int16ub, - Int24ub, - Int32ub, - PascalString, - Embedded, - Prefixed, - Range, - GreedyRange, - Switch, - Optional, -) - -ProtocolVersion = "version" / Struct( - "major" / Int8ub, - "minor" / Int8ub, -) - -TLSPlaintext = "TLSPlaintext" / Struct( - "type" / Int8ub, - ProtocolVersion, - "length" / Int16ub, # TODO: Reject packets with length > 2 ** 14 - "fragment" / Bytes(lambda ctx: ctx.length), -) - -TLSCompressed = "TLSCompressed" / Struct( - "type" / Int8ub, - ProtocolVersion, - "length" / Int16ub, # TODO: Reject packets with length > 2 ** 14 + 1024 - "fragment" / Bytes(lambda ctx: ctx.length), -) - -TLSCiphertext = "TLSCiphertext" / Struct( - "type" / Int8ub, - ProtocolVersion, - "length" / Int16ub, # TODO: Reject packets with length > 2 ** 14 + 2048 - "fragment" / Bytes(lambda ctx: ctx.length), -) - -Random = "random" / Struct( - "gmt_unix_time" / Int32ub, - "random_bytes" / Bytes(28), -) - -SessionID = "session_id" / Struct( - "length" / Int8ub, - "session_id" / Bytes(lambda ctx: ctx.length), -) - -CipherSuites = "cipher_suites" / Struct( - "length" / Int16ub, # TODO: Reject packets of length 0 - Array(lambda ctx: ctx.length // 2, "cipher_suites" / Int16ub), -) - -CompressionMethods = "compression_methods" / Struct( - "length" / Int8ub, # TODO: Reject packets of length 0 - Array(lambda ctx: ctx.length, "compression_methods" / Int8ub), -) - -ServerName = Struct( - "type" / Int8ub, - "name" / PascalString("length" / Int16ub), -) - -SNIExtension = Prefixed( - Int16ub, - Struct( - Int16ub, - "server_names" / GreedyRange( - "server_name" / Struct( - "name_type" / Int8ub, - "host_name" / PascalString("length" / Int16ub), - ) - ) - ) -) - -ALPNExtension = Prefixed( - Int16ub, - Struct( - Int16ub, - "alpn_protocols" / GreedyRange( - "name" / PascalString(Int8ub), - ), - ) -) - -UnknownExtension = Struct( - "bytes" / PascalString("length" / Int16ub) -) - -Extension = "Extension" / Struct( - "type" / Int16ub, - Embedded( - Switch( - lambda ctx: ctx.type, - { - 0x00: SNIExtension, - 0x10: ALPNExtension, - }, - default=UnknownExtension - ) - ) -) - -extensions = "extensions" / Optional( - Struct( - Int16ub, - "extensions" / GreedyRange(Extension) - ) -) - -ClientHello = "ClientHello" / Struct( - ProtocolVersion, - Random, - SessionID, - CipherSuites, - CompressionMethods, - extensions, -) - -ServerHello = "ServerHello" / Struct( - ProtocolVersion, - Random, - SessionID, - "cipher_suite" / Bytes(2), - "compression_method" / Int8ub, - extensions, -) - -ClientCertificateType = "certificate_types" / Struct( - "length" / Int8ub, # TODO: Reject packets of length 0 - Array(lambda ctx: ctx.length, "certificate_types" / Int8ub), -) - -SignatureAndHashAlgorithm = "algorithms" / Struct( - "hash" / Int8ub, - "signature" / Int8ub, -) - -SupportedSignatureAlgorithms = "supported_signature_algorithms" / Struct( - "supported_signature_algorithms_length" / Int16ub, - # TODO: Reject packets of length 0 - Array( - lambda ctx: ctx.supported_signature_algorithms_length / 2, - SignatureAndHashAlgorithm, - ), -) - -DistinguishedName = "certificate_authorities" / Struct( - "length" / Int16ub, - "certificate_authorities" / Bytes(lambda ctx: ctx.length), -) - -CertificateRequest = "CertificateRequest" / Struct( - ClientCertificateType, - SupportedSignatureAlgorithms, - DistinguishedName, -) - -ServerDHParams = "ServerDHParams" / Struct( - "dh_p_length" / Int16ub, - "dh_p" / Bytes(lambda ctx: ctx.dh_p_length), - "dh_g_length" / Int16ub, - "dh_g" / Bytes(lambda ctx: ctx.dh_g_length), - "dh_Ys_length" / Int16ub, - "dh_Ys" / Bytes(lambda ctx: ctx.dh_Ys_length), -) - -PreMasterSecret = "pre_master_secret" / Struct( - ProtocolVersion, - "random_bytes" / Bytes(46), -) - -ASN1Cert = "ASN1Cert" / Struct( - "length" / Int32ub, # TODO: Reject packets with length not in 1..2^24-1 - "asn1_cert" / Bytes(lambda ctx: ctx.length), -) - -Certificate = "Certificate" / Struct( - # TODO: Reject packets with length > 2 ** 24 - 1 - "certificates_length" / Int32ub, - "certificates_bytes" / Bytes(lambda ctx: ctx.certificates_length), -) - -Handshake = "Handshake" / Struct( - "msg_type" / Int8ub, - "length" / Int24ub, - "body" / Bytes(lambda ctx: ctx.length), -) - -Alert = "Alert" / Struct( - "level" / Int8ub, - "description" / Int8ub, -) diff --git a/mitmproxy/flowfilter.py b/mitmproxy/flowfilter.py index 83c98bad..4edf0413 100644 --- a/mitmproxy/flowfilter.py +++ b/mitmproxy/flowfilter.py @@ -344,6 +344,8 @@ class FUrl(_Rex): @only(http.HTTPFlow) def __call__(self, f): + if not f.request: + return False return self.re.search(f.request.pretty_url) diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py index cdac4cd5..12cf7337 100644 --- a/mitmproxy/net/tcp.py +++ b/mitmproxy/net/tcp.py @@ -502,7 +502,7 @@ class _Connection: # Cipher List if cipher_list: try: - context.set_cipher_list(cipher_list) + context.set_cipher_list(cipher_list.encode()) context.set_tmp_ecdh(OpenSSL.crypto.get_elliptic_curve('prime256v1')) except SSL.Error as v: raise exceptions.TlsException("SSL cipher specification error: %s" % str(v)) diff --git a/mitmproxy/proxy/protocol/http2.py b/mitmproxy/proxy/protocol/http2.py index 2191b54b..ace7ecde 100644 --- a/mitmproxy/proxy/protocol/http2.py +++ b/mitmproxy/proxy/protocol/http2.py @@ -206,14 +206,15 @@ class Http2Layer(base.Layer): return True def _handle_stream_reset(self, eid, event, is_server, other_conn): - self.streams[eid].kill() - if eid in self.streams and event.error_code == h2.errors.ErrorCodes.CANCEL: - if is_server: - other_stream_id = self.streams[eid].client_stream_id - else: - other_stream_id = self.streams[eid].server_stream_id - if other_stream_id is not None: - self.connections[other_conn].safe_reset_stream(other_stream_id, event.error_code) + if eid in self.streams: + self.streams[eid].kill() + if event.error_code == h2.errors.ErrorCodes.CANCEL: + if is_server: + other_stream_id = self.streams[eid].client_stream_id + else: + other_stream_id = self.streams[eid].server_stream_id + if other_stream_id is not None: + self.connections[other_conn].safe_reset_stream(other_stream_id, event.error_code) return True def _handle_remote_settings_changed(self, event, other_conn): diff --git a/mitmproxy/proxy/protocol/tls.py b/mitmproxy/proxy/protocol/tls.py index f55855f0..d42c7fdd 100644 --- a/mitmproxy/proxy/protocol/tls.py +++ b/mitmproxy/proxy/protocol/tls.py @@ -1,10 +1,11 @@ import struct from typing import Optional # noqa from typing import Union +import io -import construct +from kaitaistruct import KaitaiStream from mitmproxy import exceptions -from mitmproxy.contrib import tls_parser +from mitmproxy.contrib.kaitaistruct import tls_client_hello from mitmproxy.proxy.protocol import base from mitmproxy.net import check @@ -263,7 +264,7 @@ def get_client_hello(client_conn): class TlsClientHello: def __init__(self, raw_client_hello): - self._client_hello = tls_parser.ClientHello.parse(raw_client_hello) + self._client_hello = tls_client_hello.TlsClientHello(KaitaiStream(io.BytesIO(raw_client_hello))) def raw(self): return self._client_hello @@ -278,12 +279,12 @@ class TlsClientHello: for extension in self._client_hello.extensions.extensions: is_valid_sni_extension = ( extension.type == 0x00 and - len(extension.server_names) == 1 and - extension.server_names[0].name_type == 0 and - check.is_valid_host(extension.server_names[0].host_name) + len(extension.body.server_names) == 1 and + extension.body.server_names[0].name_type == 0 and + check.is_valid_host(extension.body.server_names[0].host_name) ) if is_valid_sni_extension: - return extension.server_names[0].host_name.decode("idna") + return extension.body.server_names[0].host_name.decode("idna") return None @property @@ -291,7 +292,7 @@ class TlsClientHello: if self._client_hello.extensions: for extension in self._client_hello.extensions.extensions: if extension.type == 0x10: - return list(extension.alpn_protocols) + return list(extension.body.alpn_protocols) return [] @classmethod @@ -310,7 +311,7 @@ class TlsClientHello: try: return cls(raw_client_hello) - except construct.ConstructError as e: + except EOFError as e: raise exceptions.TlsProtocolException( 'Cannot parse Client Hello: %s, Raw Client Hello: %s' % (repr(e), raw_client_hello.encode("hex")) @@ -518,7 +519,8 @@ class TlsLayer(base.Layer): # We only support http/1.1 and h2. # If the server only supports spdy (next to http/1.1), it may select that # and mitmproxy would enter TCP passthrough mode, which we want to avoid. - alpn = [x for x in self._client_hello.alpn_protocols if not (x.startswith(b"h2-") or x.startswith(b"spdy"))] + alpn = [x.name for x in self._client_hello.alpn_protocols if + not (x.name.startswith(b"h2-") or x.name.startswith(b"spdy"))] if alpn and b"h2" in alpn and not self.config.options.http2: alpn.remove(b"h2") @@ -537,8 +539,8 @@ class TlsLayer(base.Layer): if not ciphers_server and self._client_tls: ciphers_server = [] for id in self._client_hello.cipher_suites: - if id in CIPHER_ID_NAME_MAP.keys(): - ciphers_server.append(CIPHER_ID_NAME_MAP[id]) + if id.cipher_suite in CIPHER_ID_NAME_MAP.keys(): + ciphers_server.append(CIPHER_ID_NAME_MAP[id.cipher_suite]) ciphers_server = ':'.join(ciphers_server) self.server_conn.establish_ssl( diff --git a/pathod/language/generators.py b/pathod/language/generators.py index 93db3014..1961df74 100644 --- a/pathod/language/generators.py +++ b/pathod/language/generators.py @@ -1,7 +1,7 @@ +import os import string import random import mmap - import sys DATATYPES = dict( @@ -74,24 +74,20 @@ class RandomGenerator: class FileGenerator: - def __init__(self, path): self.path = path - self.fp = open(path, "rb") - self.map = mmap.mmap(self.fp.fileno(), 0, access=mmap.ACCESS_READ) def __len__(self): - return len(self.map) + return os.path.getsize(self.path) def __getitem__(self, x): - if isinstance(x, slice): - return self.map.__getitem__(x) - # A slice of length 1 returns a byte object (not an integer) - return self.map.__getitem__(slice(x, x + 1 or self.map.size())) + with open(self.path, mode="rb") as f: + if isinstance(x, slice): + with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mapped: + return mapped.__getitem__(x) + else: + f.seek(x) + return f.read(1) def __repr__(self): return "<%s" % self.path - - def close(self): - self.map.close() - self.fp.close() diff --git a/pathod/pathod_cmdline.py b/pathod/pathod_cmdline.py index ef1e983f..dee19f4f 100644 --- a/pathod/pathod_cmdline.py +++ b/pathod/pathod_cmdline.py @@ -216,7 +216,8 @@ def args_pathod(argv, stdout_=sys.stdout, stderr_=sys.stderr): anchors = [] for patt, spec in args.anchors: if os.path.isfile(spec): - data = open(spec).read() + with open(spec) as f: + data = f.read() spec = data try: arex = re.compile(patt) diff --git a/release/setup.py b/release/setup.py index 01d0672d..17b02ebc 100644 --- a/release/setup.py +++ b/release/setup.py @@ -6,9 +6,9 @@ setup( py_modules=["rtool"], install_requires=[ "click>=6.2, <7.0", - "twine>=1.6.5, <1.9", + "twine>=1.6.5, <1.10", "pysftp==0.2.8", - "cryptography>=1.6, <1.7", + "cryptography>=1.6, <1.9", ], entry_points={ "console_scripts": [ diff --git a/requirements.txt b/requirements.txt index ab8e8a0b..28a0b495 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ --e .[dev,examples,contentviews] +-e .[dev,examples] @@ -64,7 +64,6 @@ setup( "brotlipy>=0.5.1, <0.7", "certifi>=2015.11.20.1", # no semver here - this should always be on the last release! "click>=6.2, <7", - "construct>=2.8, <2.9", "cryptography>=1.4, <1.9", "cssutils>=1.0.1, <1.1", "h2>=3.0, <4", diff --git a/test/mitmproxy/contrib/test_tls_parser.py b/test/mitmproxy/contrib/test_tls_parser.py deleted file mode 100644 index 66972b62..00000000 --- a/test/mitmproxy/contrib/test_tls_parser.py +++ /dev/null @@ -1,38 +0,0 @@ -from mitmproxy.contrib import tls_parser - - -def test_parse_chrome(): - """ - Test if we properly parse a ClientHello sent by Chrome 54. - """ - data = bytes.fromhex( - "03033b70638d2523e1cba15f8364868295305e9c52aceabda4b5147210abc783e6e1000022c02bc02fc02cc030" - "cca9cca8cc14cc13c009c013c00ac014009c009d002f0035000a0100006cff0100010000000010000e00000b65" - "78616d706c652e636f6d0017000000230000000d00120010060106030501050304010403020102030005000501" - "00000000001200000010000e000c02683208687474702f312e3175500000000b00020100000a00080006001d00" - "170018" - ) - c = tls_parser.ClientHello.parse(data) - assert c.version.major == 3 - assert c.version.minor == 3 - - alpn = [a for a in c.extensions.extensions if a.type == 16] - assert len(alpn) == 1 - assert alpn[0].alpn_protocols == [b"h2", b"http/1.1"] - - sni = [a for a in c.extensions.extensions if a.type == 0] - assert len(sni) == 1 - assert sni[0].server_names[0].name_type == 0 - assert sni[0].server_names[0].host_name == b"example.com" - - -def test_parse_no_extensions(): - data = bytes.fromhex( - "03015658a756ab2c2bff55f636814deac086b7ca56b65058c7893ffc6074f5245f70205658a75475103a152637" - "78e1bb6d22e8bbd5b6b0a3a59760ad354e91ba20d353001a0035002f000a000500040009000300060008006000" - "61006200640100" - ) - c = tls_parser.ClientHello.parse(data) - assert c.version.major == 3 - assert c.version.minor == 1 - assert c.extensions is None diff --git a/test/mitmproxy/net/test_tcp.py b/test/mitmproxy/net/test_tcp.py index 234e8afb..adf8701a 100644 --- a/test/mitmproxy/net/test_tcp.py +++ b/test/mitmproxy/net/test_tcp.py @@ -391,7 +391,7 @@ class TestSNI(tservers.ServerTestBase): class TestServerCipherList(tservers.ServerTestBase): handler = ClientCipherListHandler ssl = dict( - cipher_list=b'AES256-GCM-SHA384' + cipher_list='AES256-GCM-SHA384' ) def test_echo(self): diff --git a/test/mitmproxy/proxy/protocol/test_tls.py b/test/mitmproxy/proxy/protocol/test_tls.py index e17ee46f..980ba7bd 100644 --- a/test/mitmproxy/proxy/protocol/test_tls.py +++ b/test/mitmproxy/proxy/protocol/test_tls.py @@ -23,4 +23,5 @@ class TestClientHello: ) c = TlsClientHello(data) assert c.sni == 'example.com' - assert c.alpn_protocols == [b'h2', b'http/1.1'] + assert c.alpn_protocols[0].name == b'h2' + assert c.alpn_protocols[1].name == b'http/1.1' diff --git a/test/pathod/language/test_generators.py b/test/pathod/language/test_generators.py index 6a67ab72..5e64c726 100644 --- a/test/pathod/language/test_generators.py +++ b/test/pathod/language/test_generators.py @@ -14,16 +14,14 @@ def test_randomgenerator(): def test_filegenerator(tmpdir): f = tmpdir.join("foo") - f.write(b"x" * 10000) + f.write(b"abcdefghijklmnopqrstuvwxyz" * 1000) g = generators.FileGenerator(str(f)) - assert len(g) == 10000 - assert g[0] == b"x" - assert g[-1] == b"x" - assert g[0:5] == b"xxxxx" + assert len(g) == 26000 + assert g[0] == b"a" + assert g[2:7] == b"cdefg" assert len(g[1:10]) == 9 - assert len(g[10000:10001]) == 0 + assert len(g[26000:26001]) == 0 assert repr(g) - g.close() def test_transform_generator(): diff --git a/test/pathod/test_test.py b/test/pathod/test_test.py index 40f45f53..d51a2c7a 100644 --- a/test/pathod/test_test.py +++ b/test/pathod/test_test.py @@ -1,15 +1,9 @@ -import logging +import os import requests import pytest from pathod import test - -from mitmproxy.test import tutils - -import requests.packages.urllib3 - -requests.packages.urllib3.disable_warnings() -logging.disable(logging.CRITICAL) +from pathod.pathod import SSLOptions, CA_CERT_NAME class TestDaemonManual: @@ -22,29 +16,17 @@ class TestDaemonManual: with pytest.raises(requests.ConnectionError): requests.get("http://localhost:%s/p/202:da" % d.port) - def test_startstop_ssl(self): - d = test.Daemon(ssl=True) - rsp = requests.get( - "https://localhost:%s/p/202:da" % - d.port, - verify=False) - assert rsp.ok - assert rsp.status_code == 202 - d.shutdown() - with pytest.raises(requests.ConnectionError): - requests.get("http://localhost:%s/p/202:da" % d.port) - - def test_startstop_ssl_explicit(self): - ssloptions = dict( - certfile=tutils.test_data.path("pathod/data/testkey.pem"), - cacert=tutils.test_data.path("pathod/data/testkey.pem"), - ssl_after_connect=False + @pytest.mark.parametrize('not_after_connect', [True, False]) + def test_startstop_ssl(self, not_after_connect): + ssloptions = SSLOptions( + cn=b'localhost', + sans=[b'localhost', b'127.0.0.1'], + not_after_connect=not_after_connect, ) - d = test.Daemon(ssl=ssloptions) + d = test.Daemon(ssl=True, ssloptions=ssloptions) rsp = requests.get( - "https://localhost:%s/p/202:da" % - d.port, - verify=False) + "https://localhost:%s/p/202:da" % d.port, + verify=os.path.expanduser(os.path.join(d.thread.server.ssloptions.confdir, CA_CERT_NAME))) assert rsp.ok assert rsp.status_code == 202 d.shutdown() diff --git a/test/pathod/tservers.py b/test/pathod/tservers.py index fab09288..a7c92964 100644 --- a/test/pathod/tservers.py +++ b/test/pathod/tservers.py @@ -1,3 +1,4 @@ +import os import tempfile import re import shutil @@ -13,6 +14,7 @@ from pathod import language from pathod import pathoc from pathod import pathod from pathod import test +from pathod.pathod import CA_CERT_NAME def treader(bytes): @@ -72,7 +74,7 @@ class DaemonTests: self.d.port, path ), - verify=False, + verify=os.path.join(self.d.thread.server.ssloptions.confdir, CA_CERT_NAME), params=params ) return resp |