blob: 72e6a6e6d4ca65b40f594435e206b133a17d525c [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
386 # disallow ciphers with known vulnerabilities
387 context.set_ciphers(_RESTRICTED_CIPHERS)
388 # verify certs in client mode
389 if purpose == Purpose.SERVER_AUTH:
390 context.verify_mode = CERT_REQUIRED
391 if cafile or capath or cadata:
392 context.load_verify_locations(cafile, capath, cadata)
393 elif context.verify_mode != CERT_NONE:
394 # no explicit cafile, capath or cadata but the verify mode is
395 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
396 # root CA certificates for the given purpose. This may fail silently.
397 context.load_default_certs(purpose)
398 return context
399
400
Christian Heimes67986f92013-11-23 22:43:47 +0100401def _create_stdlib_context(protocol=PROTOCOL_SSLv23, *, cert_reqs=None,
402 purpose=Purpose.SERVER_AUTH,
403 certfile=None, keyfile=None,
404 cafile=None, capath=None, cadata=None):
405 """Create a SSLContext object for Python stdlib modules
406
407 All Python stdlib modules shall use this function to create SSLContext
408 objects in order to keep common settings in one place. The configuration
409 is less restrict than create_default_context()'s to increase backward
410 compatibility.
411 """
412 if not isinstance(purpose, _ASN1Object):
413 raise TypeError(purpose)
414
415 context = SSLContext(protocol)
416 # SSLv2 considered harmful.
417 context.options |= OP_NO_SSLv2
418
419 if cert_reqs is not None:
420 context.verify_mode = cert_reqs
421
422 if keyfile and not certfile:
423 raise ValueError("certfile must be specified")
424 if certfile or keyfile:
425 context.load_cert_chain(certfile, keyfile)
426
427 # load CA root certs
428 if cafile or capath or cadata:
429 context.load_verify_locations(cafile, capath, cadata)
430 elif context.verify_mode != CERT_NONE:
431 # no explicit cafile, capath or cadata but the verify mode is
432 # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system
433 # root CA certificates for the given purpose. This may fail silently.
434 context.load_default_certs(purpose)
435
436 return context
437
Antoine Pitrou152efa22010-05-16 18:19:27 +0000438class SSLSocket(socket):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000439 """This class implements a subtype of socket.socket that wraps
440 the underlying OS socket in an SSL context when necessary, and
441 provides read and write methods over that channel."""
442
Bill Janssen6e027db2007-11-15 22:23:56 +0000443 def __init__(self, sock=None, keyfile=None, certfile=None,
Thomas Woutersed03b412007-08-28 21:37:11 +0000444 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000445 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
446 do_handshake_on_connect=True,
447 family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100448 suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
Antoine Pitroud5323212010-10-22 18:19:07 +0000449 server_hostname=None,
Antoine Pitrou152efa22010-05-16 18:19:27 +0000450 _context=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000451
Antoine Pitrou152efa22010-05-16 18:19:27 +0000452 if _context:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100453 self._context = _context
Antoine Pitrou152efa22010-05-16 18:19:27 +0000454 else:
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000455 if server_side and not certfile:
456 raise ValueError("certfile must be specified for server-side "
457 "operations")
Giampaolo RodolĂ 8b7da622010-08-30 18:28:05 +0000458 if keyfile and not certfile:
459 raise ValueError("certfile must be specified")
Antoine Pitrou152efa22010-05-16 18:19:27 +0000460 if certfile and not keyfile:
461 keyfile = certfile
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100462 self._context = SSLContext(ssl_version)
463 self._context.verify_mode = cert_reqs
Antoine Pitrou152efa22010-05-16 18:19:27 +0000464 if ca_certs:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100465 self._context.load_verify_locations(ca_certs)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000466 if certfile:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100467 self._context.load_cert_chain(certfile, keyfile)
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100468 if npn_protocols:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100469 self._context.set_npn_protocols(npn_protocols)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000470 if ciphers:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100471 self._context.set_ciphers(ciphers)
Antoine Pitrou152efa22010-05-16 18:19:27 +0000472 self.keyfile = keyfile
473 self.certfile = certfile
474 self.cert_reqs = cert_reqs
475 self.ssl_version = ssl_version
476 self.ca_certs = ca_certs
477 self.ciphers = ciphers
Antoine Pitroud5323212010-10-22 18:19:07 +0000478 if server_side and server_hostname:
479 raise ValueError("server_hostname can only be specified "
480 "in client mode")
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000481 self.server_side = server_side
Antoine Pitroud5323212010-10-22 18:19:07 +0000482 self.server_hostname = server_hostname
Antoine Pitrou152efa22010-05-16 18:19:27 +0000483 self.do_handshake_on_connect = do_handshake_on_connect
484 self.suppress_ragged_eofs = suppress_ragged_eofs
Bill Janssen6e027db2007-11-15 22:23:56 +0000485 if sock is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000486 socket.__init__(self,
487 family=sock.family,
488 type=sock.type,
489 proto=sock.proto,
Antoine Pitroue43f9d02010-08-08 23:24:50 +0000490 fileno=sock.fileno())
Antoine Pitrou40f08742010-04-24 22:04:40 +0000491 self.settimeout(sock.gettimeout())
Antoine Pitrou6e451df2010-08-09 20:39:54 +0000492 sock.detach()
Bill Janssen6e027db2007-11-15 22:23:56 +0000493 elif fileno is not None:
494 socket.__init__(self, fileno=fileno)
495 else:
496 socket.__init__(self, family=family, type=type, proto=proto)
497
Antoine Pitrou242db722013-05-01 20:52:07 +0200498 # See if we are connected
499 try:
500 self.getpeername()
501 except OSError as e:
502 if e.errno != errno.ENOTCONN:
503 raise
504 connected = False
505 else:
506 connected = True
507
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000508 self._closed = False
509 self._sslobj = None
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000510 self._connected = connected
Antoine Pitroufa2b9382010-04-26 22:17:47 +0000511 if connected:
512 # create the SSL object
Bill Janssen6e027db2007-11-15 22:23:56 +0000513 try:
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100514 self._sslobj = self._context._wrap_socket(self, server_side,
Antoine Pitroud5323212010-10-22 18:19:07 +0000515 server_hostname)
Bill Janssen6e027db2007-11-15 22:23:56 +0000516 if do_handshake_on_connect:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000517 timeout = self.gettimeout()
518 if timeout == 0.0:
519 # non-blocking
520 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
Bill Janssen6e027db2007-11-15 22:23:56 +0000521 self.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000522
Andrew Svetlov0832af62012-12-18 23:10:48 +0200523 except OSError as x:
Bill Janssen6e027db2007-11-15 22:23:56 +0000524 self.close()
525 raise x
Antoine Pitrou242db722013-05-01 20:52:07 +0200526
Antoine Pitrou58ddc9d2013-01-05 21:20:29 +0100527 @property
528 def context(self):
529 return self._context
530
531 @context.setter
532 def context(self, ctx):
533 self._context = ctx
534 self._sslobj.context = ctx
Bill Janssen6e027db2007-11-15 22:23:56 +0000535
Guido van Rossumb7b030e2007-11-16 01:28:45 +0000536 def dup(self):
537 raise NotImplemented("Can't dup() %s instances" %
538 self.__class__.__name__)
539
Bill Janssen6e027db2007-11-15 22:23:56 +0000540 def _checkClosed(self, msg=None):
541 # raise an exception here if you wish to check for spurious closes
542 pass
543
Antoine Pitrou242db722013-05-01 20:52:07 +0200544 def _check_connected(self):
545 if not self._connected:
546 # getpeername() will raise ENOTCONN if the socket is really
547 # not connected; note that we can be connected even without
548 # _connected being set, e.g. if connect() first returned
549 # EAGAIN.
550 self.getpeername()
551
Bill Janssen54cc54c2007-12-14 22:08:56 +0000552 def read(self, len=0, buffer=None):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000553 """Read up to LEN bytes and return them.
554 Return zero-length string on EOF."""
555
Bill Janssen6e027db2007-11-15 22:23:56 +0000556 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200557 if not self._sslobj:
558 raise ValueError("Read on closed or unwrapped SSL socket.")
Bill Janssen6e027db2007-11-15 22:23:56 +0000559 try:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000560 if buffer is not None:
561 v = self._sslobj.read(len, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000562 else:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000563 v = self._sslobj.read(len or 1024)
564 return v
Bill Janssen6e027db2007-11-15 22:23:56 +0000565 except SSLError as x:
566 if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
Antoine Pitrou24e561a2010-09-03 18:38:17 +0000567 if buffer is not None:
Bill Janssen54cc54c2007-12-14 22:08:56 +0000568 return 0
569 else:
570 return b''
Bill Janssen6e027db2007-11-15 22:23:56 +0000571 else:
572 raise
Thomas Woutersed03b412007-08-28 21:37:11 +0000573
574 def write(self, data):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000575 """Write DATA to the underlying SSL channel. Returns
576 number of bytes of DATA actually transmitted."""
577
Bill Janssen6e027db2007-11-15 22:23:56 +0000578 self._checkClosed()
Antoine Pitrou60a26e02013-07-20 19:35:16 +0200579 if not self._sslobj:
580 raise ValueError("Write on closed or unwrapped SSL socket.")
Thomas Woutersed03b412007-08-28 21:37:11 +0000581 return self._sslobj.write(data)
582
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000583 def getpeercert(self, binary_form=False):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000584 """Returns a formatted version of the data in the
585 certificate provided by the other end of the SSL channel.
586 Return None if no certificate was provided, {} if a
587 certificate was provided, but not validated."""
588
Bill Janssen6e027db2007-11-15 22:23:56 +0000589 self._checkClosed()
Antoine Pitrou242db722013-05-01 20:52:07 +0200590 self._check_connected()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000591 return self._sslobj.peer_certificate(binary_form)
592
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100593 def selected_npn_protocol(self):
594 self._checkClosed()
595 if not self._sslobj or not _ssl.HAS_NPN:
596 return None
597 else:
598 return self._sslobj.selected_npn_protocol()
599
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000600 def cipher(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000601 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000602 if not self._sslobj:
603 return None
604 else:
605 return self._sslobj.cipher()
Thomas Woutersed03b412007-08-28 21:37:11 +0000606
Antoine Pitrou8abdb8a2011-12-20 10:13:40 +0100607 def compression(self):
608 self._checkClosed()
609 if not self._sslobj:
610 return None
611 else:
612 return self._sslobj.compression()
613
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000614 def send(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000615 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000616 if self._sslobj:
617 if flags != 0:
618 raise ValueError(
619 "non-zero flags not allowed in calls to send() on %s" %
620 self.__class__)
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200621 try:
622 v = self._sslobj.write(data)
623 except SSLError as x:
624 if x.args[0] == SSL_ERROR_WANT_READ:
625 return 0
626 elif x.args[0] == SSL_ERROR_WANT_WRITE:
627 return 0
Bill Janssen6e027db2007-11-15 22:23:56 +0000628 else:
Giampaolo Rodola'06d0c1e2013-04-03 12:01:44 +0200629 raise
630 else:
631 return v
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000632 else:
633 return socket.send(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000634
Antoine Pitroua468adc2010-09-14 14:43:44 +0000635 def sendto(self, data, flags_or_addr, addr=None):
Bill Janssen6e027db2007-11-15 22:23:56 +0000636 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000637 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000638 raise ValueError("sendto not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000639 self.__class__)
Antoine Pitroua468adc2010-09-14 14:43:44 +0000640 elif addr is None:
641 return socket.sendto(self, data, flags_or_addr)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000642 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000643 return socket.sendto(self, data, flags_or_addr, addr)
Thomas Woutersed03b412007-08-28 21:37:11 +0000644
Nick Coghlan513886a2011-08-28 00:00:27 +1000645 def sendmsg(self, *args, **kwargs):
646 # Ensure programs don't send data unencrypted if they try to
647 # use this method.
648 raise NotImplementedError("sendmsg not allowed on instances of %s" %
649 self.__class__)
650
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000651 def sendall(self, data, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000652 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000653 if self._sslobj:
Giampaolo RodolĂ 374f8352010-08-29 12:08:09 +0000654 if flags != 0:
655 raise ValueError(
656 "non-zero flags not allowed in calls to sendall() on %s" %
657 self.__class__)
Bill Janssen6e027db2007-11-15 22:23:56 +0000658 amount = len(data)
659 count = 0
660 while (count < amount):
661 v = self.send(data[count:])
662 count += v
663 return amount
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000664 else:
665 return socket.sendall(self, data, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000666
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000667 def recv(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000668 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000669 if self._sslobj:
670 if flags != 0:
671 raise ValueError(
Antoine Pitrou5733c082010-03-22 14:49:10 +0000672 "non-zero flags not allowed in calls to recv() on %s" %
673 self.__class__)
674 return self.read(buflen)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000675 else:
676 return socket.recv(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000677
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000678 def recv_into(self, buffer, nbytes=None, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000679 self._checkClosed()
680 if buffer and (nbytes is None):
681 nbytes = len(buffer)
682 elif nbytes is None:
683 nbytes = 1024
684 if self._sslobj:
685 if flags != 0:
686 raise ValueError(
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000687 "non-zero flags not allowed in calls to recv_into() on %s" %
688 self.__class__)
Antoine Pitrou5733c082010-03-22 14:49:10 +0000689 return self.read(nbytes, buffer)
Bill Janssen6e027db2007-11-15 22:23:56 +0000690 else:
691 return socket.recv_into(self, buffer, nbytes, flags)
692
Antoine Pitroua468adc2010-09-14 14:43:44 +0000693 def recvfrom(self, buflen=1024, flags=0):
Bill Janssen6e027db2007-11-15 22:23:56 +0000694 self._checkClosed()
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000695 if self._sslobj:
Bill Janssen980f3142008-06-29 00:05:51 +0000696 raise ValueError("recvfrom not allowed on instances of %s" %
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000697 self.__class__)
698 else:
Antoine Pitroua468adc2010-09-14 14:43:44 +0000699 return socket.recvfrom(self, buflen, flags)
Thomas Woutersed03b412007-08-28 21:37:11 +0000700
Bill Janssen58afe4c2008-09-08 16:45:19 +0000701 def recvfrom_into(self, buffer, nbytes=None, flags=0):
702 self._checkClosed()
703 if self._sslobj:
704 raise ValueError("recvfrom_into not allowed on instances of %s" %
705 self.__class__)
706 else:
707 return socket.recvfrom_into(self, buffer, nbytes, flags)
708
Nick Coghlan513886a2011-08-28 00:00:27 +1000709 def recvmsg(self, *args, **kwargs):
710 raise NotImplementedError("recvmsg not allowed on instances of %s" %
711 self.__class__)
712
713 def recvmsg_into(self, *args, **kwargs):
714 raise NotImplementedError("recvmsg_into not allowed on instances of "
715 "%s" % self.__class__)
716
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000717 def pending(self):
Bill Janssen6e027db2007-11-15 22:23:56 +0000718 self._checkClosed()
719 if self._sslobj:
720 return self._sslobj.pending()
721 else:
722 return 0
723
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000724 def shutdown(self, how):
Bill Janssen6e027db2007-11-15 22:23:56 +0000725 self._checkClosed()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000726 self._sslobj = None
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000727 socket.shutdown(self, how)
Thomas Woutersed03b412007-08-28 21:37:11 +0000728
Ezio Melottidc55e672010-01-18 09:15:14 +0000729 def unwrap(self):
Bill Janssen40a0f662008-08-12 16:56:25 +0000730 if self._sslobj:
731 s = self._sslobj.shutdown()
732 self._sslobj = None
733 return s
734 else:
735 raise ValueError("No SSL wrapper around " + str(self))
736
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000737 def _real_close(self):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000738 self._sslobj = None
Bill Janssen54cc54c2007-12-14 22:08:56 +0000739 socket._real_close(self)
Bill Janssen6e027db2007-11-15 22:23:56 +0000740
Bill Janssen48dc27c2007-12-05 03:38:10 +0000741 def do_handshake(self, block=False):
Bill Janssen6e027db2007-11-15 22:23:56 +0000742 """Perform a TLS/SSL handshake."""
Antoine Pitrou242db722013-05-01 20:52:07 +0200743 self._check_connected()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000744 timeout = self.gettimeout()
Bill Janssen6e027db2007-11-15 22:23:56 +0000745 try:
Bill Janssen48dc27c2007-12-05 03:38:10 +0000746 if timeout == 0.0 and block:
747 self.settimeout(None)
Bill Janssen6e027db2007-11-15 22:23:56 +0000748 self._sslobj.do_handshake()
Bill Janssen48dc27c2007-12-05 03:38:10 +0000749 finally:
750 self.settimeout(timeout)
Thomas Woutersed03b412007-08-28 21:37:11 +0000751
Antoine Pitroub4410db2011-05-18 18:51:06 +0200752 def _real_connect(self, addr, connect_ex):
Giampaolo RodolĂ 745ab382010-08-29 19:25:49 +0000753 if self.server_side:
754 raise ValueError("can't connect in server-side mode")
Thomas Woutersed03b412007-08-28 21:37:11 +0000755 # Here we assume that the socket is client-side, and not
756 # connected at the time of the call. We connect it, then wrap it.
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000757 if self._connected:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000758 raise ValueError("attempt to connect already-connected SSLSocket!")
Antoine Pitroud5323212010-10-22 18:19:07 +0000759 self._sslobj = self.context._wrap_socket(self, False, self.server_hostname)
Bill Janssen54cc54c2007-12-14 22:08:56 +0000760 try:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200761 if connect_ex:
762 rc = socket.connect_ex(self, addr)
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000763 else:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200764 rc = None
765 socket.connect(self, addr)
766 if not rc:
Antoine Pitrou242db722013-05-01 20:52:07 +0200767 self._connected = True
Antoine Pitroub4410db2011-05-18 18:51:06 +0200768 if self.do_handshake_on_connect:
769 self.do_handshake()
Antoine Pitroub4410db2011-05-18 18:51:06 +0200770 return rc
Andrew Svetlov0832af62012-12-18 23:10:48 +0200771 except OSError:
Antoine Pitroub4410db2011-05-18 18:51:06 +0200772 self._sslobj = None
773 raise
Antoine Pitroue93bf7a2011-02-26 23:24:06 +0000774
775 def connect(self, addr):
776 """Connects to remote ADDR, and then wraps the connection in
777 an SSL channel."""
778 self._real_connect(addr, False)
779
780 def connect_ex(self, addr):
781 """Connects to remote ADDR, and then wraps the connection in
782 an SSL channel."""
783 return self._real_connect(addr, True)
Thomas Woutersed03b412007-08-28 21:37:11 +0000784
785 def accept(self):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000786 """Accepts a new connection from a remote client, and returns
787 a tuple containing that new connection wrapped with a server-side
788 SSL channel, and the address of the remote client."""
789
790 newsock, addr = socket.accept(self)
Antoine Pitrou5c89b4e2012-11-11 01:25:36 +0100791 newsock = self.context.wrap_socket(newsock,
792 do_handshake_on_connect=self.do_handshake_on_connect,
793 suppress_ragged_eofs=self.suppress_ragged_eofs,
794 server_side=True)
795 return newsock, addr
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000796
Antoine Pitroud6494802011-07-21 01:11:30 +0200797 def get_channel_binding(self, cb_type="tls-unique"):
798 """Get channel binding data for current connection. Raise ValueError
799 if the requested `cb_type` is not supported. Return bytes of the data
800 or None if the data is not available (e.g. before the handshake).
801 """
802 if cb_type not in CHANNEL_BINDING_TYPES:
803 raise ValueError("Unsupported channel binding type")
804 if cb_type != "tls-unique":
805 raise NotImplementedError(
806 "{0} channel binding type not implemented"
807 .format(cb_type))
808 if self._sslobj is None:
809 return None
810 return self._sslobj.tls_unique_cb()
811
Bill Janssen54cc54c2007-12-14 22:08:56 +0000812
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000813def wrap_socket(sock, keyfile=None, certfile=None,
814 server_side=False, cert_reqs=CERT_NONE,
Bill Janssen6e027db2007-11-15 22:23:56 +0000815 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000816 do_handshake_on_connect=True,
Antoine Pitroud5d17eb2012-03-22 00:23:03 +0100817 suppress_ragged_eofs=True,
818 ciphers=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000819
Bill Janssen6e027db2007-11-15 22:23:56 +0000820 return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000821 server_side=server_side, cert_reqs=cert_reqs,
Bill Janssen6e027db2007-11-15 22:23:56 +0000822 ssl_version=ssl_version, ca_certs=ca_certs,
Bill Janssen48dc27c2007-12-05 03:38:10 +0000823 do_handshake_on_connect=do_handshake_on_connect,
Antoine Pitrou2d9cb9c2010-04-17 17:40:45 +0000824 suppress_ragged_eofs=suppress_ragged_eofs,
825 ciphers=ciphers)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000826
Thomas Woutersed03b412007-08-28 21:37:11 +0000827# some utility functions
828
829def cert_time_to_seconds(cert_time):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000830 """Takes a date-time string in standard ASN1_print form
831 ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return
832 a Python time value in seconds past the epoch."""
833
Thomas Woutersed03b412007-08-28 21:37:11 +0000834 import time
835 return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT"))
836
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000837PEM_HEADER = "-----BEGIN CERTIFICATE-----"
838PEM_FOOTER = "-----END CERTIFICATE-----"
839
840def DER_cert_to_PEM_cert(der_cert_bytes):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000841 """Takes a certificate in binary DER format and returns the
842 PEM version of it as a string."""
843
Bill Janssen6e027db2007-11-15 22:23:56 +0000844 f = str(base64.standard_b64encode(der_cert_bytes), 'ASCII', 'strict')
845 return (PEM_HEADER + '\n' +
846 textwrap.fill(f, 64) + '\n' +
847 PEM_FOOTER + '\n')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000848
849def PEM_cert_to_DER_cert(pem_cert_string):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000850 """Takes a certificate in ASCII PEM format and returns the
851 DER-encoded version of it as a byte sequence"""
852
853 if not pem_cert_string.startswith(PEM_HEADER):
854 raise ValueError("Invalid PEM encoding; must start with %s"
855 % PEM_HEADER)
856 if not pem_cert_string.strip().endswith(PEM_FOOTER):
857 raise ValueError("Invalid PEM encoding; must end with %s"
858 % PEM_FOOTER)
859 d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)]
Georg Brandl706824f2009-06-04 09:42:55 +0000860 return base64.decodebytes(d.encode('ASCII', 'strict'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000861
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000862def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000863 """Retrieve the certificate from the server at the specified address,
864 and return it as a PEM-encoded string.
865 If 'ca_certs' is specified, validate the server cert against it.
866 If 'ssl_version' is specified, use it in the connection attempt."""
867
868 host, port = addr
Christian Heimes67986f92013-11-23 22:43:47 +0100869 if ca_certs is not None:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000870 cert_reqs = CERT_REQUIRED
871 else:
872 cert_reqs = CERT_NONE
Christian Heimes67986f92013-11-23 22:43:47 +0100873 context = _create_stdlib_context(ssl_version,
874 cert_reqs=cert_reqs,
875 cafile=ca_certs)
876 with create_connection(addr) as sock:
877 with context.wrap_socket(sock) as sslsock:
878 dercert = sslsock.getpeercert(True)
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000879 return DER_cert_to_PEM_cert(dercert)
880
Guido van Rossum5b8b1552007-11-16 00:06:11 +0000881def get_protocol_name(protocol_code):
Victor Stinner3de49192011-05-09 00:42:58 +0200882 return _PROTOCOL_NAMES.get(protocol_code, '<unknown>')