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