blob: 08b2df2fc1974c6411cf046ecc20dd91dab2e561 [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001# Wrapper module for _ssl, providing some additional facilities
2# implemented in Python. Written by Bill Janssen.
3
Guido van Rossum5b8b1552007-11-16 00:06:11 +00004"""This module provides some more Pythonic support for SSL.
Thomas Woutersed03b412007-08-28 21:37:11 +00005
6Object types:
7
Thomas Wouters1b7f8912007-09-19 03:06:30 +00008 SSLSocket -- subtype of socket.socket which does SSL over the socket
Thomas Woutersed03b412007-08-28 21:37:11 +00009
10Exceptions:
11
Thomas Wouters1b7f8912007-09-19 03:06:30 +000012 SSLError -- exception raised for I/O errors
Thomas Woutersed03b412007-08-28 21:37:11 +000013
14Functions:
15
16 cert_time_to_seconds -- convert time string used for certificate
17 notBefore and notAfter functions to integer
18 seconds past the Epoch (the time values
19 returned from time.time())
20
21 fetch_server_certificate (HOST, PORT) -- fetch the certificate provided
22 by the server running on HOST at port PORT. No
23 validation of the certificate is performed.
24
25Integer constants:
26
27SSL_ERROR_ZERO_RETURN
28SSL_ERROR_WANT_READ
29SSL_ERROR_WANT_WRITE
30SSL_ERROR_WANT_X509_LOOKUP
31SSL_ERROR_SYSCALL
32SSL_ERROR_SSL
33SSL_ERROR_WANT_CONNECT
34
35SSL_ERROR_EOF
36SSL_ERROR_INVALID_ERROR_CODE
37
38The following group define certificate requirements that one side is
39allowing/requiring from the other side:
40
41CERT_NONE - no certificates from the other side are required (or will
42 be looked at if provided)
43CERT_OPTIONAL - certificates are not required, but if provided will be
44 validated, and if validation fails, the connection will
45 also fail
46CERT_REQUIRED - certificates are required, and will be validated, and
47 if validation fails, the connection will also fail
48
49The following constants identify various SSL protocol variants:
50
51PROTOCOL_SSLv2
52PROTOCOL_SSLv3
53PROTOCOL_SSLv23
54PROTOCOL_TLSv1
Antoine Pitrou2463e5f2013-03-28 22:24:43 +010055PROTOCOL_TLSv1_1
56PROTOCOL_TLSv1_2
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +010057
58The following constants identify various SSL alert message descriptions as per
59http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6
60
61ALERT_DESCRIPTION_CLOSE_NOTIFY
62ALERT_DESCRIPTION_UNEXPECTED_MESSAGE
63ALERT_DESCRIPTION_BAD_RECORD_MAC
64ALERT_DESCRIPTION_RECORD_OVERFLOW
65ALERT_DESCRIPTION_DECOMPRESSION_FAILURE
66ALERT_DESCRIPTION_HANDSHAKE_FAILURE
67ALERT_DESCRIPTION_BAD_CERTIFICATE
68ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE
69ALERT_DESCRIPTION_CERTIFICATE_REVOKED
70ALERT_DESCRIPTION_CERTIFICATE_EXPIRED
71ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN
72ALERT_DESCRIPTION_ILLEGAL_PARAMETER
73ALERT_DESCRIPTION_UNKNOWN_CA
74ALERT_DESCRIPTION_ACCESS_DENIED
75ALERT_DESCRIPTION_DECODE_ERROR
76ALERT_DESCRIPTION_DECRYPT_ERROR
77ALERT_DESCRIPTION_PROTOCOL_VERSION
78ALERT_DESCRIPTION_INSUFFICIENT_SECURITY
79ALERT_DESCRIPTION_INTERNAL_ERROR
80ALERT_DESCRIPTION_USER_CANCELLED
81ALERT_DESCRIPTION_NO_RENEGOTIATION
82ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION
83ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE
84ALERT_DESCRIPTION_UNRECOGNIZED_NAME
85ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE
86ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE
87ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY
Thomas Woutersed03b412007-08-28 21:37:11 +000088"""
89
Christian Heimes05e8be12008-02-23 18:30:17 +000090import textwrap
Antoine Pitrou59fdd672010-10-08 10:37:08 +000091import re
Christian Heimes46bebee2013-06-09 19:03:31 +020092import sys
Christian Heimes6d7ad132013-06-09 18:02:55 +020093import os
Christian Heimesa6bc95a2013-11-17 19:59:14 +010094from collections import namedtuple
Christian Heimes72d28502013-11-23 13:56:58 +010095from enum import Enum as _Enum
Thomas Woutersed03b412007-08-28 21:37:11 +000096
97import _ssl # if we can't import it, let the error propagate
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098
Antoine Pitrou04f6a322010-04-05 21:40:07 +000099from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION
Antoine Pitrou41032a62011-10-27 23:56:55 +0200100from _ssl import _SSLContext
101from _ssl import (
102 SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError,
103 SSLSyscallError, SSLEOFError,
104 )
Thomas Woutersed03b412007-08-28 21:37:11 +0000105from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
Christian Heimes22587792013-11-21 23:56:13 +0100106from _ssl import (VERIFY_DEFAULT, VERIFY_CRL_CHECK_LEAF, VERIFY_CRL_CHECK_CHAIN,
107 VERIFY_X509_STRICT)
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100108from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj
Victor Stinner99c8b162011-05-24 12:05:19 +0200109from _ssl import RAND_status, RAND_egd, RAND_add, RAND_bytes, RAND_pseudo_bytes
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100110
111def _import_symbols(prefix):
112 for n in dir(_ssl):
113 if n.startswith(prefix):
114 globals()[n] = getattr(_ssl, n)
115
116_import_symbols('OP_')
117_import_symbols('ALERT_DESCRIPTION_')
118_import_symbols('SSL_ERROR_')
119
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100120from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100121
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100122from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
Antoine Pitroub9ac25d2011-07-08 18:47:06 +0200123from _ssl import _OPENSSL_API_VERSION
124
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100125
Victor Stinner3de49192011-05-09 00:42:58 +0200126_PROTOCOL_NAMES = {
127 PROTOCOL_TLSv1: "TLSv1",
128 PROTOCOL_SSLv23: "SSLv23",
129 PROTOCOL_SSLv3: "SSLv3",
130}
131try:
132 from _ssl import PROTOCOL_SSLv2
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100133 _SSLv2_IF_EXISTS = PROTOCOL_SSLv2
Brett Cannoncd171c82013-07-04 17:43:24 -0400134except ImportError:
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100135 _SSLv2_IF_EXISTS = None
Victor Stinner3de49192011-05-09 00:42:58 +0200136else:
137 _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2"
Thomas Woutersed03b412007-08-28 21:37:11 +0000138
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100139try:
140 from _ssl import PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2
Brett Cannoncd171c82013-07-04 17:43:24 -0400141except ImportError:
Antoine Pitrou2463e5f2013-03-28 22:24:43 +0100142 pass
143else:
144 _PROTOCOL_NAMES[PROTOCOL_TLSv1_1] = "TLSv1.1"
145 _PROTOCOL_NAMES[PROTOCOL_TLSv1_2] = "TLSv1.2"
146
Christian Heimes46bebee2013-06-09 19:03:31 +0200147if sys.platform == "win32":
Christian Heimes44109d72013-11-22 01:51:30 +0100148 from _ssl import enum_certificates, enum_crls
Christian Heimes46bebee2013-06-09 19:03:31 +0200149
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000150from socket import getnameinfo as _getnameinfo
Christian Heimes1aa9a752013-12-02 02:41:19 +0100151from socket import SHUT_RDWR as _SHUT_RDWR
Antoine Pitrou15399c32011-04-28 19:23:55 +0200152from socket import socket, AF_INET, SOCK_STREAM, create_connection
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000153import base64 # for DER-to-PEM translation
Bill Janssen54cc54c2007-12-14 22:08:56 +0000154import traceback
Antoine Pitroude8cf322010-04-26 17:29:05 +0000155import errno
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000156
Andrew Svetlov0832af62012-12-18 23:10:48 +0200157
158socket_error = OSError # keep that public name in module namespace
159
Antoine Pitroud6494802011-07-21 01:11:30 +0200160if _ssl.HAS_TLS_UNIQUE:
161 CHANNEL_BINDING_TYPES = ['tls-unique']
162else:
163 CHANNEL_BINDING_TYPES = []
Thomas Woutersed03b412007-08-28 21:37:11 +0000164
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100165# Disable weak or insecure ciphers by default
166# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
167_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
168
Christian Heimes4c05b472013-11-23 15:58:30 +0100169# restricted and more secure ciphers
170# HIGH: high encryption cipher suites with key length >= 128 bits (no MD5)
171# !aNULL: only authenticated cipher suites (no anonymous DH)
172# !RC4: no RC4 streaming cipher, RC4 is broken
173# !DSS: RSA is preferred over DSA
174_RESTRICTED_CIPHERS = 'HIGH:!aNULL:!RC4:!DSS'
175
Thomas Woutersed03b412007-08-28 21:37:11 +0000176
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000177class CertificateError(ValueError):
178 pass
179
180
Georg Brandl72c98d32013-10-27 07:16:53 +0100181def _dnsname_match(dn, hostname, max_wildcards=1):
182 """Matching according to RFC 6125, section 6.4.3
183
184 http://tools.ietf.org/html/rfc6125#section-6.4.3
185 """
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000186 pats = []
Georg Brandl72c98d32013-10-27 07:16:53 +0100187 if not dn:
188 return False
189
190 leftmost, *remainder = dn.split(r'.')
191
192 wildcards = leftmost.count('*')
193 if wildcards > max_wildcards:
194 # Issue #17980: avoid denials of service by refusing more
195 # than one wildcard per fragment. A survery of established
196 # policy among SSL implementations showed it to be a
197 # reasonable choice.
198 raise CertificateError(
199 "too many wildcards in certificate DNS name: " + repr(dn))
200
201 # speed up common case w/o wildcards
202 if not wildcards:
203 return dn.lower() == hostname.lower()
204
205 # RFC 6125, section 6.4.3, subitem 1.
206 # The client SHOULD NOT attempt to match a presented identifier in which
207 # the wildcard character comprises a label other than the left-most label.
208 if leftmost == '*':
209 # When '*' is a fragment by itself, it matches a non-empty dotless
210 # fragment.
211 pats.append('[^.]+')
212 elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
213 # RFC 6125, section 6.4.3, subitem 3.
214 # The client SHOULD NOT attempt to match a presented identifier
215 # where the wildcard character is embedded within an A-label or
216 # U-label of an internationalized domain name.
217 pats.append(re.escape(leftmost))
218 else:
219 # Otherwise, '*' matches any dotless string, e.g. www*
220 pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
221
222 # add the remaining fragments, ignore any wildcards
223 for frag in remainder:
224 pats.append(re.escape(frag))
225
226 pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
227 return pat.match(hostname)
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000228
229
230def match_hostname(cert, hostname):
231 """Verify that *cert* (in decoded format as returned by
Georg Brandl72c98d32013-10-27 07:16:53 +0100232 SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
233 rules are followed, but IP addresses are not accepted for *hostname*.
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000234
235 CertificateError is raised on failure. On success, the function
236 returns nothing.
237 """
238 if not cert:
Christian Heimes1aa9a752013-12-02 02:41:19 +0100239 raise ValueError("empty or no certificate, match_hostname needs a "
240 "SSL socket or SSL context with either "
241 "CERT_OPTIONAL or CERT_REQUIRED")
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000242 dnsnames = []
243 san = cert.get('subjectAltName', ())
244 for key, value in san:
245 if key == 'DNS':
Georg Brandl72c98d32013-10-27 07:16:53 +0100246 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000247 return
248 dnsnames.append(value)
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200249 if not dnsnames:
250 # The subject is only checked when there is no dNSName entry
251 # in subjectAltName
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000252 for sub in cert.get('subject', ()):
253 for key, value in sub:
254 # XXX according to RFC 2818, the most specific Common Name
255 # must be used.
256 if key == 'commonName':
Georg Brandl72c98d32013-10-27 07:16:53 +0100257 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000258 return
259 dnsnames.append(value)
260 if len(dnsnames) > 1:
261 raise CertificateError("hostname %r "
262 "doesn't match either of %s"
263 % (hostname, ', '.join(map(repr, dnsnames))))
264 elif len(dnsnames) == 1:
265 raise CertificateError("hostname %r "
266 "doesn't match %r"
267 % (hostname, dnsnames[0]))
268 else:
269 raise CertificateError("no appropriate commonName or "
270 "subjectAltName fields were found")
271
272
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100273DefaultVerifyPaths = namedtuple("DefaultVerifyPaths",
Christian Heimes6d7ad132013-06-09 18:02:55 +0200274 "cafile capath openssl_cafile_env openssl_cafile openssl_capath_env "
275 "openssl_capath")
276
277def get_default_verify_paths():
278 """Return paths to default cafile and capath.
279 """
280 parts = _ssl.get_default_verify_paths()
281
282 # environment vars shadow paths
283 cafile = os.environ.get(parts[0], parts[1])
284 capath = os.environ.get(parts[2], parts[3])
285
286 return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None,
287 capath if os.path.isdir(capath) else None,
288 *parts)
289
290
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100291class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")):
292 """ASN.1 object identifier lookup
293 """
294 __slots__ = ()
295
296 def __new__(cls, oid):
297 return super().__new__(cls, *_txt2obj(oid, name=False))
298
299 @classmethod
300 def fromnid(cls, nid):
301 """Create _ASN1Object from OpenSSL numeric ID
302 """
303 return super().__new__(cls, *_nid2obj(nid))
304
305 @classmethod
306 def fromname(cls, name):
307 """Create _ASN1Object from short name, long name or OID
308 """
309 return super().__new__(cls, *_txt2obj(name, name=True))
310
311
Christian Heimes72d28502013-11-23 13:56:58 +0100312class Purpose(_ASN1Object, _Enum):
313 """SSLContext purpose flags with X509v3 Extended Key Usage objects
314 """
315 SERVER_AUTH = '1.3.6.1.5.5.7.3.1'
316 CLIENT_AUTH = '1.3.6.1.5.5.7.3.2'
317
318
Antoine Pitrou152efa22010-05-16 18:19:27 +0000319class SSLContext(_SSLContext):
320 """An SSLContext holds various SSL-related configuration options and
321 data, such as certificates and possibly a private key."""
322
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100323 __slots__ = ('protocol', '__weakref__')
Christian Heimes72d28502013-11-23 13:56:58 +0100324 _windows_cert_stores = ("CA", "ROOT")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000325
326 def __new__(cls, protocol, *args, **kwargs):
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100327 self = _SSLContext.__new__(cls, protocol)
328 if protocol != _SSLv2_IF_EXISTS:
329 self.set_ciphers(_DEFAULT_CIPHERS)
330 return self
Antoine Pitrou152efa22010-05-16 18:19:27 +0000331
332 def __init__(self, protocol):
333 self.protocol = protocol
334
335 def wrap_socket(self, sock, server_side=False,
336 do_handshake_on_connect=True,
Antoine Pitroud5323212010-10-22 18:19:07 +0000337 suppress_ragged_eofs=True,
338 server_hostname=None):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000339 return SSLSocket(sock=sock, server_side=server_side,
340 do_handshake_on_connect=do_handshake_on_connect,
341 suppress_ragged_eofs=suppress_ragged_eofs,
Antoine Pitroud5323212010-10-22 18:19:07 +0000342 server_hostname=server_hostname,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000343 _context=self)
344
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100345 def set_npn_protocols(self, npn_protocols):
346 protos = bytearray()
347 for protocol in npn_protocols:
348 b = bytes(protocol, 'ascii')
349 if len(b) == 0 or len(b) > 255:
350 raise SSLError('NPN protocols must be 1 to 255 in length')
351 protos.append(len(b))
352 protos.extend(b)
353
354 self._set_npn_protocols(protos)
355
Christian Heimes72d28502013-11-23 13:56:58 +0100356 def _load_windows_store_certs(self, storename, purpose):
357 certs = bytearray()
358 for cert, encoding, trust in enum_certificates(storename):
359 # CA certs are never PKCS#7 encoded
360 if encoding == "x509_asn":
361 if trust is True or purpose.oid in trust:
362 certs.extend(cert)
363 self.load_verify_locations(cadata=certs)
364 return certs
365
366 def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
367 if not isinstance(purpose, _ASN1Object):
368 raise TypeError(purpose)
369 if sys.platform == "win32":
370 for storename in self._windows_cert_stores:
371 self._load_windows_store_certs(storename, purpose)
372 else:
373 self.set_default_verify_paths()
374
Antoine Pitrou152efa22010-05-16 18:19:27 +0000375
Christian Heimes4c05b472013-11-23 15:58:30 +0100376def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
377 capath=None, cadata=None):
378 """Create a SSLContext object with default settings.
379
380 NOTE: The protocol and settings may change anytime without prior
381 deprecation. The values represent a fair balance between maximum
382 compatibility and security.
383 """
384 if not isinstance(purpose, _ASN1Object):
385 raise TypeError(purpose)
386 context = SSLContext(PROTOCOL_TLSv1)
387 # SSLv2 considered harmful.
388 context.options |= OP_NO_SSLv2
Christian Heimesdec813f2013-11-28 08:06:54 +0100389 # disable compression to prevent CRIME attacks (OpenSSL 1.0+)
390 context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0)
Christian Heimes4c05b472013-11-23 15:58:30 +0100391 # disallow ciphers with known vulnerabilities
392 context.set_ciphers(_RESTRICTED_CIPHERS)
Christian Heimes1aa9a752013-12-02 02:41:19 +0100393 # verify certs and host name in client mode
Christian Heimes4c05b472013-11-23 15:58:30 +0100394 if purpose == Purpose.SERVER_AUTH:
395 context.verify_mode = CERT_REQUIRED
Christian Heimes1aa9a752013-12-02 02:41:19 +0100396 context.check_hostname = True
Christian Heimes4c05b472013-11-23 15:58:30 +0100397 if cafile or capath or cadata:
398 context.load_verify_locations(cafile, capath, cadata)
399 elif context.verify_mode != CERT_NONE:
400 # no explicit cafile, capath or cadata but the verify mode is
401 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
402 # root CA certificates for the given purpose. This may fail silently.
403 context.load_default_certs(purpose)
404 return context
405
406
Christian Heimes67986f92013-11-23 22:43:47 +0100407def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
Christian Heimesa02c69a2013-12-02 20:59:28 +0100408 check_hostname=False, purpose=Purpose.SERVER_AUTH,
Christian Heimes67986f92013-11-23 22:43:47 +0100409 certfile=None, keyfile=None,
410 cafile=None, capath=None, cadata=None):
411 """Create a SSLContext object for Python stdlib modules
412
413 All Python stdlib modules shall use this function to create SSLContext
414 objects in order to keep common settings in one place. The configuration
415 is less restrict than create_default_context()'s to increase backward
416 compatibility.
417 """
418 if not isinstance(purpose, _ASN1Object):
419 raise TypeError(purpose)
420
421 context = SSLContext(protocol)
422 # SSLv2 considered harmful.
423 context.options |= OP_NO_SSLv2
424
425 if cert_reqs is not None:
426 context.verify_mode = cert_reqs
Christian Heimesa02c69a2013-12-02 20:59:28 +0100427 context.check_hostname = check_hostname
Christian Heimes67986f92013-11-23 22:43:47 +0100428
429 if keyfile and not certfile:
430 raise ValueError("certfile must be specified")
431 if certfile or keyfile:
432 context.load_cert_chain(certfile, keyfile)
433
434 # load CA root certs
435 if cafile or capath or cadata:
436 context.load_verify_locations(cafile, capath, cadata)
437 elif context.verify_mode != CERT_NONE:
438 # no explicit cafile, capath or cadata but the verify mode is
439 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
440 # root CA certificates for the given purpose. This may fail silently.
441 context.load_default_certs(purpose)
442
443 return context
444
Antoine Pitrou152efa22010-05-16 18:19:27 +0000445class SSLSocket(socket):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000446 """This class implements a subtype of socket.socket that wraps
447 the underlying OS socket in an SSL context when necessary, and
448 provides read and write methods over that channel."""
449
Bill Janssen6e027db2007-11-15 22:23:56 +0000450 def __init__(self, sock=None, keyfile=None, certfile=None,
Thomas Woutersed03b412007-08-28 21:37:11 +0000451 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000452 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
453 do_handshake_on_connect=True,
454 family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100455 suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
Antoine Pitroud5323212010-10-22 18:19:07 +0000456 server_hostname=None,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000457 _context=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000458
Antoine Pitrou152efa22010-05-16 18:19:27 +0000459 if _context:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100460 self._context = _context
Antoine Pitrou152efa22010-05-16 18:19:27 +0000461 else:
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000462 if server_side and not certfile:
463 raise ValueError("certfile must be specified for server-side "
464 "operations")
Giampaolo RodolĂ 8b7da622010-08-30 18:28:05 +0000465 if keyfile and not certfile:
466 raise ValueError("certfile must be specified")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000467 if certfile and not keyfile:
468 keyfile = certfile
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100469 self._context = SSLContext(ssl_version)
470 self._context.verify_mode = cert_reqs
Antoine Pitrou152efa22010-05-16 18:19:27 +0000471 if ca_certs:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100472 self._context.load_verify_locations(ca_certs)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000473 if certfile:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100474 self._context.load_cert_chain(certfile, keyfile)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100475 if npn_protocols:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100476 self._context.set_npn_protocols(npn_protocols)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000477 if ciphers:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100478 self._context.set_ciphers(ciphers)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000479 self.keyfile = keyfile
480 self.certfile = certfile
481 self.cert_reqs = cert_reqs
482 self.ssl_version = ssl_version
483 self.ca_certs = ca_certs
484 self.ciphers = ciphers
Antoine Pitroud5323212010-10-22 18:19:07 +0000485 if server_side and server_hostname:
486 raise ValueError("server_hostname can only be specified "
487 "in client mode")
Christian Heimes1aa9a752013-12-02 02:41:19 +0100488 if self._context.check_hostname and not server_hostname:
489 if HAS_SNI:
490 raise ValueError("check_hostname requires server_hostname")
491 else:
492 raise ValueError("check_hostname requires server_hostname, "
493 "but it's not supported by your OpenSSL "
494 "library")
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000495 self.server_side = server_side
Antoine Pitroud5323212010-10-22 18:19:07 +0000496 self.server_hostname = server_hostname
Antoine Pitrou152efa22010-05-16 18:19:27 +0000497 self.do_handshake_on_connect = do_handshake_on_connect
498 self.suppress_ragged_eofs = suppress_ragged_eofs
Bill Janssen6e027db2007-11-15 22:23:56 +0000499 if sock is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000500 socket.__init__(self,
501 family=sock.family,
502 type=sock.type,
503 proto=sock.proto,
Antoine Pitroue43f9d02010-08-08 23:24:50 +0000504 fileno=sock.fileno())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000505 self.settimeout(sock.gettimeout())
Antoine Pitrou6e451df2010-08-09 20:39:54 +0000506 sock.detach()
Bill Janssen6e027db2007-11-15 22:23:56 +0000507 elif fileno is not None:
508 socket.__init__(self, fileno=fileno)
509 else:
510 socket.__init__(self, family=family, type=type, proto=proto)
511
Antoine Pitrou242db722013-05-01 20:52:07 +0200512 # See if we are connected
513 try:
514 self.getpeername()
515 except OSError as e:
516 if e.errno != errno.ENOTCONN:
517 raise
518 connected = False
519 else:
520 connected = True
521
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000522 self._closed = False
523 self._sslobj = None
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000524 self._connected = connected
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000525 if connected:
526 # create the SSL object
Bill Janssen6e027db2007-11-15 22:23:56 +0000527 try:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100528 self._sslobj = self._context._wrap_socket(self, server_side,
Antoine Pitroud5323212010-10-22 18:19:07 +0000529 server_hostname)
Bill Janssen6e027db2007-11-15 22:23:56 +0000530 if do_handshake_on_connect:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000531 timeout = self.gettimeout()
532 if timeout == 0.0:
533 # non-blocking
534 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
Bill Janssen6e027db2007-11-15 22:23:56 +0000535 self.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000536
Christian Heimes1aa9a752013-12-02 02:41:19 +0100537 except (OSError, ValueError):
Bill Janssen6e027db2007-11-15 22:23:56 +0000538 self.close()
Christian Heimes1aa9a752013-12-02 02:41:19 +0100539 raise
Antoine Pitrou242db722013-05-01 20:52:07 +0200540
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100541 @property
542 def context(self):
543 return self._context
544
545 @context.setter
546 def context(self, ctx):
547 self._context = ctx
548 self._sslobj.context = ctx
Bill Janssen6e027db2007-11-15 22:23:56 +0000549
Guido van Rossumb7b030e2007-11-16 01:28:45 +0000550 def dup(self):
551 raise NotImplemented("Can't dup() %s instances" %
552 self.__class__.__name__)
553
Bill Janssen6e027db2007-11-15 22:23:56 +0000554 def _checkClosed(self, msg=None):
555 # raise an exception here if you wish to check for spurious closes
556 pass
557
Antoine Pitrou242db722013-05-01 20:52:07 +0200558 def _check_connected(self):
559 if not self._connected:
560 # getpeername() will raise ENOTCONN if the socket is really
561 # not connected; note that we can be connected even without
562 # _connected being set, e.g. if connect() first returned
563 # EAGAIN.
564 self.getpeername()
565
Bill Janssen54cc54c2007-12-14 22:08:56 +0000566 def read(self, len=0, buffer=None):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000567 """Read up to LEN bytes and return them.
568 Return zero-length string on EOF."""
569
Bill Janssen6e027db2007-11-15 22:23:56 +0000570 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200571 if not self._sslobj:
572 raise ValueError("Read on closed or unwrapped SSL socket.")
Bill Janssen6e027db2007-11-15 22:23:56 +0000573 try:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000574 if buffer is not None:
575 v = self._sslobj.read(len, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000576 else:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000577 v = self._sslobj.read(len or 1024)
578 return v
Bill Janssen6e027db2007-11-15 22:23:56 +0000579 except SSLError as x:
580 if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000581 if buffer is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000582 return 0
583 else:
584 return b''
Bill Janssen6e027db2007-11-15 22:23:56 +0000585 else:
586 raise
Thomas Woutersed03b412007-08-28 21:37:11 +0000587
588 def write(self, data):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000589 """Write DATA to the underlying SSL channel. Returns
590 number of bytes of DATA actually transmitted."""
591
Bill Janssen6e027db2007-11-15 22:23:56 +0000592 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200593 if not self._sslobj:
594 raise ValueError("Write on closed or unwrapped SSL socket.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000595 return self._sslobj.write(data)
596
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000597 def getpeercert(self, binary_form=False):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000598 """Returns a formatted version of the data in the
599 certificate provided by the other end of the SSL channel.
600 Return None if no certificate was provided, {} if a
601 certificate was provided, but not validated."""
602
Bill Janssen6e027db2007-11-15 22:23:56 +0000603 self._checkClosed()
Antoine Pitrou242db722013-05-01 20:52:07 +0200604 self._check_connected()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000605 return self._sslobj.peer_certificate(binary_form)
606
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100607 def selected_npn_protocol(self):
608 self._checkClosed()
609 if not self._sslobj or not _ssl.HAS_NPN:
610 return None
611 else:
612 return self._sslobj.selected_npn_protocol()
613
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000614 def cipher(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000615 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000616 if not self._sslobj:
617 return None
618 else:
619 return self._sslobj.cipher()
Thomas Woutersed03b412007-08-28 21:37:11 +0000620
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100621 def compression(self):
622 self._checkClosed()
623 if not self._sslobj:
624 return None
625 else:
626 return self._sslobj.compression()
627
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000628 def send(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000629 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000630 if self._sslobj:
631 if flags != 0:
632 raise ValueError(
633 "non-zero flags not allowed in calls to send() on %s" %
634 self.__class__)
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200635 try:
636 v = self._sslobj.write(data)
637 except SSLError as x:
638 if x.args[0] == SSL_ERROR_WANT_READ:
639 return 0
640 elif x.args[0] == SSL_ERROR_WANT_WRITE:
641 return 0
Bill Janssen6e027db2007-11-15 22:23:56 +0000642 else:
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200643 raise
644 else:
645 return v
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000646 else:
647 return socket.send(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000648
Antoine Pitroua468adc2010-09-14 14:43:44 +0000649 def sendto(self, data, flags_or_addr, addr=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000650 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000651 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000652 raise ValueError("sendto not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000653 self.__class__)
Antoine Pitroua468adc2010-09-14 14:43:44 +0000654 elif addr is None:
655 return socket.sendto(self, data, flags_or_addr)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000656 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000657 return socket.sendto(self, data, flags_or_addr, addr)
Thomas Woutersed03b412007-08-28 21:37:11 +0000658
Nick Coghlan513886a2011-08-28 00:00:27 +1000659 def sendmsg(self, *args, **kwargs):
660 # Ensure programs don't send data unencrypted if they try to
661 # use this method.
662 raise NotImplementedError("sendmsg not allowed on instances of %s" %
663 self.__class__)
664
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000665 def sendall(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000666 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000667 if self._sslobj:
Giampaolo RodolĂ 374f8352010-08-29 12:08:09 +0000668 if flags != 0:
669 raise ValueError(
670 "non-zero flags not allowed in calls to sendall() on %s" %
671 self.__class__)
Bill Janssen6e027db2007-11-15 22:23:56 +0000672 amount = len(data)
673 count = 0
674 while (count < amount):
675 v = self.send(data[count:])
676 count += v
677 return amount
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000678 else:
679 return socket.sendall(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000680
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000681 def recv(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000682 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000683 if self._sslobj:
684 if flags != 0:
685 raise ValueError(
Antoine Pitrou5733c082010-03-22 14:49:10 +0000686 "non-zero flags not allowed in calls to recv() on %s" %
687 self.__class__)
688 return self.read(buflen)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000689 else:
690 return socket.recv(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000691
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000692 def recv_into(self, buffer, nbytes=None, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000693 self._checkClosed()
694 if buffer and (nbytes is None):
695 nbytes = len(buffer)
696 elif nbytes is None:
697 nbytes = 1024
698 if self._sslobj:
699 if flags != 0:
700 raise ValueError(
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000701 "non-zero flags not allowed in calls to recv_into() on %s" %
702 self.__class__)
Antoine Pitrou5733c082010-03-22 14:49:10 +0000703 return self.read(nbytes, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000704 else:
705 return socket.recv_into(self, buffer, nbytes, flags)
706
Antoine Pitroua468adc2010-09-14 14:43:44 +0000707 def recvfrom(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000708 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000709 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000710 raise ValueError("recvfrom not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000711 self.__class__)
712 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000713 return socket.recvfrom(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000714
Bill Janssen58afe4c2008-09-08 16:45:19 +0000715 def recvfrom_into(self, buffer, nbytes=None, flags=0):
716 self._checkClosed()
717 if self._sslobj:
718 raise ValueError("recvfrom_into not allowed on instances of %s" %
719 self.__class__)
720 else:
721 return socket.recvfrom_into(self, buffer, nbytes, flags)
722
Nick Coghlan513886a2011-08-28 00:00:27 +1000723 def recvmsg(self, *args, **kwargs):
724 raise NotImplementedError("recvmsg not allowed on instances of %s" %
725 self.__class__)
726
727 def recvmsg_into(self, *args, **kwargs):
728 raise NotImplementedError("recvmsg_into not allowed on instances of "
729 "%s" % self.__class__)
730
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000731 def pending(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000732 self._checkClosed()
733 if self._sslobj:
734 return self._sslobj.pending()
735 else:
736 return 0
737
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000738 def shutdown(self, how):
Bill Janssen6e027db2007-11-15 22:23:56 +0000739 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 self._sslobj = None
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000741 socket.shutdown(self, how)
Thomas Woutersed03b412007-08-28 21:37:11 +0000742
Ezio Melottidc55e672010-01-18 09:15:14 +0000743 def unwrap(self):
Bill Janssen40a0f662008-08-12 16:56:25 +0000744 if self._sslobj:
745 s = self._sslobj.shutdown()
746 self._sslobj = None
747 return s
748 else:
749 raise ValueError("No SSL wrapper around " + str(self))
750
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000751 def _real_close(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000752 self._sslobj = None
Bill Janssen54cc54c2007-12-14 22:08:56 +0000753 socket._real_close(self)
Bill Janssen6e027db2007-11-15 22:23:56 +0000754
Bill Janssen48dc27c2007-12-05 03:38:10 +0000755 def do_handshake(self, block=False):
Bill Janssen6e027db2007-11-15 22:23:56 +0000756 """Perform a TLS/SSL handshake."""
Antoine Pitrou242db722013-05-01 20:52:07 +0200757 self._check_connected()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000758 timeout = self.gettimeout()
Bill Janssen6e027db2007-11-15 22:23:56 +0000759 try:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000760 if timeout == 0.0 and block:
761 self.settimeout(None)
Bill Janssen6e027db2007-11-15 22:23:56 +0000762 self._sslobj.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000763 finally:
764 self.settimeout(timeout)
Thomas Woutersed03b412007-08-28 21:37:11 +0000765
Christian Heimes1aa9a752013-12-02 02:41:19 +0100766 if self.context.check_hostname:
767 try:
768 if not self.server_hostname:
769 raise ValueError("check_hostname needs server_hostname "
770 "argument")
771 match_hostname(self.getpeercert(), self.server_hostname)
772 except Exception:
773 self.shutdown(_SHUT_RDWR)
774 self.close()
775 raise
776
Antoine Pitroub4410db2011-05-18 18:51:06 +0200777 def _real_connect(self, addr, connect_ex):
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000778 if self.server_side:
779 raise ValueError("can't connect in server-side mode")
Thomas Woutersed03b412007-08-28 21:37:11 +0000780 # Here we assume that the socket is client-side, and not
781 # connected at the time of the call. We connect it, then wrap it.
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000782 if self._connected:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000783 raise ValueError("attempt to connect already-connected SSLSocket!")
Antoine Pitroud5323212010-10-22 18:19:07 +0000784 self._sslobj = self.context._wrap_socket(self, False, self.server_hostname)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000785 try:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200786 if connect_ex:
787 rc = socket.connect_ex(self, addr)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000788 else:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200789 rc = None
790 socket.connect(self, addr)
791 if not rc:
Antoine Pitrou242db722013-05-01 20:52:07 +0200792 self._connected = True
Antoine Pitroub4410db2011-05-18 18:51:06 +0200793 if self.do_handshake_on_connect:
794 self.do_handshake()
Antoine Pitroub4410db2011-05-18 18:51:06 +0200795 return rc
Christian Heimes1aa9a752013-12-02 02:41:19 +0100796 except (OSError, ValueError):
Antoine Pitroub4410db2011-05-18 18:51:06 +0200797 self._sslobj = None
798 raise
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000799
800 def connect(self, addr):
801 """Connects to remote ADDR, and then wraps the connection in
802 an SSL channel."""
803 self._real_connect(addr, False)
804
805 def connect_ex(self, addr):
806 """Connects to remote ADDR, and then wraps the connection in
807 an SSL channel."""
808 return self._real_connect(addr, True)
Thomas Woutersed03b412007-08-28 21:37:11 +0000809
810 def accept(self):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000811 """Accepts a new connection from a remote client, and returns
812 a tuple containing that new connection wrapped with a server-side
813 SSL channel, and the address of the remote client."""
814
815 newsock, addr = socket.accept(self)
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +0100816 newsock = self.context.wrap_socket(newsock,
817 do_handshake_on_connect=self.do_handshake_on_connect,
818 suppress_ragged_eofs=self.suppress_ragged_eofs,
819 server_side=True)
820 return newsock, addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821
Antoine Pitroud6494802011-07-21 01:11:30 +0200822 def get_channel_binding(self, cb_type="tls-unique"):
823 """Get channel binding data for current connection. Raise ValueError
824 if the requested `cb_type` is not supported. Return bytes of the data
825 or None if the data is not available (e.g. before the handshake).
826 """
827 if cb_type not in CHANNEL_BINDING_TYPES:
828 raise ValueError("Unsupported channel binding type")
829 if cb_type != "tls-unique":
830 raise NotImplementedError(
831 "{0} channel binding type not implemented"
832 .format(cb_type))
833 if self._sslobj is None:
834 return None
835 return self._sslobj.tls_unique_cb()
836
Bill Janssen54cc54c2007-12-14 22:08:56 +0000837
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000838def wrap_socket(sock, keyfile=None, certfile=None,
839 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000840 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000841 do_handshake_on_connect=True,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100842 suppress_ragged_eofs=True,
843 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000844
Bill Janssen6e027db2007-11-15 22:23:56 +0000845 return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000846 server_side=server_side, cert_reqs=cert_reqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000847 ssl_version=ssl_version, ca_certs=ca_certs,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000848 do_handshake_on_connect=do_handshake_on_connect,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000849 suppress_ragged_eofs=suppress_ragged_eofs,
850 ciphers=ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000851
Thomas Woutersed03b412007-08-28 21:37:11 +0000852# some utility functions
853
854def cert_time_to_seconds(cert_time):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000855 """Takes a date-time string in standard ASN1_print form
856 ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return
857 a Python time value in seconds past the epoch."""
858
Thomas Woutersed03b412007-08-28 21:37:11 +0000859 import time
860 return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT"))
861
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000862PEM_HEADER = "-----BEGIN CERTIFICATE-----"
863PEM_FOOTER = "-----END CERTIFICATE-----"
864
865def DER_cert_to_PEM_cert(der_cert_bytes):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000866 """Takes a certificate in binary DER format and returns the
867 PEM version of it as a string."""
868
Bill Janssen6e027db2007-11-15 22:23:56 +0000869 f = str(base64.standard_b64encode(der_cert_bytes), 'ASCII', 'strict')
870 return (PEM_HEADER + '\n' +
871 textwrap.fill(f, 64) + '\n' +
872 PEM_FOOTER + '\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000873
874def PEM_cert_to_DER_cert(pem_cert_string):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000875 """Takes a certificate in ASCII PEM format and returns the
876 DER-encoded version of it as a byte sequence"""
877
878 if not pem_cert_string.startswith(PEM_HEADER):
879 raise ValueError("Invalid PEM encoding; must start with %s"
880 % PEM_HEADER)
881 if not pem_cert_string.strip().endswith(PEM_FOOTER):
882 raise ValueError("Invalid PEM encoding; must end with %s"
883 % PEM_FOOTER)
884 d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)]
Georg Brandl706824f2009-06-04 09:42:55 +0000885 return base64.decodebytes(d.encode('ASCII', 'strict'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000886
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000887def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000888 """Retrieve the certificate from the server at the specified address,
889 and return it as a PEM-encoded string.
890 If 'ca_certs' is specified, validate the server cert against it.
891 If 'ssl_version' is specified, use it in the connection attempt."""
892
893 host, port = addr
Christian Heimes67986f92013-11-23 22:43:47 +0100894 if ca_certs is not None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000895 cert_reqs = CERT_REQUIRED
896 else:
897 cert_reqs = CERT_NONE
Christian Heimes67986f92013-11-23 22:43:47 +0100898 context = _create_stdlib_context(ssl_version,
899 cert_reqs=cert_reqs,
900 cafile=ca_certs)
901 with create_connection(addr) as sock:
902 with context.wrap_socket(sock) as sslsock:
903 dercert = sslsock.getpeercert(True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000904 return DER_cert_to_PEM_cert(dercert)
905
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000906def get_protocol_name(protocol_code):
Victor Stinner3de49192011-05-09 00:42:58 +0200907 return _PROTOCOL_NAMES.get(protocol_code, '<unknown>')