def __init__(self, abstract_socket: AbstractAioSocket, context: ssl.SSLContext = ssl.create_default_context(), server_side: bool = False, server_hostname: str = None, loop: asyncio.AbstractEventLoop = None): self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.client_random = None self.master_secret = None self.abstract_socket = abstract_socket self.server_side = server_side self.tls: ssl.SSLObject = context.wrap_bio(self.incoming, self.outgoing, server_side, server_hostname) self.wrapped = False if loop is None: self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() else: self.loop: asyncio.AbstractEventLoop = loop
def __init__(self, socket, ssl_context, server_hostname=None, suppress_ragged_eofs=True): """ Create an SSLTransport around socket using the provided ssl_context. """ self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.suppress_ragged_eofs = suppress_ragged_eofs self.socket = socket self.sslobj = ssl_context.wrap_bio(self.incoming, self.outgoing, server_hostname=server_hostname) # Perform initial handshake. self._ssl_io_loop(self.sslobj.do_handshake)
def init_tls(self): self.log.debug("initializing TLS context...") self.tls_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) self.tls_in = ssl.MemoryBIO() self.tls_out = ssl.MemoryBIO() self.tls = self.tls_ctx.wrap_bio(self.tls_in, self.tls_out, False, None)
def __init__(self, transport_stream, ssl_context, *, server_hostname=None, server_side=False, https_compatible=False, max_refill_bytes=_default_max_refill_bytes): self.transport_stream = transport_stream self._state = _State.OK self._max_refill_bytes = max_refill_bytes self._https_compatible = https_compatible self._outgoing = _stdlib_ssl.MemoryBIO() self._incoming = _stdlib_ssl.MemoryBIO() self._ssl_object = ssl_context.wrap_bio( self._incoming, self._outgoing, server_side=server_side, server_hostname=server_hostname) # Tracks whether we've already done the initial handshake self._handshook = _Once(self._do_handshake) # These are used to synchronize access to self.transport_stream self._inner_send_lock = _sync.StrictFIFOLock() self._inner_recv_count = 0 self._inner_recv_lock = _sync.Lock() # These are used to make sure that our caller doesn't attempt to make # multiple concurrent calls to send_all/wait_send_all_might_not_block # or to receive_some. self._outer_send_conflict_detector = ConflictDetector( "another task is currently sending data on this SSLStream") self._outer_recv_conflict_detector = ConflictDetector( "another task is currently receiving data on this SSLStream")
def check_handshake(server_context, client_context, err=None): hostname = 'localhost' c_in = ssl.MemoryBIO() c_out = ssl.MemoryBIO() s_in = ssl.MemoryBIO() s_out = ssl.MemoryBIO() client = client_context.wrap_bio(c_in, c_out, server_hostname=hostname) server = server_context.wrap_bio(s_in, s_out, server_side=True) try: for _ in range(5): try: client.do_handshake() except ssl.SSLWantReadError: pass if c_out.pending: s_in.write(c_out.read()) try: server.do_handshake() except ssl.SSLWantReadError: pass if s_out.pending: c_in.write(s_out.read()) except Exception as e: if err is None: assert False else: assert isinstance(e, err) else: if err is not None: assert False
def __init__(self, server_side: bool = False, alpn: typing.Optional[typing.List[str]] = None, sni: typing.Optional[bytes] = b"example.mitmproxy.org"): self.inc = ssl.MemoryBIO() self.out = ssl.MemoryBIO() self.ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER if server_side else ssl.PROTOCOL_TLS_CLIENT) self.ctx.verify_mode = ssl.CERT_OPTIONAL self.ctx.load_verify_locations(cafile=tlsdata.path( "../../net/data/verificationcerts/trusted-root.crt"), ) if alpn: self.ctx.set_alpn_protocols(alpn) if server_side: self.ctx.load_cert_chain( certfile=tlsdata.path( "../../net/data/verificationcerts/trusted-leaf.crt"), keyfile=tlsdata.path( "../../net/data/verificationcerts/trusted-leaf.key"), ) self.obj = self.ctx.wrap_bio( self.inc, self.out, server_hostname=None if server_side else sni, server_side=server_side, )
def __init__(self, socket, ssl_context, suppress_ragged_eofs=True, **wrap_bio_kwargs): """ Create an SSLTransport around socket using the provided ssl_context. :param socket: The socket object to wrap. :param ssl_context: :class:`ssl.SSLContext` to use call :func:`ssl.SSLContext.wrap_bio` on. :param suppress_ragged_eofs: Suppress ``ssl.SSL_ERROR_EOF`` read errors. :param wrap_bio_kwargs: These args will be passed to :func:`ssl.SSLContext.wrap_bio` """ self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.suppress_ragged_eofs = suppress_ragged_eofs self.socket = socket self.sslobj = ssl_context.wrap_bio(self.incoming, self.outgoing, **wrap_bio_kwargs) # Perform initial handshake. self._ssl_io_loop(self.sslobj.do_handshake)
def handle_notification_connection(self): self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() try: notif_tls_ctx.load_verify_locations(cadata=parse_authorized_certs()) self.tls_bio = notif_tls_ctx.wrap_bio(incoming=self.incoming, outgoing=self.outgoing, server_side=True) self.do_handshake() except Exception as e: print_with_timestamp('(Bluetooth) Failed TLS handshake notif_conn: {}'.format(e)) return # one recv should not take longer than 10 sec self.socket.settimeout(10) notification_flags_size = struct.unpack('>I', recvall(self.socket, 4))[0] notification_flags_encrypted = recvall(self.socket, notification_flags_size) notification_flags = struct.unpack('>B', self.tls_decrypt(notification_flags_encrypted))[0] if notification_flags & FLAG_INCLUDE_TITLE == FLAG_INCLUDE_TITLE: include_title = True else: include_title = False if notification_flags & FLAG_INCLUDE_MESSAGE == FLAG_INCLUDE_MESSAGE: include_message = True else: include_message = False if notification_flags & FLAG_INCLUDE_ICON == FLAG_INCLUDE_ICON: include_icon = True else: include_icon = False title = '' message = '' if include_title or include_message: title_and_or_message_size = struct.unpack('>I', recvall(self.socket, 4))[0] title_and_or_message_encrypted = recvall(self.socket, title_and_or_message_size) title_and_or_message = self.tls_decrypt(title_and_or_message_encrypted).decode() if include_title: title = title_and_or_message.split('|||')[0] if include_message: message = title_and_or_message.split('|||')[1] if include_icon: icon_tmp_file = tempfile.NamedTemporaryFile(buffering=0, dir=TMP_DIR_PATH) icon_size = struct.unpack('>I', recvall(self.socket, 4))[0] icon_encrypted = recvall(self.socket, icon_size) icon = self.tls_decrypt(icon_encrypted) try: icon_tmp_file.write(icon) Notification(title, message, hashlib.sha1(title.encode() + message.encode() + icon).digest(), icon_tmp_file).show() except Exception: Notification(title, message, hashlib.sha1(title.encode() + message.encode()).digest()).show() else: Notification(title, message, hashlib.sha1(title.encode() + message.encode()).digest()).show()
def make_tls_objects(): tls_in_buff = ssl.MemoryBIO() tls_out_buff = ssl.MemoryBIO() ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.load_cert_chain(cert_file, key_file) ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 ctx.set_alpn_protocols(["h2"]) tls_obj = ctx.wrap_bio(tls_in_buff, tls_out_buff, server_side=True) return tls_obj, tls_in_buff, tls_out_buff
def __init__(self, src: ScanHost[IPAddressType], dst: ScanHost[IPAddressType]) -> None: super(TLSProtocol, self).__init__(src, dst) self._in_bio = ssl.MemoryBIO() self._out_bio = ssl.MemoryBIO() self._ssl = self._SSL_CTX.wrap_bio(self._in_bio, self._out_bio, server_side=False, server_hostname=self._dst.host)
def __init__(self, handle, readable=True, writable=True, server_side=False): super().__init__(handle, readable=readable, writable=writable, server_side=server_side) self.finish_handshake = False from .http_proxy_server import CertUtil self._context = CertUtil.get_context() self._incoming = ssl.MemoryBIO() self._outgoing = ssl.MemoryBIO() self._handshake_lock = asyncio.Lock() self._ssl_obj = self._context.wrap_bio(self._incoming, self._outgoing, self._server_side) self.__must_write = lambda: self._MustDo(self.__write_to_pipe())
async def wrap( cls, transport_stream: AnyByteStream, *, server_side: Optional[bool] = None, hostname: Optional[str] = None, ssl_context: Optional[ssl.SSLContext] = None, standard_compatible: bool = True, ) -> "TLSStream": """ Wrap an existing stream with Transport Layer Security. This performs a TLS handshake with the peer. :param transport_stream: a bytes-transporting stream to wrap :param server_side: ``True`` if this is the server side of the connection, ``False`` if this is the client side (if omitted, will be set to ``False`` if ``hostname`` has been provided, ``False`` otherwise). Used only to create a default context when an explicit context has not been provided. :param hostname: host name of the peer (if host name checking is desired) :param ssl_context: the SSLContext object to use (if not provided, a secure default will be created) :param standard_compatible: if ``False``, skip the closing handshake when closing the connection, and don't raise an exception if the peer does the same :raises ~ssl.SSLError: if the TLS handshake fails """ if server_side is None: server_side = not hostname if not ssl_context: purpose = ( ssl.Purpose.CLIENT_AUTH if server_side else ssl.Purpose.SERVER_AUTH ) ssl_context = ssl.create_default_context(purpose) # Re-enable detection of unexpected EOFs if it was disabled by Python if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"): ssl_context.options ^= ssl.OP_IGNORE_UNEXPECTED_EOF # type: ignore[attr-defined] bio_in = ssl.MemoryBIO() bio_out = ssl.MemoryBIO() ssl_object = ssl_context.wrap_bio( bio_in, bio_out, server_side=server_side, server_hostname=hostname ) wrapper = cls( transport_stream=transport_stream, standard_compatible=standard_compatible, _ssl_object=ssl_object, _read_bio=bio_in, _write_bio=bio_out, ) await wrapper._call_sslobject_method(ssl_object.do_handshake) return wrapper
async def StartTLS(self): self._normal_send = self._ssl_send self._normal_recv = self._ssl_recv if (self._Debug): self.Send = self._debug_send self.Recv = self._debug_recv self.Close = self._debug_close else: self.Send = self._normal_send self.Recv = self._normal_recv self.Close = self._normal_close self._tls_in_buff = ssl.MemoryBIO() self._tls_out_buff = ssl.MemoryBIO() self._tls_obj = self._SSL_Context.wrap_bio( self._tls_in_buff, self._tls_out_buff, server_side=self._server_side) if (self._server_side): # Recv Client Hello self._tls_in_buff.write(await asyncio.wait_for( self._Reader.read(self._Recvsize), timeout=self._Timeout)) # || TLS Handshake try: self._tls_obj.do_handshake() except ssl.SSLWantReadError: if (self._server_side): self._Writer.write(self._tls_out_buff.read()) await asyncio.wait_for(self._Writer.drain(), timeout=self._Timeout) self._tls_in_buff.write(await asyncio.wait_for( self._Reader.read(self._Recvsize), timeout=self._Timeout)) self._tls_obj.do_handshake() self._Writer.write(self._tls_out_buff.read()) await asyncio.wait_for(self._Writer.drain(), timeout=self._Timeout) else: # Client Hello self._Writer.write(self._tls_out_buff.read()) await asyncio.wait_for(self._Writer.drain(), timeout=self._Timeout) # Server Hello self._tls_in_buff.write(await asyncio.wait_for( self._Reader.read(self._Recvsize), timeout=self._Timeout)) try: self._tls_obj.do_handshake() except ssl.SSLWantReadError: self._Writer.write(self._tls_out_buff.read()) await asyncio.wait_for(self._Writer.drain(), timeout=self._Timeout) self._tls_in_buff.write(await asyncio.wait_for( self._Reader.read(self._Recvsize), timeout=self._Timeout))
def __init__(self, writer, reader, pem_file): """@param: writer and reader are asyncio stream writer and reader objects""" self._tlsInBuff = ssl.MemoryBIO() self._tlsOutBuff = ssl.MemoryBIO() ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1) ctx.set_ciphers('RSA:!aNULL') ctx.check_hostname = False ctx.load_cert_chain(pem_file) self._tlsObj = ctx.wrap_bio(self._tlsInBuff, self._tlsOutBuff, server_side=True) self.writer = writer self.reader = reader
def __init__(self, reader, writer): super().__init__(reader, writer) self.ServerSide = True self.ServerName = None self.ALPN = None self.SslContext = None self.isTryingHandshake = False self._tls_in_buff = ssl.MemoryBIO() self._tls_out_buff = ssl.MemoryBIO() self._tls_Readsize = 8 self._client_hello_buf = None
def handle_notification_connection(self): self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() try: if bluetooth_support_kitkat: notif_tls_ctx_kitkat_bt.load_verify_locations(cadata=parse_authorized_certs()) self.tls_bio = notif_tls_ctx_kitkat_bt.wrap_bio(incoming=self.incoming, outgoing=self.outgoing, server_side=True) else: notif_tls_ctx.load_verify_locations(cadata=parse_authorized_certs()) self.tls_bio = notif_tls_ctx.wrap_bio(incoming=self.incoming, outgoing=self.outgoing, server_side=True) self.do_handshake() except Exception as e: logging.error('(Bluetooth) Failed TLS handshake notif_conn: {}'.format(e)) return # one recv should not take longer than 10 sec self.socket.settimeout(10) notification_flags_size = struct.unpack('>I', recvall(self.socket, 4))[0] notification_flags_encrypted = recvall(self.socket, notification_flags_size) notification_flags = struct.unpack('>B', self.tls_decrypt(notification_flags_encrypted))[0] include_title = chkflags(notification_flags, FLAG_INCLUDE_TITLE) include_message = chkflags(notification_flags, FLAG_INCLUDE_MESSAGE) include_icon = chkflags(notification_flags, FLAG_INCLUDE_ICON) title = '' message = '' if include_title or include_message: title_and_or_message_size = struct.unpack('>I', recvall(self.socket, 4))[0] title_and_or_message_encrypted = recvall(self.socket, title_and_or_message_size) title_and_or_message = self.tls_decrypt(title_and_or_message_encrypted).decode() if include_title: title = title_and_or_message.split('|||')[0] if include_message: message = title_and_or_message.split('|||')[1] if include_icon: icon_size = struct.unpack('>I', recvall(self.socket, 4))[0] icon_encrypted = recvall(self.socket, icon_size) icon_bytes = self.tls_decrypt(icon_encrypted) try: Notification(title, message, icon_bytes).show() except Exception: Notification(title, message).show() else: Notification(title, message).show()
def __init__(self, netstream, hostname, log=None): if log is None: self.log = logging.getLogger('SSLStream.%s' % (hostname, )) else: self.log = log self.reof = False self.netstream = netstream self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.ctx = ssl.create_default_context() self.obj = self.ctx.wrap_bio(self.incoming, self.outgoing, server_side=False, server_hostname=hostname) self.handshake_done = False self.log.debug('%s', f'wrapped {self.netstream!r}')
def __init__( self, transport_stream, ssl_context, *, server_hostname=None, server_side=False, https_compatible=False, max_refill_bytes="unused and deprecated" ): self.transport_stream = transport_stream self._state = _State.OK if max_refill_bytes != "unused and deprecated": warn_deprecated( "max_refill_bytes=...", "0.12.0", issue=959, instead=None ) self._https_compatible = https_compatible self._outgoing = _stdlib_ssl.MemoryBIO() self._delayed_outgoing = None self._incoming = _stdlib_ssl.MemoryBIO() self._ssl_object = ssl_context.wrap_bio( self._incoming, self._outgoing, server_side=server_side, server_hostname=server_hostname ) # Tracks whether we've already done the initial handshake self._handshook = _Once(self._do_handshake) # These are used to synchronize access to self.transport_stream self._inner_send_lock = _sync.StrictFIFOLock() self._inner_recv_count = 0 self._inner_recv_lock = _sync.Lock() # These are used to make sure that our caller doesn't attempt to make # multiple concurrent calls to send_all/wait_send_all_might_not_block # or to receive_some. self._outer_send_conflict_detector = ConflictDetector( "another task is currently sending data on this SSLStream" ) self._outer_recv_conflict_detector = ConflictDetector( "another task is currently receiving data on this SSLStream" ) self._estimated_receive_size = STARTING_RECEIVE_SIZE
def __init__(self, maxlen=-1): """ Creates StreamReader instance. Params: maxlen - maximal allowed netstring length. """ self._maxlen = maxlen self._incoming = ssl.MemoryBIO() self._fetcher = None
def __init__(self, context, server_side, server_hostname=None): """ The *context* argument specifies the ssl.SSLContext to use. The *server_side* argument indicates whether this is a server side or client side transport. The optional *server_hostname* argument can be used to specify the hostname you are connecting to. You may only specify this parameter if the _ssl module supports Server Name Indication (SNI). """ self._context = context self._server_side = server_side self._server_hostname = server_hostname self._state = _UNWRAPPED self._incoming = ssl.MemoryBIO() self._outgoing = ssl.MemoryBIO() self._sslobj = None self._need_ssldata = False self._handshake_cb = None self._shutdown_cb = None
def __init__(self, loop, app_protocol, sslcontext, waiter, server_side=False, server_hostname=None, call_connection_made=True, ssl_handshake_timeout=None): if ssl is None: raise RuntimeError('stdlib ssl module not available') if ssl_handshake_timeout is None: ssl_handshake_timeout = constants.SSL_HANDSHAKE_TIMEOUT elif ssl_handshake_timeout <= 0: raise ValueError( f"ssl_handshake_timeout should be a positive number, " f"got {ssl_handshake_timeout}") if not sslcontext: sslcontext = _create_transport_context(server_side, server_hostname) self._waiter = waiter self._app_transport = _SSLTransport(loop, self) self._app_protocol = app_protocol self._server_side = server_side if server_hostname and not server_side: self._server_hostname = server_hostname else: self._server_hostname = None self._sslcontext = sslcontext # SSL-specific extra info. More info are set when the handshake # completes. self._extra = dict(sslcontext=sslcontext) self._sslobj = None self._transport = None self._state = _UNWRAPPED self._incoming = ssl.MemoryBIO() self._outgoing = ssl.MemoryBIO() self._ssl_buffer = bytearray(262144)
def _do_ssl_handshake(self): context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) incoming = ssl.MemoryBIO() outgoing = ssl.MemoryBIO() sslobj = context.wrap_bio(incoming, outgoing, False) # do_handshake() while True: try: sslobj.do_handshake() except ssl.SSLWantReadError: self._send_message(TDS_PRELOGIN, outgoing.read()) tag, _, _, buf = self._read_response_packet() assert tag == TDS_PRELOGIN incoming.write(buf) else: break return sslobj, incoming, outgoing
def test_spoof_https_site_through_https_proxy(self): # This is a proof-of-concept for proxying HTTPS requests through an # HTTPS server. Typically, HTTPS requests are proxied via CONNECT verb # on a plain-text HTTP server. This means proxy credentials are sent # in the clear, as well as the intended destination. Proxying via HTTPS # allows these to be nominally protected. At this time, no major # HTTP libraries support proxying HTTPS requests through HTTPS servers, # so the actual request portion of the test is quite crude, reading and # writing directly to sockets. The use of the `ssl.SSLContext.wrap_bio` # method allows arbitrary SSL I/O, provided data is written to and read # out of BIO instances. This is required as it's not possible to for an # `ssl.SSLContext` socket to wrap another `ssl.SSLContext` socket. expected = upstream_content = b"octet-comeback-squirmy" chunk_size = 4096 httpd = spoof.HTTPServer( sslContext=spoof.SSLContext.fromCertChain(self.cert, self.key)) httpd.defaultResponse = [200, [], ""] httpd.start() httpd.upstream = spoof.HTTPUpstreamServer( sslContext=spoof.SSLContext.fromCertChain(self.cert, self.key)) httpd.upstream.defaultResponse = [200, [], upstream_content] httpd.upstream.start() client = ssl.create_default_context(cafile=self.cert).wrap_socket( socket.create_connection(httpd.serverAddress), server_hostname=httpd.address) client.sendall(b"CONNECT google.com HTTP/1.0\r\n\r\n") client.recv(chunk_size) # response headers tunnel_in = ssl.MemoryBIO() tunnel_out = ssl.MemoryBIO() tunnel = ssl.create_default_context(cafile=self.cert).wrap_bio( tunnel_in, tunnel_out, server_hostname="google.com") tunnel_cmd = functools.partial(utils.ssl_io_loop, client, tunnel_in, tunnel_out) tunnel_cmd(tunnel.do_handshake) tunnel_cmd(tunnel.write, b"GET / HTTP/1.0\r\n\r\n") tunnel_cmd(tunnel.read, chunk_size) # response headers result = tunnel_cmd(tunnel.read, chunk_size) client.close() httpd.upstream.stop() httpd.stop() self.assertEqual(expected, result)
def test_set_keylog_bio(tmpdir, context, ssl_server): keylog = tmpdir / "sslkeylog.txt" sslkeylog.set_keylog(str(keylog)) with closing(socket.create_connection(ADDRESS)) as sock: incoming = ssl.MemoryBIO() outgoing = ssl.MemoryBIO() sslobj = context.wrap_bio(incoming, outgoing, server_side=False, server_hostname=ADDRESS[0]) ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake) time.sleep(2) data = keylog.read_text("utf-8").splitlines() if sslkeylog.OPENSSL111: assert len(data) == 10 else: assert len(data) == 2 for line in data: assert LOG_LINE_REGEX.search(line)
def __init__(self, parent_context, ssl_context, server_hostname): self._parent_context = parent_context self._ssl_context = ssl_context # We need this extra buffer to implement the peek/consume API, which # the MemoryBIO object does not allow. self._ciphertext_buffer = bytearray() # Set up the SSLObject we're going to back this with. server_side = isinstance(parent_context, ServerContext) self._in_bio = ssl.MemoryBIO() self._out_bio = ssl.MemoryBIO() self._object = ssl_context.wrap_bio(self._in_bio, self._out_bio, server_side=server_side, server_hostname=server_hostname) # Keep track of the fact that we are the owner of this object. _object_to_buffer_map[self._object] = self # We need to track whether the connection is established to properly # report the TLS version. This is to work around a Python bug: # https://bugs.python.org/issue29781 self._connection_established = False
async def handle(self): """ does the thing """ self.body = b'' try: method_line, self.headers, self.body = await self.read_request(self ) except asyncio.streams.IncompleteReadError: self.writer.close() return False # GET http://www.example.com/ HTTP/1.1 self.method, self.url, self.version = method_line.decode().split() if self.ssl: # if https, the host is omitted because the client thinks its talking directly to the server self.url = f"https://{self.ssl_hostname}{self.url}" self.log(f"{self.method} {self.url} {self.version}") """ if self.url == 'http://oopsiewhoopsie.proxy/breakhttps.crt': async with aiofiles.open(CA_PATH + "/ca.crt", "rb") as f: self.body = await f.read() await self.send_response("200 :ok_hand:", body=self.body, addn_headers={ 'Content-Type': 'application/x-x509-ca-cert', 'Connection': 'close' }) self.writer.close() return False """ # SSL proxy # CONNECT example.com:443 HTTP/1.1 if self.method == "CONNECT" and self.url.endswith(":443"): self.ssl_hostname = self.url.split(':')[0] cert_path = os.path.join(CERTS_PATH, self.ssl_hostname + ".crt") if not os.path.isfile(cert_path): subprocess.check_call(["./mkcrt", self.ssl_hostname]) self.log(f"./mkcrt {self.ssl_hostname} -> {cert_path}") self.writer.write(b"HTTP/1.1 200 Yeet Dab\r\n\r\n") # REALLY hacky lul self.ssl = True self._ssl_ctx = ssl.SSLContext() self._ssl_ctx.load_cert_chain(cert_path, keyfile=f"{CA_PATH}/cert.key") self._ssl_in = ssl.MemoryBIO() self._ssl_out = ssl.MemoryBIO() self._ssl_obj = self._ssl_ctx.wrap_bio( self._ssl_in, self._ssl_out, server_side=True, server_hostname=self.ssl_hostname) self._ssl_buf = b'' await self.ssl_handshake() return True # drop unsupported headers oopsy whoopsy # reee keepalives keepalive = self.headers.get("Connection", "f").lower() == "keep-alive" or \ self.headers.get("Proxy-Connection", "f").lower() == "keep-alive" # to hell with trailers, also the client doesn't support keepalive for k in ["Connection", "Proxy-Connection", "TE"]: try: del self.headers[k] except KeyError: pass # make the request to the host await self.respond() #self.log(f"keepalive == {keepalive}") if not keepalive: self.writer.close() return keepalive
from contextlib import contextmanager import ssl client_ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) client_ctx.check_hostname = False client_ctx.verify_mode = ssl.CERT_NONE cinb = ssl.MemoryBIO() coutb = ssl.MemoryBIO() cso = client_ctx.wrap_bio(cinb, coutb) server_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) server_ctx.load_cert_chain("server.crt", "server.key", "xxxx") sinb = ssl.MemoryBIO() soutb = ssl.MemoryBIO() sso = server_ctx.wrap_bio(sinb, soutb, server_side=True) @contextmanager def expect(etype): try: yield except etype: pass else: raise AssertionError("expected {}".format(etype)) with expect(ssl.SSLWantReadError): cso.do_handshake() assert not cinb.pending
def handle_pair_request(self): if bluetooth_support_kitkat: pair_tls_ctx = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1) pair_tls_ctx.set_ciphers('DHE-RSA-AES256-SHA') pair_tls_ctx.load_dh_params(DHPARAM_PATH) else: pair_tls_ctx = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1_2) pair_tls_ctx.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA') pair_tls_ctx.set_ecdh_curve('prime256v1') pair_tls_ctx.load_cert_chain(CERTIFICATE_PATH, RSA_PRIVATE_KEY_PATH) self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.tls_bio = pair_tls_ctx.wrap_bio(incoming=self.incoming, outgoing=self.outgoing, server_side=True) try: self.do_handshake() except ssl.SSLError as ssle: logging.error('(Bluetooth) Failed TLS handshake pair_request: {}'.format(ssle)) return logging.info('(Bluetooth) Pair request from: {}\n'.format(self.address)) '''I don't know how else to do this when using SSLEngine/SSL_BIO, I don't see any security issue with sending the length of the encrypted data in cleartext, using something like wireshark it's possible to see the length anyway''' client_cert_size = struct.unpack('>I', recvall(self.socket, 4))[0] client_cert_encrypted = recvall(self.socket, client_cert_size) client_cert = self.tls_decrypt(client_cert_encrypted) sha256 = hashlib.sha256(client_cert + SERVER_CERT_DER).hexdigest().upper() sha256_format = [sha256[x:x + 2] for x in range(0, len(sha256), 2)] print('It is very important that you verify that the following hash matches what is viewed on your phone\n' 'It is a sha256 hash like so: sha256(client_cert + server_cert)\n\n' 'If the hash don\'t match there could be a man-in-the-middle attack\n' 'Or something else is not right, you should abort if they don\'t match!\n') print(' '.join(sha256_format[:8])) print(' '.join(sha256_format[8:16])) print(' '.join(sha256_format[16:24])) print(' '.join(sha256_format[24:])) self.server_allow_pair = False self.client_allow_pair = False try: termios.tcflush(sys.stdin, termios.TCIFLUSH) except Exception: pass self.user_input_prompt = 'Enter "yes" to accept pairing or "no" to deny: ' print('\n{}'.format(self.user_input_prompt), end='') threading.Thread(target=self.pair_response_thread).start() while not BluetoothHandler.cancel_pairing: ready = select.select([sys.stdin], [], [], 1)[0] if ready: user_input = sys.stdin.readline().strip() if user_input.casefold() == 'yes'.casefold(): encrypted = self.tls_encrypt(ACCEPT_PAIRING) encrypted_size = struct.pack('>I', len(encrypted)) self.socket.sendall(encrypted_size) self.socket.sendall(encrypted) self.server_allow_pair = True if not self.client_allow_pair: print('Waiting for client response') while not BluetoothHandler.cancel_pairing: if self.client_allow_pair: add_to_authorized_certs(client_cert) break else: time.sleep(1) break elif user_input.casefold() == 'no'.casefold(): encrypted = self.tls_encrypt(DENY_PAIRING) encrypted_size = struct.pack('>I', len(encrypted)) self.socket.sendall(encrypted_size) self.socket.sendall(encrypted) print('Pairing canceled') BluetoothHandler.cancel_pairing = True else: print(self.user_input_prompt, end='', flush=True)
def __init__(self, ctx, sock, **kwargs): self.incoming = ssl.MemoryBIO() self.outgoing = ssl.MemoryBIO() self.obj = ctx.wrap_bio(self.incoming, self.outgoing, **kwargs) self.sock = sock
def __init__(self, loop, app_protocol, sslcontext, waiter, server_side=False, server_hostname=None, call_connection_made=True, ssl_handshake_timeout=None, ssl_shutdown_timeout=None): if ssl is None: raise RuntimeError("stdlib ssl module not available") self._ssl_buffer = bytearray(self.max_size) self._ssl_buffer_view = memoryview(self._ssl_buffer) if ssl_handshake_timeout is None: ssl_handshake_timeout = constants.SSL_HANDSHAKE_TIMEOUT elif ssl_handshake_timeout <= 0: raise ValueError( f"ssl_handshake_timeout should be a positive number, " f"got {ssl_handshake_timeout}") if ssl_shutdown_timeout is None: ssl_shutdown_timeout = constants.SSL_SHUTDOWN_TIMEOUT elif ssl_shutdown_timeout <= 0: raise ValueError( f"ssl_shutdown_timeout should be a positive number, " f"got {ssl_shutdown_timeout}") if not sslcontext: sslcontext = _create_transport_context( server_side, server_hostname) self._server_side = server_side if server_hostname and not server_side: self._server_hostname = server_hostname else: self._server_hostname = None self._sslcontext = sslcontext # SSL-specific extra info. More info are set when the handshake # completes. self._extra = dict(sslcontext=sslcontext) # App data write buffering self._write_backlog = collections.deque() self._write_buffer_size = 0 self._waiter = waiter self._loop = loop self._set_app_protocol(app_protocol) self._app_transport = None self._app_transport_created = False # transport, ex: SelectorSocketTransport self._transport = None self._ssl_handshake_timeout = ssl_handshake_timeout self._ssl_shutdown_timeout = ssl_shutdown_timeout # SSL and state machine self._incoming = ssl.MemoryBIO() self._outgoing = ssl.MemoryBIO() self._state = SSLProtocolState.UNWRAPPED self._conn_lost = 0 # Set when connection_lost called if call_connection_made: self._app_state = AppProtocolState.STATE_INIT else: self._app_state = AppProtocolState.STATE_CON_MADE self._sslobj = self._sslcontext.wrap_bio( self._incoming, self._outgoing, server_side=self._server_side, server_hostname=self._server_hostname) # Flow Control self._ssl_writing_paused = False self._app_reading_paused = False self._ssl_reading_paused = False self._incoming_high_water = 0 self._incoming_low_water = 0 self._set_read_buffer_limits() self._eof_received = False self._app_writing_paused = False self._outgoing_high_water = 0 self._outgoing_low_water = 0 self._set_write_buffer_limits() self._get_app_transport()