blob: b29b90582ed2103c6c08bf5674c3d6fd7938499c [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
Antoine Pitrou15399c32011-04-28 19:23:55 +0200151from socket import socket, AF_INET, SOCK_STREAM, create_connection
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000152import base64 # for DER-to-PEM translation
Bill Janssen54cc54c2007-12-14 22:08:56 +0000153import traceback
Antoine Pitroude8cf322010-04-26 17:29:05 +0000154import errno
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000155
Andrew Svetlov0832af62012-12-18 23:10:48 +0200156
157socket_error = OSError # keep that public name in module namespace
158
Antoine Pitroud6494802011-07-21 01:11:30 +0200159if _ssl.HAS_TLS_UNIQUE:
160 CHANNEL_BINDING_TYPES = ['tls-unique']
161else:
162 CHANNEL_BINDING_TYPES = []
Thomas Woutersed03b412007-08-28 21:37:11 +0000163
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100164# Disable weak or insecure ciphers by default
165# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
166_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2'
167
Christian Heimes4c05b472013-11-23 15:58:30 +0100168# restricted and more secure ciphers
169# HIGH: high encryption cipher suites with key length >= 128 bits (no MD5)
170# !aNULL: only authenticated cipher suites (no anonymous DH)
171# !RC4: no RC4 streaming cipher, RC4 is broken
172# !DSS: RSA is preferred over DSA
173_RESTRICTED_CIPHERS = 'HIGH:!aNULL:!RC4:!DSS'
174
Thomas Woutersed03b412007-08-28 21:37:11 +0000175
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000176class CertificateError(ValueError):
177 pass
178
179
Georg Brandl72c98d32013-10-27 07:16:53 +0100180def _dnsname_match(dn, hostname, max_wildcards=1):
181 """Matching according to RFC 6125, section 6.4.3
182
183 http://tools.ietf.org/html/rfc6125#section-6.4.3
184 """
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000185 pats = []
Georg Brandl72c98d32013-10-27 07:16:53 +0100186 if not dn:
187 return False
188
189 leftmost, *remainder = dn.split(r'.')
190
191 wildcards = leftmost.count('*')
192 if wildcards > max_wildcards:
193 # Issue #17980: avoid denials of service by refusing more
194 # than one wildcard per fragment. A survery of established
195 # policy among SSL implementations showed it to be a
196 # reasonable choice.
197 raise CertificateError(
198 "too many wildcards in certificate DNS name: " + repr(dn))
199
200 # speed up common case w/o wildcards
201 if not wildcards:
202 return dn.lower() == hostname.lower()
203
204 # RFC 6125, section 6.4.3, subitem 1.
205 # The client SHOULD NOT attempt to match a presented identifier in which
206 # the wildcard character comprises a label other than the left-most label.
207 if leftmost == '*':
208 # When '*' is a fragment by itself, it matches a non-empty dotless
209 # fragment.
210 pats.append('[^.]+')
211 elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
212 # RFC 6125, section 6.4.3, subitem 3.
213 # The client SHOULD NOT attempt to match a presented identifier
214 # where the wildcard character is embedded within an A-label or
215 # U-label of an internationalized domain name.
216 pats.append(re.escape(leftmost))
217 else:
218 # Otherwise, '*' matches any dotless string, e.g. www*
219 pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
220
221 # add the remaining fragments, ignore any wildcards
222 for frag in remainder:
223 pats.append(re.escape(frag))
224
225 pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
226 return pat.match(hostname)
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000227
228
229def match_hostname(cert, hostname):
230 """Verify that *cert* (in decoded format as returned by
Georg Brandl72c98d32013-10-27 07:16:53 +0100231 SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
232 rules are followed, but IP addresses are not accepted for *hostname*.
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000233
234 CertificateError is raised on failure. On success, the function
235 returns nothing.
236 """
237 if not cert:
238 raise ValueError("empty or no certificate")
239 dnsnames = []
240 san = cert.get('subjectAltName', ())
241 for key, value in san:
242 if key == 'DNS':
Georg Brandl72c98d32013-10-27 07:16:53 +0100243 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000244 return
245 dnsnames.append(value)
Antoine Pitrou1c86b442011-05-06 15:19:49 +0200246 if not dnsnames:
247 # The subject is only checked when there is no dNSName entry
248 # in subjectAltName
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000249 for sub in cert.get('subject', ()):
250 for key, value in sub:
251 # XXX according to RFC 2818, the most specific Common Name
252 # must be used.
253 if key == 'commonName':
Georg Brandl72c98d32013-10-27 07:16:53 +0100254 if _dnsname_match(value, hostname):
Antoine Pitrou59fdd672010-10-08 10:37:08 +0000255 return
256 dnsnames.append(value)
257 if len(dnsnames) > 1:
258 raise CertificateError("hostname %r "
259 "doesn't match either of %s"
260 % (hostname, ', '.join(map(repr, dnsnames))))
261 elif len(dnsnames) == 1:
262 raise CertificateError("hostname %r "
263 "doesn't match %r"
264 % (hostname, dnsnames[0]))
265 else:
266 raise CertificateError("no appropriate commonName or "
267 "subjectAltName fields were found")
268
269
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100270DefaultVerifyPaths = namedtuple("DefaultVerifyPaths",
Christian Heimes6d7ad132013-06-09 18:02:55 +0200271 "cafile capath openssl_cafile_env openssl_cafile openssl_capath_env "
272 "openssl_capath")
273
274def get_default_verify_paths():
275 """Return paths to default cafile and capath.
276 """
277 parts = _ssl.get_default_verify_paths()
278
279 # environment vars shadow paths
280 cafile = os.environ.get(parts[0], parts[1])
281 capath = os.environ.get(parts[2], parts[3])
282
283 return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None,
284 capath if os.path.isdir(capath) else None,
285 *parts)
286
287
Christian Heimesa6bc95a2013-11-17 19:59:14 +0100288class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")):
289 """ASN.1 object identifier lookup
290 """
291 __slots__ = ()
292
293 def __new__(cls, oid):
294 return super().__new__(cls, *_txt2obj(oid, name=False))
295
296 @classmethod
297 def fromnid(cls, nid):
298 """Create _ASN1Object from OpenSSL numeric ID
299 """
300 return super().__new__(cls, *_nid2obj(nid))
301
302 @classmethod
303 def fromname(cls, name):
304 """Create _ASN1Object from short name, long name or OID
305 """
306 return super().__new__(cls, *_txt2obj(name, name=True))
307
308
Christian Heimes72d28502013-11-23 13:56:58 +0100309class Purpose(_ASN1Object, _Enum):
310 """SSLContext purpose flags with X509v3 Extended Key Usage objects
311 """
312 SERVER_AUTH = '1.3.6.1.5.5.7.3.1'
313 CLIENT_AUTH = '1.3.6.1.5.5.7.3.2'
314
315
Antoine Pitrou152efa22010-05-16 18:19:27 +0000316class SSLContext(_SSLContext):
317 """An SSLContext holds various SSL-related configuration options and
318 data, such as certificates and possibly a private key."""
319
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100320 __slots__ = ('protocol', '__weakref__')
Christian Heimes72d28502013-11-23 13:56:58 +0100321 _windows_cert_stores = ("CA", "ROOT")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000322
323 def __new__(cls, protocol, *args, **kwargs):
Antoine Pitrou8f85f902012-01-03 22:46:48 +0100324 self = _SSLContext.__new__(cls, protocol)
325 if protocol != _SSLv2_IF_EXISTS:
326 self.set_ciphers(_DEFAULT_CIPHERS)
327 return self
Antoine Pitrou152efa22010-05-16 18:19:27 +0000328
329 def __init__(self, protocol):
330 self.protocol = protocol
331
332 def wrap_socket(self, sock, server_side=False,
333 do_handshake_on_connect=True,
Antoine Pitroud5323212010-10-22 18:19:07 +0000334 suppress_ragged_eofs=True,
335 server_hostname=None):
Antoine Pitrou152efa22010-05-16 18:19:27 +0000336 return SSLSocket(sock=sock, server_side=server_side,
337 do_handshake_on_connect=do_handshake_on_connect,
338 suppress_ragged_eofs=suppress_ragged_eofs,
Antoine Pitroud5323212010-10-22 18:19:07 +0000339 server_hostname=server_hostname,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000340 _context=self)
341
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100342 def set_npn_protocols(self, npn_protocols):
343 protos = bytearray()
344 for protocol in npn_protocols:
345 b = bytes(protocol, 'ascii')
346 if len(b) == 0 or len(b) > 255:
347 raise SSLError('NPN protocols must be 1 to 255 in length')
348 protos.append(len(b))
349 protos.extend(b)
350
351 self._set_npn_protocols(protos)
352
Christian Heimes72d28502013-11-23 13:56:58 +0100353 def _load_windows_store_certs(self, storename, purpose):
354 certs = bytearray()
355 for cert, encoding, trust in enum_certificates(storename):
356 # CA certs are never PKCS#7 encoded
357 if encoding == "x509_asn":
358 if trust is True or purpose.oid in trust:
359 certs.extend(cert)
360 self.load_verify_locations(cadata=certs)
361 return certs
362
363 def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
364 if not isinstance(purpose, _ASN1Object):
365 raise TypeError(purpose)
366 if sys.platform == "win32":
367 for storename in self._windows_cert_stores:
368 self._load_windows_store_certs(storename, purpose)
369 else:
370 self.set_default_verify_paths()
371
Antoine Pitrou152efa22010-05-16 18:19:27 +0000372
Christian Heimes4c05b472013-11-23 15:58:30 +0100373def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None,
374 capath=None, cadata=None):
375 """Create a SSLContext object with default settings.
376
377 NOTE: The protocol and settings may change anytime without prior
378 deprecation. The values represent a fair balance between maximum
379 compatibility and security.
380 """
381 if not isinstance(purpose, _ASN1Object):
382 raise TypeError(purpose)
383 context = SSLContext(PROTOCOL_TLSv1)
384 # SSLv2 considered harmful.
385 context.options |= OP_NO_SSLv2
Christian Heimesdec813f2013-11-28 08:06:54 +0100386 # disable compression to prevent CRIME attacks (OpenSSL 1.0+)
387 context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0)
Christian Heimes4c05b472013-11-23 15:58:30 +0100388 # disallow ciphers with known vulnerabilities
389 context.set_ciphers(_RESTRICTED_CIPHERS)
390 # verify certs in client mode
391 if purpose == Purpose.SERVER_AUTH:
392 context.verify_mode = CERT_REQUIRED
393 if cafile or capath or cadata:
394 context.load_verify_locations(cafile, capath, cadata)
395 elif context.verify_mode != CERT_NONE:
396 # no explicit cafile, capath or cadata but the verify mode is
397 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
398 # root CA certificates for the given purpose. This may fail silently.
399 context.load_default_certs(purpose)
400 return context
401
402
Christian Heimes67986f92013-11-23 22:43:47 +0100403def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
404 purpose=Purpose.SERVER_AUTH,
405 certfile=None, keyfile=None,
406 cafile=None, capath=None, cadata=None):
407 """Create a SSLContext object for Python stdlib modules
408
409 All Python stdlib modules shall use this function to create SSLContext
410 objects in order to keep common settings in one place. The configuration
411 is less restrict than create_default_context()'s to increase backward
412 compatibility.
413 """
414 if not isinstance(purpose, _ASN1Object):
415 raise TypeError(purpose)
416
417 context = SSLContext(protocol)
418 # SSLv2 considered harmful.
419 context.options |= OP_NO_SSLv2
420
421 if cert_reqs is not None:
422 context.verify_mode = cert_reqs
423
424 if keyfile and not certfile:
425 raise ValueError("certfile must be specified")
426 if certfile or keyfile:
427 context.load_cert_chain(certfile, keyfile)
428
429 # load CA root certs
430 if cafile or capath or cadata:
431 context.load_verify_locations(cafile, capath, cadata)
432 elif context.verify_mode != CERT_NONE:
433 # no explicit cafile, capath or cadata but the verify mode is
434 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
435 # root CA certificates for the given purpose. This may fail silently.
436 context.load_default_certs(purpose)
437
438 return context
439
Antoine Pitrou152efa22010-05-16 18:19:27 +0000440class SSLSocket(socket):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000441 """This class implements a subtype of socket.socket that wraps
442 the underlying OS socket in an SSL context when necessary, and
443 provides read and write methods over that channel."""
444
Bill Janssen6e027db2007-11-15 22:23:56 +0000445 def __init__(self, sock=None, keyfile=None, certfile=None,
Thomas Woutersed03b412007-08-28 21:37:11 +0000446 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000447 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
448 do_handshake_on_connect=True,
449 family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100450 suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
Antoine Pitroud5323212010-10-22 18:19:07 +0000451 server_hostname=None,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000452 _context=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000453
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 if _context:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100455 self._context = _context
Antoine Pitrou152efa22010-05-16 18:19:27 +0000456 else:
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000457 if server_side and not certfile:
458 raise ValueError("certfile must be specified for server-side "
459 "operations")
Giampaolo RodolĂ 8b7da622010-08-30 18:28:05 +0000460 if keyfile and not certfile:
461 raise ValueError("certfile must be specified")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000462 if certfile and not keyfile:
463 keyfile = certfile
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100464 self._context = SSLContext(ssl_version)
465 self._context.verify_mode = cert_reqs
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 if ca_certs:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100467 self._context.load_verify_locations(ca_certs)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000468 if certfile:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100469 self._context.load_cert_chain(certfile, keyfile)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100470 if npn_protocols:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100471 self._context.set_npn_protocols(npn_protocols)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000472 if ciphers:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100473 self._context.set_ciphers(ciphers)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000474 self.keyfile = keyfile
475 self.certfile = certfile
476 self.cert_reqs = cert_reqs
477 self.ssl_version = ssl_version
478 self.ca_certs = ca_certs
479 self.ciphers = ciphers
Antoine Pitroud5323212010-10-22 18:19:07 +0000480 if server_side and server_hostname:
481 raise ValueError("server_hostname can only be specified "
482 "in client mode")
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000483 self.server_side = server_side
Antoine Pitroud5323212010-10-22 18:19:07 +0000484 self.server_hostname = server_hostname
Antoine Pitrou152efa22010-05-16 18:19:27 +0000485 self.do_handshake_on_connect = do_handshake_on_connect
486 self.suppress_ragged_eofs = suppress_ragged_eofs
Bill Janssen6e027db2007-11-15 22:23:56 +0000487 if sock is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000488 socket.__init__(self,
489 family=sock.family,
490 type=sock.type,
491 proto=sock.proto,
Antoine Pitroue43f9d02010-08-08 23:24:50 +0000492 fileno=sock.fileno())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000493 self.settimeout(sock.gettimeout())
Antoine Pitrou6e451df2010-08-09 20:39:54 +0000494 sock.detach()
Bill Janssen6e027db2007-11-15 22:23:56 +0000495 elif fileno is not None:
496 socket.__init__(self, fileno=fileno)
497 else:
498 socket.__init__(self, family=family, type=type, proto=proto)
499
Antoine Pitrou242db722013-05-01 20:52:07 +0200500 # See if we are connected
501 try:
502 self.getpeername()
503 except OSError as e:
504 if e.errno != errno.ENOTCONN:
505 raise
506 connected = False
507 else:
508 connected = True
509
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000510 self._closed = False
511 self._sslobj = None
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000512 self._connected = connected
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000513 if connected:
514 # create the SSL object
Bill Janssen6e027db2007-11-15 22:23:56 +0000515 try:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100516 self._sslobj = self._context._wrap_socket(self, server_side,
Antoine Pitroud5323212010-10-22 18:19:07 +0000517 server_hostname)
Bill Janssen6e027db2007-11-15 22:23:56 +0000518 if do_handshake_on_connect:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000519 timeout = self.gettimeout()
520 if timeout == 0.0:
521 # non-blocking
522 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
Bill Janssen6e027db2007-11-15 22:23:56 +0000523 self.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000524
Andrew Svetlov0832af62012-12-18 23:10:48 +0200525 except OSError as x:
Bill Janssen6e027db2007-11-15 22:23:56 +0000526 self.close()
527 raise x
Antoine Pitrou242db722013-05-01 20:52:07 +0200528
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100529 @property
530 def context(self):
531 return self._context
532
533 @context.setter
534 def context(self, ctx):
535 self._context = ctx
536 self._sslobj.context = ctx
Bill Janssen6e027db2007-11-15 22:23:56 +0000537
Guido van Rossumb7b030e2007-11-16 01:28:45 +0000538 def dup(self):
539 raise NotImplemented("Can't dup() %s instances" %
540 self.__class__.__name__)
541
Bill Janssen6e027db2007-11-15 22:23:56 +0000542 def _checkClosed(self, msg=None):
543 # raise an exception here if you wish to check for spurious closes
544 pass
545
Antoine Pitrou242db722013-05-01 20:52:07 +0200546 def _check_connected(self):
547 if not self._connected:
548 # getpeername() will raise ENOTCONN if the socket is really
549 # not connected; note that we can be connected even without
550 # _connected being set, e.g. if connect() first returned
551 # EAGAIN.
552 self.getpeername()
553
Bill Janssen54cc54c2007-12-14 22:08:56 +0000554 def read(self, len=0, buffer=None):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000555 """Read up to LEN bytes and return them.
556 Return zero-length string on EOF."""
557
Bill Janssen6e027db2007-11-15 22:23:56 +0000558 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200559 if not self._sslobj:
560 raise ValueError("Read on closed or unwrapped SSL socket.")
Bill Janssen6e027db2007-11-15 22:23:56 +0000561 try:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000562 if buffer is not None:
563 v = self._sslobj.read(len, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000564 else:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000565 v = self._sslobj.read(len or 1024)
566 return v
Bill Janssen6e027db2007-11-15 22:23:56 +0000567 except SSLError as x:
568 if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000569 if buffer is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000570 return 0
571 else:
572 return b''
Bill Janssen6e027db2007-11-15 22:23:56 +0000573 else:
574 raise
Thomas Woutersed03b412007-08-28 21:37:11 +0000575
576 def write(self, data):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000577 """Write DATA to the underlying SSL channel. Returns
578 number of bytes of DATA actually transmitted."""
579
Bill Janssen6e027db2007-11-15 22:23:56 +0000580 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200581 if not self._sslobj:
582 raise ValueError("Write on closed or unwrapped SSL socket.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000583 return self._sslobj.write(data)
584
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000585 def getpeercert(self, binary_form=False):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000586 """Returns a formatted version of the data in the
587 certificate provided by the other end of the SSL channel.
588 Return None if no certificate was provided, {} if a
589 certificate was provided, but not validated."""
590
Bill Janssen6e027db2007-11-15 22:23:56 +0000591 self._checkClosed()
Antoine Pitrou242db722013-05-01 20:52:07 +0200592 self._check_connected()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000593 return self._sslobj.peer_certificate(binary_form)
594
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100595 def selected_npn_protocol(self):
596 self._checkClosed()
597 if not self._sslobj or not _ssl.HAS_NPN:
598 return None
599 else:
600 return self._sslobj.selected_npn_protocol()
601
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000602 def cipher(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000603 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000604 if not self._sslobj:
605 return None
606 else:
607 return self._sslobj.cipher()
Thomas Woutersed03b412007-08-28 21:37:11 +0000608
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100609 def compression(self):
610 self._checkClosed()
611 if not self._sslobj:
612 return None
613 else:
614 return self._sslobj.compression()
615
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000616 def send(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000617 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000618 if self._sslobj:
619 if flags != 0:
620 raise ValueError(
621 "non-zero flags not allowed in calls to send() on %s" %
622 self.__class__)
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200623 try:
624 v = self._sslobj.write(data)
625 except SSLError as x:
626 if x.args[0] == SSL_ERROR_WANT_READ:
627 return 0
628 elif x.args[0] == SSL_ERROR_WANT_WRITE:
629 return 0
Bill Janssen6e027db2007-11-15 22:23:56 +0000630 else:
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200631 raise
632 else:
633 return v
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000634 else:
635 return socket.send(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000636
Antoine Pitroua468adc2010-09-14 14:43:44 +0000637 def sendto(self, data, flags_or_addr, addr=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000638 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000639 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000640 raise ValueError("sendto not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000641 self.__class__)
Antoine Pitroua468adc2010-09-14 14:43:44 +0000642 elif addr is None:
643 return socket.sendto(self, data, flags_or_addr)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000644 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000645 return socket.sendto(self, data, flags_or_addr, addr)
Thomas Woutersed03b412007-08-28 21:37:11 +0000646
Nick Coghlan513886a2011-08-28 00:00:27 +1000647 def sendmsg(self, *args, **kwargs):
648 # Ensure programs don't send data unencrypted if they try to
649 # use this method.
650 raise NotImplementedError("sendmsg not allowed on instances of %s" %
651 self.__class__)
652
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000653 def sendall(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000654 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000655 if self._sslobj:
Giampaolo RodolĂ 374f8352010-08-29 12:08:09 +0000656 if flags != 0:
657 raise ValueError(
658 "non-zero flags not allowed in calls to sendall() on %s" %
659 self.__class__)
Bill Janssen6e027db2007-11-15 22:23:56 +0000660 amount = len(data)
661 count = 0
662 while (count < amount):
663 v = self.send(data[count:])
664 count += v
665 return amount
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000666 else:
667 return socket.sendall(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000668
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000669 def recv(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000670 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000671 if self._sslobj:
672 if flags != 0:
673 raise ValueError(
Antoine Pitrou5733c082010-03-22 14:49:10 +0000674 "non-zero flags not allowed in calls to recv() on %s" %
675 self.__class__)
676 return self.read(buflen)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000677 else:
678 return socket.recv(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000679
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000680 def recv_into(self, buffer, nbytes=None, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000681 self._checkClosed()
682 if buffer and (nbytes is None):
683 nbytes = len(buffer)
684 elif nbytes is None:
685 nbytes = 1024
686 if self._sslobj:
687 if flags != 0:
688 raise ValueError(
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000689 "non-zero flags not allowed in calls to recv_into() on %s" %
690 self.__class__)
Antoine Pitrou5733c082010-03-22 14:49:10 +0000691 return self.read(nbytes, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000692 else:
693 return socket.recv_into(self, buffer, nbytes, flags)
694
Antoine Pitroua468adc2010-09-14 14:43:44 +0000695 def recvfrom(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000696 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000697 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000698 raise ValueError("recvfrom not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000699 self.__class__)
700 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000701 return socket.recvfrom(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000702
Bill Janssen58afe4c2008-09-08 16:45:19 +0000703 def recvfrom_into(self, buffer, nbytes=None, flags=0):
704 self._checkClosed()
705 if self._sslobj:
706 raise ValueError("recvfrom_into not allowed on instances of %s" %
707 self.__class__)
708 else:
709 return socket.recvfrom_into(self, buffer, nbytes, flags)
710
Nick Coghlan513886a2011-08-28 00:00:27 +1000711 def recvmsg(self, *args, **kwargs):
712 raise NotImplementedError("recvmsg not allowed on instances of %s" %
713 self.__class__)
714
715 def recvmsg_into(self, *args, **kwargs):
716 raise NotImplementedError("recvmsg_into not allowed on instances of "
717 "%s" % self.__class__)
718
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000719 def pending(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000720 self._checkClosed()
721 if self._sslobj:
722 return self._sslobj.pending()
723 else:
724 return 0
725
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000726 def shutdown(self, how):
Bill Janssen6e027db2007-11-15 22:23:56 +0000727 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000728 self._sslobj = None
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000729 socket.shutdown(self, how)
Thomas Woutersed03b412007-08-28 21:37:11 +0000730
Ezio Melottidc55e672010-01-18 09:15:14 +0000731 def unwrap(self):
Bill Janssen40a0f662008-08-12 16:56:25 +0000732 if self._sslobj:
733 s = self._sslobj.shutdown()
734 self._sslobj = None
735 return s
736 else:
737 raise ValueError("No SSL wrapper around " + str(self))
738
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000739 def _real_close(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000740 self._sslobj = None
Bill Janssen54cc54c2007-12-14 22:08:56 +0000741 socket._real_close(self)
Bill Janssen6e027db2007-11-15 22:23:56 +0000742
Bill Janssen48dc27c2007-12-05 03:38:10 +0000743 def do_handshake(self, block=False):
Bill Janssen6e027db2007-11-15 22:23:56 +0000744 """Perform a TLS/SSL handshake."""
Antoine Pitrou242db722013-05-01 20:52:07 +0200745 self._check_connected()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000746 timeout = self.gettimeout()
Bill Janssen6e027db2007-11-15 22:23:56 +0000747 try:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000748 if timeout == 0.0 and block:
749 self.settimeout(None)
Bill Janssen6e027db2007-11-15 22:23:56 +0000750 self._sslobj.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000751 finally:
752 self.settimeout(timeout)
Thomas Woutersed03b412007-08-28 21:37:11 +0000753
Antoine Pitroub4410db2011-05-18 18:51:06 +0200754 def _real_connect(self, addr, connect_ex):
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000755 if self.server_side:
756 raise ValueError("can't connect in server-side mode")
Thomas Woutersed03b412007-08-28 21:37:11 +0000757 # Here we assume that the socket is client-side, and not
758 # connected at the time of the call. We connect it, then wrap it.
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000759 if self._connected:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000760 raise ValueError("attempt to connect already-connected SSLSocket!")
Antoine Pitroud5323212010-10-22 18:19:07 +0000761 self._sslobj = self.context._wrap_socket(self, False, self.server_hostname)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000762 try:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200763 if connect_ex:
764 rc = socket.connect_ex(self, addr)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000765 else:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200766 rc = None
767 socket.connect(self, addr)
768 if not rc:
Antoine Pitrou242db722013-05-01 20:52:07 +0200769 self._connected = True
Antoine Pitroub4410db2011-05-18 18:51:06 +0200770 if self.do_handshake_on_connect:
771 self.do_handshake()
Antoine Pitroub4410db2011-05-18 18:51:06 +0200772 return rc
Andrew Svetlov0832af62012-12-18 23:10:48 +0200773 except OSError:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200774 self._sslobj = None
775 raise
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000776
777 def connect(self, addr):
778 """Connects to remote ADDR, and then wraps the connection in
779 an SSL channel."""
780 self._real_connect(addr, False)
781
782 def connect_ex(self, addr):
783 """Connects to remote ADDR, and then wraps the connection in
784 an SSL channel."""
785 return self._real_connect(addr, True)
Thomas Woutersed03b412007-08-28 21:37:11 +0000786
787 def accept(self):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000788 """Accepts a new connection from a remote client, and returns
789 a tuple containing that new connection wrapped with a server-side
790 SSL channel, and the address of the remote client."""
791
792 newsock, addr = socket.accept(self)
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +0100793 newsock = self.context.wrap_socket(newsock,
794 do_handshake_on_connect=self.do_handshake_on_connect,
795 suppress_ragged_eofs=self.suppress_ragged_eofs,
796 server_side=True)
797 return newsock, addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000798
Antoine Pitroud6494802011-07-21 01:11:30 +0200799 def get_channel_binding(self, cb_type="tls-unique"):
800 """Get channel binding data for current connection. Raise ValueError
801 if the requested `cb_type` is not supported. Return bytes of the data
802 or None if the data is not available (e.g. before the handshake).
803 """
804 if cb_type not in CHANNEL_BINDING_TYPES:
805 raise ValueError("Unsupported channel binding type")
806 if cb_type != "tls-unique":
807 raise NotImplementedError(
808 "{0} channel binding type not implemented"
809 .format(cb_type))
810 if self._sslobj is None:
811 return None
812 return self._sslobj.tls_unique_cb()
813
Bill Janssen54cc54c2007-12-14 22:08:56 +0000814
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000815def wrap_socket(sock, keyfile=None, certfile=None,
816 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000817 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000818 do_handshake_on_connect=True,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100819 suppress_ragged_eofs=True,
820 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821
Bill Janssen6e027db2007-11-15 22:23:56 +0000822 return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000823 server_side=server_side, cert_reqs=cert_reqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000824 ssl_version=ssl_version, ca_certs=ca_certs,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000825 do_handshake_on_connect=do_handshake_on_connect,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000826 suppress_ragged_eofs=suppress_ragged_eofs,
827 ciphers=ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000828
Thomas Woutersed03b412007-08-28 21:37:11 +0000829# some utility functions
830
831def cert_time_to_seconds(cert_time):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000832 """Takes a date-time string in standard ASN1_print form
833 ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return
834 a Python time value in seconds past the epoch."""
835
Thomas Woutersed03b412007-08-28 21:37:11 +0000836 import time
837 return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT"))
838
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000839PEM_HEADER = "-----BEGIN CERTIFICATE-----"
840PEM_FOOTER = "-----END CERTIFICATE-----"
841
842def DER_cert_to_PEM_cert(der_cert_bytes):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000843 """Takes a certificate in binary DER format and returns the
844 PEM version of it as a string."""
845
Bill Janssen6e027db2007-11-15 22:23:56 +0000846 f = str(base64.standard_b64encode(der_cert_bytes), 'ASCII', 'strict')
847 return (PEM_HEADER + '\n' +
848 textwrap.fill(f, 64) + '\n' +
849 PEM_FOOTER + '\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850
851def PEM_cert_to_DER_cert(pem_cert_string):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000852 """Takes a certificate in ASCII PEM format and returns the
853 DER-encoded version of it as a byte sequence"""
854
855 if not pem_cert_string.startswith(PEM_HEADER):
856 raise ValueError("Invalid PEM encoding; must start with %s"
857 % PEM_HEADER)
858 if not pem_cert_string.strip().endswith(PEM_FOOTER):
859 raise ValueError("Invalid PEM encoding; must end with %s"
860 % PEM_FOOTER)
861 d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)]
Georg Brandl706824f2009-06-04 09:42:55 +0000862 return base64.decodebytes(d.encode('ASCII', 'strict'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000863
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000864def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000865 """Retrieve the certificate from the server at the specified address,
866 and return it as a PEM-encoded string.
867 If 'ca_certs' is specified, validate the server cert against it.
868 If 'ssl_version' is specified, use it in the connection attempt."""
869
870 host, port = addr
Christian Heimes67986f92013-11-23 22:43:47 +0100871 if ca_certs is not None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000872 cert_reqs = CERT_REQUIRED
873 else:
874 cert_reqs = CERT_NONE
Christian Heimes67986f92013-11-23 22:43:47 +0100875 context = _create_stdlib_context(ssl_version,
876 cert_reqs=cert_reqs,
877 cafile=ca_certs)
878 with create_connection(addr) as sock:
879 with context.wrap_socket(sock) as sslsock:
880 dercert = sslsock.getpeercert(True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000881 return DER_cert_to_PEM_cert(dercert)
882
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000883def get_protocol_name(protocol_code):
Victor Stinner3de49192011-05-09 00:42:58 +0200884 return _PROTOCOL_NAMES.get(protocol_code, '<unknown>')