def get_certificate_chain(host: str, port: int) -> List[str]: """ Connect to the host on the port and obtain certificate chain. TODO: Tests against WantReadError and WantX509LookupError needed. """ cert_chain = [] soc = socket(AF_INET, SOCK_STREAM, proto=0) soc.settimeout(3) try: soc.connect((host, port)) except gaierror: raise Exception(f"{host}:{port} is invalid or not known.") from None except timeout: raise Exception(f"Connection to {host}:{port} timed out.") from None except OverflowError: raise Exception(f"Illegal port: {port}. Port must be between 0-65535.") from None except TypeError: raise Exception(f"Illegal port: {port}. Port must be between 0-65535.") from None ssl_client = SslClient( ssl_version=OpenSslVersionEnum.SSLV23, underlying_socket=soc, ssl_verify=OpenSslVerifyEnum.NONE ) # Add Server Name Indication (SNI) extension to the CLIENT HELLO ssl_client.set_tlsext_host_name(host) try: ssl_client.do_handshake() cert_chain = ssl_client.get_received_chain() except WantReadError as err: raise ValueError(err.strerror) from None except WantX509LookupError as err: raise ValueError(err.strerror) from None except OpenSSLError as err: raise ValueError(err) from None finally: ssl_client.shutdown() soc = None return cert_chain
mozilla_store = Path("tests") / "mozilla.pem" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect(("www.yahoo.com", 443)) ssl_client = SslClient( ssl_version=OpenSslVersionEnum.TLSV1_2, underlying_socket=sock, ssl_verify=OpenSslVerifyEnum.PEER, ssl_verify_locations=mozilla_store, ) ssl_client.set_tlsext_status_ocsp() ssl_client.do_handshake() print("Received certificate chain") for pem_cert in ssl_client.get_received_chain(): print(pem_cert) print("Verified certificate chain") for pem_cert in ssl_client.get_verified_chain(): print(pem_cert) print("OCSP Stapling") ocsp_resp = ssl_client.get_tlsext_status_ocsp_resp() if ocsp_resp: ocsp_resp.verify(Path(mozilla_store)) print(ocsp_resp.status) print("\nCipher suite") print(ssl_client.get_current_cipher_name())
def get_certificate_chain(host: str, port: int) -> List[str]: """Connect to the host on the port and obtain certificate chain""" func_name: str = "get_certificate_chain" cert_chain: list = [] soc = socket(AF_INET, SOCK_STREAM, proto=0) soc.settimeout(3) try: soc.connect((host, port)) except gaierror: raise Exception( f"{func_name}: {host}:{port} is invalid or not known.") from None except timeout: raise Exception( f"{func_name}: Connection to {host}:{port} timed out.") from None except (OverflowError, TypeError): raise Exception( f"{func_name}: Illegal port: {port}. Port must be between 0-65535." ) from None except ConnectionRefusedError: raise Exception( f"{func_name}: Connection to {host}:{port} refused.") from None ssl_client = SslClient( ssl_version=OpenSslVersionEnum.SSLV23, underlying_socket=soc, ssl_verify=OpenSslVerifyEnum.NONE, ) # Add Server Name Indication (SNI) extension to the Client Hello ssl_client.set_tlsext_host_name(host) try: ssl_client.do_handshake() cert_chain = ssl_client.get_received_chain() except IOError as err: raise ValueError( f"{func_name}: {host} did not respond to the Client Hello." ) from None except (WantReadError, WantX509LookupError) as err: raise ValueError(f"{func_name}: {err.strerror}") from None except OpenSSLError as err: if "1408F10B" in err.args[0]: # https://github.com/openssl/openssl/issues/6805 raise ValueError( f"{func_name}: Remote host is not using SSL/TLS on port: {port}" ) from None raise ValueError(f"{func_name}: {err}") from None finally: # shutdown() will also close the underlying socket ssl_client.shutdown() return cert_chain
mozilla_store = 'tests/mozilla.pem' sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect(('www.yahoo.com', 443)) ssl_client = SslClient( ssl_version=OpenSslVersionEnum.TLSV1_2, underlying_socket=sock, ssl_verify=OpenSslVerifyEnum.PEER, ssl_verify_locations=mozilla_store, ) ssl_client.set_tlsext_status_ocsp() ssl_client.do_handshake() print('Received certificate chain') for pem_cert in ssl_client.get_received_chain(): print(pem_cert) print('Verified certificate chain') for pem_cert in ssl_client.get_verified_chain(): print(pem_cert) print('OCSP Stapling') ocsp_resp = ssl_client.get_tlsext_status_ocsp_resp() if ocsp_resp: ocsp_resp.verify(mozilla_store) print(ocsp_resp.as_dict()) print('\nCipher suite') print(ssl_client.get_current_cipher_name())