blob: 4408e7b74364803d78bd54ff5e5a75b77ce12757 [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
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100153from socket import SOL_SOCKET, SO_TYPE
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000154import base64 # for DER-to-PEM translation
Bill Janssen54cc54c2007-12-14 22:08:56 +0000155import traceback
Antoine Pitroude8cf322010-04-26 17:29:05 +0000156import errno
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000157
Andrew Svetlov0832af62012-12-18 23:10:48 +0200158
159socket_error = OSError # keep that public name in module namespace
160
Antoine Pitroud6494802011-07-21 01:11:30 +0200161if _ssl.HAS_TLS_UNIQUE:
162 CHANNEL_BINDING_TYPES = ['tls-unique']
163else:
164 CHANNEL_BINDING_TYPES = []
Thomas Woutersed03b412007-08-28 21:37:11 +0000165
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100166# Disable weak or insecure ciphers by default
167# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
168_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
169
Christian Heimes4c05b472013-11-23 15:58:30 +0100170# restricted and more secure ciphers
171# HIGH: high encryption cipher suites with key length >= 128 bits (no MD5)
172# !aNULL: only authenticated cipher suites (no anonymous DH)
173# !RC4: no RC4 streaming cipher, RC4 is broken
174# !DSS: RSA is preferred over DSA
175_RESTRICTED_CIPHERS = 'HIGH:!aNULL:!RC4:!DSS'
176
Thomas Woutersed03b412007-08-28 21:37:11 +0000177
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000178class CertificateError(ValueError):
179 pass
180
181
Georg Brandl72c98d32013-10-27 07:16:53 +0100182def _dnsname_match(dn, hostname, max_wildcards=1):
183 """Matching according to RFC 6125, section 6.4.3
184
185 http://tools.ietf.org/html/rfc6125#section-6.4.3
186 """
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000187 pats = []
Georg Brandl72c98d32013-10-27 07:16:53 +0100188 if not dn:
189 return False
190
191 leftmost, *remainder = dn.split(r'.')
192
193 wildcards = leftmost.count('*')
194 if wildcards > max_wildcards:
195 # Issue #17980: avoid denials of service by refusing more
196 # than one wildcard per fragment. A survery of established
197 # policy among SSL implementations showed it to be a
198 # reasonable choice.
199 raise CertificateError(
200 "too many wildcards in certificate DNS name: " + repr(dn))
201
202 # speed up common case w/o wildcards
203 if not wildcards:
204 return dn.lower() == hostname.lower()
205
206 # RFC 6125, section 6.4.3, subitem 1.
207 # The client SHOULD NOT attempt to match a presented identifier in which
208 # the wildcard character comprises a label other than the left-most label.
209 if leftmost == '*':
210 # When '*' is a fragment by itself, it matches a non-empty dotless
211 # fragment.
212 pats.append('[^.]+')
213 elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
214 # RFC 6125, section 6.4.3, subitem 3.
215 # The client SHOULD NOT attempt to match a presented identifier
216 # where the wildcard character is embedded within an A-label or
217 # U-label of an internationalized domain name.
218 pats.append(re.escape(leftmost))
219 else:
220 # Otherwise, '*' matches any dotless string, e.g. www*
221 pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
222
223 # add the remaining fragments, ignore any wildcards
224 for frag in remainder:
225 pats.append(re.escape(frag))
226
227 pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
228 return pat.match(hostname)
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000229
230
231def match_hostname(cert, hostname):
232 """Verify that *cert* (in decoded format as returned by
Georg Brandl72c98d32013-10-27 07:16:53 +0100233 SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
234 rules are followed, but IP addresses are not accepted for *hostname*.
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000235
236 CertificateError is raised on failure. On success, the function
237 returns nothing.
238 """
239 if not cert:
Christian Heimes1aa9a752013-12-02 02:41:19 +0100240 raise ValueError("empty or no certificate, match_hostname needs a "
241 "SSL socket or SSL context with either "
242 "CERT_OPTIONAL or CERT_REQUIRED")
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000243 dnsnames = []
244 san = cert.get('subjectAltName', ())
245 for key, value in san:
246 if key == 'DNS':
Georg Brandl72c98d32013-10-27 07:16:53 +0100247 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000248 return
249 dnsnames.append(value)
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200250 if not dnsnames:
251 # The subject is only checked when there is no dNSName entry
252 # in subjectAltName
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000253 for sub in cert.get('subject', ()):
254 for key, value in sub:
255 # XXX according to RFC 2818, the most specific Common Name
256 # must be used.
257 if key == 'commonName':
Georg Brandl72c98d32013-10-27 07:16:53 +0100258 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000259 return
260 dnsnames.append(value)
261 if len(dnsnames) > 1:
262 raise CertificateError("hostname %r "
263 "doesn't match either of %s"
264 % (hostname, ', '.join(map(repr, dnsnames))))
265 elif len(dnsnames) == 1:
266 raise CertificateError("hostname %r "
267 "doesn't match %r"
268 % (hostname, dnsnames[0]))
269 else:
270 raise CertificateError("no appropriate commonName or "
271 "subjectAltName fields were found")
272
273
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100274DefaultVerifyPaths = namedtuple("DefaultVerifyPaths",
Christian Heimes6d7ad132013-06-09 18:02:55 +0200275 "cafile capath openssl_cafile_env openssl_cafile openssl_capath_env "
276 "openssl_capath")
277
278def get_default_verify_paths():
279 """Return paths to default cafile and capath.
280 """
281 parts = _ssl.get_default_verify_paths()
282
283 # environment vars shadow paths
284 cafile = os.environ.get(parts[0], parts[1])
285 capath = os.environ.get(parts[2], parts[3])
286
287 return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None,
288 capath if os.path.isdir(capath) else None,
289 *parts)
290
291
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100292class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")):
293 """ASN.1 object identifier lookup
294 """
295 __slots__ = ()
296
297 def __new__(cls, oid):
298 return super().__new__(cls, *_txt2obj(oid, name=False))
299
300 @classmethod
301 def fromnid(cls, nid):
302 """Create _ASN1Object from OpenSSL numeric ID
303 """
304 return super().__new__(cls, *_nid2obj(nid))
305
306 @classmethod
307 def fromname(cls, name):
308 """Create _ASN1Object from short name, long name or OID
309 """
310 return super().__new__(cls, *_txt2obj(name, name=True))
311
312
Christian Heimes72d28502013-11-23 13:56:58 +0100313class Purpose(_ASN1Object, _Enum):
314 """SSLContext purpose flags with X509v3 Extended Key Usage objects
315 """
316 SERVER_AUTH = '1.3.6.1.5.5.7.3.1'
317 CLIENT_AUTH = '1.3.6.1.5.5.7.3.2'
318
319
Antoine Pitrou152efa22010-05-16 18:19:27 +0000320class SSLContext(_SSLContext):
321 """An SSLContext holds various SSL-related configuration options and
322 data, such as certificates and possibly a private key."""
323
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100324 __slots__ = ('protocol', '__weakref__')
Christian Heimes72d28502013-11-23 13:56:58 +0100325 _windows_cert_stores = ("CA", "ROOT")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000326
327 def __new__(cls, protocol, *args, **kwargs):
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100328 self = _SSLContext.__new__(cls, protocol)
329 if protocol != _SSLv2_IF_EXISTS:
330 self.set_ciphers(_DEFAULT_CIPHERS)
331 return self
Antoine Pitrou152efa22010-05-16 18:19:27 +0000332
333 def __init__(self, protocol):
334 self.protocol = protocol
335
336 def wrap_socket(self, sock, server_side=False,
337 do_handshake_on_connect=True,
Antoine Pitroud5323212010-10-22 18:19:07 +0000338 suppress_ragged_eofs=True,
339 server_hostname=None):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000340 return SSLSocket(sock=sock, server_side=server_side,
341 do_handshake_on_connect=do_handshake_on_connect,
342 suppress_ragged_eofs=suppress_ragged_eofs,
Antoine Pitroud5323212010-10-22 18:19:07 +0000343 server_hostname=server_hostname,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000344 _context=self)
345
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100346 def set_npn_protocols(self, npn_protocols):
347 protos = bytearray()
348 for protocol in npn_protocols:
349 b = bytes(protocol, 'ascii')
350 if len(b) == 0 or len(b) > 255:
351 raise SSLError('NPN protocols must be 1 to 255 in length')
352 protos.append(len(b))
353 protos.extend(b)
354
355 self._set_npn_protocols(protos)
356
Christian Heimes72d28502013-11-23 13:56:58 +0100357 def _load_windows_store_certs(self, storename, purpose):
358 certs = bytearray()
359 for cert, encoding, trust in enum_certificates(storename):
360 # CA certs are never PKCS#7 encoded
361 if encoding == "x509_asn":
362 if trust is True or purpose.oid in trust:
363 certs.extend(cert)
364 self.load_verify_locations(cadata=certs)
365 return certs
366
367 def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
368 if not isinstance(purpose, _ASN1Object):
369 raise TypeError(purpose)
370 if sys.platform == "win32":
371 for storename in self._windows_cert_stores:
372 self._load_windows_store_certs(storename, purpose)
373 else:
374 self.set_default_verify_paths()
375
Antoine Pitrou152efa22010-05-16 18:19:27 +0000376
Christian Heimes4c05b472013-11-23 15:58:30 +0100377def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
378 capath=None, cadata=None):
379 """Create a SSLContext object with default settings.
380
381 NOTE: The protocol and settings may change anytime without prior
382 deprecation. The values represent a fair balance between maximum
383 compatibility and security.
384 """
385 if not isinstance(purpose, _ASN1Object):
386 raise TypeError(purpose)
387 context = SSLContext(PROTOCOL_TLSv1)
388 # SSLv2 considered harmful.
389 context.options |= OP_NO_SSLv2
Christian Heimesdec813f2013-11-28 08:06:54 +0100390 # disable compression to prevent CRIME attacks (OpenSSL 1.0+)
391 context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0)
Christian Heimes4c05b472013-11-23 15:58:30 +0100392 # disallow ciphers with known vulnerabilities
393 context.set_ciphers(_RESTRICTED_CIPHERS)
Christian Heimes1aa9a752013-12-02 02:41:19 +0100394 # verify certs and host name in client mode
Christian Heimes4c05b472013-11-23 15:58:30 +0100395 if purpose == Purpose.SERVER_AUTH:
396 context.verify_mode = CERT_REQUIRED
Christian Heimes1aa9a752013-12-02 02:41:19 +0100397 context.check_hostname = True
Christian Heimes4c05b472013-11-23 15:58:30 +0100398 if cafile or capath or cadata:
399 context.load_verify_locations(cafile, capath, cadata)
400 elif context.verify_mode != CERT_NONE:
401 # no explicit cafile, capath or cadata but the verify mode is
402 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
403 # root CA certificates for the given purpose. This may fail silently.
404 context.load_default_certs(purpose)
405 return context
406
407
Christian Heimes67986f92013-11-23 22:43:47 +0100408def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
Christian Heimesa02c69a2013-12-02 20:59:28 +0100409 check_hostname=False, purpose=Purpose.SERVER_AUTH,
Christian Heimes67986f92013-11-23 22:43:47 +0100410 certfile=None, keyfile=None,
411 cafile=None, capath=None, cadata=None):
412 """Create a SSLContext object for Python stdlib modules
413
414 All Python stdlib modules shall use this function to create SSLContext
415 objects in order to keep common settings in one place. The configuration
416 is less restrict than create_default_context()'s to increase backward
417 compatibility.
418 """
419 if not isinstance(purpose, _ASN1Object):
420 raise TypeError(purpose)
421
422 context = SSLContext(protocol)
423 # SSLv2 considered harmful.
424 context.options |= OP_NO_SSLv2
425
426 if cert_reqs is not None:
427 context.verify_mode = cert_reqs
Christian Heimesa02c69a2013-12-02 20:59:28 +0100428 context.check_hostname = check_hostname
Christian Heimes67986f92013-11-23 22:43:47 +0100429
430 if keyfile and not certfile:
431 raise ValueError("certfile must be specified")
432 if certfile or keyfile:
433 context.load_cert_chain(certfile, keyfile)
434
435 # load CA root certs
436 if cafile or capath or cadata:
437 context.load_verify_locations(cafile, capath, cadata)
438 elif context.verify_mode != CERT_NONE:
439 # no explicit cafile, capath or cadata but the verify mode is
440 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
441 # root CA certificates for the given purpose. This may fail silently.
442 context.load_default_certs(purpose)
443
444 return context
445
Antoine Pitrou152efa22010-05-16 18:19:27 +0000446class SSLSocket(socket):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000447 """This class implements a subtype of socket.socket that wraps
448 the underlying OS socket in an SSL context when necessary, and
449 provides read and write methods over that channel."""
450
Bill Janssen6e027db2007-11-15 22:23:56 +0000451 def __init__(self, sock=None, keyfile=None, certfile=None,
Thomas Woutersed03b412007-08-28 21:37:11 +0000452 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000453 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
454 do_handshake_on_connect=True,
455 family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100456 suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
Antoine Pitroud5323212010-10-22 18:19:07 +0000457 server_hostname=None,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000458 _context=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000459
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 if _context:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100461 self._context = _context
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 else:
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000463 if server_side and not certfile:
464 raise ValueError("certfile must be specified for server-side "
465 "operations")
Giampaolo RodolĂ 8b7da622010-08-30 18:28:05 +0000466 if keyfile and not certfile:
467 raise ValueError("certfile must be specified")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000468 if certfile and not keyfile:
469 keyfile = certfile
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100470 self._context = SSLContext(ssl_version)
471 self._context.verify_mode = cert_reqs
Antoine Pitrou152efa22010-05-16 18:19:27 +0000472 if ca_certs:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100473 self._context.load_verify_locations(ca_certs)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474 if certfile:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100475 self._context.load_cert_chain(certfile, keyfile)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100476 if npn_protocols:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100477 self._context.set_npn_protocols(npn_protocols)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000478 if ciphers:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100479 self._context.set_ciphers(ciphers)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000480 self.keyfile = keyfile
481 self.certfile = certfile
482 self.cert_reqs = cert_reqs
483 self.ssl_version = ssl_version
484 self.ca_certs = ca_certs
485 self.ciphers = ciphers
Antoine Pitrou3e86ba42013-12-28 17:26:33 +0100486 # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get
487 # mixed in.
488 if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM:
489 raise NotImplementedError("only stream sockets are supported")
Antoine Pitroud5323212010-10-22 18:19:07 +0000490 if server_side and server_hostname:
491 raise ValueError("server_hostname can only be specified "
492 "in client mode")
Christian Heimes1aa9a752013-12-02 02:41:19 +0100493 if self._context.check_hostname and not server_hostname:
494 if HAS_SNI:
495 raise ValueError("check_hostname requires server_hostname")
496 else:
497 raise ValueError("check_hostname requires server_hostname, "
498 "but it's not supported by your OpenSSL "
499 "library")
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000500 self.server_side = server_side
Antoine Pitroud5323212010-10-22 18:19:07 +0000501 self.server_hostname = server_hostname
Antoine Pitrou152efa22010-05-16 18:19:27 +0000502 self.do_handshake_on_connect = do_handshake_on_connect
503 self.suppress_ragged_eofs = suppress_ragged_eofs
Bill Janssen6e027db2007-11-15 22:23:56 +0000504 if sock is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000505 socket.__init__(self,
506 family=sock.family,
507 type=sock.type,
508 proto=sock.proto,
Antoine Pitroue43f9d02010-08-08 23:24:50 +0000509 fileno=sock.fileno())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000510 self.settimeout(sock.gettimeout())
Antoine Pitrou6e451df2010-08-09 20:39:54 +0000511 sock.detach()
Bill Janssen6e027db2007-11-15 22:23:56 +0000512 elif fileno is not None:
513 socket.__init__(self, fileno=fileno)
514 else:
515 socket.__init__(self, family=family, type=type, proto=proto)
516
Antoine Pitrou242db722013-05-01 20:52:07 +0200517 # See if we are connected
518 try:
519 self.getpeername()
520 except OSError as e:
521 if e.errno != errno.ENOTCONN:
522 raise
523 connected = False
524 else:
525 connected = True
526
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000527 self._closed = False
528 self._sslobj = None
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000529 self._connected = connected
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000530 if connected:
531 # create the SSL object
Bill Janssen6e027db2007-11-15 22:23:56 +0000532 try:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100533 self._sslobj = self._context._wrap_socket(self, server_side,
Antoine Pitroud5323212010-10-22 18:19:07 +0000534 server_hostname)
Bill Janssen6e027db2007-11-15 22:23:56 +0000535 if do_handshake_on_connect:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000536 timeout = self.gettimeout()
537 if timeout == 0.0:
538 # non-blocking
539 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
Bill Janssen6e027db2007-11-15 22:23:56 +0000540 self.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000541
Christian Heimes1aa9a752013-12-02 02:41:19 +0100542 except (OSError, ValueError):
Bill Janssen6e027db2007-11-15 22:23:56 +0000543 self.close()
Christian Heimes1aa9a752013-12-02 02:41:19 +0100544 raise
Antoine Pitrou242db722013-05-01 20:52:07 +0200545
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100546 @property
547 def context(self):
548 return self._context
549
550 @context.setter
551 def context(self, ctx):
552 self._context = ctx
553 self._sslobj.context = ctx
Bill Janssen6e027db2007-11-15 22:23:56 +0000554
Guido van Rossumb7b030e2007-11-16 01:28:45 +0000555 def dup(self):
556 raise NotImplemented("Can't dup() %s instances" %
557 self.__class__.__name__)
558
Bill Janssen6e027db2007-11-15 22:23:56 +0000559 def _checkClosed(self, msg=None):
560 # raise an exception here if you wish to check for spurious closes
561 pass
562
Antoine Pitrou242db722013-05-01 20:52:07 +0200563 def _check_connected(self):
564 if not self._connected:
565 # getpeername() will raise ENOTCONN if the socket is really
566 # not connected; note that we can be connected even without
567 # _connected being set, e.g. if connect() first returned
568 # EAGAIN.
569 self.getpeername()
570
Bill Janssen54cc54c2007-12-14 22:08:56 +0000571 def read(self, len=0, buffer=None):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000572 """Read up to LEN bytes and return them.
573 Return zero-length string on EOF."""
574
Bill Janssen6e027db2007-11-15 22:23:56 +0000575 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200576 if not self._sslobj:
577 raise ValueError("Read on closed or unwrapped SSL socket.")
Bill Janssen6e027db2007-11-15 22:23:56 +0000578 try:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000579 if buffer is not None:
580 v = self._sslobj.read(len, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000581 else:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000582 v = self._sslobj.read(len or 1024)
583 return v
Bill Janssen6e027db2007-11-15 22:23:56 +0000584 except SSLError as x:
585 if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000586 if buffer is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000587 return 0
588 else:
589 return b''
Bill Janssen6e027db2007-11-15 22:23:56 +0000590 else:
591 raise
Thomas Woutersed03b412007-08-28 21:37:11 +0000592
593 def write(self, data):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000594 """Write DATA to the underlying SSL channel. Returns
595 number of bytes of DATA actually transmitted."""
596
Bill Janssen6e027db2007-11-15 22:23:56 +0000597 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200598 if not self._sslobj:
599 raise ValueError("Write on closed or unwrapped SSL socket.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000600 return self._sslobj.write(data)
601
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000602 def getpeercert(self, binary_form=False):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000603 """Returns a formatted version of the data in the
604 certificate provided by the other end of the SSL channel.
605 Return None if no certificate was provided, {} if a
606 certificate was provided, but not validated."""
607
Bill Janssen6e027db2007-11-15 22:23:56 +0000608 self._checkClosed()
Antoine Pitrou242db722013-05-01 20:52:07 +0200609 self._check_connected()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000610 return self._sslobj.peer_certificate(binary_form)
611
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100612 def selected_npn_protocol(self):
613 self._checkClosed()
614 if not self._sslobj or not _ssl.HAS_NPN:
615 return None
616 else:
617 return self._sslobj.selected_npn_protocol()
618
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000619 def cipher(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000620 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000621 if not self._sslobj:
622 return None
623 else:
624 return self._sslobj.cipher()
Thomas Woutersed03b412007-08-28 21:37:11 +0000625
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100626 def compression(self):
627 self._checkClosed()
628 if not self._sslobj:
629 return None
630 else:
631 return self._sslobj.compression()
632
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000633 def send(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000634 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000635 if self._sslobj:
636 if flags != 0:
637 raise ValueError(
638 "non-zero flags not allowed in calls to send() on %s" %
639 self.__class__)
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200640 try:
641 v = self._sslobj.write(data)
642 except SSLError as x:
643 if x.args[0] == SSL_ERROR_WANT_READ:
644 return 0
645 elif x.args[0] == SSL_ERROR_WANT_WRITE:
646 return 0
Bill Janssen6e027db2007-11-15 22:23:56 +0000647 else:
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200648 raise
649 else:
650 return v
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000651 else:
652 return socket.send(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000653
Antoine Pitroua468adc2010-09-14 14:43:44 +0000654 def sendto(self, data, flags_or_addr, addr=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000655 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000656 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000657 raise ValueError("sendto not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000658 self.__class__)
Antoine Pitroua468adc2010-09-14 14:43:44 +0000659 elif addr is None:
660 return socket.sendto(self, data, flags_or_addr)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000661 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000662 return socket.sendto(self, data, flags_or_addr, addr)
Thomas Woutersed03b412007-08-28 21:37:11 +0000663
Nick Coghlan513886a2011-08-28 00:00:27 +1000664 def sendmsg(self, *args, **kwargs):
665 # Ensure programs don't send data unencrypted if they try to
666 # use this method.
667 raise NotImplementedError("sendmsg not allowed on instances of %s" %
668 self.__class__)
669
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000670 def sendall(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000671 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000672 if self._sslobj:
Giampaolo RodolĂ 374f8352010-08-29 12:08:09 +0000673 if flags != 0:
674 raise ValueError(
675 "non-zero flags not allowed in calls to sendall() on %s" %
676 self.__class__)
Bill Janssen6e027db2007-11-15 22:23:56 +0000677 amount = len(data)
678 count = 0
679 while (count < amount):
680 v = self.send(data[count:])
681 count += v
682 return amount
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000683 else:
684 return socket.sendall(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000685
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000686 def recv(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000687 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000688 if self._sslobj:
689 if flags != 0:
690 raise ValueError(
Antoine Pitrou5733c082010-03-22 14:49:10 +0000691 "non-zero flags not allowed in calls to recv() on %s" %
692 self.__class__)
693 return self.read(buflen)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000694 else:
695 return socket.recv(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000696
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000697 def recv_into(self, buffer, nbytes=None, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000698 self._checkClosed()
699 if buffer and (nbytes is None):
700 nbytes = len(buffer)
701 elif nbytes is None:
702 nbytes = 1024
703 if self._sslobj:
704 if flags != 0:
705 raise ValueError(
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000706 "non-zero flags not allowed in calls to recv_into() on %s" %
707 self.__class__)
Antoine Pitrou5733c082010-03-22 14:49:10 +0000708 return self.read(nbytes, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000709 else:
710 return socket.recv_into(self, buffer, nbytes, flags)
711
Antoine Pitroua468adc2010-09-14 14:43:44 +0000712 def recvfrom(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000713 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000714 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000715 raise ValueError("recvfrom not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000716 self.__class__)
717 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000718 return socket.recvfrom(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000719
Bill Janssen58afe4c2008-09-08 16:45:19 +0000720 def recvfrom_into(self, buffer, nbytes=None, flags=0):
721 self._checkClosed()
722 if self._sslobj:
723 raise ValueError("recvfrom_into not allowed on instances of %s" %
724 self.__class__)
725 else:
726 return socket.recvfrom_into(self, buffer, nbytes, flags)
727
Nick Coghlan513886a2011-08-28 00:00:27 +1000728 def recvmsg(self, *args, **kwargs):
729 raise NotImplementedError("recvmsg not allowed on instances of %s" %
730 self.__class__)
731
732 def recvmsg_into(self, *args, **kwargs):
733 raise NotImplementedError("recvmsg_into not allowed on instances of "
734 "%s" % self.__class__)
735
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000736 def pending(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000737 self._checkClosed()
738 if self._sslobj:
739 return self._sslobj.pending()
740 else:
741 return 0
742
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000743 def shutdown(self, how):
Bill Janssen6e027db2007-11-15 22:23:56 +0000744 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000745 self._sslobj = None
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000746 socket.shutdown(self, how)
Thomas Woutersed03b412007-08-28 21:37:11 +0000747
Ezio Melottidc55e672010-01-18 09:15:14 +0000748 def unwrap(self):
Bill Janssen40a0f662008-08-12 16:56:25 +0000749 if self._sslobj:
750 s = self._sslobj.shutdown()
751 self._sslobj = None
752 return s
753 else:
754 raise ValueError("No SSL wrapper around " + str(self))
755
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000756 def _real_close(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000757 self._sslobj = None
Bill Janssen54cc54c2007-12-14 22:08:56 +0000758 socket._real_close(self)
Bill Janssen6e027db2007-11-15 22:23:56 +0000759
Bill Janssen48dc27c2007-12-05 03:38:10 +0000760 def do_handshake(self, block=False):
Bill Janssen6e027db2007-11-15 22:23:56 +0000761 """Perform a TLS/SSL handshake."""
Antoine Pitrou242db722013-05-01 20:52:07 +0200762 self._check_connected()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000763 timeout = self.gettimeout()
Bill Janssen6e027db2007-11-15 22:23:56 +0000764 try:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000765 if timeout == 0.0 and block:
766 self.settimeout(None)
Bill Janssen6e027db2007-11-15 22:23:56 +0000767 self._sslobj.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000768 finally:
769 self.settimeout(timeout)
Thomas Woutersed03b412007-08-28 21:37:11 +0000770
Christian Heimes1aa9a752013-12-02 02:41:19 +0100771 if self.context.check_hostname:
Christian Heimes1da3ba82013-12-04 20:46:20 +0100772 if not self.server_hostname:
773 raise ValueError("check_hostname needs server_hostname "
774 "argument")
775 match_hostname(self.getpeercert(), self.server_hostname)
Christian Heimes1aa9a752013-12-02 02:41:19 +0100776
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>')