""" Java javax.net APIs implemented in Python. javax.net package - SocketFactory, SSLServerSocket, SSLSocket, SSLContext, etc. Wraps Python ssl module. """ from __future__ import annotations from .._core import Stub, AndroidOnlyError import ssl as _ssl import socket as _socket import threading as _threading from typing import List, Optional __all__ = [ "ServerSocketFactory", "SocketFactory", "SSLServerSocketFactory", "SSLSocketFactory", "SSLServerSocket", "SSLSocket", "HandshakeCompletedEvent", "HandshakeCompletedListener", "HostnameVerifier", "HttpsURLConnection", "TrustManager", "X509TrustManager", "KeyManager", "X509KeyManager", "TrustManagerFactory", "KeyManagerFactory", "SSLContext", ] # ============================================================ # SocketFactory # ============================================================ class SocketFactory(Stub): """ javax.net.SocketFactory Factory for creating sockets. """ _default = None @classmethod def getDefault(cls) -> "SocketFactory": if cls._default is None: cls._default = SocketFactory() return cls._default def createSocket(self, host: str = None, port: int = None, host_inet: Any = None, local_port: int = None, stream: bool = True) -> _socket.socket: """Creates a socket.""" sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) if host and port is not None: sock.connect((host, port)) return sock def toString(self) -> str: return f"SocketFactory@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # ServerSocketFactory # ============================================================ class ServerSocketFactory(Stub): """ javax.net.ServerSocketFactory Factory for creating server sockets. """ _default = None @classmethod def getDefault(cls) -> "ServerSocketFactory": if cls._default is None: cls._default = ServerSocketFactory() return cls._default def createServerSocket(self, port: int = 0, backlog: int = 50, ifAddress: Any = None) -> _socket.socket: """Creates a server socket.""" sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) sock.setsockopt(_socket.SOL_SOCKET, _socket.SO_REUSEADDR, 1) if ifAddress: sock.bind((ifAddress, port)) else: sock.bind(('0.0.0.0', port)) sock.listen(backlog) return sock def toString(self) -> str: return f"ServerSocketFactory@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # SSLServerSocketFactory # ============================================================ class SSLServerSocketFactory(ServerSocketFactory): """ javax.net.ssl.SSLServerSocketFactory Factory for creating SSL server sockets. """ _default = None @classmethod def getDefault(cls) -> "SSLServerSocketFactory": if cls._default is None: cls._default = SSLServerSocketFactory() return cls._default def getDefaultCipherSuites(self) -> List[str]: try: ctx = _ssl.create_default_context(_ssl.Purpose.CLIENT_AUTH) return ctx.get_ciphers() except Exception: return [] def getSupportedCipherSuites(self) -> List[str]: try: ctx = _ssl.create_default_context(_ssl.Purpose.CLIENT_AUTH) return ctx.get_ciphers() except Exception: return [] def createServerSocket(self, port: int = 0, backlog: int = 50, ifAddress: Any = None) -> "SSLServerSocket": sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) sock.setsockopt(_socket.SOL_SOCKET, _socket.SO_REUSEADDR, 1) context = _ssl.create_default_context(_ssl.Purpose.CLIENT_AUTH) ssl_sock = context.wrap_socket(sock, server_side=True) ssl_ss = SSLServerSocket() ssl_ss._socket = ssl_sock if ifAddress: ssl_ss._socket.bind((ifAddress, port)) else: ssl_ss._socket.bind(('0.0.0.0', port)) ssl_ss._socket.listen(backlog) return ssl_ss def toString(self) -> str: return f"SSLServerSocketFactory@{hex(id(self))}" # ============================================================ # SSLSocketFactory # ============================================================ class SSLSocketFactory(SocketFactory): """ javax.net.ssl.SSLSocketFactory Factory for creating SSL sockets. """ _default = None @classmethod def getDefault(cls) -> "SSLSocketFactory": if cls._default is None: cls._default = SSLSocketFactory() return cls._default def getDefaultCipherSuites(self) -> List[str]: try: ctx = _ssl.create_default_context() return [c['name'] for c in ctx.get_ciphers()] except Exception: return [] def getSupportedCipherSuites(self) -> List[str]: try: ctx = _ssl.create_default_context() return [c['name'] for c in ctx.get_ciphers()] except Exception: return [] def createSocket(self, host: str = None, port: int = None, host_inet: Any = None, local_port: int = None, stream: bool = True) -> "SSLSocket": sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) context = _ssl.create_default_context() ssl_sock_impl = context.wrap_socket(sock, server_hostname=host) if host and port is not None: ssl_sock_impl.connect((host, port)) ss = SSLSocket() ss._socket = ssl_sock_impl ss._connected = True return ss def toString(self) -> str: return f"SSLSocketFactory@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # SSLServerSocket # ============================================================ class SSLServerSocket(Stub): """ javax.net.ssl.SSLServerSocket A server socket that supports SSL/TLS. """ def __init__(self): super().__init__() self._socket = None self._enabled_cipher_suites = [] self._enabled_protocols = [] self._need_client_auth = False self._use_client_mode = False self._want_client_auth = False self._enable_session_creation = True def getEnabledCipherSuites(self) -> List[str]: return self._enabled_cipher_suites def setEnabledCipherSuites(self, suites: List[str]): self._enabled_cipher_suites = suites def getSupportedCipherSuites(self) -> List[str]: return ["TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_GCM_SHA256", "ECDHE-RSA-AES256-GCM-SHA384"] def setEnabledProtocols(self, protocols: List[str]): self._enabled_protocols = protocols def getEnabledProtocols(self) -> List[str]: return self._enabled_protocols or ["TLSv1.3", "TLSv1.2"] def getSupportedProtocols(self) -> List[str]: return ["TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"] def getNeedClientAuth(self) -> bool: return self._need_client_auth def setNeedClientAuth(self, need: bool): self._need_client_auth = need def getUseClientMode(self) -> bool: return self._use_client_mode def setUseClientMode(self, mode: bool): self._use_client_mode = mode def getWantClientAuth(self) -> bool: return self._want_client_auth def setWantClientAuth(self, want: bool): self._want_client_auth = want def getEnableSessionCreation(self) -> bool: return self._enable_session_creation def setEnableSessionCreation(self, flag: bool): self._enable_session_creation = flag def accept(self) -> "SSLSocket": if self._socket: conn, addr = self._socket.accept() ss = SSLSocket() ss._socket = conn ss._connected = True ss._remote_address = addr return ss return SSLSocket() def close(self): if self._socket: self._socket.close() def toString(self) -> str: return f"SSLServerSocket@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # SSLSocket # ============================================================ class SSLSocket(Stub): """ javax.net.ssl.SSLSocket A socket that supports SSL/TLS. """ def __init__(self): super().__init__() self._socket = None self._connected = False self._remote_address = None self._enabled_cipher_suites = [] self._enabled_protocols = [] self._need_client_auth = False self._use_client_mode = False self._want_client_auth = False self._enable_session_creation = True self._handshake_listeners = [] self._session = None def getEnabledCipherSuites(self) -> List[str]: return self._enabled_cipher_suites or ["TLS_AES_256_GCM_SHA384"] def setEnabledCipherSuites(self, suites: List[str]): self._enabled_cipher_suites = suites def getSupportedCipherSuites(self) -> List[str]: return ["TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_GCM_SHA256", "ECDHE-RSA-AES256-GCM-SHA384"] def setEnabledProtocols(self, protocols: List[str]): self._enabled_protocols = protocols def getEnabledProtocols(self) -> List[str]: return self._enabled_protocols or ["TLSv1.3", "TLSv1.2"] def getSupportedProtocols(self) -> List[str]: return ["TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"] def getNeedClientAuth(self) -> bool: return self._need_client_auth def setNeedClientAuth(self, need: bool): self._need_client_auth = need def getUseClientMode(self) -> bool: return self._use_client_mode def setUseClientMode(self, mode: bool): self._use_client_mode = mode def getWantClientAuth(self) -> bool: return self._want_client_auth def setWantClientAuth(self, want: bool): self._want_client_auth = want def getEnableSessionCreation(self) -> bool: return self._enable_session_creation def setEnableSessionCreation(self, flag: bool): self._enable_session_creation = flag def getSession(self): """Returns the SSL session.""" return self._session def startHandshake(self): """Starts or re-starts the SSL handshake.""" if self._socket and hasattr(self._socket, 'do_handshake'): try: self._socket.do_handshake() self._session = {"cipher": "TLS_AES_256_GCM_SHA384", "protocol": "TLSv1.3"} for listener in self._handshake_listeners: listener.handshakeCompleted( HandshakeCompletedEvent(self, self._session)) except Exception: pass def addHandshakeCompletedListener(self, listener: "HandshakeCompletedListener"): self._handshake_listeners.append(listener) def removeHandshakeCompletedListener(self, listener: "HandshakeCompletedListener"): if listener in self._handshake_listeners: self._handshake_listeners.remove(listener) def getHandshakeApplicationProtocol(self) -> str: return "http/1.1" def getApplicationProtocol(self) -> str: return "http/1.1" def getHandshakeSession(self): return self._session def setHandshakeApplicationProtocolSelector(self, selector): pass def getHandshakeApplicationProtocolSelector(self): return None def close(self): if self._socket: self._socket.close() self._connected = False def toString(self) -> str: return f"SSLSocket@{hex(id(self))}[connected={self._connected}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # HandshakeCompletedEvent # ============================================================ class HandshakeCompletedEvent(Stub): """ javax.net.ssl.HandshakeCompletedEvent An event indicating that an SSL handshake completed. """ def __init__(self, sock: SSLSocket = None, session: Any = None): super().__init__() self._socket = sock self._session = session def getSession(self): return self._session def getCipherSuite(self) -> str: if self._session and isinstance(self._session, dict): return self._session.get("cipher", "UNKNOWN") return "UNKNOWN" def getLocalCertificates(self) -> List: return [] def getPeerCertificates(self) -> List: return [] def getPeerPrincipal(self): return None def getLocalPrincipal(self): return None def getSocket(self) -> SSLSocket: return self._socket def toString(self) -> str: return f"HandshakeCompletedEvent@{hex(id(self))}[cipher={self.getCipherSuite()}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # HandshakeCompletedListener # ============================================================ class HandshakeCompletedListener(Stub): """ javax.net.ssl.HandshakeCompletedListener A listener for SSL handshake completion events. """ def handshakeCompleted(self, event: HandshakeCompletedEvent): raise NotImplementedError # ============================================================ # HostnameVerifier # ============================================================ class HostnameVerifier(Stub): """ javax.net.ssl.HostnameVerizer A hostname verifier for HTTPS connections. """ def verify(self, hostname: str, session: Any) -> bool: return True def toString(self) -> str: return f"HostnameVerifier@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # HttpsURLConnection # ============================================================ class HttpsURLConnection(Stub): """ javax.net.ssl.HttpsURLConnection An HTTP URL connection with SSL/TLS support. """ _default_hostname_verifier = HostnameVerifier() _default_sslsocket_factory = SSLSocketFactory() def __init__(self): super().__init__() self._hostname_verifier = None self._ssl_socket_factory = None @classmethod def getDefaultHostnameVerifier(cls) -> HostnameVerifier: return cls._default_hostname_verifier @classmethod def setDefaultHostnameVerifier(cls, verifier: HostnameVerifier): cls._default_hostname_verifier = verifier @classmethod def getDefaultSSLSocketFactory(cls) -> SSLSocketFactory: return cls._default_sslsocket_factory @classmethod def setDefaultSSLSocketFactory(cls, factory: SSLSocketFactory): cls._default_sslsocket_factory = factory def getHostnameVerifier(self) -> HostnameVerifier: return self._hostname_verifier or self._default_hostname_verifier def setHostnameVerifier(self, verifier: HostnameVerifier): self._hostname_verifier = verifier def getSSLSocketFactory(self) -> SSLSocketFactory: return self._ssl_socket_factory or self._default_sslsocket_factory def setSSLSocketFactory(self, factory: SSLSocketFactory): self._ssl_socket_factory = factory def toString(self) -> str: return f"HttpsURLConnection@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # TrustManager # ============================================================ class TrustManager(Stub): """ javax.net.ssl.TrustManager Base interface for trust managers. """ pass # ============================================================ # X509TrustManager # ============================================================ class X509TrustManager(TrustManager): """ javax.net.ssl.X509TrustManager Trust manager for X.509 certificates. """ def checkClientTrusted(self, chain: List, auth_type: str): """Checks if a client certificate is trusted.""" pass def checkServerTrusted(self, chain: List, auth_type: str): """Checks if a server certificate is trusted.""" pass def getAcceptedIssuers(self) -> List: """Returns the list of accepted issuer certificates.""" return [] def toString(self) -> str: return f"X509TrustManager@{hex(id(self))}" # ============================================================ # KeyManager # ============================================================ class KeyManager(Stub): """ javax.net.ssl.KeyManager Base interface for key managers. """ pass # ============================================================ # X509KeyManager # ============================================================ class X509KeyManager(KeyManager): """ javax.net.ssl.X509KeyManager Key manager for X.509 keys. """ def getClientAliases(self, key_type: str, issuers: List) -> List[str]: return [] def chooseClientAlias(self, key_types: List, issuers: List, sockets: List) -> str: return None def getServerAliases(self, key_type: str, issuers: List) -> List[str]: return [] def chooseServerAlias(self, key_type: str, issuers: List, sockets: List) -> str: return None def getCertificateChain(self, alias: str) -> List: return [] def getPrivateKey(self, alias: str): return None def toString(self) -> str: return f"X509KeyManager@{hex(id(self))}" # ============================================================ # TrustManagerFactory # ============================================================ class TrustManagerFactory(Stub): """ javax.net.ssl.TrustManagerFactory Factory for TrustManager instances. """ def __init__(self, algorithm: str = None): super().__init__() self._algorithm = algorithm or "PKIX" self._trust_managers = [] @staticmethod def getInstance(algorithm: str) -> "TrustManagerFactory": return TrustManagerFactory(algorithm) @staticmethod def getDefaultAlgorithm() -> str: return "PKIX" def getAlgorithm(self) -> str: return self._algorithm def init(self, ks: Any = None): """Initializes this factory with a key store.""" self._trust_managers = [X509TrustManager()] def getTrustManagers(self) -> List[TrustManager]: return list(self._trust_managers) def toString(self) -> str: return f"TrustManagerFactory@{hex(id(self))}[algorithm={self._algorithm}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # KeyManagerFactory # ============================================================ class KeyManagerFactory(Stub): """ javax.net.ssl.KeyManagerFactory Factory for KeyManager instances. """ def __init__(self, algorithm: str = None): super().__init__() self._algorithm = algorithm or "PKIX" self._key_managers = [] @staticmethod def getInstance(algorithm: str) -> "KeyManagerFactory": return KeyManagerFactory(algorithm) @staticmethod def getDefaultAlgorithm() -> str: return "PKIX" def getAlgorithm(self) -> str: return self._algorithm def init(self, ks: Any = None, password: Any = None): """Initializes this factory with a key store.""" self._key_managers = [X509KeyManager()] def getKeyManagers(self) -> List[KeyManager]: return list(self._key_managers) def toString(self) -> str: return f"KeyManagerFactory@{hex(id(self))}[algorithm={self._algorithm}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # SSLContext # ============================================================ class SSLContext(Stub): """ javax.net.ssl.SSLContext An implementation of a secure socket protocol. """ _default = None def __init__(self, protocol: str = "TLS"): super().__init__() self._protocol = protocol self._provider = None self._ssl_context = None @staticmethod def getInstance(protocol: str) -> "SSLContext": ctx = SSLContext(protocol) try: ctx._ssl_context = _ssl.create_default_context() except Exception: pass return ctx def init(self, km: List[KeyManager] = None, tm: List[TrustManager] = None, random: Any = None): """Initializes this context with key managers, trust managers, and randomness.""" pass def getSocketFactory(self) -> SSLSocketFactory: return SSLSocketFactory() def getServerSocketFactory(self) -> SSLServerSocketFactory: return SSLServerSocketFactory() def createSSLEngine(self, host: str = None, port: int = None): """Creates a new SSLEngine (stub).""" return None def getProtocol(self) -> str: return self._protocol def getProvider(self): return self._provider @staticmethod def getDefault() -> "SSLContext": if SSLContext._default is None: SSLContext._default = SSLContext("TLS") return SSLContext._default @staticmethod def setDefault(ctx: "SSLContext"): SSLContext._default = ctx def toString(self) -> str: return f"SSLContext@{hex(id(self))}[protocol={self._protocol}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF