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
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