1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Wrapper module for _ssl, providing some additional facilities 2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# implemented in Python. Written by Bill Janssen. 3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""\ 5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepThis module provides some more Pythonic support for SSL. 6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepObject types: 8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSLSocket -- subtype of socket.socket which does SSL over the socket 10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepExceptions: 12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSLError -- exception raised for I/O errors 14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepFunctions: 16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_time_to_seconds -- convert time string used for certificate 18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep notBefore and notAfter functions to integer 19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep seconds past the Epoch (the time values 20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep returned from time.time()) 21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep fetch_server_certificate (HOST, PORT) -- fetch the certificate provided 23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep by the server running on HOST at port PORT. No 24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep validation of the certificate is performed. 25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepInteger constants: 27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_ZERO_RETURN 29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_WANT_READ 30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_WANT_WRITE 31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_WANT_X509_LOOKUP 32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_SYSCALL 33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_SSL 34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_WANT_CONNECT 35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_EOF 37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepSSL_ERROR_INVALID_ERROR_CODE 38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepThe following group define certificate requirements that one side is 40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepallowing/requiring from the other side: 41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepCERT_NONE - no certificates from the other side are required (or will 43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep be looked at if provided) 44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepCERT_OPTIONAL - certificates are not required, but if provided will be 45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep validated, and if validation fails, the connection will 46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep also fail 47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepCERT_REQUIRED - certificates are required, and will be validated, and 48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if validation fails, the connection will also fail 49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepThe following constants identify various SSL protocol variants: 51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPROTOCOL_SSLv2 53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPROTOCOL_SSLv3 54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPROTOCOL_SSLv23 55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPROTOCOL_TLSv1 56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep""" 57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport textwrap 59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport _ssl # if we can't import it, let the error propagate 61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION 63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import SSLError 64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED 65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import RAND_status, RAND_egd, RAND_add 66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import \ 67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_ZERO_RETURN, \ 68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_WANT_READ, \ 69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_WANT_WRITE, \ 70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_WANT_X509_LOOKUP, \ 71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_SYSCALL, \ 72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_SSL, \ 73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_WANT_CONNECT, \ 74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_EOF, \ 75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL_ERROR_INVALID_ERROR_CODE 76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_PROTOCOL_NAMES = { 78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PROTOCOL_TLSv1: "TLSv1", 79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PROTOCOL_SSLv23: "SSLv23", 80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PROTOCOL_SSLv3: "SSLv3", 81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep} 82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeptry: 83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep from _ssl import PROTOCOL_SSLv2 84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _SSLv2_IF_EXISTS = PROTOCOL_SSLv2 85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepexcept ImportError: 86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _SSLv2_IF_EXISTS = None 87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepelse: 88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" 89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom socket import socket, _fileobject, _delegate_methods, error as socket_error 91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom socket import getnameinfo as _getnameinfo 92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport base64 # for DER-to-PEM translation 93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport errno 94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Disable weak or insecure ciphers by default 96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') 97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2' 98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass SSLSocket(socket): 101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """This class implements a subtype of socket.socket that wraps 103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep the underlying OS socket in an SSL context when necessary, and 104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep provides read and write methods over that channel.""" 105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __init__(self, sock, keyfile=None, certfile=None, 107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep server_side=False, cert_reqs=CERT_NONE, 108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_version=PROTOCOL_SSLv23, ca_certs=None, 109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep do_handshake_on_connect=True, 110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep suppress_ragged_eofs=True, ciphers=None): 111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep socket.__init__(self, _sock=sock._sock) 112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # The initializer for socket overrides the methods send(), recv(), etc. 113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # in the instancce, which we don't need -- but we want to provide the 114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # methods defined in SSLSocket. 115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for attr in _delegate_methods: 116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep delattr(self, attr) 118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except AttributeError: 119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep pass 120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if ciphers is None and ssl_version != _SSLv2_IF_EXISTS: 122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ciphers = _DEFAULT_CIPHERS 123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if certfile and not keyfile: 125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep keyfile = certfile 126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # see if it's connected 127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep socket.getpeername(self) 129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except socket_error, e: 130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if e.errno != errno.ENOTCONN: 131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise 132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # no, no connection yet 133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._connected = False 134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = None 135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # yes, create the SSL object 137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._connected = True 138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = _ssl.sslwrap(self._sock, server_side, 139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep keyfile, certfile, 140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_reqs, ssl_version, ca_certs, 141edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ciphers) 142edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if do_handshake_on_connect: 143edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.do_handshake() 144edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.keyfile = keyfile 145edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.certfile = certfile 146edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.cert_reqs = cert_reqs 147edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.ssl_version = ssl_version 148edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.ca_certs = ca_certs 149edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.ciphers = ciphers 150edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.do_handshake_on_connect = do_handshake_on_connect 151edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.suppress_ragged_eofs = suppress_ragged_eofs 152edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._makefile_refs = 0 153edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 154edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def read(self, len=1024): 155edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 156edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Read up to LEN bytes and return them. 157edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Return zero-length string on EOF.""" 158edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 159edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 160edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sslobj.read(len) 161edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except SSLError, x: 162edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: 163edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return '' 164edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 165edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise 166edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 167edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def write(self, data): 168edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 169edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Write DATA to the underlying SSL channel. Returns 170edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep number of bytes of DATA actually transmitted.""" 171edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 172edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sslobj.write(data) 173edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 174edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def getpeercert(self, binary_form=False): 175edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 176edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Returns a formatted version of the data in the 177edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep certificate provided by the other end of the SSL channel. 178edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Return None if no certificate was provided, {} if a 179edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep certificate was provided, but not validated.""" 180edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 181edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sslobj.peer_certificate(binary_form) 182edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 183edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def cipher(self): 184edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 185edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not self._sslobj: 186edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return None 187edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 188edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sslobj.cipher() 189edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 190edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def send(self, data, flags=0): 191edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 192edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if flags != 0: 193edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError( 194edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "non-zero flags not allowed in calls to send() on %s" % 195edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 196edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep while True: 197edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 198edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep v = self._sslobj.write(data) 199edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except SSLError, x: 200edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if x.args[0] == SSL_ERROR_WANT_READ: 201edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 0 202edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif x.args[0] == SSL_ERROR_WANT_WRITE: 203edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 0 204edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 205edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise 206edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 207edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return v 208edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 209edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.send(data, flags) 210edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 211edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def sendto(self, data, flags_or_addr, addr=None): 212edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 213edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("sendto not allowed on instances of %s" % 214edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 215edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif addr is None: 216edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.sendto(data, flags_or_addr) 217edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 218edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.sendto(data, flags_or_addr, addr) 219edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 220edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def sendall(self, data, flags=0): 221edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 222edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if flags != 0: 223edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError( 224edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "non-zero flags not allowed in calls to sendall() on %s" % 225edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 226edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep amount = len(data) 227edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep count = 0 228edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep while (count < amount): 229edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep v = self.send(data[count:]) 230edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep count += v 231edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return amount 232edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 233edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return socket.sendall(self, data, flags) 234edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 235edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def recv(self, buflen=1024, flags=0): 236edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 237edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if flags != 0: 238edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError( 239edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "non-zero flags not allowed in calls to recv() on %s" % 240edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 241edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.read(buflen) 242edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 243edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.recv(buflen, flags) 244edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 245edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def recv_into(self, buffer, nbytes=None, flags=0): 246edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if buffer and (nbytes is None): 247edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep nbytes = len(buffer) 248edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif nbytes is None: 249edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep nbytes = 1024 250edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 251edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if flags != 0: 252edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError( 253edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep "non-zero flags not allowed in calls to recv_into() on %s" % 254edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 255edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep tmp_buffer = self.read(nbytes) 256edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep v = len(tmp_buffer) 257edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep buffer[:v] = tmp_buffer 258edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return v 259edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 260edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.recv_into(buffer, nbytes, flags) 261edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 262edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def recvfrom(self, buflen=1024, flags=0): 263edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 264edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("recvfrom not allowed on instances of %s" % 265edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 266edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 267edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.recvfrom(buflen, flags) 268edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 269edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def recvfrom_into(self, buffer, nbytes=None, flags=0): 270edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 271edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("recvfrom_into not allowed on instances of %s" % 272edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.__class__) 273edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 274edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sock.recvfrom_into(buffer, nbytes, flags) 275edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 276edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pending(self): 277edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 278edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._sslobj.pending() 279edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 280edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 0 281edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 282edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def unwrap(self): 283edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._sslobj: 284edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep s = self._sslobj.shutdown() 285edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = None 286edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return s 287edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 288edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("No SSL wrapper around " + str(self)) 289edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 290edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def shutdown(self, how): 291edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = None 292edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep socket.shutdown(self, how) 293edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 294edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def close(self): 295edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._makefile_refs < 1: 296edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = None 297edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep socket.close(self) 298edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 299edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._makefile_refs -= 1 300edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 301edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def do_handshake(self): 302edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 303edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Perform a TLS/SSL handshake.""" 304edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 305edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj.do_handshake() 306edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 307edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def _real_connect(self, addr, return_errno): 308edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # Here we assume that the socket is client-side, and not 309edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # connected at the time of the call. We connect it, then wrap it. 310edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self._connected: 311edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("attempt to connect already-connected SSLSocket!") 312edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, 313edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.cert_reqs, self.ssl_version, 314edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.ca_certs, self.ciphers) 315edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 316edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if return_errno: 317edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rc = socket.connect_ex(self, addr) 318edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 319edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep rc = None 320edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep socket.connect(self, addr) 321edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not rc: 322edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self.do_handshake_on_connect: 323edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.do_handshake() 324edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._connected = True 325edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return rc 326edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except socket_error: 327edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._sslobj = None 328edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise 329edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 330edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def connect(self, addr): 331edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Connects to remote ADDR, and then wraps the connection in 332edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep an SSL channel.""" 333edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._real_connect(addr, False) 334edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 335edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def connect_ex(self, addr): 336edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Connects to remote ADDR, and then wraps the connection in 337edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep an SSL channel.""" 338edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self._real_connect(addr, True) 339edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 340edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def accept(self): 341edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 342edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Accepts a new connection from a remote client, and returns 343edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep a tuple containing that new connection wrapped with a server-side 344edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep SSL channel, and the address of the remote client.""" 345edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 346edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep newsock, addr = socket.accept(self) 347edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 348edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return (SSLSocket(newsock, 349edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep keyfile=self.keyfile, 350edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep certfile=self.certfile, 351edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep server_side=True, 352edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_reqs=self.cert_reqs, 353edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_version=self.ssl_version, 354edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ca_certs=self.ca_certs, 355edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ciphers=self.ciphers, 356edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep do_handshake_on_connect=self.do_handshake_on_connect, 357edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep suppress_ragged_eofs=self.suppress_ragged_eofs), 358edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep addr) 359edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except socket_error as e: 360edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep newsock.close() 361edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise e 362edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 363edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def makefile(self, mode='r', bufsize=-1): 364edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 365edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Make and return a file-like object that 366edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep works with the SSL connection. Just use the code 367edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep from the socket module.""" 368edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 369edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self._makefile_refs += 1 370edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # close=True so as to decrement the reference count when done with 371edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # the file-like object. 372edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _fileobject(self, mode, bufsize, close=True) 373edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 374edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 375edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 376edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef wrap_socket(sock, keyfile=None, certfile=None, 377edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep server_side=False, cert_reqs=CERT_NONE, 378edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_version=PROTOCOL_SSLv23, ca_certs=None, 379edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep do_handshake_on_connect=True, 380edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep suppress_ragged_eofs=True, ciphers=None): 381edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 382edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return SSLSocket(sock, keyfile=keyfile, certfile=certfile, 383edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep server_side=server_side, cert_reqs=cert_reqs, 384edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_version=ssl_version, ca_certs=ca_certs, 385edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep do_handshake_on_connect=do_handshake_on_connect, 386edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep suppress_ragged_eofs=suppress_ragged_eofs, 387edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ciphers=ciphers) 388edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 389edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 390edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# some utility functions 391edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 392edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef cert_time_to_seconds(cert_time): 393edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 394edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Takes a date-time string in standard ASN1_print form 395edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return 396edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep a Python time value in seconds past the epoch.""" 397edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 398edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep import time 399edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT")) 400edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 401edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPEM_HEADER = "-----BEGIN CERTIFICATE-----" 402edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepPEM_FOOTER = "-----END CERTIFICATE-----" 403edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 404edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef DER_cert_to_PEM_cert(der_cert_bytes): 405edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 406edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Takes a certificate in binary DER format and returns the 407edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PEM version of it as a string.""" 408edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 409edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if hasattr(base64, 'standard_b64encode'): 410edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # preferred because older API gets line-length wrong 411edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep f = base64.standard_b64encode(der_cert_bytes) 412edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return (PEM_HEADER + '\n' + 413edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep textwrap.fill(f, 64) + '\n' + 414edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PEM_FOOTER + '\n') 415edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 416edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return (PEM_HEADER + '\n' + 417edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep base64.encodestring(der_cert_bytes) + 418edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PEM_FOOTER + '\n') 419edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 420edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef PEM_cert_to_DER_cert(pem_cert_string): 421edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 422edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Takes a certificate in ASCII PEM format and returns the 423edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep DER-encoded version of it as a byte sequence""" 424edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 425edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not pem_cert_string.startswith(PEM_HEADER): 426edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("Invalid PEM encoding; must start with %s" 427edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep % PEM_HEADER) 428edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if not pem_cert_string.strip().endswith(PEM_FOOTER): 429edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise ValueError("Invalid PEM encoding; must end with %s" 430edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep % PEM_FOOTER) 431edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] 432edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return base64.decodestring(d) 433edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 434edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): 435edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 436edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """Retrieve the certificate from the server at the specified address, 437edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep and return it as a PEM-encoded string. 438edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep If 'ca_certs' is specified, validate the server cert against it. 439edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep If 'ssl_version' is specified, use it in the connection attempt.""" 440edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 441edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep host, port = addr 442edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if (ca_certs is not None): 443edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_reqs = CERT_REQUIRED 444edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 445edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_reqs = CERT_NONE 446edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep s = wrap_socket(socket(), ssl_version=ssl_version, 447edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep cert_reqs=cert_reqs, ca_certs=ca_certs) 448edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep s.connect(addr) 449edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep dercert = s.getpeercert(True) 450edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep s.close() 451edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return DER_cert_to_PEM_cert(dercert) 452edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 453edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef get_protocol_name(protocol_code): 454edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return _PROTOCOL_NAMES.get(protocol_code, '<unknown>') 455edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 456edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 457edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# a replacement for the old socket.ssl function 458edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 459edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef sslwrap_simple(sock, keyfile=None, certfile=None): 460edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 461edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep """A replacement for the old socket.ssl function. Designed 462edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for compability with Python 2.5 and earlier. Will disappear in 463edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep Python 3.0.""" 464edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 465edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if hasattr(sock, "_sock"): 466edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep sock = sock._sock 467edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 468edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_sock = _ssl.sslwrap(sock, 0, keyfile, certfile, CERT_NONE, 469edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep PROTOCOL_SSLv23, None) 470edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 471edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep sock.getpeername() 472edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except socket_error: 473edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # no, no connection yet 474edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep pass 475edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 476edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # yes, do the handshake 477edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep ssl_sock.do_handshake() 478edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 479edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return ssl_sock 480