diff --git a/00055-systemtap.patch b/00055-systemtap.patch index 67ec005..63bc3f8 100644 --- a/00055-systemtap.patch +++ b/00055-systemtap.patch @@ -88,8 +88,8 @@ diff -up Python-2.7rc1/Makefile.pre.in.systemtap Python-2.7rc1/Makefile.pre.in .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean --.PHONY: smelly funny patchcheck touch altmaninstall -+.PHONY: smelly funny patchcheck touch altmaninstall buildinclude +-.PHONY: smelly funny patchcheck touch altmaninstall commoninstall ++.PHONY: smelly funny patchcheck touch altmaninstall commoninstall buildinclude .PHONY: gdbhooks # IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch b/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch index 8653772..7122a29 100644 --- a/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch +++ b/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch @@ -7,6 +7,6 @@ diff -up Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py.mark-tests-that-fail +@unittest._skipInRpmBuild("don't try to nest one rpm build inside another rpm build") class BuildRpmTestCase(support.TempdirManager, + support.EnvironGuard, support.LoggingSilencer, - unittest.TestCase): diff -up Python-2.7.3/Lib/distutils/tests/test_build_ext.py.mark-tests-that-fail-in-rpmbuild Python-2.7.3/Lib/distutils/tests/test_build_ext.py diff --git a/00146-hashlib-fips.patch b/00146-hashlib-fips.patch index 696aa29..badb629 100644 --- a/00146-hashlib-fips.patch +++ b/00146-hashlib-fips.patch @@ -38,8 +38,8 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py Hash objects have these methods: - update(arg): Update the hash object with the string arg. Repeated calls are equivalent to a single call with the concatenation of all -@@ -63,74 +80,39 @@ algorithms = __always_supported - __all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac') +@@ -63,76 +80,41 @@ algorithms = __always_supported + 'pbkdf2_hmac') -def __get_builtin_constructor(name): @@ -118,6 +118,8 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py import _hashlib new = __hash_new __get_hash = __get_openssl_constructor + algorithms_available = algorithms_available.union( + _hashlib.openssl_md_meth_names) except ImportError: - new = __py_new - __get_hash = __get_builtin_constructor @@ -570,7 +572,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py return ret_obj; @@ -713,51 +785,111 @@ - #endif + /* - * This macro generates constructor function definitions for specific @@ -711,13 +713,14 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py GEN_CONSTRUCTOR(md5) GEN_CONSTRUCTOR(sha1) #ifdef _OPENSSL_SUPPORTS_SHA2 -@@ -794,13 +926,10 @@ +@@ -794,14 +926,11 @@ { - PyObject *m; + PyObject *m, *openssl_md_meth_names; + SSL_load_error_strings(); + SSL_library_init(); OpenSSL_add_all_digests(); + ERR_load_crypto_strings(); - /* TODO build EVP_functions openssl_* entries dynamically based - * on what hashes are supported rather than listing many diff --git a/00153-fix-test_gdb-noise.patch b/00153-fix-test_gdb-noise.patch index 50a0917..8b0a76c 100644 --- a/00153-fix-test_gdb-noise.patch +++ b/00153-fix-test_gdb-noise.patch @@ -19,8 +19,8 @@ --- Lib/test/test_gdb.py.old 2012-04-11 21:04:01.367073855 -0400 +++ Lib/test/test_gdb.py 2012-04-12 08:52:58.320288761 -0400 @@ -144,6 +153,10 @@ - 'Do you need "set solib-search-path" or ' - '"set sysroot"?', + 'Missing separate debuginfo for ', + 'Try: zypper install -C ', ) + ignore_patterns += ('warning: Unable to open', + 'Missing separate debuginfo for', diff --git a/00156-gdb-autoload-safepath.patch b/00156-gdb-autoload-safepath.patch index 54a5a6e..7193ad1 100644 --- a/00156-gdb-autoload-safepath.patch +++ b/00156-gdb-autoload-safepath.patch @@ -45,7 +45,7 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.gdb-autoload-safepath Python-2.7.3/Li # print commands # Use "commands" to generate the arguments with which to invoke "gdb": - args = ["gdb", "--batch"] + args = ["gdb", "--batch", "-nx"] + args += ['--init-eval-command=%s' % cmd for cmd in init_commands] args += ['--eval-command=%s' % cmd for cmd in commands] args += ["--args", diff --git a/00196-ssl-backport.patch b/00196-ssl-backport.patch deleted file mode 100644 index 79cd81d..0000000 --- a/00196-ssl-backport.patch +++ /dev/null @@ -1,12963 +0,0 @@ -diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst -index c115976..84dd332 100644 ---- a/Doc/library/ssl.rst -+++ b/Doc/library/ssl.rst -@@ -28,19 +28,14 @@ probably additional platforms, as long as OpenSSL is installed on that platform. - - Some behavior may be platform dependent, since calls are made to the - operating system socket APIs. The installed version of OpenSSL may also -- cause variations in behavior. -+ cause variations in behavior. For example, TLSv1.1 and TLSv1.2 come with -+ openssl version 1.0.1. - - .. warning:: -- The ssl module won't validate certificates by default. When used in -- client mode, this means you are vulnerable to man-in-the-middle attacks. -+ Don't use this module without reading the :ref:`ssl-security`. Doing so -+ may lead to a false sense of security, as the default settings of the -+ ssl module are not necessarily appropriate for your application. - --.. warning:: -- -- OpenSSL's internal random number generator does not properly handle fork. -- Applications must change the PRNG state of the parent process if they use -- any SSL feature with :func:`os.fork`. Any successful call of -- :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or -- :func:`~ssl.RAND_pseudo_bytes` is sufficient. - - This section documents the objects and functions in the ``ssl`` module; for more - general information about TLS, SSL, and certificates, the reader is referred to -@@ -49,23 +44,101 @@ the documents in the "See Also" section at the bottom. - This module provides a class, :class:`ssl.SSLSocket`, which is derived from the - :class:`socket.socket` type, and provides a socket-like wrapper that also - encrypts and decrypts the data going over the socket with SSL. It supports --additional :meth:`read` and :meth:`write` methods, along with a method, --:meth:`getpeercert`, to retrieve the certificate of the other side of the --connection, and a method, :meth:`cipher`, to retrieve the cipher being used for --the secure connection. -+additional methods such as :meth:`getpeercert`, which retrieves the -+certificate of the other side of the connection, and :meth:`cipher`,which -+retrieves the cipher being used for the secure connection. -+ -+For more sophisticated applications, the :class:`ssl.SSLContext` class -+helps manage settings and certificates, which can then be inherited -+by SSL sockets created through the :meth:`SSLContext.wrap_socket` method. -+ - - Functions, Constants, and Exceptions - ------------------------------------ - - .. exception:: SSLError - -- Raised to signal an error from the underlying SSL implementation. This -- signifies some problem in the higher-level encryption and authentication -- layer that's superimposed on the underlying network connection. This error -- is a subtype of :exc:`socket.error`, which in turn is a subtype of -- :exc:`IOError`. -+ Raised to signal an error from the underlying SSL implementation (currently -+ provided by the OpenSSL library). This signifies some problem in the -+ higher-level encryption and authentication layer that's superimposed on the -+ underlying network connection. This error is a subtype of -+ :exc:`socket.error`, which in turn is a subtype of :exc:`IOError`. The -+ error code and message of :exc:`SSLError` instances are provided by the -+ OpenSSL library. -+ -+ .. attribute:: library -+ -+ A string mnemonic designating the OpenSSL submodule in which the error -+ occurred, such as ``SSL``, ``PEM`` or ``X509``. The range of possible -+ values depends on the OpenSSL version. -+ -+ .. versionadded:: 2.7.9 -+ -+ .. attribute:: reason -+ -+ A string mnemonic designating the reason this error occurred, for -+ example ``CERTIFICATE_VERIFY_FAILED``. The range of possible -+ values depends on the OpenSSL version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLZeroReturnError -+ -+ A subclass of :exc:`SSLError` raised when trying to read or write and -+ the SSL connection has been closed cleanly. Note that this doesn't -+ mean that the underlying transport (read TCP) has been closed. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLWantReadError -+ -+ A subclass of :exc:`SSLError` raised by a :ref:`non-blocking SSL socket -+ ` when trying to read or write data, but more data needs -+ to be received on the underlying TCP transport before the request can be -+ fulfilled. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLWantWriteError -+ -+ A subclass of :exc:`SSLError` raised by a :ref:`non-blocking SSL socket -+ ` when trying to read or write data, but more data needs -+ to be sent on the underlying TCP transport before the request can be -+ fulfilled. - --.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLSyscallError -+ -+ A subclass of :exc:`SSLError` raised when a system error was encountered -+ while trying to fulfill an operation on a SSL socket. Unfortunately, -+ there is no easy way to inspect the original errno number. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLEOFError -+ -+ A subclass of :exc:`SSLError` raised when the SSL connection has been -+ terminated abruptly. Generally, you shouldn't try to reuse the underlying -+ transport when this error is encountered. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: CertificateError -+ -+ Raised to signal an error with a certificate (such as mismatching -+ hostname). Certificate errors detected by OpenSSL, though, raise -+ an :exc:`SSLError`. -+ -+ -+Socket creation -+^^^^^^^^^^^^^^^ -+ -+The following function allows for standalone socket creation. Starting from -+Python 2.7.9, it can be more flexible to use :meth:`SSLContext.wrap_socket` -+instead. -+ -+.. function:: wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) - - Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance - of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps -@@ -85,19 +158,6 @@ Functions, Constants, and Exceptions - connection. See the discussion of :ref:`ssl-certificates` for more - information on how the certificate is stored in the ``certfile``. - -- Often the private key is stored in the same file as the certificate; in this -- case, only the ``certfile`` parameter need be passed. If the private key is -- stored in a separate file, both parameters must be used. If the private key -- is stored in the ``certfile``, it should come before the first certificate in -- the certificate chain:: -- -- -----BEGIN RSA PRIVATE KEY----- -- ... (private key in base64 encoding) ... -- -----END RSA PRIVATE KEY----- -- -----BEGIN CERTIFICATE----- -- ... (certificate in base64 PEM encoding) ... -- -----END CERTIFICATE----- -- - The parameter ``server_side`` is a boolean which identifies whether - server-side or client-side behavior is desired from this socket. - -@@ -127,14 +187,16 @@ Functions, Constants, and Exceptions - - .. table:: - -- ======================== ========= ========= ========== ========= -- *client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** -- ------------------------ --------- --------- ---------- --------- -- *SSLv2* yes no yes no -- *SSLv3* no yes yes no -- *SSLv23* yes no yes no -- *TLSv1* no no yes yes -- ======================== ========= ========= ========== ========= -+ ======================== ========= ========= ========== ========= =========== =========== -+ *client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** **TLSv1.1** **TLSv1.2** -+ ------------------------ --------- --------- ---------- --------- ----------- ----------- -+ *SSLv2* yes no yes no no no -+ *SSLv3* no yes yes no no no -+ *SSLv23* yes no yes no no no -+ *TLSv1* no no yes yes no no -+ *TLSv1.1* no no yes no yes no -+ *TLSv1.2* no no yes no no yes -+ ======================== ========= ========= ========== ========= =========== =========== - - .. note:: - -@@ -161,22 +223,79 @@ Functions, Constants, and Exceptions - The parameter ``suppress_ragged_eofs`` specifies how the - :meth:`SSLSocket.read` method should signal unexpected EOF from the other end - of the connection. If specified as :const:`True` (the default), it returns a -- normal EOF in response to unexpected EOF errors raised from the underlying -- socket; if :const:`False`, it will raise the exceptions back to the caller. -+ normal EOF (an empty bytes object) in response to unexpected EOF errors -+ raised from the underlying socket; if :const:`False`, it will raise the -+ exceptions back to the caller. - - .. versionchanged:: 2.7 - New optional argument *ciphers*. - -+ -+Context creation -+^^^^^^^^^^^^^^^^ -+ -+A convenience function helps create :class:`SSLContext` objects for common -+purposes. -+ -+.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) -+ -+ Return a new :class:`SSLContext` object with default settings for -+ the given *purpose*. The settings are chosen by the :mod:`ssl` module, -+ and usually represent a higher security level than when calling the -+ :class:`SSLContext` constructor directly. -+ -+ *cafile*, *capath*, *cadata* represent optional CA certificates to -+ trust for certificate verification, as in -+ :meth:`SSLContext.load_verify_locations`. If all three are -+ :const:`None`, this function can choose to trust the system's default -+ CA certificates instead. -+ -+ The settings in Python 2.7.9 are: :data:`PROTOCOL_SSLv23`, -+ :data:`OP_NO_SSLv2`, and :data:`OP_NO_SSLv3` with high encryption cipher -+ suites without RC4 and without unauthenticated cipher suites. Passing -+ :data:`~Purpose.SERVER_AUTH` as *purpose* sets -+ :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` and either loads CA -+ certificates (when at least one of *cafile*, *capath* or *cadata* is given) -+ or uses :meth:`SSLContext.load_default_certs` to load default CA -+ certificates. -+ -+ .. note:: -+ The protocol, options, cipher and other settings may change to more -+ restrictive values anytime without prior deprecation. The values -+ represent a fair balance between compatibility and security. -+ -+ If your application needs specific settings, you should create a -+ :class:`SSLContext` and apply the settings yourself. -+ -+ .. note:: -+ If you find that when certain older clients or servers attempt to connect -+ with a :class:`SSLContext` created by this function that they get an -+ error stating "Protocol or cipher suite mismatch", it may be that they -+ only support SSL3.0 which this function excludes using the -+ :data:`OP_NO_SSLv3`. SSL3.0 has problematic security due to a number of -+ poor implementations and it's reliance on MD5 within the protocol. If you -+ wish to continue to use this function but still allow SSL 3.0 connections -+ you can re-enable them using:: -+ -+ ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) -+ ctx.options &= ~ssl.OP_NO_SSLv3 -+ -+ .. versionadded:: 2.7.9 -+ -+ -+Random generation -+^^^^^^^^^^^^^^^^^ -+ - .. function:: RAND_status() - - Returns ``True`` if the SSL pseudo-random number generator has been seeded with -- 'enough' randomness, and False otherwise. You can use :func:`ssl.RAND_egd` -+ 'enough' randomness, and ``False`` otherwise. You can use :func:`ssl.RAND_egd` - and :func:`ssl.RAND_add` to increase the randomness of the pseudo-random - number generator. - - .. function:: RAND_egd(path) - -- If you are running an entropy-gathering daemon (EGD) somewhere, and ``path`` -+ If you are running an entropy-gathering daemon (EGD) somewhere, and *path* - is the pathname of a socket connection open to it, this will read 256 bytes - of randomness from the socket, and add it to the SSL pseudo-random number - generator to increase the security of generated secret keys. This is -@@ -187,28 +306,66 @@ Functions, Constants, and Exceptions - - .. function:: RAND_add(bytes, entropy) - -- Mixes the given ``bytes`` into the SSL pseudo-random number generator. The -- parameter ``entropy`` (a float) is a lower bound on the entropy contained in -+ Mixes the given *bytes* into the SSL pseudo-random number generator. The -+ parameter *entropy* (a float) is a lower bound on the entropy contained in - string (so you can always use :const:`0.0`). See :rfc:`1750` for more - information on sources of entropy. - --.. function:: cert_time_to_seconds(timestring) -+Certificate handling -+^^^^^^^^^^^^^^^^^^^^ -+ -+.. function:: match_hostname(cert, hostname) -+ -+ Verify that *cert* (in decoded format as returned by -+ :meth:`SSLSocket.getpeercert`) matches the given *hostname*. The rules -+ applied are those for checking the identity of HTTPS servers as outlined -+ in :rfc:`2818` and :rfc:`6125`, except that IP addresses are not currently -+ supported. In addition to HTTPS, this function should be suitable for -+ checking the identity of servers in various SSL-based protocols such as -+ FTPS, IMAPS, POPS and others. -+ -+ :exc:`CertificateError` is raised on failure. On success, the function -+ returns nothing:: - -- Returns a floating-point value containing a normal seconds-after-the-epoch -- time value, given the time-string representing the "notBefore" or "notAfter" -- date from a certificate. -+ >>> cert = {'subject': ((('commonName', 'example.com'),),)} -+ >>> ssl.match_hostname(cert, "example.com") -+ >>> ssl.match_hostname(cert, "example.org") -+ Traceback (most recent call last): -+ File "", line 1, in -+ File "/home/py3k/Lib/ssl.py", line 130, in match_hostname -+ ssl.CertificateError: hostname 'example.org' doesn't match 'example.com' - -- Here's an example:: -+ .. versionadded:: 2.7.9 - -- >>> import ssl -- >>> ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT") -- 1178694000.0 -- >>> import time -- >>> time.ctime(ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT")) -- 'Wed May 9 00:00:00 2007' -- >>> - --.. function:: get_server_certificate (addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None) -+.. function:: cert_time_to_seconds(cert_time) -+ -+ Return the time in seconds since the Epoch, given the ``cert_time`` -+ string representing the "notBefore" or "notAfter" date from a -+ certificate in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C -+ locale). -+ -+ Here's an example: -+ -+ .. doctest:: newcontext -+ -+ >>> import ssl -+ >>> timestamp = ssl.cert_time_to_seconds("Jan 5 09:34:43 2018 GMT") -+ >>> timestamp -+ 1515144883 -+ >>> from datetime import datetime -+ >>> print(datetime.utcfromtimestamp(timestamp)) -+ 2018-01-05 09:34:43 -+ -+ "notBefore" or "notAfter" dates must use GMT (:rfc:`5280`). -+ -+ .. versionchanged:: 2.7.9 -+ Interpret the input time as a time in UTC as specified by 'GMT' -+ timezone in the input string. Local timezone was used -+ previously. Return an integer (no fractions of a second in the -+ input format) -+ -+.. function:: get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None) - - Given the address ``addr`` of an SSL-protected server, as a (*hostname*, - *port-number*) pair, fetches the server's certificate, and returns it as a -@@ -219,36 +376,144 @@ Functions, Constants, and Exceptions - will attempt to validate the server certificate against that set of root - certificates, and will fail if the validation attempt fails. - --.. function:: DER_cert_to_PEM_cert (DER_cert_bytes) -+ .. versionchanged:: 2.7.9 -+ -+ This function is now IPv6-compatible, and the default *ssl_version* is -+ changed from :data:`PROTOCOL_SSLv3` to :data:`PROTOCOL_SSLv23` for -+ maximum compatibility with modern servers. -+ -+.. function:: DER_cert_to_PEM_cert(DER_cert_bytes) - - Given a certificate as a DER-encoded blob of bytes, returns a PEM-encoded - string version of the same certificate. - --.. function:: PEM_cert_to_DER_cert (PEM_cert_string) -+.. function:: PEM_cert_to_DER_cert(PEM_cert_string) - - Given a certificate as an ASCII PEM string, returns a DER-encoded sequence of - bytes for that same certificate. - -+.. function:: get_default_verify_paths() -+ -+ Returns a named tuple with paths to OpenSSL's default cafile and capath. -+ The paths are the same as used by -+ :meth:`SSLContext.set_default_verify_paths`. The return value is a -+ :term:`named tuple` ``DefaultVerifyPaths``: -+ -+ * :attr:`cafile` - resolved path to cafile or None if the file doesn't exist, -+ * :attr:`capath` - resolved path to capath or None if the directory doesn't exist, -+ * :attr:`openssl_cafile_env` - OpenSSL's environment key that points to a cafile, -+ * :attr:`openssl_cafile` - hard coded path to a cafile, -+ * :attr:`openssl_capath_env` - OpenSSL's environment key that points to a capath, -+ * :attr:`openssl_capath` - hard coded path to a capath directory -+ -+ .. versionadded:: 2.7.9 -+ -+.. function:: enum_certificates(store_name) -+ -+ Retrieve certificates from Windows' system cert store. *store_name* may be -+ one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert -+ stores, too. -+ -+ The function returns a list of (cert_bytes, encoding_type, trust) tuples. -+ The encoding_type specifies the encoding of cert_bytes. It is either -+ :const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for -+ PKCS#7 ASN.1 data. Trust specifies the purpose of the certificate as a set -+ of OIDS or exactly ``True`` if the certificate is trustworthy for all -+ purposes. -+ -+ Example:: -+ -+ >>> ssl.enum_certificates("CA") -+ [(b'data...', 'x509_asn', {'1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2'}), -+ (b'data...', 'x509_asn', True)] -+ -+ Availability: Windows. -+ -+ .. versionadded:: 2.7.9 -+ -+.. function:: enum_crls(store_name) -+ -+ Retrieve CRLs from Windows' system cert store. *store_name* may be -+ one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert -+ stores, too. -+ -+ The function returns a list of (cert_bytes, encoding_type, trust) tuples. -+ The encoding_type specifies the encoding of cert_bytes. It is either -+ :const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for -+ PKCS#7 ASN.1 data. -+ -+ Availability: Windows. -+ -+ .. versionadded:: 2.7.9 -+ -+ -+Constants -+^^^^^^^^^ -+ - .. data:: CERT_NONE - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no -- certificates will be required or validated from the other side of the socket -- connection. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode (the default), no -+ certificates will be required from the other side of the socket connection. -+ If a certificate is received from the other end, no attempt to validate it -+ is made. -+ -+ See the discussion of :ref:`ssl-security` below. - - .. data:: CERT_OPTIONAL - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no -- certificates will be required from the other side of the socket connection, -- but if they are provided, will be validated. Note that use of this setting -- requires a valid certificate validation file also be passed as a value of the -- ``ca_certs`` parameter. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode no certificates will be -+ required from the other side of the socket connection; but if they -+ are provided, validation will be attempted and an :class:`SSLError` -+ will be raised on failure. -+ -+ Use of this setting requires a valid set of CA certificates to -+ be passed, either to :meth:`SSLContext.load_verify_locations` or as a -+ value of the ``ca_certs`` parameter to :func:`wrap_socket`. - - .. data:: CERT_REQUIRED - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when -- certificates will be required from the other side of the socket connection. -- Note that use of this setting requires a valid certificate validation file -- also be passed as a value of the ``ca_certs`` parameter. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode, certificates are -+ required from the other side of the socket connection; an :class:`SSLError` -+ will be raised if no certificate is provided, or if its validation fails. -+ -+ Use of this setting requires a valid set of CA certificates to -+ be passed, either to :meth:`SSLContext.load_verify_locations` or as a -+ value of the ``ca_certs`` parameter to :func:`wrap_socket`. -+ -+.. data:: VERIFY_DEFAULT -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, -+ certificate revocation lists (CRLs) are not checked. By default OpenSSL -+ does neither require nor verify CRLs. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_CRL_CHECK_LEAF -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, only the -+ peer cert is check but non of the intermediate CA certificates. The mode -+ requires a valid CRL that is signed by the peer cert's issuer (its direct -+ ancestor CA). If no proper has been loaded -+ :attr:`SSLContext.load_verify_locations`, validation will fail. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_CRL_CHECK_CHAIN -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, CRLs of -+ all certificates in the peer cert chain are checked. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_X509_STRICT -+ -+ Possible value for :attr:`SSLContext.verify_flags` to disable workarounds -+ for broken X.509 certificates. -+ -+ .. versionadded:: 2.7.9 - - .. data:: PROTOCOL_SSLv2 - -@@ -275,9 +540,136 @@ Functions, Constants, and Exceptions - - .. data:: PROTOCOL_TLSv1 - -- Selects TLS version 1 as the channel encryption protocol. This is the most -+ Selects TLS version 1.0 as the channel encryption protocol. -+ -+.. data:: PROTOCOL_TLSv1_1 -+ -+ Selects TLS version 1.1 as the channel encryption protocol. -+ Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: PROTOCOL_TLSv1_2 -+ -+ Selects TLS version 1.2 as the channel encryption protocol. This is the most - modern version, and probably the best choice for maximum protection, if both -- sides can speak it. -+ sides can speak it. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_ALL -+ -+ Enables workarounds for various bugs present in other SSL implementations. -+ This option is set by default. It does not necessarily set the same -+ flags as OpenSSL's ``SSL_OP_ALL`` constant. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_SSLv2 -+ -+ Prevents an SSLv2 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing SSLv2 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_SSLv3 -+ -+ Prevents an SSLv3 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing SSLv3 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1 -+ -+ Prevents a TLSv1 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing TLSv1 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1_1 -+ -+ Prevents a TLSv1.1 connection. This option is only applicable in conjunction -+ with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.1 as -+ the protocol version. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1_2 -+ -+ Prevents a TLSv1.2 connection. This option is only applicable in conjunction -+ with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.2 as -+ the protocol version. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_CIPHER_SERVER_PREFERENCE -+ -+ Use the server's cipher ordering preference, rather than the client's. -+ This option has no effect on client sockets and SSLv2 server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_SINGLE_DH_USE -+ -+ Prevents re-use of the same DH key for distinct SSL sessions. This -+ improves forward secrecy but requires more computational resources. -+ This option only applies to server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_SINGLE_ECDH_USE -+ -+ Prevents re-use of the same ECDH key for distinct SSL sessions. This -+ improves forward secrecy but requires more computational resources. -+ This option only applies to server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_COMPRESSION -+ -+ Disable compression on the SSL channel. This is useful if the application -+ protocol supports its own compression scheme. -+ -+ This option is only available with OpenSSL 1.0.0 and later. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_ECDH -+ -+ Whether the OpenSSL library has built-in support for Elliptic Curve-based -+ Diffie-Hellman key exchange. This should be true unless the feature was -+ explicitly disabled by the distributor. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_SNI -+ -+ Whether the OpenSSL library has built-in support for the *Server Name -+ Indication* extension to the SSLv3 and TLSv1 protocols (as defined in -+ :rfc:`4366`). When true, you can use the *server_hostname* argument to -+ :meth:`SSLContext.wrap_socket`. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_NPN -+ -+ Whether the OpenSSL library has built-in support for *Next Protocol -+ Negotiation* as described in the `NPN draft specification -+ `_. When true, -+ you can use the :meth:`SSLContext.set_npn_protocols` method to advertise -+ which protocols you want to support. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: CHANNEL_BINDING_TYPES -+ -+ List of supported TLS channel binding types. Strings in this list -+ can be used as arguments to :meth:`SSLSocket.get_channel_binding`. -+ -+ .. versionadded:: 2.7.9 - - .. data:: OPENSSL_VERSION - -@@ -309,9 +701,40 @@ Functions, Constants, and Exceptions - - .. versionadded:: 2.7 - -+.. data:: ALERT_DESCRIPTION_HANDSHAKE_FAILURE -+ ALERT_DESCRIPTION_INTERNAL_ERROR -+ ALERT_DESCRIPTION_* -+ -+ Alert Descriptions from :rfc:`5246` and others. The `IANA TLS Alert Registry -+ `_ -+ contains this list and references to the RFCs where their meaning is defined. -+ -+ Used as the return value of the callback function in -+ :meth:`SSLContext.set_servername_callback`. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: Purpose.SERVER_AUTH -+ -+ Option for :func:`create_default_context` and -+ :meth:`SSLContext.load_default_certs`. This value indicates that the -+ context may be used to authenticate Web servers (therefore, it will -+ be used to create client-side sockets). -+ -+ .. versionadded:: 2.7.9 - --SSLSocket Objects ------------------- -+.. data:: Purpose.CLIENT_AUTH -+ -+ Option for :func:`create_default_context` and -+ :meth:`SSLContext.load_default_certs`. This value indicates that the -+ context may be used to authenticate Web clients (therefore, it will -+ be used to create server-side sockets). -+ -+ .. versionadded:: 2.7.9 -+ -+ -+SSL Sockets -+----------- - - SSL sockets provide the following methods of :ref:`socket-objects`: - -@@ -334,37 +757,64 @@ SSL sockets provide the following methods of :ref:`socket-objects`: - - However, since the SSL (and TLS) protocol has its own framing atop - of TCP, the SSL sockets abstraction can, in certain respects, diverge from --the specification of normal, OS-level sockets. -+the specification of normal, OS-level sockets. See especially the -+:ref:`notes on non-blocking sockets `. - - SSL sockets also have the following additional methods and attributes: - -+.. method:: SSLSocket.do_handshake() -+ -+ Perform the SSL setup handshake. -+ -+ .. versionchanged:: 2.7.9 -+ -+ The handshake method also performs :func:`match_hostname` when the -+ :attr:`~SSLContext.check_hostname` attribute of the socket's -+ :attr:`~SSLSocket.context` is true. -+ - .. method:: SSLSocket.getpeercert(binary_form=False) - - If there is no certificate for the peer on the other end of the connection, -- returns ``None``. -+ return ``None``. If the SSL handshake hasn't been done yet, raise -+ :exc:`ValueError`. - - If the ``binary_form`` parameter is :const:`False`, and a certificate was - received from the peer, this method returns a :class:`dict` instance. If the - certificate was not validated, the dict is empty. If the certificate was -- validated, it returns a dict with the keys ``subject`` (the principal for -- which the certificate was issued), and ``notAfter`` (the time after which the -- certificate should not be trusted). The certificate was already validated, -- so the ``notBefore`` and ``issuer`` fields are not returned. If a -- certificate contains an instance of the *Subject Alternative Name* extension -- (see :rfc:`3280`), there will also be a ``subjectAltName`` key in the -- dictionary. -- -- The "subject" field is a tuple containing the sequence of relative -- distinguished names (RDNs) given in the certificate's data structure for the -- principal, and each RDN is a sequence of name-value pairs:: -- -- {'notAfter': 'Feb 16 16:54:50 2013 GMT', -- 'subject': ((('countryName', u'US'),), -- (('stateOrProvinceName', u'Delaware'),), -- (('localityName', u'Wilmington'),), -- (('organizationName', u'Python Software Foundation'),), -- (('organizationalUnitName', u'SSL'),), -- (('commonName', u'somemachine.python.org'),))} -+ validated, it returns a dict with several keys, amongst them ``subject`` -+ (the principal for which the certificate was issued) and ``issuer`` -+ (the principal issuing the certificate). If a certificate contains an -+ instance of the *Subject Alternative Name* extension (see :rfc:`3280`), -+ there will also be a ``subjectAltName`` key in the dictionary. -+ -+ The ``subject`` and ``issuer`` fields are tuples containing the sequence -+ of relative distinguished names (RDNs) given in the certificate's data -+ structure for the respective fields, and each RDN is a sequence of -+ name-value pairs. Here is a real-world example:: -+ -+ {'issuer': ((('countryName', 'IL'),), -+ (('organizationName', 'StartCom Ltd.'),), -+ (('organizationalUnitName', -+ 'Secure Digital Certificate Signing'),), -+ (('commonName', -+ 'StartCom Class 2 Primary Intermediate Server CA'),)), -+ 'notAfter': 'Nov 22 08:15:19 2013 GMT', -+ 'notBefore': 'Nov 21 03:09:52 2011 GMT', -+ 'serialNumber': '95F0', -+ 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),), -+ (('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'San Francisco'),), -+ (('organizationName', 'Electronic Frontier Foundation, Inc.'),), -+ (('commonName', '*.eff.org'),), -+ (('emailAddress', 'hostmaster@eff.org'),)), -+ 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')), -+ 'version': 3} -+ -+ .. note:: -+ -+ To validate a certificate for a particular service, you can use the -+ :func:`match_hostname` function. - - If the ``binary_form`` parameter is :const:`True`, and a certificate was - provided, this method returns the DER-encoded form of the entire certificate -@@ -380,40 +830,388 @@ SSL sockets also have the following additional methods and attributes: - :const:`None` if you used :const:`CERT_NONE` (rather than - :const:`CERT_OPTIONAL` or :const:`CERT_REQUIRED`). - -+ .. versionchanged:: 2.7.9 -+ The returned dictionary includes additional items such as ``issuer`` and -+ ``notBefore``. Additionall :exc:`ValueError` is raised when the handshake -+ isn't done. The returned dictionary includes additional X509v3 extension -+ items such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs. -+ - .. method:: SSLSocket.cipher() - - Returns a three-value tuple containing the name of the cipher being used, the - version of the SSL protocol that defines its use, and the number of secret - bits being used. If no connection has been established, returns ``None``. - --.. method:: SSLSocket.do_handshake() -+.. method:: SSLSocket.compression() -+ -+ Return the compression algorithm being used as a string, or ``None`` -+ if the connection isn't compressed. -+ -+ If the higher-level protocol supports its own compression mechanism, -+ you can use :data:`OP_NO_COMPRESSION` to disable SSL-level compression. -+ -+ .. versionadded:: 2.7.9 -+ -+.. method:: SSLSocket.get_channel_binding(cb_type="tls-unique") - -- Perform a TLS/SSL handshake. If this is used with a non-blocking socket, it -- may raise :exc:`SSLError` with an ``arg[0]`` of :const:`SSL_ERROR_WANT_READ` -- or :const:`SSL_ERROR_WANT_WRITE`, in which case it must be called again until -- it completes successfully. For example, to simulate the behavior of a -- blocking socket, one might write:: -- -- while True: -- try: -- s.do_handshake() -- break -- except ssl.SSLError as err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], []) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], []) -- else: -- raise -+ Get channel binding data for current connection, as a bytes object. Returns -+ ``None`` if not connected or the handshake has not been completed. -+ -+ The *cb_type* parameter allow selection of the desired channel binding -+ type. Valid channel binding types are listed in the -+ :data:`CHANNEL_BINDING_TYPES` list. Currently only the 'tls-unique' channel -+ binding, defined by :rfc:`5929`, is supported. :exc:`ValueError` will be -+ raised if an unsupported channel binding type is requested. -+ -+ .. versionadded:: 2.7.9 -+ -+.. method:: SSLSocket.selected_npn_protocol() -+ -+ Returns the protocol that was selected during the TLS/SSL handshake. If -+ :meth:`SSLContext.set_npn_protocols` was not called, or if the other party -+ does not support NPN, or if the handshake has not yet happened, this will -+ return ``None``. -+ -+ .. versionadded:: 2.7.9 - - .. method:: SSLSocket.unwrap() - - Performs the SSL shutdown handshake, which removes the TLS layer from the - underlying socket, and returns the underlying socket object. This can be - used to go from encrypted operation over a connection to unencrypted. The -- socket instance returned should always be used for further communication with -- the other side of the connection, rather than the original socket instance -- (which may not function properly after the unwrap). -+ returned socket should always be used for further communication with the -+ other side of the connection, rather than the original socket. -+ -+.. attribute:: SSLSocket.context -+ -+ The :class:`SSLContext` object this SSL socket is tied to. If the SSL -+ socket was created using the top-level :func:`wrap_socket` function -+ (rather than :meth:`SSLContext.wrap_socket`), this is a custom context -+ object created for this SSL socket. -+ -+ .. versionadded:: 2.7.9 -+ -+ -+SSL Contexts -+------------ -+ -+.. versionadded:: 2.7.9 -+ -+An SSL context holds various data longer-lived than single SSL connections, -+such as SSL configuration options, certificate(s) and private key(s). -+It also manages a cache of SSL sessions for server-side sockets, in order -+to speed up repeated connections from the same clients. -+ -+.. class:: SSLContext(protocol) -+ -+ Create a new SSL context. You must pass *protocol* which must be one -+ of the ``PROTOCOL_*`` constants defined in this module. -+ :data:`PROTOCOL_SSLv23` is currently recommended for maximum -+ interoperability. -+ -+ .. seealso:: -+ :func:`create_default_context` lets the :mod:`ssl` module choose -+ security settings for a given purpose. -+ -+ -+:class:`SSLContext` objects have the following methods and attributes: -+ -+.. method:: SSLContext.cert_store_stats() -+ -+ Get statistics about quantities of loaded X.509 certificates, count of -+ X.509 certificates flagged as CA certificates and certificate revocation -+ lists as dictionary. -+ -+ Example for a context with one CA cert and one other cert:: -+ -+ >>> context.cert_store_stats() -+ {'crl': 0, 'x509_ca': 1, 'x509': 2} -+ -+ -+.. method:: SSLContext.load_cert_chain(certfile, keyfile=None, password=None) -+ -+ Load a private key and the corresponding certificate. The *certfile* -+ string must be the path to a single file in PEM format containing the -+ certificate as well as any number of CA certificates needed to establish -+ the certificate's authenticity. The *keyfile* string, if present, must -+ point to a file containing the private key in. Otherwise the private -+ key will be taken from *certfile* as well. See the discussion of -+ :ref:`ssl-certificates` for more information on how the certificate -+ is stored in the *certfile*. -+ -+ The *password* argument may be a function to call to get the password for -+ decrypting the private key. It will only be called if the private key is -+ encrypted and a password is necessary. It will be called with no arguments, -+ and it should return a string, bytes, or bytearray. If the return value is -+ a string it will be encoded as UTF-8 before using it to decrypt the key. -+ Alternatively a string, bytes, or bytearray value may be supplied directly -+ as the *password* argument. It will be ignored if the private key is not -+ encrypted and no password is needed. -+ -+ If the *password* argument is not specified and a password is required, -+ OpenSSL's built-in password prompting mechanism will be used to -+ interactively prompt the user for a password. -+ -+ An :class:`SSLError` is raised if the private key doesn't -+ match with the certificate. -+ -+.. method:: SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH) -+ -+ Load a set of default "certification authority" (CA) certificates from -+ default locations. On Windows it loads CA certs from the ``CA`` and -+ ``ROOT`` system stores. On other systems it calls -+ :meth:`SSLContext.set_default_verify_paths`. In the future the method may -+ load CA certificates from other locations, too. -+ -+ The *purpose* flag specifies what kind of CA certificates are loaded. The -+ default settings :data:`Purpose.SERVER_AUTH` loads certificates, that are -+ flagged and trusted for TLS web server authentication (client side -+ sockets). :data:`Purpose.CLIENT_AUTH` loads CA certificates for client -+ certificate verification on the server side. -+ -+.. method:: SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None) -+ -+ Load a set of "certification authority" (CA) certificates used to validate -+ other peers' certificates when :data:`verify_mode` is other than -+ :data:`CERT_NONE`. At least one of *cafile* or *capath* must be specified. -+ -+ This method can also load certification revocation lists (CRLs) in PEM or -+ DER format. In order to make use of CRLs, :attr:`SSLContext.verify_flags` -+ must be configured properly. -+ -+ The *cafile* string, if present, is the path to a file of concatenated -+ CA certificates in PEM format. See the discussion of -+ :ref:`ssl-certificates` for more information about how to arrange the -+ certificates in this file. -+ -+ The *capath* string, if present, is -+ the path to a directory containing several CA certificates in PEM format, -+ following an `OpenSSL specific layout -+ `_. -+ -+ The *cadata* object, if present, is either an ASCII string of one or more -+ PEM-encoded certificates or a bytes-like object of DER-encoded -+ certificates. Like with *capath* extra lines around PEM-encoded -+ certificates are ignored but at least one certificate must be present. -+ -+.. method:: SSLContext.get_ca_certs(binary_form=False) -+ -+ Get a list of loaded "certification authority" (CA) certificates. If the -+ ``binary_form`` parameter is :const:`False` each list -+ entry is a dict like the output of :meth:`SSLSocket.getpeercert`. Otherwise -+ the method returns a list of DER-encoded certificates. The returned list -+ does not contain certificates from *capath* unless a certificate was -+ requested and loaded by a SSL connection. -+ -+.. method:: SSLContext.set_default_verify_paths() -+ -+ Load a set of default "certification authority" (CA) certificates from -+ a filesystem path defined when building the OpenSSL library. Unfortunately, -+ there's no easy way to know whether this method succeeds: no error is -+ returned if no certificates are to be found. When the OpenSSL library is -+ provided as part of the operating system, though, it is likely to be -+ configured properly. -+ -+.. method:: SSLContext.set_ciphers(ciphers) -+ -+ Set the available ciphers for sockets created with this context. -+ It should be a string in the `OpenSSL cipher list format -+ `_. -+ If no cipher can be selected (because compile-time options or other -+ configuration forbids use of all the specified ciphers), an -+ :class:`SSLError` will be raised. -+ -+ .. note:: -+ when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will -+ give the currently selected cipher. -+ -+.. method:: SSLContext.set_npn_protocols(protocols) -+ -+ Specify which protocols the socket should advertise during the SSL/TLS -+ handshake. It should be a list of strings, like ``['http/1.1', 'spdy/2']``, -+ ordered by preference. The selection of a protocol will happen during the -+ handshake, and will play out according to the `NPN draft specification -+ `_. After a -+ successful handshake, the :meth:`SSLSocket.selected_npn_protocol` method will -+ return the agreed-upon protocol. -+ -+ This method will raise :exc:`NotImplementedError` if :data:`HAS_NPN` is -+ False. -+ -+.. method:: SSLContext.set_servername_callback(server_name_callback) -+ -+ Register a callback function that will be called after the TLS Client Hello -+ handshake message has been received by the SSL/TLS server when the TLS client -+ specifies a server name indication. The server name indication mechanism -+ is specified in :rfc:`6066` section 3 - Server Name Indication. -+ -+ Only one callback can be set per ``SSLContext``. If *server_name_callback* -+ is ``None`` then the callback is disabled. Calling this function a -+ subsequent time will disable the previously registered callback. -+ -+ The callback function, *server_name_callback*, will be called with three -+ arguments; the first being the :class:`ssl.SSLSocket`, the second is a string -+ that represents the server name that the client is intending to communicate -+ (or :const:`None` if the TLS Client Hello does not contain a server name) -+ and the third argument is the original :class:`SSLContext`. The server name -+ argument is the IDNA decoded server name. -+ -+ A typical use of this callback is to change the :class:`ssl.SSLSocket`'s -+ :attr:`SSLSocket.context` attribute to a new object of type -+ :class:`SSLContext` representing a certificate chain that matches the server -+ name. -+ -+ Due to the early negotiation phase of the TLS connection, only limited -+ methods and attributes are usable like -+ :meth:`SSLSocket.selected_npn_protocol` and :attr:`SSLSocket.context`. -+ :meth:`SSLSocket.getpeercert`, :meth:`SSLSocket.getpeercert`, -+ :meth:`SSLSocket.cipher` and :meth:`SSLSocket.compress` methods require that -+ the TLS connection has progressed beyond the TLS Client Hello and therefore -+ will not contain return meaningful values nor can they be called safely. -+ -+ The *server_name_callback* function must return ``None`` to allow the -+ TLS negotiation to continue. If a TLS failure is required, a constant -+ :const:`ALERT_DESCRIPTION_* ` can be -+ returned. Other return values will result in a TLS fatal error with -+ :const:`ALERT_DESCRIPTION_INTERNAL_ERROR`. -+ -+ If there is an IDNA decoding error on the server name, the TLS connection -+ will terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS -+ alert message to the client. -+ -+ If an exception is raised from the *server_name_callback* function the TLS -+ connection will terminate with a fatal TLS alert message -+ :const:`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`. -+ -+ This method will raise :exc:`NotImplementedError` if the OpenSSL library -+ had OPENSSL_NO_TLSEXT defined when it was built. -+ -+.. method:: SSLContext.load_dh_params(dhfile) -+ -+ Load the key generation parameters for Diffie-Helman (DH) key exchange. -+ Using DH key exchange improves forward secrecy at the expense of -+ computational resources (both on the server and on the client). -+ The *dhfile* parameter should be the path to a file containing DH -+ parameters in PEM format. -+ -+ This setting doesn't apply to client sockets. You can also use the -+ :data:`OP_SINGLE_DH_USE` option to further improve security. -+ -+.. method:: SSLContext.set_ecdh_curve(curve_name) -+ -+ Set the curve name for Elliptic Curve-based Diffie-Hellman (ECDH) key -+ exchange. ECDH is significantly faster than regular DH while arguably -+ as secure. The *curve_name* parameter should be a string describing -+ a well-known elliptic curve, for example ``prime256v1`` for a widely -+ supported curve. -+ -+ This setting doesn't apply to client sockets. You can also use the -+ :data:`OP_SINGLE_ECDH_USE` option to further improve security. -+ -+ This method is not available if :data:`HAS_ECDH` is False. -+ -+ .. seealso:: -+ `SSL/TLS & Perfect Forward Secrecy `_ -+ Vincent Bernat. -+ -+.. method:: SSLContext.wrap_socket(sock, server_side=False, \ -+ do_handshake_on_connect=True, suppress_ragged_eofs=True, \ -+ server_hostname=None) -+ -+ Wrap an existing Python socket *sock* and return an :class:`SSLSocket` -+ object. *sock* must be a :data:`~socket.SOCK_STREAM` socket; other socket -+ types are unsupported. -+ -+ The returned SSL socket is tied to the context, its settings and -+ certificates. The parameters *server_side*, *do_handshake_on_connect* -+ and *suppress_ragged_eofs* have the same meaning as in the top-level -+ :func:`wrap_socket` function. -+ -+ On client connections, the optional parameter *server_hostname* specifies -+ the hostname of the service which we are connecting to. This allows a -+ single server to host multiple SSL-based services with distinct certificates, -+ quite similarly to HTTP virtual hosts. Specifying *server_hostname* -+ will raise a :exc:`ValueError` if the OpenSSL library doesn't have support -+ for it (that is, if :data:`HAS_SNI` is :const:`False`). Specifying -+ *server_hostname* will also raise a :exc:`ValueError` if *server_side* -+ is true. -+ -+.. method:: SSLContext.session_stats() -+ -+ Get statistics about the SSL sessions created or managed by this context. -+ A dictionary is returned which maps the names of each `piece of information -+ `_ to their -+ numeric values. For example, here is the total number of hits and misses -+ in the session cache since the context was created:: -+ -+ >>> stats = context.session_stats() -+ >>> stats['hits'], stats['misses'] -+ (0, 0) -+ -+.. method:: SSLContext.get_ca_certs(binary_form=False) -+ -+ Returns a list of dicts with information of loaded CA certs. If the -+ optional argument is true, returns a DER-encoded copy of the CA -+ certificate. -+ -+ .. note:: -+ Certificates in a capath directory aren't loaded unless they have -+ been used at least once. -+ -+.. attribute:: SSLContext.check_hostname -+ -+ Wether to match the peer cert's hostname with :func:`match_hostname` in -+ :meth:`SSLSocket.do_handshake`. The context's -+ :attr:`~SSLContext.verify_mode` must be set to :data:`CERT_OPTIONAL` or -+ :data:`CERT_REQUIRED`, and you must pass *server_hostname* to -+ :meth:`~SSLContext.wrap_socket` in order to match the hostname. -+ -+ Example:: -+ -+ import socket, ssl -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.check_hostname = True -+ context.load_default_certs() -+ -+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ ssl_sock = context.wrap_socket(s, server_hostname='www.verisign.com') -+ ssl_sock.connect(('www.verisign.com', 443)) -+ -+ .. note:: -+ -+ This features requires OpenSSL 0.9.8f or newer. -+ -+.. attribute:: SSLContext.options -+ -+ An integer representing the set of SSL options enabled on this context. -+ The default value is :data:`OP_ALL`, but you can specify other options -+ such as :data:`OP_NO_SSLv2` by ORing them together. -+ -+ .. note:: -+ With versions of OpenSSL older than 0.9.8m, it is only possible -+ to set options, not to clear them. Attempting to clear an option -+ (by resetting the corresponding bits) will raise a ``ValueError``. -+ -+.. attribute:: SSLContext.protocol -+ -+ The protocol version chosen when constructing the context. This attribute -+ is read-only. -+ -+.. attribute:: SSLContext.verify_flags -+ -+ The flags for certificate verification operations. You can set flags like -+ :data:`VERIFY_CRL_CHECK_LEAF` by ORing them together. By default OpenSSL -+ does neither require nor verify certificate revocation lists (CRLs). -+ Available only with openssl version 0.9.8+. -+ -+.. attribute:: SSLContext.verify_mode -+ -+ Whether to try to verify other peers' certificates and how to behave -+ if verification fails. This attribute must be one of -+ :data:`CERT_NONE`, :data:`CERT_OPTIONAL` or :data:`CERT_REQUIRED`. -+ - - .. index:: single: certificates - -@@ -460,6 +1258,9 @@ and a footer line:: - ... (certificate in base64 PEM encoding) ... - -----END CERTIFICATE----- - -+Certificate chains -+^^^^^^^^^^^^^^^^^^ -+ - The Python files which contain certificates can contain a sequence of - certificates, sometimes called a *certificate chain*. This chain should start - with the specific certificate for the principal who "is" the client or server, -@@ -483,24 +1284,35 @@ certification authority's certificate:: - ... (the root certificate for the CA's issuer)... - -----END CERTIFICATE----- - -+CA certificates -+^^^^^^^^^^^^^^^ -+ - If you are going to require validation of the other side of the connection's - certificate, you need to provide a "CA certs" file, filled with the certificate - chains for each issuer you are willing to trust. Again, this file just contains - these chains concatenated together. For validation, Python will use the first --chain it finds in the file which matches. -+chain it finds in the file which matches. The platform's certificates file can -+be used by calling :meth:`SSLContext.load_default_certs`, this is done -+automatically with :func:`.create_default_context`. -+ -+Combined key and certificate -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+Often the private key is stored in the same file as the certificate; in this -+case, only the ``certfile`` parameter to :meth:`SSLContext.load_cert_chain` -+and :func:`wrap_socket` needs to be passed. If the private key is stored -+with the certificate, it should come before the first certificate in -+the certificate chain:: - --Some "standard" root certificates are available from various certification --authorities: `Thawte `_, `Verisign --`_, `Positive SSL --`_ --(used by python.org), `Equifax and GeoTrust --`_. -+ -----BEGIN RSA PRIVATE KEY----- -+ ... (private key in base64 encoding) ... -+ -----END RSA PRIVATE KEY----- -+ -----BEGIN CERTIFICATE----- -+ ... (certificate in base64 PEM encoding) ... -+ -----END CERTIFICATE----- - --In general, if you are using SSL3 or TLS1, you don't need to put the full chain --in your "CA certs" file; you only need the root certificates, and the remote --peer is supposed to furnish the other certificates necessary to chain from its --certificate to a root certificate. See :rfc:`4158` for more discussion of the --way in which certification chains can be built. -+Self-signed certificates -+^^^^^^^^^^^^^^^^^^^^^^^^ - - If you are going to create a server that provides SSL-encrypted connection - services, you will need to acquire a certificate for that service. There are -@@ -555,87 +1367,156 @@ should use the following idiom:: - Client-side operation - ^^^^^^^^^^^^^^^^^^^^^ - --This example connects to an SSL server, prints the server's address and --certificate, sends some bytes, and reads part of the response:: -+This example connects to an SSL server and prints the server's certificate:: - - import socket, ssl, pprint - - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -- - # require a certificate from the server - ssl_sock = ssl.wrap_socket(s, - ca_certs="/etc/ca_certs_file", - cert_reqs=ssl.CERT_REQUIRED) -- - ssl_sock.connect(('www.verisign.com', 443)) - -- print repr(ssl_sock.getpeername()) -- print ssl_sock.cipher() -- print pprint.pformat(ssl_sock.getpeercert()) -- -- # Set a simple HTTP request -- use httplib in actual code. -- ssl_sock.write("""GET / HTTP/1.0\r -- Host: www.verisign.com\r\n\r\n""") -- -- # Read a chunk of data. Will not necessarily -- # read all the data returned by the server. -- data = ssl_sock.read() -- -+ pprint.pprint(ssl_sock.getpeercert()) - # note that closing the SSLSocket will also close the underlying socket - ssl_sock.close() - --As of September 6, 2007, the certificate printed by this program looked like -+As of January 6, 2012, the certificate printed by this program looks like - this:: - -- {'notAfter': 'May 8 23:59:59 2009 GMT', -- 'subject': ((('serialNumber', u'2497886'),), -- (('1.3.6.1.4.1.311.60.2.1.3', u'US'),), -- (('1.3.6.1.4.1.311.60.2.1.2', u'Delaware'),), -- (('countryName', u'US'),), -- (('postalCode', u'94043'),), -- (('stateOrProvinceName', u'California'),), -- (('localityName', u'Mountain View'),), -- (('streetAddress', u'487 East Middlefield Road'),), -- (('organizationName', u'VeriSign, Inc.'),), -- (('organizationalUnitName', -- u'Production Security Services'),), -- (('organizationalUnitName', -- u'Terms of use at www.verisign.com/rpa (c)06'),), -- (('commonName', u'www.verisign.com'),))} -- --which is a fairly poorly-formed ``subject`` field. -+ {'issuer': ((('countryName', 'US'),), -+ (('organizationName', 'VeriSign, Inc.'),), -+ (('organizationalUnitName', 'VeriSign Trust Network'),), -+ (('organizationalUnitName', -+ 'Terms of use at https://www.verisign.com/rpa (c)06'),), -+ (('commonName', -+ 'VeriSign Class 3 Extended Validation SSL SGC CA'),)), -+ 'notAfter': 'May 25 23:59:59 2012 GMT', -+ 'notBefore': 'May 26 00:00:00 2010 GMT', -+ 'serialNumber': '53D2BEF924A7245E83CA01E46CAA2477', -+ 'subject': ((('1.3.6.1.4.1.311.60.2.1.3', 'US'),), -+ (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),), -+ (('businessCategory', 'V1.0, Clause 5.(b)'),), -+ (('serialNumber', '2497886'),), -+ (('countryName', 'US'),), -+ (('postalCode', '94043'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('streetAddress', '487 East Middlefield Road'),), -+ (('organizationName', 'VeriSign, Inc.'),), -+ (('organizationalUnitName', ' Production Security Services'),), -+ (('commonName', 'www.verisign.com'),)), -+ 'subjectAltName': (('DNS', 'www.verisign.com'), -+ ('DNS', 'verisign.com'), -+ ('DNS', 'www.verisign.net'), -+ ('DNS', 'verisign.net'), -+ ('DNS', 'www.verisign.mobi'), -+ ('DNS', 'verisign.mobi'), -+ ('DNS', 'www.verisign.eu'), -+ ('DNS', 'verisign.eu')), -+ 'version': 3} -+ -+This other example first creates an SSL context, instructs it to verify -+certificates sent by peers, and feeds it a set of recognized certificate -+authorities (CA):: -+ -+ >>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ >>> context.verify_mode = ssl.CERT_REQUIRED -+ >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") -+ -+(it is assumed your operating system places a bundle of all CA certificates -+in ``/etc/ssl/certs/ca-bundle.crt``; if not, you'll get an error and have -+to adjust the location) -+ -+When you use the context to connect to a server, :const:`CERT_REQUIRED` -+validates the server certificate: it ensures that the server certificate -+was signed with one of the CA certificates, and checks the signature for -+correctness:: -+ -+ >>> conn = context.wrap_socket(socket.socket(socket.AF_INET)) -+ >>> conn.connect(("linuxfr.org", 443)) -+ -+You should then fetch the certificate and check its fields for conformity:: -+ -+ >>> cert = conn.getpeercert() -+ >>> ssl.match_hostname(cert, "linuxfr.org") -+ -+Visual inspection shows that the certificate does identify the desired service -+(that is, the HTTPS host ``linuxfr.org``):: -+ -+ >>> pprint.pprint(cert) -+ {'issuer': ((('organizationName', 'CAcert Inc.'),), -+ (('organizationalUnitName', 'http://www.CAcert.org'),), -+ (('commonName', 'CAcert Class 3 Root'),)), -+ 'notAfter': 'Jun 7 21:02:24 2013 GMT', -+ 'notBefore': 'Jun 8 21:02:24 2011 GMT', -+ 'serialNumber': 'D3E9', -+ 'subject': ((('commonName', 'linuxfr.org'),),), -+ 'subjectAltName': (('DNS', 'linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'dev.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'prod.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'alpha.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', '*.linuxfr.org'), -+ ('othername', '')), -+ 'version': 3} -+ -+Now that you are assured of its authenticity, you can proceed to talk with -+the server:: -+ -+ >>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n") -+ >>> pprint.pprint(conn.recv(1024).split(b"\r\n")) -+ [b'HTTP/1.1 302 Found', -+ b'Date: Sun, 16 May 2010 13:43:28 GMT', -+ b'Server: Apache/2.2', -+ b'Location: https://linuxfr.org/pub/', -+ b'Vary: Accept-Encoding', -+ b'Connection: close', -+ b'Content-Type: text/html; charset=iso-8859-1', -+ b'', -+ b''] -+ -+See the discussion of :ref:`ssl-security` below. -+ - - Server-side operation - ^^^^^^^^^^^^^^^^^^^^^ - --For server operation, typically you'd need to have a server certificate, and --private key, each in a file. You'd open a socket, bind it to a port, call --:meth:`listen` on it, then start waiting for clients to connect:: -+For server operation, typically you'll need to have a server certificate, and -+private key, each in a file. You'll first create a context holding the key -+and the certificate, so that clients can check your authenticity. Then -+you'll open a socket, bind it to a port, call :meth:`listen` on it, and start -+waiting for clients to connect:: - - import socket, ssl - -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile") -+ - bindsocket = socket.socket() - bindsocket.bind(('myaddr.mydomain.com', 10023)) - bindsocket.listen(5) - --When one did, you'd call :meth:`accept` on the socket to get the new socket from --the other end, and use :func:`wrap_socket` to create a server-side SSL context --for it:: -+When a client connects, you'll call :meth:`accept` on the socket to get the -+new socket from the other end, and use the context's :meth:`SSLContext.wrap_socket` -+method to create a server-side SSL socket for the connection:: - - while True: - newsocket, fromaddr = bindsocket.accept() -- connstream = ssl.wrap_socket(newsocket, -- server_side=True, -- certfile="mycertfile", -- keyfile="mykeyfile", -- ssl_version=ssl.PROTOCOL_TLSv1) -+ connstream = context.wrap_socket(newsocket, server_side=True) - try: - deal_with_client(connstream) - finally: - connstream.shutdown(socket.SHUT_RDWR) - connstream.close() - --Then you'd read data from the ``connstream`` and do something with it till you -+Then you'll read data from the ``connstream`` and do something with it till you - are finished with the client (or the client is finished with you):: - - def deal_with_client(connstream): -@@ -649,7 +1530,138 @@ are finished with the client (or the client is finished with you):: - data = connstream.read() - # finished with client - --And go back to listening for new client connections. -+And go back to listening for new client connections (of course, a real server -+would probably handle each client connection in a separate thread, or put -+the sockets in non-blocking mode and use an event loop). -+ -+ -+.. _ssl-nonblocking: -+ -+Notes on non-blocking sockets -+----------------------------- -+ -+When working with non-blocking sockets, there are several things you need -+to be aware of: -+ -+- Calling :func:`~select.select` tells you that the OS-level socket can be -+ read from (or written to), but it does not imply that there is sufficient -+ data at the upper SSL layer. For example, only part of an SSL frame might -+ have arrived. Therefore, you must be ready to handle :meth:`SSLSocket.recv` -+ and :meth:`SSLSocket.send` failures, and retry after another call to -+ :func:`~select.select`. -+ -+- Conversely, since the SSL layer has its own framing, a SSL socket may -+ still have data available for reading without :func:`~select.select` -+ being aware of it. Therefore, you should first call -+ :meth:`SSLSocket.recv` to drain any potentially available data, and then -+ only block on a :func:`~select.select` call if still necessary. -+ -+ (of course, similar provisions apply when using other primitives such as -+ :func:`~select.poll`, or those in the :mod:`selectors` module) -+ -+- The SSL handshake itself will be non-blocking: the -+ :meth:`SSLSocket.do_handshake` method has to be retried until it returns -+ successfully. Here is a synopsis using :func:`~select.select` to wait for -+ the socket's readiness:: -+ -+ while True: -+ try: -+ sock.do_handshake() -+ break -+ except ssl.SSLWantReadError: -+ select.select([sock], [], []) -+ except ssl.SSLWantWriteError: -+ select.select([], [sock], []) -+ -+ -+.. _ssl-security: -+ -+Security considerations -+----------------------- -+ -+Best defaults -+^^^^^^^^^^^^^ -+ -+For **client use**, if you don't have any special requirements for your -+security policy, it is highly recommended that you use the -+:func:`create_default_context` function to create your SSL context. -+It will load the system's trusted CA certificates, enable certificate -+validation and hostname checking, and try to choose reasonably secure -+protocol and cipher settings. -+ -+If a client certificate is needed for the connection, it can be added with -+:meth:`SSLContext.load_cert_chain`. -+ -+By contrast, if you create the SSL context by calling the :class:`SSLContext` -+constructor yourself, it will not have certificate validation nor hostname -+checking enabled by default. If you do so, please read the paragraphs below -+to achieve a good security level. -+ -+Manual settings -+^^^^^^^^^^^^^^^ -+ -+Verifying certificates -+'''''''''''''''''''''' -+ -+When calling the :class:`SSLContext` constructor directly, -+:const:`CERT_NONE` is the default. Since it does not authenticate the other -+peer, it can be insecure, especially in client mode where most of time you -+would like to ensure the authenticity of the server you're talking to. -+Therefore, when in client mode, it is highly recommended to use -+:const:`CERT_REQUIRED`. However, it is in itself not sufficient; you also -+have to check that the server certificate, which can be obtained by calling -+:meth:`SSLSocket.getpeercert`, matches the desired service. For many -+protocols and applications, the service can be identified by the hostname; -+in this case, the :func:`match_hostname` function can be used. This common -+check is automatically performed when :attr:`SSLContext.check_hostname` is -+enabled. -+ -+In server mode, if you want to authenticate your clients using the SSL layer -+(rather than using a higher-level authentication mechanism), you'll also have -+to specify :const:`CERT_REQUIRED` and similarly check the client certificate. -+ -+ .. note:: -+ -+ In client mode, :const:`CERT_OPTIONAL` and :const:`CERT_REQUIRED` are -+ equivalent unless anonymous ciphers are enabled (they are disabled -+ by default). -+ -+Protocol versions -+''''''''''''''''' -+ -+SSL version 2 is considered insecure and is therefore dangerous to use. If -+you want maximum compatibility between clients and servers, it is recommended -+to use :const:`PROTOCOL_SSLv23` as the protocol version and then disable -+SSLv2 explicitly using the :data:`SSLContext.options` attribute:: -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.options |= ssl.OP_NO_SSLv2 -+ -+The SSL context created above will allow SSLv3 and TLSv1 (and later, if -+supported by your system) connections, but not SSLv2. -+ -+Cipher selection -+'''''''''''''''' -+ -+If you have advanced security requirements, fine-tuning of the ciphers -+enabled when negotiating a SSL session is possible through the -+:meth:`SSLContext.set_ciphers` method. Starting from Python 2.7.9, the -+ssl module disables certain weak ciphers by default, but you may want -+to further restrict the cipher choice. Be sure to read OpenSSL's documentation -+about the `cipher list format `_. -+If you want to check which ciphers are enabled by a given cipher list, use the -+``openssl ciphers`` command on your system. -+ -+Multi-processing -+^^^^^^^^^^^^^^^^ -+ -+If using this module as part of a multi-processed application (using, -+for example the :mod:`multiprocessing` or :mod:`concurrent.futures` modules), -+be aware that OpenSSL's internal random number generator does not properly -+handle forked processes. Applications must change the PRNG state of the -+parent process if they use any SSL feature with :func:`os.fork`. Any -+successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or -+:func:`~ssl.RAND_pseudo_bytes` is sufficient. - - - .. seealso:: -@@ -668,3 +1680,15 @@ And go back to listening for new client connections. - - `RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile `_ - Housley et. al. -+ -+ `RFC 4366: Transport Layer Security (TLS) Extensions `_ -+ Blake-Wilson et. al. -+ -+ `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 `_ -+ T. Dierks et. al. -+ -+ `RFC 6066: Transport Layer Security (TLS) Extensions `_ -+ D. Eastlake -+ -+ `IANA TLS: Transport Layer Security (TLS) Parameters `_ -+ IANA -diff --git a/Lib/ssl.py b/Lib/ssl.py -index 666cea3..882b60e 100644 ---- a/Lib/ssl.py -+++ b/Lib/ssl.py -@@ -1,8 +1,7 @@ - # Wrapper module for _ssl, providing some additional facilities - # implemented in Python. Written by Bill Janssen. - --"""\ --This module provides some more Pythonic support for SSL. -+"""This module provides some more Pythonic support for SSL. - - Object types: - -@@ -53,62 +52,461 @@ PROTOCOL_SSLv2 - PROTOCOL_SSLv3 - PROTOCOL_SSLv23 - PROTOCOL_TLSv1 -+PROTOCOL_TLSv1_1 -+PROTOCOL_TLSv1_2 -+ -+The following constants identify various SSL alert message descriptions as per -+http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 -+ -+ALERT_DESCRIPTION_CLOSE_NOTIFY -+ALERT_DESCRIPTION_UNEXPECTED_MESSAGE -+ALERT_DESCRIPTION_BAD_RECORD_MAC -+ALERT_DESCRIPTION_RECORD_OVERFLOW -+ALERT_DESCRIPTION_DECOMPRESSION_FAILURE -+ALERT_DESCRIPTION_HANDSHAKE_FAILURE -+ALERT_DESCRIPTION_BAD_CERTIFICATE -+ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE -+ALERT_DESCRIPTION_CERTIFICATE_REVOKED -+ALERT_DESCRIPTION_CERTIFICATE_EXPIRED -+ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN -+ALERT_DESCRIPTION_ILLEGAL_PARAMETER -+ALERT_DESCRIPTION_UNKNOWN_CA -+ALERT_DESCRIPTION_ACCESS_DENIED -+ALERT_DESCRIPTION_DECODE_ERROR -+ALERT_DESCRIPTION_DECRYPT_ERROR -+ALERT_DESCRIPTION_PROTOCOL_VERSION -+ALERT_DESCRIPTION_INSUFFICIENT_SECURITY -+ALERT_DESCRIPTION_INTERNAL_ERROR -+ALERT_DESCRIPTION_USER_CANCELLED -+ALERT_DESCRIPTION_NO_RENEGOTIATION -+ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION -+ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE -+ALERT_DESCRIPTION_UNRECOGNIZED_NAME -+ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE -+ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE -+ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY - """ - - import textwrap -+import re -+import sys -+import os -+from collections import namedtuple -+from contextlib import closing - - import _ssl # if we can't import it, let the error propagate - - from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION --from _ssl import SSLError -+from _ssl import _SSLContext -+from _ssl import ( -+ SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError, -+ SSLSyscallError, SSLEOFError, -+ ) - from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -+from _ssl import (VERIFY_DEFAULT, VERIFY_CRL_CHECK_LEAF, VERIFY_CRL_CHECK_CHAIN, -+ VERIFY_X509_STRICT) -+from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj - from _ssl import RAND_status, RAND_egd, RAND_add --from _ssl import \ -- SSL_ERROR_ZERO_RETURN, \ -- SSL_ERROR_WANT_READ, \ -- SSL_ERROR_WANT_WRITE, \ -- SSL_ERROR_WANT_X509_LOOKUP, \ -- SSL_ERROR_SYSCALL, \ -- SSL_ERROR_SSL, \ -- SSL_ERROR_WANT_CONNECT, \ -- SSL_ERROR_EOF, \ -- SSL_ERROR_INVALID_ERROR_CODE --from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 --_PROTOCOL_NAMES = { -- PROTOCOL_TLSv1: "TLSv1", -- PROTOCOL_SSLv23: "SSLv23", -- PROTOCOL_SSLv3: "SSLv3", --} -+ -+def _import_symbols(prefix): -+ for n in dir(_ssl): -+ if n.startswith(prefix): -+ globals()[n] = getattr(_ssl, n) -+ -+_import_symbols('OP_') -+_import_symbols('ALERT_DESCRIPTION_') -+_import_symbols('SSL_ERROR_') -+_import_symbols('PROTOCOL_') -+ -+from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN -+ -+from _ssl import _OPENSSL_API_VERSION -+ -+_PROTOCOL_NAMES = {value: name for name, value in globals().items() if name.startswith('PROTOCOL_')} -+ - try: -- from _ssl import PROTOCOL_SSLv2 - _SSLv2_IF_EXISTS = PROTOCOL_SSLv2 --except ImportError: -+except NameError: - _SSLv2_IF_EXISTS = None --else: -- _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" - - from socket import socket, _fileobject, _delegate_methods, error as socket_error --from socket import getnameinfo as _getnameinfo --from socket import SOL_SOCKET, SO_TYPE, SOCK_STREAM -+if sys.platform == "win32": -+ from _ssl import enum_certificates, enum_crls -+ -+from socket import socket, AF_INET, SOCK_STREAM, create_connection -+from socket import SOL_SOCKET, SO_TYPE - import base64 # for DER-to-PEM translation - import errno - -+if _ssl.HAS_TLS_UNIQUE: -+ CHANNEL_BINDING_TYPES = ['tls-unique'] -+else: -+ CHANNEL_BINDING_TYPES = [] -+ - # Disable weak or insecure ciphers by default - # (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') --_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2' -- -+# Enable a better set of ciphers by default -+# This list has been explicitly chosen to: -+# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) -+# * Prefer ECDHE over DHE for better performance -+# * Prefer any AES-GCM over any AES-CBC for better performance and security -+# * Then Use HIGH cipher suites as a fallback -+# * Then Use 3DES as fallback which is secure but slow -+# * Finally use RC4 as a fallback which is problematic but needed for -+# compatibility some times. -+# * Disable NULL authentication, NULL encryption, and MD5 MACs for security -+# reasons -+_DEFAULT_CIPHERS = ( -+ 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' -+ 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:ECDH+RC4:' -+ 'DH+RC4:RSA+RC4:!aNULL:!eNULL:!MD5' -+) -+ -+# Restricted and more secure ciphers for the server side -+# This list has been explicitly chosen to: -+# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) -+# * Prefer ECDHE over DHE for better performance -+# * Prefer any AES-GCM over any AES-CBC for better performance and security -+# * Then Use HIGH cipher suites as a fallback -+# * Then Use 3DES as fallback which is secure but slow -+# * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, and RC4 for -+# security reasons -+_RESTRICTED_SERVER_CIPHERS = ( -+ 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' -+ 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:' -+ '!eNULL:!MD5:!DSS:!RC4' -+) -+ -+ -+class CertificateError(ValueError): -+ pass -+ -+ -+def _dnsname_match(dn, hostname, max_wildcards=1): -+ """Matching according to RFC 6125, section 6.4.3 -+ -+ http://tools.ietf.org/html/rfc6125#section-6.4.3 -+ """ -+ pats = [] -+ if not dn: -+ return False -+ -+ pieces = dn.split(r'.') -+ leftmost = pieces[0] -+ remainder = pieces[1:] -+ -+ wildcards = leftmost.count('*') -+ if wildcards > max_wildcards: -+ # Issue #17980: avoid denials of service by refusing more -+ # than one wildcard per fragment. A survery of established -+ # policy among SSL implementations showed it to be a -+ # reasonable choice. -+ raise CertificateError( -+ "too many wildcards in certificate DNS name: " + repr(dn)) -+ -+ # speed up common case w/o wildcards -+ if not wildcards: -+ return dn.lower() == hostname.lower() -+ -+ # RFC 6125, section 6.4.3, subitem 1. -+ # The client SHOULD NOT attempt to match a presented identifier in which -+ # the wildcard character comprises a label other than the left-most label. -+ if leftmost == '*': -+ # When '*' is a fragment by itself, it matches a non-empty dotless -+ # fragment. -+ pats.append('[^.]+') -+ elif leftmost.startswith('xn--') or hostname.startswith('xn--'): -+ # RFC 6125, section 6.4.3, subitem 3. -+ # The client SHOULD NOT attempt to match a presented identifier -+ # where the wildcard character is embedded within an A-label or -+ # U-label of an internationalized domain name. -+ pats.append(re.escape(leftmost)) -+ else: -+ # Otherwise, '*' matches any dotless string, e.g. www* -+ pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) -+ -+ # add the remaining fragments, ignore any wildcards -+ for frag in remainder: -+ pats.append(re.escape(frag)) -+ -+ pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) -+ return pat.match(hostname) -+ -+ -+def match_hostname(cert, hostname): -+ """Verify that *cert* (in decoded format as returned by -+ SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 -+ rules are followed, but IP addresses are not accepted for *hostname*. -+ -+ CertificateError is raised on failure. On success, the function -+ returns nothing. -+ """ -+ if not cert: -+ raise ValueError("empty or no certificate, match_hostname needs a " -+ "SSL socket or SSL context with either " -+ "CERT_OPTIONAL or CERT_REQUIRED") -+ dnsnames = [] -+ san = cert.get('subjectAltName', ()) -+ for key, value in san: -+ if key == 'DNS': -+ if _dnsname_match(value, hostname): -+ return -+ dnsnames.append(value) -+ if not dnsnames: -+ # The subject is only checked when there is no dNSName entry -+ # in subjectAltName -+ for sub in cert.get('subject', ()): -+ for key, value in sub: -+ # XXX according to RFC 2818, the most specific Common Name -+ # must be used. -+ if key == 'commonName': -+ if _dnsname_match(value, hostname): -+ return -+ dnsnames.append(value) -+ if len(dnsnames) > 1: -+ raise CertificateError("hostname %r " -+ "doesn't match either of %s" -+ % (hostname, ', '.join(map(repr, dnsnames)))) -+ elif len(dnsnames) == 1: -+ raise CertificateError("hostname %r " -+ "doesn't match %r" -+ % (hostname, dnsnames[0])) -+ else: -+ raise CertificateError("no appropriate commonName or " -+ "subjectAltName fields were found") -+ -+ -+DefaultVerifyPaths = namedtuple("DefaultVerifyPaths", -+ "cafile capath openssl_cafile_env openssl_cafile openssl_capath_env " -+ "openssl_capath") -+ -+def get_default_verify_paths(): -+ """Return paths to default cafile and capath. -+ """ -+ parts = _ssl.get_default_verify_paths() -+ -+ # environment vars shadow paths -+ cafile = os.environ.get(parts[0], parts[1]) -+ capath = os.environ.get(parts[2], parts[3]) -+ -+ return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None, -+ capath if os.path.isdir(capath) else None, -+ *parts) -+ -+ -+class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")): -+ """ASN.1 object identifier lookup -+ """ -+ __slots__ = () -+ -+ def __new__(cls, oid): -+ return super(_ASN1Object, cls).__new__(cls, *_txt2obj(oid, name=False)) -+ -+ @classmethod -+ def fromnid(cls, nid): -+ """Create _ASN1Object from OpenSSL numeric ID -+ """ -+ return super(_ASN1Object, cls).__new__(cls, *_nid2obj(nid)) -+ -+ @classmethod -+ def fromname(cls, name): -+ """Create _ASN1Object from short name, long name or OID -+ """ -+ return super(_ASN1Object, cls).__new__(cls, *_txt2obj(name, name=True)) -+ -+ -+class Purpose(_ASN1Object): -+ """SSLContext purpose flags with X509v3 Extended Key Usage objects -+ """ -+ -+Purpose.SERVER_AUTH = Purpose('1.3.6.1.5.5.7.3.1') -+Purpose.CLIENT_AUTH = Purpose('1.3.6.1.5.5.7.3.2') -+ -+ -+class SSLContext(_SSLContext): -+ """An SSLContext holds various SSL-related configuration options and -+ data, such as certificates and possibly a private key.""" -+ -+ __slots__ = ('protocol', '__weakref__') -+ _windows_cert_stores = ("CA", "ROOT") -+ -+ def __new__(cls, protocol, *args, **kwargs): -+ self = _SSLContext.__new__(cls, protocol) -+ if protocol != _SSLv2_IF_EXISTS: -+ self.set_ciphers(_DEFAULT_CIPHERS) -+ return self -+ -+ def __init__(self, protocol): -+ self.protocol = protocol -+ -+ def wrap_socket(self, sock, server_side=False, -+ do_handshake_on_connect=True, -+ suppress_ragged_eofs=True, -+ server_hostname=None): -+ return SSLSocket(sock=sock, server_side=server_side, -+ do_handshake_on_connect=do_handshake_on_connect, -+ suppress_ragged_eofs=suppress_ragged_eofs, -+ server_hostname=server_hostname, -+ _context=self) -+ -+ def set_npn_protocols(self, npn_protocols): -+ protos = bytearray() -+ for protocol in npn_protocols: -+ b = protocol.encode('ascii') -+ if len(b) == 0 or len(b) > 255: -+ raise SSLError('NPN protocols must be 1 to 255 in length') -+ protos.append(len(b)) -+ protos.extend(b) -+ -+ self._set_npn_protocols(protos) -+ -+ def _load_windows_store_certs(self, storename, purpose): -+ certs = bytearray() -+ for cert, encoding, trust in enum_certificates(storename): -+ # CA certs are never PKCS#7 encoded -+ if encoding == "x509_asn": -+ if trust is True or purpose.oid in trust: -+ certs.extend(cert) -+ self.load_verify_locations(cadata=certs) -+ return certs -+ -+ def load_default_certs(self, purpose=Purpose.SERVER_AUTH): -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ if sys.platform == "win32": -+ for storename in self._windows_cert_stores: -+ self._load_windows_store_certs(storename, purpose) -+ else: -+ self.set_default_verify_paths() -+ -+ -+def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, -+ capath=None, cadata=None): -+ """Create a SSLContext object with default settings. -+ -+ NOTE: The protocol and settings may change anytime without prior -+ deprecation. The values represent a fair balance between maximum -+ compatibility and security. -+ """ -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ -+ context = SSLContext(PROTOCOL_SSLv23) -+ -+ # SSLv2 considered harmful. -+ context.options |= OP_NO_SSLv2 -+ -+ # SSLv3 has problematic security and is only required for really old -+ # clients such as IE6 on Windows XP -+ context.options |= OP_NO_SSLv3 -+ -+ # disable compression to prevent CRIME attacks (OpenSSL 1.0+) -+ context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0) -+ -+ if purpose == Purpose.SERVER_AUTH: -+ # verify certs and host name in client mode -+ context.verify_mode = CERT_REQUIRED -+ context.check_hostname = True -+ elif purpose == Purpose.CLIENT_AUTH: -+ # Prefer the server's ciphers by default so that we get stronger -+ # encryption -+ context.options |= getattr(_ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) -+ -+ # Use single use keys in order to improve forward secrecy -+ context.options |= getattr(_ssl, "OP_SINGLE_DH_USE", 0) -+ context.options |= getattr(_ssl, "OP_SINGLE_ECDH_USE", 0) -+ -+ # disallow ciphers with known vulnerabilities -+ context.set_ciphers(_RESTRICTED_SERVER_CIPHERS) -+ -+ if cafile or capath or cadata: -+ context.load_verify_locations(cafile, capath, cadata) -+ elif context.verify_mode != CERT_NONE: -+ # no explicit cafile, capath or cadata but the verify mode is -+ # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system -+ # root CA certificates for the given purpose. This may fail silently. -+ context.load_default_certs(purpose) -+ return context -+ -+ -+def _create_stdlib_context(protocol=PROTOCOL_SSLv23, cert_reqs=None, -+ check_hostname=False, purpose=Purpose.SERVER_AUTH, -+ certfile=None, keyfile=None, -+ cafile=None, capath=None, cadata=None): -+ """Create a SSLContext object for Python stdlib modules -+ -+ All Python stdlib modules shall use this function to create SSLContext -+ objects in order to keep common settings in one place. The configuration -+ is less restrict than create_default_context()'s to increase backward -+ compatibility. -+ """ -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ -+ context = SSLContext(protocol) -+ # SSLv2 considered harmful. -+ context.options |= OP_NO_SSLv2 -+ -+ if cert_reqs is not None: -+ context.verify_mode = cert_reqs -+ context.check_hostname = check_hostname -+ -+ if keyfile and not certfile: -+ raise ValueError("certfile must be specified") -+ if certfile or keyfile: -+ context.load_cert_chain(certfile, keyfile) -+ -+ # load CA root certs -+ if cafile or capath or cadata: -+ context.load_verify_locations(cafile, capath, cadata) -+ elif context.verify_mode != CERT_NONE: -+ # no explicit cafile, capath or cadata but the verify mode is -+ # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system -+ # root CA certificates for the given purpose. This may fail silently. -+ context.load_default_certs(purpose) -+ -+ return context - - class SSLSocket(socket): -- - """This class implements a subtype of socket.socket that wraps - the underlying OS socket in an SSL context when necessary, and - provides read and write methods over that channel.""" - -- def __init__(self, sock, keyfile=None, certfile=None, -+ def __init__(self, sock=None, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, -- suppress_ragged_eofs=True, ciphers=None): -+ family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, -+ suppress_ragged_eofs=True, npn_protocols=None, ciphers=None, -+ server_hostname=None, -+ _context=None): -+ -+ if _context: -+ self._context = _context -+ else: -+ if server_side and not certfile: -+ raise ValueError("certfile must be specified for server-side " -+ "operations") -+ if keyfile and not certfile: -+ raise ValueError("certfile must be specified") -+ if certfile and not keyfile: -+ keyfile = certfile -+ self._context = SSLContext(ssl_version) -+ self._context.verify_mode = cert_reqs -+ if ca_certs: -+ self._context.load_verify_locations(ca_certs) -+ if certfile: -+ self._context.load_cert_chain(certfile, keyfile) -+ if npn_protocols: -+ self._context.set_npn_protocols(npn_protocols) -+ if ciphers: -+ self._context.set_ciphers(ciphers) -+ self.keyfile = keyfile -+ self.certfile = certfile -+ self.cert_reqs = cert_reqs -+ self.ssl_version = ssl_version -+ self.ca_certs = ca_certs -+ self.ciphers = ciphers - # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get - # mixed in. - if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM: -@@ -122,98 +520,161 @@ class SSLSocket(socket): - delattr(self, attr) - except AttributeError: - pass -+ if server_side and server_hostname: -+ raise ValueError("server_hostname can only be specified " -+ "in client mode") -+ if self._context.check_hostname and not server_hostname: -+ if HAS_SNI: -+ raise ValueError("check_hostname requires server_hostname") -+ else: -+ raise ValueError("check_hostname requires server_hostname, " -+ "but it's not supported by your OpenSSL " -+ "library") -+ self.server_side = server_side -+ self.server_hostname = server_hostname -+ self.do_handshake_on_connect = do_handshake_on_connect -+ self.suppress_ragged_eofs = suppress_ragged_eofs - -- if ciphers is None and ssl_version != _SSLv2_IF_EXISTS: -- ciphers = _DEFAULT_CIPHERS -- -- if certfile and not keyfile: -- keyfile = certfile -- # see if it's connected -+ # See if we are connected - try: -- socket.getpeername(self) -- except socket_error, e: -+ self.getpeername() -+ except socket_error as e: - if e.errno != errno.ENOTCONN: - raise -- # no, no connection yet -- self._connected = False -- self._sslobj = None -+ connected = False - else: -- # yes, create the SSL object -- self._connected = True -- self._sslobj = _ssl.sslwrap(self._sock, server_side, -- keyfile, certfile, -- cert_reqs, ssl_version, ca_certs, -- ciphers) -- if do_handshake_on_connect: -- self.do_handshake() -- self.keyfile = keyfile -- self.certfile = certfile -- self.cert_reqs = cert_reqs -- self.ssl_version = ssl_version -- self.ca_certs = ca_certs -- self.ciphers = ciphers -- self.do_handshake_on_connect = do_handshake_on_connect -- self.suppress_ragged_eofs = suppress_ragged_eofs -+ connected = True -+ -+ self._closed = False -+ self._sslobj = None -+ self._connected = connected -+ if connected: -+ # create the SSL object -+ try: -+ self._sslobj = self._context._wrap_socket(self._sock, server_side, -+ server_hostname, ssl_sock=self) -+ if do_handshake_on_connect: -+ timeout = self.gettimeout() -+ if timeout == 0.0: -+ # non-blocking -+ raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") -+ self.do_handshake() -+ -+ except (OSError, ValueError): -+ self.close() -+ raise - self._makefile_refs = 0 - -- def read(self, len=1024): -+ @property -+ def context(self): -+ return self._context -+ -+ @context.setter -+ def context(self, ctx): -+ self._context = ctx -+ self._sslobj.context = ctx -+ -+ def dup(self): -+ raise NotImplemented("Can't dup() %s instances" % -+ self.__class__.__name__) -+ -+ def _checkClosed(self, msg=None): -+ # raise an exception here if you wish to check for spurious closes -+ pass - -+ def _check_connected(self): -+ if not self._connected: -+ # getpeername() will raise ENOTCONN if the socket is really -+ # not connected; note that we can be connected even without -+ # _connected being set, e.g. if connect() first returned -+ # EAGAIN. -+ self.getpeername() -+ -+ def read(self, len=0, buffer=None): - """Read up to LEN bytes and return them. - Return zero-length string on EOF.""" - -+ self._checkClosed() -+ if not self._sslobj: -+ raise ValueError("Read on closed or unwrapped SSL socket.") - try: -- return self._sslobj.read(len) -- except SSLError, x: -+ if buffer is not None: -+ v = self._sslobj.read(len, buffer) -+ else: -+ v = self._sslobj.read(len or 1024) -+ return v -+ except SSLError as x: - if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: -- return '' -+ if buffer is not None: -+ return 0 -+ else: -+ return b'' - else: - raise - - def write(self, data): -- - """Write DATA to the underlying SSL channel. Returns - number of bytes of DATA actually transmitted.""" - -+ self._checkClosed() -+ if not self._sslobj: -+ raise ValueError("Write on closed or unwrapped SSL socket.") - return self._sslobj.write(data) - - def getpeercert(self, binary_form=False): -- - """Returns a formatted version of the data in the - certificate provided by the other end of the SSL channel. - Return None if no certificate was provided, {} if a - certificate was provided, but not validated.""" - -+ self._checkClosed() -+ self._check_connected() - return self._sslobj.peer_certificate(binary_form) - -- def cipher(self): -+ def selected_npn_protocol(self): -+ self._checkClosed() -+ if not self._sslobj or not _ssl.HAS_NPN: -+ return None -+ else: -+ return self._sslobj.selected_npn_protocol() - -+ def cipher(self): -+ self._checkClosed() - if not self._sslobj: - return None - else: - return self._sslobj.cipher() - -+ def compression(self): -+ self._checkClosed() -+ if not self._sslobj: -+ return None -+ else: -+ return self._sslobj.compression() -+ - def send(self, data, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( - "non-zero flags not allowed in calls to send() on %s" % - self.__class__) -- while True: -- try: -- v = self._sslobj.write(data) -- except SSLError, x: -- if x.args[0] == SSL_ERROR_WANT_READ: -- return 0 -- elif x.args[0] == SSL_ERROR_WANT_WRITE: -- return 0 -- else: -- raise -+ try: -+ v = self._sslobj.write(data) -+ except SSLError as x: -+ if x.args[0] == SSL_ERROR_WANT_READ: -+ return 0 -+ elif x.args[0] == SSL_ERROR_WANT_WRITE: -+ return 0 - else: -- return v -+ raise -+ else: -+ return v - else: - return self._sock.send(data, flags) - - def sendto(self, data, flags_or_addr, addr=None): -+ self._checkClosed() - if self._sslobj: - raise ValueError("sendto not allowed on instances of %s" % - self.__class__) -@@ -222,7 +683,9 @@ class SSLSocket(socket): - else: - return self._sock.sendto(data, flags_or_addr, addr) - -+ - def sendall(self, data, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( -@@ -238,6 +701,7 @@ class SSLSocket(socket): - return socket.sendall(self, data, flags) - - def recv(self, buflen=1024, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( -@@ -248,6 +712,7 @@ class SSLSocket(socket): - return self._sock.recv(buflen, flags) - - def recv_into(self, buffer, nbytes=None, flags=0): -+ self._checkClosed() - if buffer and (nbytes is None): - nbytes = len(buffer) - elif nbytes is None: -@@ -257,14 +722,12 @@ class SSLSocket(socket): - raise ValueError( - "non-zero flags not allowed in calls to recv_into() on %s" % - self.__class__) -- tmp_buffer = self.read(nbytes) -- v = len(tmp_buffer) -- buffer[:v] = tmp_buffer -- return v -+ return self.read(nbytes, buffer) - else: - return self._sock.recv_into(buffer, nbytes, flags) - - def recvfrom(self, buflen=1024, flags=0): -+ self._checkClosed() - if self._sslobj: - raise ValueError("recvfrom not allowed on instances of %s" % - self.__class__) -@@ -272,27 +735,23 @@ class SSLSocket(socket): - return self._sock.recvfrom(buflen, flags) - - def recvfrom_into(self, buffer, nbytes=None, flags=0): -+ self._checkClosed() - if self._sslobj: - raise ValueError("recvfrom_into not allowed on instances of %s" % - self.__class__) - else: - return self._sock.recvfrom_into(buffer, nbytes, flags) - -+ - def pending(self): -+ self._checkClosed() - if self._sslobj: - return self._sslobj.pending() - else: - return 0 - -- def unwrap(self): -- if self._sslobj: -- s = self._sslobj.shutdown() -- self._sslobj = None -- return s -- else: -- raise ValueError("No SSL wrapper around " + str(self)) -- - def shutdown(self, how): -+ self._checkClosed() - self._sslobj = None - socket.shutdown(self, how) - -@@ -303,32 +762,55 @@ class SSLSocket(socket): - else: - self._makefile_refs -= 1 - -- def do_handshake(self): -- -- """Perform a TLS/SSL handshake.""" -+ def unwrap(self): -+ if self._sslobj: -+ s = self._sslobj.shutdown() -+ self._sslobj = None -+ return s -+ else: -+ raise ValueError("No SSL wrapper around " + str(self)) - -- self._sslobj.do_handshake() -+ def _real_close(self): -+ self._sslobj = None -+ socket._real_close(self) - -- def _real_connect(self, addr, return_errno): -+ def do_handshake(self, block=False): -+ """Perform a TLS/SSL handshake.""" -+ self._check_connected() -+ timeout = self.gettimeout() -+ try: -+ if timeout == 0.0 and block: -+ self.settimeout(None) -+ self._sslobj.do_handshake() -+ finally: -+ self.settimeout(timeout) -+ -+ if self.context.check_hostname: -+ if not self.server_hostname: -+ raise ValueError("check_hostname needs server_hostname " -+ "argument") -+ match_hostname(self.getpeercert(), self.server_hostname) -+ -+ def _real_connect(self, addr, connect_ex): -+ if self.server_side: -+ raise ValueError("can't connect in server-side mode") - # Here we assume that the socket is client-side, and not - # connected at the time of the call. We connect it, then wrap it. - if self._connected: - raise ValueError("attempt to connect already-connected SSLSocket!") -- self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, -- self.cert_reqs, self.ssl_version, -- self.ca_certs, self.ciphers) -+ self._sslobj = self.context._wrap_socket(self._sock, False, self.server_hostname, ssl_sock=self) - try: -- if return_errno: -+ if connect_ex: - rc = socket.connect_ex(self, addr) - else: - rc = None - socket.connect(self, addr) - if not rc: -+ self._connected = True - if self.do_handshake_on_connect: - self.do_handshake() -- self._connected = True - return rc -- except socket_error: -+ except (OSError, ValueError): - self._sslobj = None - raise - -@@ -343,27 +825,16 @@ class SSLSocket(socket): - return self._real_connect(addr, True) - - def accept(self): -- - """Accepts a new connection from a remote client, and returns - a tuple containing that new connection wrapped with a server-side - SSL channel, and the address of the remote client.""" - - newsock, addr = socket.accept(self) -- try: -- return (SSLSocket(newsock, -- keyfile=self.keyfile, -- certfile=self.certfile, -- server_side=True, -- cert_reqs=self.cert_reqs, -- ssl_version=self.ssl_version, -- ca_certs=self.ca_certs, -- ciphers=self.ciphers, -- do_handshake_on_connect=self.do_handshake_on_connect, -- suppress_ragged_eofs=self.suppress_ragged_eofs), -- addr) -- except socket_error as e: -- newsock.close() -- raise e -+ newsock = self.context.wrap_socket(newsock, -+ do_handshake_on_connect=self.do_handshake_on_connect, -+ suppress_ragged_eofs=self.suppress_ragged_eofs, -+ server_side=True) -+ return newsock, addr - - def makefile(self, mode='r', bufsize=-1): - -@@ -376,54 +847,81 @@ class SSLSocket(socket): - # the file-like object. - return _fileobject(self, mode, bufsize, close=True) - -+ def get_channel_binding(self, cb_type="tls-unique"): -+ """Get channel binding data for current connection. Raise ValueError -+ if the requested `cb_type` is not supported. Return bytes of the data -+ or None if the data is not available (e.g. before the handshake). -+ """ -+ if cb_type not in CHANNEL_BINDING_TYPES: -+ raise ValueError("Unsupported channel binding type") -+ if cb_type != "tls-unique": -+ raise NotImplementedError( -+ "{0} channel binding type not implemented" -+ .format(cb_type)) -+ if self._sslobj is None: -+ return None -+ return self._sslobj.tls_unique_cb() - - - def wrap_socket(sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, -- suppress_ragged_eofs=True, ciphers=None): -+ suppress_ragged_eofs=True, -+ ciphers=None): - -- return SSLSocket(sock, keyfile=keyfile, certfile=certfile, -+ return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, cert_reqs=cert_reqs, - ssl_version=ssl_version, ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs, - ciphers=ciphers) - -- - # some utility functions - - def cert_time_to_seconds(cert_time): -- -- """Takes a date-time string in standard ASN1_print form -- ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return -- a Python time value in seconds past the epoch.""" -- -- import time -- return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT")) -+ """Return the time in seconds since the Epoch, given the timestring -+ representing the "notBefore" or "notAfter" date from a certificate -+ in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C locale). -+ -+ "notBefore" or "notAfter" dates must use UTC (RFC 5280). -+ -+ Month is one of: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec -+ UTC should be specified as GMT (see ASN1_TIME_print()) -+ """ -+ from time import strptime -+ from calendar import timegm -+ -+ months = ( -+ "Jan","Feb","Mar","Apr","May","Jun", -+ "Jul","Aug","Sep","Oct","Nov","Dec" -+ ) -+ time_format = ' %d %H:%M:%S %Y GMT' # NOTE: no month, fixed GMT -+ try: -+ month_number = months.index(cert_time[:3].title()) + 1 -+ except ValueError: -+ raise ValueError('time data %r does not match ' -+ 'format "%%b%s"' % (cert_time, time_format)) -+ else: -+ # found valid month -+ tt = strptime(cert_time[3:], time_format) -+ # return an integer, the previous mktime()-based implementation -+ # returned a float (fractional seconds are always zero here). -+ return timegm((tt[0], month_number) + tt[2:6]) - - PEM_HEADER = "-----BEGIN CERTIFICATE-----" - PEM_FOOTER = "-----END CERTIFICATE-----" - - def DER_cert_to_PEM_cert(der_cert_bytes): -- - """Takes a certificate in binary DER format and returns the - PEM version of it as a string.""" - -- if hasattr(base64, 'standard_b64encode'): -- # preferred because older API gets line-length wrong -- f = base64.standard_b64encode(der_cert_bytes) -- return (PEM_HEADER + '\n' + -- textwrap.fill(f, 64) + '\n' + -- PEM_FOOTER + '\n') -- else: -- return (PEM_HEADER + '\n' + -- base64.encodestring(der_cert_bytes) + -- PEM_FOOTER + '\n') -+ f = base64.standard_b64encode(der_cert_bytes).decode('ascii') -+ return (PEM_HEADER + '\n' + -+ textwrap.fill(f, 64) + '\n' + -+ PEM_FOOTER + '\n') - - def PEM_cert_to_DER_cert(pem_cert_string): -- - """Takes a certificate in ASCII PEM format and returns the - DER-encoded version of it as a byte sequence""" - -@@ -434,25 +932,25 @@ def PEM_cert_to_DER_cert(pem_cert_string): - raise ValueError("Invalid PEM encoding; must end with %s" - % PEM_FOOTER) - d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] -- return base64.decodestring(d) -- --def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): -+ return base64.decodestring(d.encode('ASCII', 'strict')) - -+def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None): - """Retrieve the certificate from the server at the specified address, - and return it as a PEM-encoded string. - If 'ca_certs' is specified, validate the server cert against it. - If 'ssl_version' is specified, use it in the connection attempt.""" - - host, port = addr -- if (ca_certs is not None): -+ if ca_certs is not None: - cert_reqs = CERT_REQUIRED - else: - cert_reqs = CERT_NONE -- s = wrap_socket(socket(), ssl_version=ssl_version, -- cert_reqs=cert_reqs, ca_certs=ca_certs) -- s.connect(addr) -- dercert = s.getpeercert(True) -- s.close() -+ context = _create_stdlib_context(ssl_version, -+ cert_reqs=cert_reqs, -+ cafile=ca_certs) -+ with closing(create_connection(addr)) as sock: -+ with closing(context.wrap_socket(sock)) as sslsock: -+ dercert = sslsock.getpeercert(True) - return DER_cert_to_PEM_cert(dercert) - - def get_protocol_name(protocol_code): -diff --git a/Lib/test/capath/4e1295a3.0 b/Lib/test/capath/4e1295a3.0 -new file mode 100644 -index 0000000..9d7ac23 ---- /dev/null -+++ b/Lib/test/capath/4e1295a3.0 -@@ -0,0 +1,14 @@ -+-----BEGIN CERTIFICATE----- -+MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD -+VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv -+bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy -+dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X -+DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw -+EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l -+dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT -+EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp -+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw -+L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN -+BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX -+9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/5ed36f99.0 b/Lib/test/capath/5ed36f99.0 -new file mode 100644 -index 0000000..e7dfc82 ---- /dev/null -+++ b/Lib/test/capath/5ed36f99.0 -@@ -0,0 +1,41 @@ -+-----BEGIN CERTIFICATE----- -+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/6e88d7b8.0 b/Lib/test/capath/6e88d7b8.0 -new file mode 100644 -index 0000000..9d7ac23 ---- /dev/null -+++ b/Lib/test/capath/6e88d7b8.0 -@@ -0,0 +1,14 @@ -+-----BEGIN CERTIFICATE----- -+MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD -+VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv -+bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy -+dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X -+DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw -+EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l -+dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT -+EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp -+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw -+L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN -+BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX -+9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/99d0fa06.0 b/Lib/test/capath/99d0fa06.0 -new file mode 100644 -index 0000000..e7dfc82 ---- /dev/null -+++ b/Lib/test/capath/99d0fa06.0 -@@ -0,0 +1,41 @@ -+-----BEGIN CERTIFICATE----- -+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -+-----END CERTIFICATE----- -diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem -new file mode 100644 -index 0000000..200d16c ---- /dev/null -+++ b/Lib/test/dh512.pem -@@ -0,0 +1,9 @@ -+-----BEGIN DH PARAMETERS----- -+MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -+XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC -+-----END DH PARAMETERS----- -+ -+These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -+(http://www.skip-vpn.org/spec/numbers.html). -+See there for how they were generated. -+Note that g is not a generator, but this is not a problem since p is a safe prime. -diff --git a/Lib/test/keycert.passwd.pem b/Lib/test/keycert.passwd.pem -new file mode 100644 -index 0000000..e905748 ---- /dev/null -+++ b/Lib/test/keycert.passwd.pem -@@ -0,0 +1,33 @@ -+-----BEGIN RSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-EDE3-CBC,1A8D9D2A02EC698A -+ -+kJYbfZ8L0sfe9Oty3gw0aloNnY5E8fegRfQLZlNoxTl6jNt0nIwI8kDJ36CZgR9c -+u3FDJm/KqrfUoz8vW+qEnWhSG7QPX2wWGPHd4K94Yz/FgrRzZ0DoK7XxXq9gOtVA -+AVGQhnz32p+6WhfGsCr9ArXEwRZrTk/FvzEPaU5fHcoSkrNVAGX8IpSVkSDwEDQr -+Gv17+cfk99UV1OCza6yKHoFkTtrC+PZU71LomBabivS2Oc4B9hYuSR2hF01wTHP+ -+YlWNagZOOVtNz4oKK9x9eNQpmfQXQvPPTfusexKIbKfZrMvJoxcm1gfcZ0H/wK6P -+6wmXSG35qMOOztCZNtperjs1wzEBXznyK8QmLcAJBjkfarABJX9vBEzZV0OUKhy+ -+noORFwHTllphbmydLhu6ehLUZMHPhzAS5UN7srtpSN81eerDMy0RMUAwA7/PofX1 -+94Me85Q8jP0PC9ETdsJcPqLzAPETEYu0ELewKRcrdyWi+tlLFrpE5KT/s5ecbl9l -+7B61U4Kfd1PIXc/siINhU3A3bYK+845YyUArUOnKf1kEox7p1RpD7yFqVT04lRTo -+cibNKATBusXSuBrp2G6GNuhWEOSafWCKJQAzgCYIp6ZTV2khhMUGppc/2H3CF6cO -+zX0KtlPVZC7hLkB6HT8SxYUwF1zqWY7+/XPPdc37MeEZ87Q3UuZwqORLY+Z0hpgt -+L5JXBCoklZhCAaN2GqwFLXtGiRSRFGY7xXIhbDTlE65Wv1WGGgDLMKGE1gOz3yAo -+2jjG1+yAHJUdE69XTFHSqSkvaloA1W03LdMXZ9VuQJ/ySXCie6ABAQ== -+-----END RSA PRIVATE KEY----- -+-----BEGIN CERTIFICATE----- -+MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw -+MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH -+Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k -+YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -+gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7 -+6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt -+pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw -+FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd -+BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G -+lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1 -+CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX -+-----END CERTIFICATE----- -diff --git a/Lib/test/keycert3.pem b/Lib/test/keycert3.pem -new file mode 100644 -index 0000000..5bfa62c ---- /dev/null -+++ b/Lib/test/keycert3.pem -@@ -0,0 +1,73 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMLgD0kAKDb5cFyP -+jbwNfR5CtewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM -+9z2j1OlaN+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZ -+aggEdkj1TsSsv1zWIYKlPIjlvhuxAgMBAAECgYA0aH+T2Vf3WOPv8KdkcJg6gCRe -+yJKXOWgWRcicx/CUzOEsTxmFIDPLxqAWA3k7v0B+3vjGw5Y9lycV/5XqXNoQI14j -+y09iNsumds13u5AKkGdTJnZhQ7UKdoVHfuP44ZdOv/rJ5/VD6F4zWywpe90pcbK+ -+AWDVtusgGQBSieEl1QJBAOyVrUG5l2yoUBtd2zr/kiGm/DYyXlIthQO/A3/LngDW -+5/ydGxVsT7lAVOgCsoT+0L4efTh90PjzW8LPQrPBWVMCQQDS3h/FtYYd5lfz+FNL -+9CEe1F1w9l8P749uNUD0g317zv1tatIqVCsQWHfVHNdVvfQ+vSFw38OORO00Xqs9 -+1GJrAkBkoXXEkxCZoy4PteheO/8IWWLGGr6L7di6MzFl1lIqwT6D8L9oaV2vynFT -+DnKop0pa09Unhjyw57KMNmSE2SUJAkEArloTEzpgRmCq4IK2/NpCeGdHS5uqRlbh -+1VIa/xGps7EWQl5Mn8swQDel/YP3WGHTjfx7pgSegQfkyaRtGpZ9OQJAa9Vumj8m -+JAAtI0Bnga8hgQx7BhTQY4CadDxyiRGOGYhwUzYVCqkb2sbVRH9HnwUaJT7cWBY3 -+RnJdHOMXWem7/w== -+-----END PRIVATE KEY----- -+Certificate: -+ Data: -+ Version: 1 (0x0) -+ Serial Number: 12723342612721443281 (0xb09264b1f2da21d1) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Nov 13 19:47:07 2022 GMT -+ Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=localhost -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (1024 bit) -+ Modulus: -+ 00:c2:e0:0f:49:00:28:36:f9:70:5c:8f:8d:bc:0d: -+ 7d:1e:42:b5:ec:1d:5c:2f:a4:31:70:16:0f:c0:cb: -+ c6:24:d3:be:13:16:ee:a5:67:97:03:a6:df:a9:99: -+ 96:cc:c7:2a:fb:11:7f:4e:65:4f:8a:5e:82:21:4c: -+ f7:3d:a3:d4:e9:5a:37:e7:22:fd:7e:cd:53:6d:93: -+ 34:de:9c:ad:84:a2:37:be:c5:8d:82:4f:e3:ae:23: -+ f3:be:a7:75:2c:72:0f:ea:f3:ca:cd:fc:e9:3f:b5: -+ af:56:99:6a:08:04:76:48:f5:4e:c4:ac:bf:5c:d6: -+ 21:82:a5:3c:88:e5:be:1b:b1 -+ Exponent: 65537 (0x10001) -+ Signature Algorithm: sha1WithRSAEncryption -+ 2f:42:5f:a3:09:2c:fa:51:88:c7:37:7f:ea:0e:63:f0:a2:9a: -+ e5:5a:e2:c8:20:f0:3f:60:bc:c8:0f:b6:c6:76:ce:db:83:93: -+ f5:a3:33:67:01:8e:04:cd:00:9a:73:fd:f3:35:86:fa:d7:13: -+ e2:46:c6:9d:c0:29:53:d4:a9:90:b8:77:4b:e6:83:76:e4:92: -+ d6:9c:50:cf:43:d0:c6:01:77:61:9a:de:9b:70:f7:72:cd:59: -+ 00:31:69:d9:b4:ca:06:9c:6d:c3:c7:80:8c:68:e6:b5:a2:f8: -+ ef:1d:bb:16:9f:77:77:ef:87:62:22:9b:4d:69:a4:3a:1a:f1: -+ 21:5e:8c:32:ac:92:fd:15:6b:18:c2:7f:15:0d:98:30:ca:75: -+ 8f:1a:71:df:da:1d:b2:ef:9a:e8:2d:2e:02:fd:4a:3c:aa:96: -+ 0b:06:5d:35:b3:3d:24:87:4b:e0:b0:58:60:2f:45:ac:2e:48: -+ 8a:b0:99:10:65:27:ff:cc:b1:d8:fd:bd:26:6b:b9:0c:05:2a: -+ f4:45:63:35:51:07:ed:83:85:fe:6f:69:cb:bb:40:a8:ae:b6: -+ 3b:56:4a:2d:a4:ed:6d:11:2c:4d:ed:17:24:fd:47:bc:d3:41: -+ a2:d3:06:fe:0c:90:d8:d8:94:26:c4:ff:cc:a1:d8:42:77:eb: -+ fc:a9:94:71 -+-----BEGIN CERTIFICATE----- -+MIICpDCCAYwCCQCwkmSx8toh0TANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY -+WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV -+BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3 -+WjBfMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV -+BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRIwEAYDVQQDEwlsb2NhbGhv -+c3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMLgD0kAKDb5cFyPjbwNfR5C -+tewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM9z2j1Ola -+N+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZaggEdkj1 -+TsSsv1zWIYKlPIjlvhuxAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAC9CX6MJLPpR -+iMc3f+oOY/CimuVa4sgg8D9gvMgPtsZ2ztuDk/WjM2cBjgTNAJpz/fM1hvrXE+JG -+xp3AKVPUqZC4d0vmg3bkktacUM9D0MYBd2Ga3ptw93LNWQAxadm0ygacbcPHgIxo -+5rWi+O8duxafd3fvh2Iim01ppDoa8SFejDKskv0VaxjCfxUNmDDKdY8acd/aHbLv -+mugtLgL9SjyqlgsGXTWzPSSHS+CwWGAvRawuSIqwmRBlJ//Msdj9vSZruQwFKvRF -+YzVRB+2Dhf5vacu7QKiutjtWSi2k7W0RLE3tFyT9R7zTQaLTBv4MkNjYlCbE/8yh -+2EJ36/yplHE= -+-----END CERTIFICATE----- -diff --git a/Lib/test/keycert4.pem b/Lib/test/keycert4.pem -new file mode 100644 -index 0000000..53355c8 ---- /dev/null -+++ b/Lib/test/keycert4.pem -@@ -0,0 +1,73 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK5UQiMI5VkNs2Qv -+L7gUaiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2 -+NkX0ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1 -+L2OQhEx1GM6RydHdgX69G64LXcY5AgMBAAECgYAhsRMfJkb9ERLMl/oG/5sLQu9L -+pWDKt6+ZwdxzlZbggQ85CMYshjLKIod2DLL/sLf2x1PRXyRG131M1E3k8zkkz6de -+R1uDrIN/x91iuYzfLQZGh8bMY7Yjd2eoroa6R/7DjpElGejLxOAaDWO0ST2IFQy9 -+myTGS2jSM97wcXfsSQJBANP3jelJoS5X6BRjTSneY21wcocxVuQh8pXpErALVNsT -+drrFTeaBuZp7KvbtnIM5g2WRNvaxLZlAY/hXPJvi6ncCQQDSix1cebml6EmPlEZS -+Mm8gwI2F9ufUunwJmBJcz826Do0ZNGByWDAM/JQZH4FX4GfAFNuj8PUb+GQfadkx -+i1DPAkEA0lVsNHojvuDsIo8HGuzarNZQT2beWjJ1jdxh9t7HrTx7LIps6rb/fhOK -+Zs0R6gVAJaEbcWAPZ2tFyECInAdnsQJAUjaeXXjuxFkjOFym5PvqpvhpivEx78Bu -+JPTr3rAKXmfGMxxfuOa0xK1wSyshP6ZR/RBn/+lcXPKubhHQDOegwwJAJF1DBQnN -++/tLmOPULtDwfP4Zixn+/8GmGOahFoRcu6VIGHmRilJTn6MOButw7Glv2YdeC6l/ -+e83Gq6ffLVfKNQ== -+-----END PRIVATE KEY----- -+Certificate: -+ Data: -+ Version: 1 (0x0) -+ Serial Number: 12723342612721443282 (0xb09264b1f2da21d2) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Nov 13 19:47:07 2022 GMT -+ Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=fakehostname -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (1024 bit) -+ Modulus: -+ 00:ae:54:42:23:08:e5:59:0d:b3:64:2f:2f:b8:14: -+ 6a:20:dd:15:eb:cd:51:74:63:53:80:c7:01:ed:d9: -+ cf:36:0b:64:d1:3a:f6:1f:60:3b:d5:42:49:2d:7a: -+ b4:9e:5f:4f:95:44:bb:41:19:c8:6a:f4:7b:75:76: -+ 36:45:f4:66:85:34:1d:cf:d4:69:8e:2a:c7:b2:c7: -+ 9a:7e:52:61:9a:48:c6:12:67:91:fe:d2:c8:72:4a: -+ d7:35:1a:1a:55:34:fc:bc:58:a8:8b:86:0a:d1:79: -+ 76:ac:75:2f:63:90:84:4c:75:18:ce:91:c9:d1:dd: -+ 81:7e:bd:1b:ae:0b:5d:c6:39 -+ Exponent: 65537 (0x10001) -+ Signature Algorithm: sha1WithRSAEncryption -+ ad:45:8a:8e:ef:c6:ef:04:41:5c:2c:4a:84:dc:02:76:0c:d0: -+ 66:0f:f0:16:04:58:4d:fd:68:b7:b8:d3:a8:41:a5:5c:3c:6f: -+ 65:3c:d1:f8:ce:43:35:e7:41:5f:53:3d:c9:2c:c3:7d:fc:56: -+ 4a:fa:47:77:38:9d:bb:97:28:0a:3b:91:19:7f:bc:74:ae:15: -+ 6b:bd:20:36:67:45:a5:1e:79:d7:75:e6:89:5c:6d:54:84:d1: -+ 95:d7:a7:b4:33:3c:af:37:c4:79:8f:5e:75:dc:75:c2:18:fb: -+ 61:6f:2d:dc:38:65:5b:ba:67:28:d0:88:d7:8d:b9:23:5a:8e: -+ e8:c6:bb:db:ce:d5:b8:41:2a:ce:93:08:b6:95:ad:34:20:18: -+ d5:3b:37:52:74:50:0b:07:2c:b0:6d:a4:4c:7b:f4:e0:fd:d1: -+ af:17:aa:20:cd:62:e3:f0:9d:37:69:db:41:bd:d4:1c:fb:53: -+ 20:da:88:9d:76:26:67:ce:01:90:a7:80:1d:a9:5b:39:73:68: -+ 54:0a:d1:2a:03:1b:8f:3c:43:5d:5d:c4:51:f1:a7:e7:11:da: -+ 31:2c:49:06:af:04:f4:b8:3c:99:c4:20:b9:06:36:a2:00:92: -+ 61:1d:0c:6d:24:05:e2:82:e1:47:db:a0:5f:ba:b9:fb:ba:fa: -+ 49:12:1e:ce -+-----BEGIN CERTIFICATE----- -+MIICpzCCAY8CCQCwkmSx8toh0jANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY -+WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV -+BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3 -+WjBiMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV -+BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRUwEwYDVQQDEwxmYWtlaG9z -+dG5hbWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK5UQiMI5VkNs2QvL7gU -+aiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2NkX0 -+ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1L2OQ -+hEx1GM6RydHdgX69G64LXcY5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAK1Fio7v -+xu8EQVwsSoTcAnYM0GYP8BYEWE39aLe406hBpVw8b2U80fjOQzXnQV9TPcksw338 -+Vkr6R3c4nbuXKAo7kRl/vHSuFWu9IDZnRaUeedd15olcbVSE0ZXXp7QzPK83xHmP -+XnXcdcIY+2FvLdw4ZVu6ZyjQiNeNuSNajujGu9vO1bhBKs6TCLaVrTQgGNU7N1J0 -+UAsHLLBtpEx79OD90a8XqiDNYuPwnTdp20G91Bz7UyDaiJ12JmfOAZCngB2pWzlz -+aFQK0SoDG488Q11dxFHxp+cR2jEsSQavBPS4PJnEILkGNqIAkmEdDG0kBeKC4Ufb -+oF+6ufu6+kkSHs4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py -new file mode 100644 -index 0000000..81d04f8 ---- /dev/null -+++ b/Lib/test/make_ssl_certs.py -@@ -0,0 +1,176 @@ -+"""Make the custom certificate and private key files used by test_ssl -+and friends.""" -+ -+import os -+import shutil -+import sys -+import tempfile -+from subprocess import * -+ -+req_template = """ -+ [req] -+ distinguished_name = req_distinguished_name -+ x509_extensions = req_x509_extensions -+ prompt = no -+ -+ [req_distinguished_name] -+ C = XY -+ L = Castle Anthrax -+ O = Python Software Foundation -+ CN = {hostname} -+ -+ [req_x509_extensions] -+ subjectAltName = DNS:{hostname} -+ -+ [ ca ] -+ default_ca = CA_default -+ -+ [ CA_default ] -+ dir = cadir -+ database = $dir/index.txt -+ crlnumber = $dir/crl.txt -+ default_md = sha1 -+ default_days = 3600 -+ default_crl_days = 3600 -+ certificate = pycacert.pem -+ private_key = pycakey.pem -+ serial = $dir/serial -+ RANDFILE = $dir/.rand -+ -+ policy = policy_match -+ -+ [ policy_match ] -+ countryName = match -+ stateOrProvinceName = optional -+ organizationName = match -+ organizationalUnitName = optional -+ commonName = supplied -+ emailAddress = optional -+ -+ [ policy_anything ] -+ countryName = optional -+ stateOrProvinceName = optional -+ localityName = optional -+ organizationName = optional -+ organizationalUnitName = optional -+ commonName = supplied -+ emailAddress = optional -+ -+ -+ [ v3_ca ] -+ -+ subjectKeyIdentifier=hash -+ authorityKeyIdentifier=keyid:always,issuer -+ basicConstraints = CA:true -+ -+ """ -+ -+here = os.path.abspath(os.path.dirname(__file__)) -+ -+def make_cert_key(hostname, sign=False): -+ print("creating cert for " + hostname) -+ tempnames = [] -+ for i in range(3): -+ with tempfile.NamedTemporaryFile(delete=False) as f: -+ tempnames.append(f.name) -+ req_file, cert_file, key_file = tempnames -+ try: -+ with open(req_file, 'w') as f: -+ f.write(req_template.format(hostname=hostname)) -+ args = ['req', '-new', '-days', '3650', '-nodes', -+ '-newkey', 'rsa:1024', '-keyout', key_file, -+ '-config', req_file] -+ if sign: -+ with tempfile.NamedTemporaryFile(delete=False) as f: -+ tempnames.append(f.name) -+ reqfile = f.name -+ args += ['-out', reqfile ] -+ -+ else: -+ args += ['-x509', '-out', cert_file ] -+ check_call(['openssl'] + args) -+ -+ if sign: -+ args = ['ca', '-config', req_file, '-out', cert_file, '-outdir', 'cadir', -+ '-policy', 'policy_anything', '-batch', '-infiles', reqfile ] -+ check_call(['openssl'] + args) -+ -+ -+ with open(cert_file, 'r') as f: -+ cert = f.read() -+ with open(key_file, 'r') as f: -+ key = f.read() -+ return cert, key -+ finally: -+ for name in tempnames: -+ os.remove(name) -+ -+TMP_CADIR = 'cadir' -+ -+def unmake_ca(): -+ shutil.rmtree(TMP_CADIR) -+ -+def make_ca(): -+ os.mkdir(TMP_CADIR) -+ with open(os.path.join('cadir','index.txt'),'a+') as f: -+ pass # empty file -+ with open(os.path.join('cadir','crl.txt'),'a+') as f: -+ f.write("00") -+ with open(os.path.join('cadir','index.txt.attr'),'w+') as f: -+ f.write('unique_subject = no') -+ -+ with tempfile.NamedTemporaryFile("w") as t: -+ t.write(req_template.format(hostname='our-ca-server')) -+ t.flush() -+ with tempfile.NamedTemporaryFile() as f: -+ args = ['req', '-new', '-days', '3650', '-extensions', 'v3_ca', '-nodes', -+ '-newkey', 'rsa:2048', '-keyout', 'pycakey.pem', -+ '-out', f.name, -+ '-subj', '/C=XY/L=Castle Anthrax/O=Python Software Foundation CA/CN=our-ca-server'] -+ check_call(['openssl'] + args) -+ args = ['ca', '-config', t.name, '-create_serial', -+ '-out', 'pycacert.pem', '-batch', '-outdir', TMP_CADIR, -+ '-keyfile', 'pycakey.pem', '-days', '3650', -+ '-selfsign', '-extensions', 'v3_ca', '-infiles', f.name ] -+ check_call(['openssl'] + args) -+ args = ['ca', '-config', t.name, '-gencrl', '-out', 'revocation.crl'] -+ check_call(['openssl'] + args) -+ -+if __name__ == '__main__': -+ os.chdir(here) -+ cert, key = make_cert_key('localhost') -+ with open('ssl_cert.pem', 'w') as f: -+ f.write(cert) -+ with open('ssl_key.pem', 'w') as f: -+ f.write(key) -+ print("password protecting ssl_key.pem in ssl_key.passwd.pem") -+ check_call(['openssl','rsa','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-des3','-passout','pass:somepass']) -+ check_call(['openssl','rsa','-in','ssl_key.pem','-out','keycert.passwd.pem','-des3','-passout','pass:somepass']) -+ -+ with open('keycert.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ with open('keycert.passwd.pem', 'a+') as f: -+ f.write(cert) -+ -+ # For certificate matching tests -+ make_ca() -+ cert, key = make_cert_key('fakehostname') -+ with open('keycert2.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ cert, key = make_cert_key('localhost', True) -+ with open('keycert3.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ cert, key = make_cert_key('fakehostname', True) -+ with open('keycert4.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ unmake_ca() -+ print("\n\nPlease change the values in test_ssl.py, test_parse_cert function related to notAfter,notBefore and serialNumber") -+ check_call(['openssl','x509','-in','keycert.pem','-dates','-serial','-noout']) -diff --git a/Lib/test/pycacert.pem b/Lib/test/pycacert.pem -new file mode 100644 -index 0000000..09b1f3e ---- /dev/null -+++ b/Lib/test/pycacert.pem -@@ -0,0 +1,78 @@ -+Certificate: -+ Data: -+ Version: 3 (0x2) -+ Serial Number: 12723342612721443280 (0xb09264b1f2da21d0) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Jan 2 19:47:07 2023 GMT -+ Subject: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (2048 bit) -+ Modulus: -+ 00:e7:de:e9:e3:0c:9f:00:b6:a1:fd:2b:5b:96:d2: -+ 6f:cc:e0:be:86:b9:20:5e:ec:03:7a:55:ab:ea:a4: -+ e9:f9:49:85:d2:66:d5:ed:c7:7a:ea:56:8e:2d:8f: -+ e7:42:e2:62:28:a9:9f:d6:1b:8e:eb:b5:b4:9c:9f: -+ 14:ab:df:e6:94:8b:76:1d:3e:6d:24:61:ed:0c:bf: -+ 00:8a:61:0c:df:5c:c8:36:73:16:00:cd:47:ba:6d: -+ a4:a4:74:88:83:23:0a:19:fc:09:a7:3c:4a:4b:d3: -+ e7:1d:2d:e4:ea:4c:54:21:f3:26:db:89:37:18:d4: -+ 02:bb:40:32:5f:a4:ff:2d:1c:f7:d4:bb:ec:8e:cf: -+ 5c:82:ac:e6:7c:08:6c:48:85:61:07:7f:25:e0:5c: -+ e0:bc:34:5f:e0:b9:04:47:75:c8:47:0b:8d:bc:d6: -+ c8:68:5f:33:83:62:d2:20:44:35:b1:ad:81:1a:8a: -+ cd:bc:35:b0:5c:8b:47:d6:18:e9:9c:18:97:cc:01: -+ 3c:29:cc:e8:1e:e4:e4:c1:b8:de:e7:c2:11:18:87: -+ 5a:93:34:d8:a6:25:f7:14:71:eb:e4:21:a2:d2:0f: -+ 2e:2e:d4:62:00:35:d3:d6:ef:5c:60:4b:4c:a9:14: -+ e2:dd:15:58:46:37:33:26:b7:e7:2e:5d:ed:42:e4: -+ c5:4d -+ Exponent: 65537 (0x10001) -+ X509v3 extensions: -+ X509v3 Subject Key Identifier: -+ BC:DD:62:D9:76:DA:1B:D2:54:6B:CF:E0:66:9B:1E:1E:7B:56:0C:0B -+ X509v3 Authority Key Identifier: -+ keyid:BC:DD:62:D9:76:DA:1B:D2:54:6B:CF:E0:66:9B:1E:1E:7B:56:0C:0B -+ -+ X509v3 Basic Constraints: -+ CA:TRUE -+ Signature Algorithm: sha1WithRSAEncryption -+ 7d:0a:f5:cb:8d:d3:5d:bd:99:8e:f8:2b:0f:ba:eb:c2:d9:a6: -+ 27:4f:2e:7b:2f:0e:64:d8:1c:35:50:4e:ee:fc:90:b9:8d:6d: -+ a8:c5:c6:06:b0:af:f3:2d:bf:3b:b8:42:07:dd:18:7d:6d:95: -+ 54:57:85:18:60:47:2f:eb:78:1b:f9:e8:17:fd:5a:0d:87:17: -+ 28:ac:4c:6a:e6:bc:29:f4:f4:55:70:29:42:de:85:ea:ab:6c: -+ 23:06:64:30:75:02:8e:53:bc:5e:01:33:37:cc:1e:cd:b8:a4: -+ fd:ca:e4:5f:65:3b:83:1c:86:f1:55:02:a0:3a:8f:db:91:b7: -+ 40:14:b4:e7:8d:d2:ee:73:ba:e3:e5:34:2d:bc:94:6f:4e:24: -+ 06:f7:5f:8b:0e:a7:8e:6b:de:5e:75:f4:32:9a:50:b1:44:33: -+ 9a:d0:05:e2:78:82:ff:db:da:8a:63:eb:a9:dd:d1:bf:a0:61: -+ ad:e3:9e:8a:24:5d:62:0e:e7:4c:91:7f:ef:df:34:36:3b:2f: -+ 5d:f5:84:b2:2f:c4:6d:93:96:1a:6f:30:28:f1:da:12:9a:64: -+ b4:40:33:1d:bd:de:2b:53:a8:ea:be:d6:bc:4e:96:f5:44:fb: -+ 32:18:ae:d5:1f:f6:69:af:b6:4e:7b:1d:58:ec:3b:a9:53:a3: -+ 5e:58:c8:9e -+-----BEGIN CERTIFICATE----- -+MIIDbTCCAlWgAwIBAgIJALCSZLHy2iHQMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV -+BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW -+MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xMzAxMDQxOTQ3MDdaFw0yMzAxMDIx -+OTQ3MDdaME0xCzAJBgNVBAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUg -+Rm91bmRhdGlvbiBDQTEWMBQGA1UEAwwNb3VyLWNhLXNlcnZlcjCCASIwDQYJKoZI -+hvcNAQEBBQADggEPADCCAQoCggEBAOfe6eMMnwC2of0rW5bSb8zgvoa5IF7sA3pV -+q+qk6flJhdJm1e3HeupWji2P50LiYiipn9Ybjuu1tJyfFKvf5pSLdh0+bSRh7Qy/ -+AIphDN9cyDZzFgDNR7ptpKR0iIMjChn8Cac8SkvT5x0t5OpMVCHzJtuJNxjUArtA -+Ml+k/y0c99S77I7PXIKs5nwIbEiFYQd/JeBc4Lw0X+C5BEd1yEcLjbzWyGhfM4Ni -+0iBENbGtgRqKzbw1sFyLR9YY6ZwYl8wBPCnM6B7k5MG43ufCERiHWpM02KYl9xRx -+6+QhotIPLi7UYgA109bvXGBLTKkU4t0VWEY3Mya35y5d7ULkxU0CAwEAAaNQME4w -+HQYDVR0OBBYEFLzdYtl22hvSVGvP4GabHh57VgwLMB8GA1UdIwQYMBaAFLzdYtl2 -+2hvSVGvP4GabHh57VgwLMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB -+AH0K9cuN0129mY74Kw+668LZpidPLnsvDmTYHDVQTu78kLmNbajFxgawr/Mtvzu4 -+QgfdGH1tlVRXhRhgRy/reBv56Bf9Wg2HFyisTGrmvCn09FVwKULeheqrbCMGZDB1 -+Ao5TvF4BMzfMHs24pP3K5F9lO4MchvFVAqA6j9uRt0AUtOeN0u5zuuPlNC28lG9O -+JAb3X4sOp45r3l519DKaULFEM5rQBeJ4gv/b2opj66nd0b+gYa3jnookXWIO50yR -+f+/fNDY7L131hLIvxG2TlhpvMCjx2hKaZLRAMx293itTqOq+1rxOlvVE+zIYrtUf -+9mmvtk57HVjsO6lTo15YyJ4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/revocation.crl b/Lib/test/revocation.crl -new file mode 100644 -index 0000000..6d89b08 ---- /dev/null -+++ b/Lib/test/revocation.crl -@@ -0,0 +1,11 @@ -+-----BEGIN X509 CRL----- -+MIIBpjCBjwIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJYWTEmMCQGA1UE -+CgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNVBAMMDW91ci1j -+YS1zZXJ2ZXIXDTEzMTEyMTE3MDg0N1oXDTIzMDkzMDE3MDg0N1qgDjAMMAoGA1Ud -+FAQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQCNJXC2mVKauEeN3LlQ3ZtM5gkH3ExH -++i4bmJjtJn497WwvvoIeUdrmVXgJQR93RtV37hZwN0SXMLlNmUZPH4rHhihayw4m -+unCzVj/OhCCY7/TPjKuJ1O/0XhaLBpBVjQN7R/1ujoRKbSia/CD3vcn7Fqxzw7LK -+fSRCKRGTj1CZiuxrphtFchwALXSiFDy9mr2ZKhImcyq1PydfgEzU78APpOkMQsIC -+UNJ/cf3c9emzf+dUtcMEcejQ3mynBo4eIGg1EW42bz4q4hSjzQlKcBV0muw5qXhc -+HOxH2iTFhQ7SrvVuK/dM14rYM4B5mSX3nRC1kNmXpS9j3wJDhuwmjHed -+-----END X509 CRL----- -diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem -index 9475576..d3db4b8 100644 ---- a/Lib/test/sha256.pem -+++ b/Lib/test/sha256.pem -@@ -1,128 +1,128 @@ - # Certificate chain for https://sha256.tbs-internet.com -- 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com -- i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -+ 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com -+ i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - -----BEGIN CERTIFICATE----- --MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB --yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu --MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k --aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y --eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD --QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw --CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w --CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV --BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV --BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 --LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg --jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN --G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli --LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI --eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK --DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 --4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV --I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC --BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw --TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov --L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx --aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy --bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l --c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny --dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF --BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu --Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R --BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN --BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse --3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 --SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No --WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 --oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW --zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== -+MIIGXDCCBUSgAwIBAgIRAKpVmHgg9nfCodAVwcP4siwwDQYJKoZIhvcNAQELBQAw -+gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -+bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -+ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -+cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -+Q0EgU0dDMB4XDTEyMDEwNDAwMDAwMFoXDTE0MDIxNzIzNTk1OVowgcsxCzAJBgNV -+BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -+BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -+VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -+c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -+LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQIX/zdJcyxty0m -+PM1XQSoSSifueS3AVcgqMsaIKS/u+rYzsv4hQ/qA6vLn5m5/ewUcZDj7zdi6rBVf -+PaVNXJ6YinLX0tkaW8TEjeVuZG5yksGZlhCt1CJ1Ho9XLiLaP4uJ7MCoNUntpJ+E -+LfrOdgsIj91kPmwjDJeztVcQCvKzhjVJA/KxdInc0JvOATn7rpaSmQI5bvIjufgo -+qVsTPwVFzuUYULXBk7KxRT7MiEqnd5HvviNh0285QC478zl3v0I0Fb5El4yD3p49 -+IthcRnxzMKc0UhU5ogi0SbONyBfm/mzONVfSxpM+MlyvZmJqrbuuLoEDzJD+t8PU -+xSuzgbcCAwEAAaOCAj4wggI6MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -+2YIfMB0GA1UdDgQWBBT/qTGYdaj+f61c2IRFL/B1eEsM8DAOBgNVHQ8BAf8EBAMC -+BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -+CisGAQQBgjcKAwMGCWCGSAGG+EIEATBLBgNVHSAERDBCMEAGCisGAQQB5TcCBAEw -+MjAwBggrBgEFBQcCARYkaHR0cHM6Ly93d3cudGJzLWludGVybmV0LmNvbS9DQS9D -+UFM0MG0GA1UdHwRmMGQwMqAwoC6GLGh0dHA6Ly9jcmwudGJzLWludGVybmV0LmNv -+bS9UQlNYNTA5Q0FTR0MuY3JsMC6gLKAqhihodHRwOi8vY3JsLnRicy14NTA5LmNv -+bS9UQlNYNTA5Q0FTR0MuY3JsMIGmBggrBgEFBQcBAQSBmTCBljA4BggrBgEFBQcw -+AoYsaHR0cDovL2NydC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQVNHQy5jcnQw -+NAYIKwYBBQUHMAKGKGh0dHA6Ly9jcnQudGJzLXg1MDkuY29tL1RCU1g1MDlDQVNH -+Qy5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnRicy14NTA5LmNvbTA/BgNV -+HREEODA2ghdzaGEyNTYudGJzLWludGVybmV0LmNvbYIbd3d3LnNoYTI1Ni50YnMt -+aW50ZXJuZXQuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA0pOuL8QvAa5yksTbGShzX -+ABApagunUGoEydv4YJT1MXy9tTp7DrWaozZSlsqBxrYAXP1d9r2fuKbEniYHxaQ0 -+UYaf1VSIlDo1yuC8wE7wxbHDIpQ/E5KAyxiaJ8obtDhFstWAPAH+UoGXq0kj2teN -+21sFQ5dXgA95nldvVFsFhrRUNB6xXAcaj0VZFhttI0ZfQZmQwEI/P+N9Jr40OGun -+aa+Dn0TMeUH4U20YntfLbu2nDcJcYfyurm+8/0Tr4HznLnedXu9pCPYj0TaddrgT -+XO0oFiyy7qGaY6+qKh71yD64Y3ycCJ/HR9Wm39mjZYc9ezYwT4noP6r7Lk8YO7/q - -----END CERTIFICATE----- -- 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -+ 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - -----BEGIN CERTIFICATE----- --MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv -+MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv - MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk - ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF --eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow --gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -+eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -+gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl - bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u - ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv --cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg --Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU --qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S --jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB --xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz --m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip --rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo --sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U --pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD --VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v --Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg --MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu --Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t --b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o --dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ --YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA --h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd --nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg --IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw --oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU --k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp --J6/5 -+cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -+Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -+rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -+9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -+ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -+owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -+Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -+9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -+2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -+MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -+AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -+ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -+by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -+cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -+VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -+ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -+AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -+euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -+1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -+RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -+8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -+v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= - -----END CERTIFICATE----- - 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root -- i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -+ i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - -----BEGIN CERTIFICATE----- --MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB --lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -+MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug - Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho --dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt --SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD --VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 --IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h --bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by --AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa --gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U --j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O --n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q --fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 --e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF --lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E --BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f --BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly --c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW --onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a --gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o --2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk --I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X --OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 --jIGZ -+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -+IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -+AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -+ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -+IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -+4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -+2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -+alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -+u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -+xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -+XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -+tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -+BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -+BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -+L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -+AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -+rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -+FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -++bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -+3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -++M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= - -----END CERTIFICATE----- -- 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -- i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -+ 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC -+ i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - -----BEGIN CERTIFICATE----- --MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB --lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug - Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho --dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt --SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG --A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe --MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v --d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh --cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn --0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ --M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a --MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd --oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI --DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy --oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD --VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 --dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy --bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF --BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM --//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli --CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE --CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t --3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS --KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -+IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -+EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -+VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -+dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -+E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -+D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -+4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -+lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -+bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -+o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -+MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -+LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -+BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -+AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -+j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -+KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -+2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -+mfnGV/TJVTl4uix5yaaIK/QI - -----END CERTIFICATE----- -diff --git a/Lib/test/ssl_cert.pem b/Lib/test/ssl_cert.pem -new file mode 100644 -index 0000000..47a7d7e ---- /dev/null -+++ b/Lib/test/ssl_cert.pem -@@ -0,0 +1,15 @@ -+-----BEGIN CERTIFICATE----- -+MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw -+MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH -+Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k -+YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -+gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7 -+6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt -+pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw -+FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd -+BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G -+lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1 -+CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX -+-----END CERTIFICATE----- -diff --git a/Lib/test/ssl_key.passwd.pem b/Lib/test/ssl_key.passwd.pem -new file mode 100644 -index 0000000..2524672 ---- /dev/null -+++ b/Lib/test/ssl_key.passwd.pem -@@ -0,0 +1,18 @@ -+-----BEGIN RSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-EDE3-CBC,1A8D9D2A02EC698A -+ -+kJYbfZ8L0sfe9Oty3gw0aloNnY5E8fegRfQLZlNoxTl6jNt0nIwI8kDJ36CZgR9c -+u3FDJm/KqrfUoz8vW+qEnWhSG7QPX2wWGPHd4K94Yz/FgrRzZ0DoK7XxXq9gOtVA -+AVGQhnz32p+6WhfGsCr9ArXEwRZrTk/FvzEPaU5fHcoSkrNVAGX8IpSVkSDwEDQr -+Gv17+cfk99UV1OCza6yKHoFkTtrC+PZU71LomBabivS2Oc4B9hYuSR2hF01wTHP+ -+YlWNagZOOVtNz4oKK9x9eNQpmfQXQvPPTfusexKIbKfZrMvJoxcm1gfcZ0H/wK6P -+6wmXSG35qMOOztCZNtperjs1wzEBXznyK8QmLcAJBjkfarABJX9vBEzZV0OUKhy+ -+noORFwHTllphbmydLhu6ehLUZMHPhzAS5UN7srtpSN81eerDMy0RMUAwA7/PofX1 -+94Me85Q8jP0PC9ETdsJcPqLzAPETEYu0ELewKRcrdyWi+tlLFrpE5KT/s5ecbl9l -+7B61U4Kfd1PIXc/siINhU3A3bYK+845YyUArUOnKf1kEox7p1RpD7yFqVT04lRTo -+cibNKATBusXSuBrp2G6GNuhWEOSafWCKJQAzgCYIp6ZTV2khhMUGppc/2H3CF6cO -+zX0KtlPVZC7hLkB6HT8SxYUwF1zqWY7+/XPPdc37MeEZ87Q3UuZwqORLY+Z0hpgt -+L5JXBCoklZhCAaN2GqwFLXtGiRSRFGY7xXIhbDTlE65Wv1WGGgDLMKGE1gOz3yAo -+2jjG1+yAHJUdE69XTFHSqSkvaloA1W03LdMXZ9VuQJ/ySXCie6ABAQ== -+-----END RSA PRIVATE KEY----- -diff --git a/Lib/test/ssl_key.pem b/Lib/test/ssl_key.pem -new file mode 100644 -index 0000000..3fd3bbd ---- /dev/null -+++ b/Lib/test/ssl_key.pem -@@ -0,0 +1,16 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANtb0+YrKuxevGpm -+LrjaUhZSgz6zFAmuGFmKmUbdjmfv9zSmmdsQIksK++jK0Be9LeZy20j6ahOfuVa0 -+ufEmPoP7Fy4hXegKZR9cCWcIe/A6H2xWF1IIJLRTLaU8ol/I7T+um5HD5AwAwNPP -+USNU0Eegmvp+xxWu3NX2m1Veot85AgMBAAECgYA3ZdZ673X0oexFlq7AAmrutkHt -+CL7LvwrpOiaBjhyTxTeSNWzvtQBkIU8DOI0bIazA4UreAFffwtvEuPmonDb3F+Iq -+SMAu42XcGyVZEl+gHlTPU9XRX7nTOXVt+MlRRRxL6t9GkGfUAXI3XxJDXW3c0vBK -+UL9xqD8cORXOfE06rQJBAP8mEX1ERkR64Ptsoe4281vjTlNfIbs7NMPkUnrn9N/Y -+BLhjNIfQ3HFZG8BTMLfX7kCS9D593DW5tV4Z9BP/c6cCQQDcFzCcVArNh2JSywOQ -+ZfTfRbJg/Z5Lt9Fkngv1meeGNPgIMLN8Sg679pAOOWmzdMO3V706rNPzSVMME7E5 -+oPIfAkEA8pDddarP5tCvTTgUpmTFbakm0KoTZm2+FzHcnA4jRh+XNTjTOv98Y6Ik -+eO5d1ZnKXseWvkZncQgxfdnMqqpj5wJAcNq/RVne1DbYlwWchT2Si65MYmmJ8t+F -+0mcsULqjOnEMwf5e+ptq5LzwbyrHZYq5FNk7ocufPv/ZQrcSSC+cFwJBAKvOJByS -+x56qyGeZLOQlWS2JS3KJo59XuLFGqcbgN9Om9xFa41Yb4N9NvplFivsvZdw3m1Q/ -+SPIXQuT8RMPDVNQ= -+-----END PRIVATE KEY----- -diff --git a/Lib/test/ssl_servers.py b/Lib/test/ssl_servers.py -new file mode 100644 -index 0000000..a312e28 ---- /dev/null -+++ b/Lib/test/ssl_servers.py -@@ -0,0 +1,209 @@ -+import os -+import sys -+import ssl -+import pprint -+import urllib -+import urlparse -+# Rename HTTPServer to _HTTPServer so as to avoid confusion with HTTPSServer. -+from BaseHTTPServer import HTTPServer as _HTTPServer, BaseHTTPRequestHandler -+from SimpleHTTPServer import SimpleHTTPRequestHandler -+ -+from test import test_support as support -+threading = support.import_module("threading") -+ -+here = os.path.dirname(__file__) -+ -+HOST = support.HOST -+CERTFILE = os.path.join(here, 'keycert.pem') -+ -+# This one's based on HTTPServer, which is based on SocketServer -+ -+class HTTPSServer(_HTTPServer): -+ -+ def __init__(self, server_address, handler_class, context): -+ _HTTPServer.__init__(self, server_address, handler_class) -+ self.context = context -+ -+ def __str__(self): -+ return ('<%s %s:%s>' % -+ (self.__class__.__name__, -+ self.server_name, -+ self.server_port)) -+ -+ def get_request(self): -+ # override this to wrap socket with SSL -+ try: -+ sock, addr = self.socket.accept() -+ sslconn = self.context.wrap_socket(sock, server_side=True) -+ except OSError as e: -+ # socket errors are silenced by the caller, print them here -+ if support.verbose: -+ sys.stderr.write("Got an error:\n%s\n" % e) -+ raise -+ return sslconn, addr -+ -+class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): -+ # need to override translate_path to get a known root, -+ # instead of using os.curdir, since the test could be -+ # run from anywhere -+ -+ server_version = "TestHTTPS/1.0" -+ root = here -+ # Avoid hanging when a request gets interrupted by the client -+ timeout = 5 -+ -+ def translate_path(self, path): -+ """Translate a /-separated PATH to the local filename syntax. -+ -+ Components that mean special things to the local file system -+ (e.g. drive or directory names) are ignored. (XXX They should -+ probably be diagnosed.) -+ -+ """ -+ # abandon query parameters -+ path = urlparse.urlparse(path)[2] -+ path = os.path.normpath(urllib.unquote(path)) -+ words = path.split('/') -+ words = filter(None, words) -+ path = self.root -+ for word in words: -+ drive, word = os.path.splitdrive(word) -+ head, word = os.path.split(word) -+ path = os.path.join(path, word) -+ return path -+ -+ def log_message(self, format, *args): -+ # we override this to suppress logging unless "verbose" -+ if support.verbose: -+ sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % -+ (self.server.server_address, -+ self.server.server_port, -+ self.request.cipher(), -+ self.log_date_time_string(), -+ format%args)) -+ -+ -+class StatsRequestHandler(BaseHTTPRequestHandler): -+ """Example HTTP request handler which returns SSL statistics on GET -+ requests. -+ """ -+ -+ server_version = "StatsHTTPS/1.0" -+ -+ def do_GET(self, send_body=True): -+ """Serve a GET request.""" -+ sock = self.rfile.raw._sock -+ context = sock.context -+ stats = { -+ 'session_cache': context.session_stats(), -+ 'cipher': sock.cipher(), -+ 'compression': sock.compression(), -+ } -+ body = pprint.pformat(stats) -+ body = body.encode('utf-8') -+ self.send_response(200) -+ self.send_header("Content-type", "text/plain; charset=utf-8") -+ self.send_header("Content-Length", str(len(body))) -+ self.end_headers() -+ if send_body: -+ self.wfile.write(body) -+ -+ def do_HEAD(self): -+ """Serve a HEAD request.""" -+ self.do_GET(send_body=False) -+ -+ def log_request(self, format, *args): -+ if support.verbose: -+ BaseHTTPRequestHandler.log_request(self, format, *args) -+ -+ -+class HTTPSServerThread(threading.Thread): -+ -+ def __init__(self, context, host=HOST, handler_class=None): -+ self.flag = None -+ self.server = HTTPSServer((host, 0), -+ handler_class or RootedHTTPRequestHandler, -+ context) -+ self.port = self.server.server_port -+ threading.Thread.__init__(self) -+ self.daemon = True -+ -+ def __str__(self): -+ return "<%s %s>" % (self.__class__.__name__, self.server) -+ -+ def start(self, flag=None): -+ self.flag = flag -+ threading.Thread.start(self) -+ -+ def run(self): -+ if self.flag: -+ self.flag.set() -+ try: -+ self.server.serve_forever(0.05) -+ finally: -+ self.server.server_close() -+ -+ def stop(self): -+ self.server.shutdown() -+ -+ -+def make_https_server(case, context=None, certfile=CERTFILE, -+ host=HOST, handler_class=None): -+ if context is None: -+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ # We assume the certfile contains both private key and certificate -+ context.load_cert_chain(certfile) -+ server = HTTPSServerThread(context, host, handler_class) -+ flag = threading.Event() -+ server.start(flag) -+ flag.wait() -+ def cleanup(): -+ if support.verbose: -+ sys.stdout.write('stopping HTTPS server\n') -+ server.stop() -+ if support.verbose: -+ sys.stdout.write('joining HTTPS thread\n') -+ server.join() -+ case.addCleanup(cleanup) -+ return server -+ -+ -+if __name__ == "__main__": -+ import argparse -+ parser = argparse.ArgumentParser( -+ description='Run a test HTTPS server. ' -+ 'By default, the current directory is served.') -+ parser.add_argument('-p', '--port', type=int, default=4433, -+ help='port to listen on (default: %(default)s)') -+ parser.add_argument('-q', '--quiet', dest='verbose', default=True, -+ action='store_false', help='be less verbose') -+ parser.add_argument('-s', '--stats', dest='use_stats_handler', default=False, -+ action='store_true', help='always return stats page') -+ parser.add_argument('--curve-name', dest='curve_name', type=str, -+ action='store', -+ help='curve name for EC-based Diffie-Hellman') -+ parser.add_argument('--ciphers', dest='ciphers', type=str, -+ help='allowed cipher list') -+ parser.add_argument('--dh', dest='dh_file', type=str, action='store', -+ help='PEM file containing DH parameters') -+ args = parser.parse_args() -+ -+ support.verbose = args.verbose -+ if args.use_stats_handler: -+ handler_class = StatsRequestHandler -+ else: -+ handler_class = RootedHTTPRequestHandler -+ handler_class.root = os.getcwd() -+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ context.load_cert_chain(CERTFILE) -+ if args.curve_name: -+ context.set_ecdh_curve(args.curve_name) -+ if args.dh_file: -+ context.load_dh_params(args.dh_file) -+ if args.ciphers: -+ context.set_ciphers(args.ciphers) -+ -+ server = HTTPSServer(("", args.port), handler_class, context) -+ if args.verbose: -+ print("Listening on https://localhost:{0.port}".format(args)) -+ server.serve_forever(0.1) -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index 91b8029..a629e1b 100644 ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -1,35 +1,78 @@ -+# -*- encoding: utf-8 -*- - # Test the support for SSL and sockets - - import sys - import unittest --from test import test_support -+from test import test_support as support - import asyncore - import socket - import select - import time -+import datetime - import gc - import os - import errno - import pprint --import urllib, urlparse -+import tempfile -+import urllib - import traceback - import weakref --import functools - import platform -+import functools -+from contextlib import closing -+ -+ssl = support.import_module("ssl") -+ -+PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) -+HOST = support.HOST -+ -+def data_file(*name): -+ return os.path.join(os.path.dirname(__file__), *name) -+ -+# The custom key and certificate files used in test_ssl are generated -+# using Lib/test/make_ssl_certs.py. -+# Other certificates are simply fetched from the Internet servers they -+# are meant to authenticate. -+ -+CERTFILE = data_file("keycert.pem") -+BYTES_CERTFILE = CERTFILE.encode(sys.getfilesystemencoding()) -+ONLYCERT = data_file("ssl_cert.pem") -+ONLYKEY = data_file("ssl_key.pem") -+BYTES_ONLYCERT = ONLYCERT.encode(sys.getfilesystemencoding()) -+BYTES_ONLYKEY = ONLYKEY.encode(sys.getfilesystemencoding()) -+CERTFILE_PROTECTED = data_file("keycert.passwd.pem") -+ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem") -+KEY_PASSWORD = "somepass" -+CAPATH = data_file("capath") -+BYTES_CAPATH = CAPATH.encode(sys.getfilesystemencoding()) -+CAFILE_NEURONIO = data_file("capath", "4e1295a3.0") -+CAFILE_CACERT = data_file("capath", "5ed36f99.0") -+ -+ -+# empty CRL -+CRLFILE = data_file("revocation.crl") -+ -+# Two keys and certs signed by the same CA (for SNI tests) -+SIGNED_CERTFILE = data_file("keycert3.pem") -+SIGNED_CERTFILE2 = data_file("keycert4.pem") -+SIGNING_CA = data_file("pycacert.pem") -+ -+SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem") - --from BaseHTTPServer import HTTPServer --from SimpleHTTPServer import SimpleHTTPRequestHandler -+EMPTYCERT = data_file("nullcert.pem") -+BADCERT = data_file("badcert.pem") -+WRONGCERT = data_file("XXXnonexisting.pem") -+BADKEY = data_file("badkey.pem") -+NOKIACERT = data_file("nokia.pem") -+NULLBYTECERT = data_file("nullbytecert.pem") - --ssl = test_support.import_module("ssl") -+DHFILE = data_file("dh512.pem") -+BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding()) - --HOST = test_support.HOST --CERTFILE = None --SVN_PYTHON_ORG_ROOT_CERT = None --NULLBYTECERT = None - - def handle_error(prefix): - exc_format = ' '.join(traceback.format_exception(*sys.exc_info())) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(prefix + exc_format) - - -@@ -51,48 +94,76 @@ class BasicTests(unittest.TestCase): - pass - else: - raise -+def can_clear_options(): -+ # 0.9.8m or higher -+ return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15) -+ -+def no_sslv2_implies_sslv3_hello(): -+ # 0.9.7h or higher -+ return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15) -+ -+def have_verify_flags(): -+ # 0.9.8 or higher -+ return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15) -+ -+def utc_offset(): #NOTE: ignore issues like #1647654 -+ # local time = utc time + utc offset -+ if time.daylight and time.localtime().tm_isdst > 0: -+ return -time.altzone # seconds -+ return -time.timezone -+ -+def asn1time(cert_time): -+ # Some versions of OpenSSL ignore seconds, see #18207 -+ # 0.9.8.i -+ if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15): -+ fmt = "%b %d %H:%M:%S %Y GMT" -+ dt = datetime.datetime.strptime(cert_time, fmt) -+ dt = dt.replace(second=0) -+ cert_time = dt.strftime(fmt) -+ # %d adds leading zero but ASN1_TIME_print() uses leading space -+ if cert_time[4] == "0": -+ cert_time = cert_time[:4] + " " + cert_time[5:] -+ -+ return cert_time - - # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 - def skip_if_broken_ubuntu_ssl(func): - if hasattr(ssl, 'PROTOCOL_SSLv2'): -- # We need to access the lower-level wrapper in order to create an -- # implicit SSL context without trying to connect or listen. -- try: -- import _ssl -- except ImportError: -- # The returned function won't get executed, just ignore the error -- pass - @functools.wraps(func) - def f(*args, **kwargs): - try: -- s = socket.socket(socket.AF_INET) -- _ssl.sslwrap(s._sock, 0, None, None, -- ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None) -- except ssl.SSLError as e: -+ ssl.SSLContext(ssl.PROTOCOL_SSLv2) -+ except ssl.SSLError: - if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and -- platform.linux_distribution() == ('debian', 'squeeze/sid', '') -- and 'Invalid SSL protocol variant specified' in str(e)): -+ platform.linux_distribution() == ('debian', 'squeeze/sid', '')): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f - else: - return func - -+needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test") -+ - - class BasicSocketTests(unittest.TestCase): - - def test_constants(self): -- #ssl.PROTOCOL_SSLv2 -- ssl.PROTOCOL_SSLv23 -- ssl.PROTOCOL_SSLv3 -- ssl.PROTOCOL_TLSv1 - ssl.CERT_NONE - ssl.CERT_OPTIONAL - ssl.CERT_REQUIRED -+ ssl.OP_CIPHER_SERVER_PREFERENCE -+ ssl.OP_SINGLE_DH_USE -+ if ssl.HAS_ECDH: -+ ssl.OP_SINGLE_ECDH_USE -+ if ssl.OPENSSL_VERSION_INFO >= (1, 0): -+ ssl.OP_NO_COMPRESSION -+ self.assertIn(ssl.HAS_SNI, {True, False}) -+ self.assertIn(ssl.HAS_ECDH, {True, False}) -+ - - def test_random(self): - v = ssl.RAND_status() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n RAND_status is %d (%s)\n" - % (v, (v and "sufficient randomness") or - "insufficient randomness")) -@@ -104,9 +175,19 @@ class BasicSocketTests(unittest.TestCase): - # note that this uses an 'unofficial' function in _ssl.c, - # provided solely for this test, to exercise the certificate - # parsing code -- p = ssl._ssl._test_decode_cert(CERTFILE, False) -- if test_support.verbose: -+ p = ssl._ssl._test_decode_cert(CERTFILE) -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") -+ self.assertEqual(p['issuer'], -+ ((('countryName', 'XY'),), -+ (('localityName', 'Castle Anthrax'),), -+ (('organizationName', 'Python Software Foundation'),), -+ (('commonName', 'localhost'),)) -+ ) -+ # Note the next three asserts will fail if the keys are regenerated -+ self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT')) -+ self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT')) -+ self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E') - self.assertEqual(p['subject'], - ((('countryName', 'XY'),), - (('localityName', 'Castle Anthrax'),), -@@ -117,16 +198,22 @@ class BasicSocketTests(unittest.TestCase): - # Issue #13034: the subjectAltName in some certificates - # (notably projects.developer.nokia.com:443) wasn't parsed - p = ssl._ssl._test_decode_cert(NOKIACERT) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") - self.assertEqual(p['subjectAltName'], - (('DNS', 'projects.developer.nokia.com'), - ('DNS', 'projects.forum.nokia.com')) - ) -+ # extra OCSP and AIA fields -+ self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',)) -+ self.assertEqual(p['caIssuers'], -+ ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',)) -+ self.assertEqual(p['crlDistributionPoints'], -+ ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',)) - - def test_parse_cert_CVE_2013_4238(self): - p = ssl._ssl._test_decode_cert(NULLBYTECERT) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") - subject = ((('countryName', 'US'),), - (('stateOrProvinceName', 'Oregon'),), -@@ -137,7 +224,7 @@ class BasicSocketTests(unittest.TestCase): - (('emailAddress', 'python-dev@python.org'),)) - self.assertEqual(p['subject'], subject) - self.assertEqual(p['issuer'], subject) -- if ssl.OPENSSL_VERSION_INFO >= (0, 9, 8): -+ if ssl._OPENSSL_API_VERSION >= (0, 9, 8): - san = (('DNS', 'altnull.python.org\x00example.com'), - ('email', 'null@python.org\x00user@example.org'), - ('URI', 'http://null.python.org\x00http://example.org'), -@@ -196,24 +283,7 @@ class BasicSocketTests(unittest.TestCase): - self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)), - (s, t)) - -- @test_support.requires_resource('network') -- def test_ciphers(self): -- remote = ("svn.python.org", 443) -- with test_support.transient_internet(remote[0]): -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="ALL") -- s.connect(remote) -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") -- s.connect(remote) -- # Error checking occurs when connecting, because the SSL context -- # isn't created before. -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") -- with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -- s.connect(remote) -- -- @test_support.cpython_only -+ @support.cpython_only - def test_refcycle(self): - # Issue #7943: an SSL object doesn't create reference cycles with - # itself. -@@ -224,17 +294,319 @@ class BasicSocketTests(unittest.TestCase): - self.assertEqual(wr(), None) - - def test_wrapped_unconnected(self): -- # The _delegate_methods in socket.py are correctly delegated to by an -- # unconnected SSLSocket, so they will raise a socket.error rather than -- # something unexpected like TypeError. -+ # Methods on an unconnected SSLSocket propagate the original -+ # socket.error raise by the underlying socket object. - s = socket.socket(socket.AF_INET) -- ss = ssl.wrap_socket(s) -- self.assertRaises(socket.error, ss.recv, 1) -- self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) -- self.assertRaises(socket.error, ss.recvfrom, 1) -- self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) -- self.assertRaises(socket.error, ss.send, b'x') -- self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertRaises(socket.error, ss.recv, 1) -+ self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) -+ self.assertRaises(socket.error, ss.recvfrom, 1) -+ self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) -+ self.assertRaises(socket.error, ss.send, b'x') -+ self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) -+ -+ def test_timeout(self): -+ # Issue #8524: when creating an SSL socket, the timeout of the -+ # original socket should be retained. -+ for timeout in (None, 0.0, 5.0): -+ s = socket.socket(socket.AF_INET) -+ s.settimeout(timeout) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertEqual(timeout, ss.gettimeout()) -+ -+ def test_errors(self): -+ sock = socket.socket() -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified", -+ ssl.wrap_socket, sock, keyfile=CERTFILE) -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified for server-side operations", -+ ssl.wrap_socket, sock, server_side=True) -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified for server-side operations", -+ ssl.wrap_socket, sock, server_side=True, certfile="") -+ with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s: -+ self.assertRaisesRegexp(ValueError, "can't connect in server-side mode", -+ s.connect, (HOST, 8080)) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ -+ def test_match_hostname(self): -+ def ok(cert, hostname): -+ ssl.match_hostname(cert, hostname) -+ def fail(cert, hostname): -+ self.assertRaises(ssl.CertificateError, -+ ssl.match_hostname, cert, hostname) -+ -+ cert = {'subject': ((('commonName', 'example.com'),),)} -+ ok(cert, 'example.com') -+ ok(cert, 'ExAmple.cOm') -+ fail(cert, 'www.example.com') -+ fail(cert, '.example.com') -+ fail(cert, 'example.org') -+ fail(cert, 'exampleXcom') -+ -+ cert = {'subject': ((('commonName', '*.a.com'),),)} -+ ok(cert, 'foo.a.com') -+ fail(cert, 'bar.foo.a.com') -+ fail(cert, 'a.com') -+ fail(cert, 'Xa.com') -+ fail(cert, '.a.com') -+ -+ # only match one left-most wildcard -+ cert = {'subject': ((('commonName', 'f*.com'),),)} -+ ok(cert, 'foo.com') -+ ok(cert, 'f.com') -+ fail(cert, 'bar.com') -+ fail(cert, 'foo.a.com') -+ fail(cert, 'bar.foo.com') -+ -+ # NULL bytes are bad, CVE-2013-4073 -+ cert = {'subject': ((('commonName', -+ 'null.python.org\x00example.org'),),)} -+ ok(cert, 'null.python.org\x00example.org') # or raise an error? -+ fail(cert, 'example.org') -+ fail(cert, 'null.python.org') -+ -+ # error cases with wildcards -+ cert = {'subject': ((('commonName', '*.*.a.com'),),)} -+ fail(cert, 'bar.foo.a.com') -+ fail(cert, 'a.com') -+ fail(cert, 'Xa.com') -+ fail(cert, '.a.com') -+ -+ cert = {'subject': ((('commonName', 'a.*.com'),),)} -+ fail(cert, 'a.foo.com') -+ fail(cert, 'a..com') -+ fail(cert, 'a.com') -+ -+ # wildcard doesn't match IDNA prefix 'xn--' -+ idna = u'püthon.python.org'.encode("idna").decode("ascii") -+ cert = {'subject': ((('commonName', idna),),)} -+ ok(cert, idna) -+ cert = {'subject': ((('commonName', 'x*.python.org'),),)} -+ fail(cert, idna) -+ cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)} -+ fail(cert, idna) -+ -+ # wildcard in first fragment and IDNA A-labels in sequent fragments -+ # are supported. -+ idna = u'www*.pythön.org'.encode("idna").decode("ascii") -+ cert = {'subject': ((('commonName', idna),),)} -+ ok(cert, u'www.pythön.org'.encode("idna").decode("ascii")) -+ ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii")) -+ fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii")) -+ fail(cert, u'pythön.org'.encode("idna").decode("ascii")) -+ -+ # Slightly fake real-world example -+ cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT', -+ 'subject': ((('commonName', 'linuxfrz.org'),),), -+ 'subjectAltName': (('DNS', 'linuxfr.org'), -+ ('DNS', 'linuxfr.com'), -+ ('othername', ''))} -+ ok(cert, 'linuxfr.org') -+ ok(cert, 'linuxfr.com') -+ # Not a "DNS" entry -+ fail(cert, '') -+ # When there is a subjectAltName, commonName isn't used -+ fail(cert, 'linuxfrz.org') -+ -+ # A pristine real-world example -+ cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),), -+ (('commonName', 'mail.google.com'),))} -+ ok(cert, 'mail.google.com') -+ fail(cert, 'gmail.com') -+ # Only commonName is considered -+ fail(cert, 'California') -+ -+ # Neither commonName nor subjectAltName -+ cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),))} -+ fail(cert, 'mail.google.com') -+ -+ # No DNS entry in subjectAltName but a commonName -+ cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('commonName', 'mail.google.com'),)), -+ 'subjectAltName': (('othername', 'blabla'), )} -+ ok(cert, 'mail.google.com') -+ -+ # No DNS entry subjectAltName and no commonName -+ cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),)), -+ 'subjectAltName': (('othername', 'blabla'),)} -+ fail(cert, 'google.com') -+ -+ # Empty cert / no cert -+ self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com') -+ self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com') -+ -+ # Issue #17980: avoid denials of service by refusing more than one -+ # wildcard per fragment. -+ cert = {'subject': ((('commonName', 'a*b.com'),),)} -+ ok(cert, 'axxb.com') -+ cert = {'subject': ((('commonName', 'a*b.co*'),),)} -+ fail(cert, 'axxb.com') -+ cert = {'subject': ((('commonName', 'a*b*.com'),),)} -+ with self.assertRaises(ssl.CertificateError) as cm: -+ ssl.match_hostname(cert, 'axxbxxc.com') -+ self.assertIn("too many wildcards", str(cm.exception)) -+ -+ def test_server_side(self): -+ # server_hostname doesn't work for server sockets -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(socket.socket()) as sock: -+ self.assertRaises(ValueError, ctx.wrap_socket, sock, True, -+ server_hostname="some.hostname") -+ -+ def test_unknown_channel_binding(self): -+ # should raise ValueError for unknown type -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s)) as ss: -+ with self.assertRaises(ValueError): -+ ss.get_channel_binding("unknown-type") -+ -+ @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES, -+ "'tls-unique' channel binding not available") -+ def test_tls_unique_channel_binding(self): -+ # unconnected should return None for known type -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertIsNone(ss.get_channel_binding("tls-unique")) -+ # the same for server-side -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss: -+ self.assertIsNone(ss.get_channel_binding("tls-unique")) -+ -+ def test_get_default_verify_paths(self): -+ paths = ssl.get_default_verify_paths() -+ self.assertEqual(len(paths), 6) -+ self.assertIsInstance(paths, ssl.DefaultVerifyPaths) -+ -+ with support.EnvironmentVarGuard() as env: -+ env["SSL_CERT_DIR"] = CAPATH -+ env["SSL_CERT_FILE"] = CERTFILE -+ paths = ssl.get_default_verify_paths() -+ self.assertEqual(paths.cafile, CERTFILE) -+ self.assertEqual(paths.capath, CAPATH) -+ -+ @unittest.skipUnless(sys.platform == "win32", "Windows specific") -+ def test_enum_certificates(self): -+ self.assertTrue(ssl.enum_certificates("CA")) -+ self.assertTrue(ssl.enum_certificates("ROOT")) -+ -+ self.assertRaises(TypeError, ssl.enum_certificates) -+ self.assertRaises(WindowsError, ssl.enum_certificates, "") -+ -+ trust_oids = set() -+ for storename in ("CA", "ROOT"): -+ store = ssl.enum_certificates(storename) -+ self.assertIsInstance(store, list) -+ for element in store: -+ self.assertIsInstance(element, tuple) -+ self.assertEqual(len(element), 3) -+ cert, enc, trust = element -+ self.assertIsInstance(cert, bytes) -+ self.assertIn(enc, {"x509_asn", "pkcs_7_asn"}) -+ self.assertIsInstance(trust, (set, bool)) -+ if isinstance(trust, set): -+ trust_oids.update(trust) -+ -+ serverAuth = "1.3.6.1.5.5.7.3.1" -+ self.assertIn(serverAuth, trust_oids) -+ -+ @unittest.skipUnless(sys.platform == "win32", "Windows specific") -+ def test_enum_crls(self): -+ self.assertTrue(ssl.enum_crls("CA")) -+ self.assertRaises(TypeError, ssl.enum_crls) -+ self.assertRaises(WindowsError, ssl.enum_crls, "") -+ -+ crls = ssl.enum_crls("CA") -+ self.assertIsInstance(crls, list) -+ for element in crls: -+ self.assertIsInstance(element, tuple) -+ self.assertEqual(len(element), 2) -+ self.assertIsInstance(element[0], bytes) -+ self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"}) -+ -+ -+ def test_asn1object(self): -+ expected = (129, 'serverAuth', 'TLS Web Server Authentication', -+ '1.3.6.1.5.5.7.3.1') -+ -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1') -+ self.assertEqual(val, expected) -+ self.assertEqual(val.nid, 129) -+ self.assertEqual(val.shortname, 'serverAuth') -+ self.assertEqual(val.longname, 'TLS Web Server Authentication') -+ self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1') -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth') -+ -+ val = ssl._ASN1Object.fromnid(129) -+ self.assertEqual(val, expected) -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1) -+ with self.assertRaisesRegexp(ValueError, "unknown NID 100000"): -+ ssl._ASN1Object.fromnid(100000) -+ for i in range(1000): -+ try: -+ obj = ssl._ASN1Object.fromnid(i) -+ except ValueError: -+ pass -+ else: -+ self.assertIsInstance(obj.nid, int) -+ self.assertIsInstance(obj.shortname, str) -+ self.assertIsInstance(obj.longname, str) -+ self.assertIsInstance(obj.oid, (str, type(None))) -+ -+ val = ssl._ASN1Object.fromname('TLS Web Server Authentication') -+ self.assertEqual(val, expected) -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected) -+ self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'), -+ expected) -+ with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"): -+ ssl._ASN1Object.fromname('serverauth') -+ -+ def test_purpose_enum(self): -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1') -+ self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH, val) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth') -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.oid, -+ '1.3.6.1.5.5.7.3.1') -+ -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2') -+ self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH, val) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth') -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid, -+ '1.3.6.1.5.5.7.3.2') - - def test_unsupported_dtls(self): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -@@ -242,42 +614,606 @@ class BasicSocketTests(unittest.TestCase): - with self.assertRaises(NotImplementedError) as cx: - ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE) - self.assertEqual(str(cx.exception), "only stream sockets are supported") -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with self.assertRaises(NotImplementedError) as cx: -+ ctx.wrap_socket(s) -+ self.assertEqual(str(cx.exception), "only stream sockets are supported") -+ -+ def cert_time_ok(self, timestring, timestamp): -+ self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp) -+ -+ def cert_time_fail(self, timestring): -+ with self.assertRaises(ValueError): -+ ssl.cert_time_to_seconds(timestring) -+ -+ @unittest.skipUnless(utc_offset(), -+ 'local time needs to be different from UTC') -+ def test_cert_time_to_seconds_timezone(self): -+ # Issue #19940: ssl.cert_time_to_seconds() returns wrong -+ # results if local timezone is not UTC -+ self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0) -+ self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0) -+ -+ def test_cert_time_to_seconds(self): -+ timestring = "Jan 5 09:34:43 2018 GMT" -+ ts = 1515144883.0 -+ self.cert_time_ok(timestring, ts) -+ # accept keyword parameter, assert its name -+ self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts) -+ # accept both %e and %d (space or zero generated by strftime) -+ self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts) -+ # case-insensitive -+ self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts) -+ self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds -+ self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT -+ self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone -+ self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day -+ self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month -+ self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour -+ self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute -+ -+ newyear_ts = 1230768000.0 -+ # leap seconds -+ self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts) -+ # same timestamp -+ self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts) -+ -+ self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899) -+ # allow 60th second (even if it is not a leap second) -+ self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900) -+ # allow 2nd leap second for compatibility with time.strptime() -+ self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901) -+ self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds -+ -+ # no special treatement for the special value: -+ # 99991231235959Z (rfc 5280) -+ self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0) -+ -+ @support.run_with_locale('LC_ALL', '') -+ def test_cert_time_to_seconds_locale(self): -+ # `cert_time_to_seconds()` should be locale independent -+ -+ def local_february_name(): -+ return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0)) -+ -+ if local_february_name().lower() == 'feb': -+ self.skipTest("locale-specific month name needs to be " -+ "different from C locale") -+ -+ # locale-independent -+ self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0) -+ self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT") -+ -+ -+class ContextTests(unittest.TestCase): -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_constructor(self): -+ for protocol in PROTOCOLS: -+ ssl.SSLContext(protocol) -+ self.assertRaises(TypeError, ssl.SSLContext) -+ self.assertRaises(ValueError, ssl.SSLContext, -1) -+ self.assertRaises(ValueError, ssl.SSLContext, 42) -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_protocol(self): -+ for proto in PROTOCOLS: -+ ctx = ssl.SSLContext(proto) -+ self.assertEqual(ctx.protocol, proto) -+ -+ def test_ciphers(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_ciphers("ALL") -+ ctx.set_ciphers("DEFAULT") -+ with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -+ ctx.set_ciphers("^$:,;?*'dorothyx") -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_options(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # OP_ALL | OP_NO_SSLv2 is the default value -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, -+ ctx.options) -+ ctx.options |= ssl.OP_NO_SSLv3 -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3, -+ ctx.options) -+ if can_clear_options(): -+ ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1 -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3, -+ ctx.options) -+ ctx.options = 0 -+ self.assertEqual(0, ctx.options) -+ else: -+ with self.assertRaises(ValueError): -+ ctx.options = 0 -+ -+ def test_verify_mode(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # Default value -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ ctx.verify_mode = ssl.CERT_OPTIONAL -+ self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ ctx.verify_mode = ssl.CERT_NONE -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ with self.assertRaises(TypeError): -+ ctx.verify_mode = None -+ with self.assertRaises(ValueError): -+ ctx.verify_mode = 42 -+ -+ @unittest.skipUnless(have_verify_flags(), -+ "verify_flags need OpenSSL > 0.9.8") -+ def test_verify_flags(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # default value by OpenSSL -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT) -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF) -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN) -+ ctx.verify_flags = ssl.VERIFY_DEFAULT -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT) -+ # supports any value -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT -+ self.assertEqual(ctx.verify_flags, -+ ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT) -+ with self.assertRaises(TypeError): -+ ctx.verify_flags = None -+ -+ def test_load_cert_chain(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # Combined key and cert in a single file -+ ctx.load_cert_chain(CERTFILE) -+ ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE) -+ self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_cert_chain(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(BADCERT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(EMPTYCERT) -+ # Separate key and cert -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY) -+ ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY) -+ ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(ONLYCERT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(ONLYKEY) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT) -+ # Mismatching key and cert -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"): -+ ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY) -+ # Password protected key and cert -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode()) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, -+ password=bytearray(KEY_PASSWORD.encode())) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode()) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, -+ bytearray(KEY_PASSWORD.encode())) -+ with self.assertRaisesRegexp(TypeError, "should be a string"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=True) -+ with self.assertRaises(ssl.SSLError): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass") -+ with self.assertRaisesRegexp(ValueError, "cannot be longer"): -+ # openssl has a fixed limit on the password buffer. -+ # PEM_BUFSIZE is generally set to 1kb. -+ # Return a string larger than this. -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400) -+ # Password callback -+ def getpass_unicode(): -+ return KEY_PASSWORD -+ def getpass_bytes(): -+ return KEY_PASSWORD.encode() -+ def getpass_bytearray(): -+ return bytearray(KEY_PASSWORD.encode()) -+ def getpass_badpass(): -+ return "badpass" -+ def getpass_huge(): -+ return b'a' * (1024 * 1024) -+ def getpass_bad_type(): -+ return 9 -+ def getpass_exception(): -+ raise Exception('getpass error') -+ class GetPassCallable: -+ def __call__(self): -+ return KEY_PASSWORD -+ def getpass(self): -+ return KEY_PASSWORD -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable()) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, -+ password=GetPassCallable().getpass) -+ with self.assertRaises(ssl.SSLError): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass) -+ with self.assertRaisesRegexp(ValueError, "cannot be longer"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge) -+ with self.assertRaisesRegexp(TypeError, "must return a string"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type) -+ with self.assertRaisesRegexp(Exception, "getpass error"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception) -+ # Make sure the password function isn't called if it isn't needed -+ ctx.load_cert_chain(CERTFILE, password=getpass_exception) -+ -+ def test_load_verify_locations(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_verify_locations(CERTFILE) -+ ctx.load_verify_locations(cafile=CERTFILE, capath=None) -+ ctx.load_verify_locations(BYTES_CERTFILE) -+ ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None) -+ self.assertRaises(TypeError, ctx.load_verify_locations) -+ self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_verify_locations(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_verify_locations(BADCERT) -+ ctx.load_verify_locations(CERTFILE, CAPATH) -+ ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH) -+ -+ # Issue #10989: crash if the second argument type is invalid -+ self.assertRaises(TypeError, ctx.load_verify_locations, None, True) -+ -+ def test_load_verify_cadata(self): -+ # test cadata -+ with open(CAFILE_CACERT) as f: -+ cacert_pem = f.read().decode("ascii") -+ cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem) -+ with open(CAFILE_NEURONIO) as f: -+ neuronio_pem = f.read().decode("ascii") -+ neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem) -+ -+ # test PEM -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0) -+ ctx.load_verify_locations(cadata=cacert_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1) -+ ctx.load_verify_locations(cadata=neuronio_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ # cert already in hash table -+ ctx.load_verify_locations(cadata=neuronio_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # combined -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = "\n".join((cacert_pem, neuronio_pem)) -+ ctx.load_verify_locations(cadata=combined) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # with junk around the certs -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = ["head", cacert_pem, "other", neuronio_pem, "again", -+ neuronio_pem, "tail"] -+ ctx.load_verify_locations(cadata="\n".join(combined)) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # test DER -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_verify_locations(cadata=cacert_der) -+ ctx.load_verify_locations(cadata=neuronio_der) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ # cert already in hash table -+ ctx.load_verify_locations(cadata=cacert_der) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # combined -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = b"".join((cacert_der, neuronio_der)) -+ ctx.load_verify_locations(cadata=combined) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # error cases -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object) -+ -+ with self.assertRaisesRegexp(ssl.SSLError, "no start line"): -+ ctx.load_verify_locations(cadata=u"broken") -+ with self.assertRaisesRegexp(ssl.SSLError, "not enough data"): -+ ctx.load_verify_locations(cadata=b"broken") -+ -+ -+ def test_load_dh_params(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_dh_params(DHFILE) -+ if os.name != 'nt': -+ ctx.load_dh_params(BYTES_DHFILE) -+ self.assertRaises(TypeError, ctx.load_dh_params) -+ self.assertRaises(TypeError, ctx.load_dh_params, None) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_dh_params(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(ssl.SSLError) as cm: -+ ctx.load_dh_params(CERTFILE) -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_session_stats(self): -+ for proto in PROTOCOLS: -+ ctx = ssl.SSLContext(proto) -+ self.assertEqual(ctx.session_stats(), { -+ 'number': 0, -+ 'connect': 0, -+ 'connect_good': 0, -+ 'connect_renegotiate': 0, -+ 'accept': 0, -+ 'accept_good': 0, -+ 'accept_renegotiate': 0, -+ 'hits': 0, -+ 'misses': 0, -+ 'timeouts': 0, -+ 'cache_full': 0, -+ }) -+ -+ def test_set_default_verify_paths(self): -+ # There's not much we can do to test that it acts as expected, -+ # so just check it doesn't crash or raise an exception. -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_default_verify_paths() -+ -+ @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build") -+ def test_set_ecdh_curve(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_ecdh_curve("prime256v1") -+ ctx.set_ecdh_curve(b"prime256v1") -+ self.assertRaises(TypeError, ctx.set_ecdh_curve) -+ self.assertRaises(TypeError, ctx.set_ecdh_curve, None) -+ self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo") -+ self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo") -+ -+ @needs_sni -+ def test_sni_callback(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ -+ # set_servername_callback expects a callable, or None -+ self.assertRaises(TypeError, ctx.set_servername_callback) -+ self.assertRaises(TypeError, ctx.set_servername_callback, 4) -+ self.assertRaises(TypeError, ctx.set_servername_callback, "") -+ self.assertRaises(TypeError, ctx.set_servername_callback, ctx) -+ -+ def dummycallback(sock, servername, ctx): -+ pass -+ ctx.set_servername_callback(None) -+ ctx.set_servername_callback(dummycallback) -+ -+ @needs_sni -+ def test_sni_callback_refcycle(self): -+ # Reference cycles through the servername callback are detected -+ # and cleared. -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ def dummycallback(sock, servername, ctx, cycle=ctx): -+ pass -+ ctx.set_servername_callback(dummycallback) -+ wr = weakref.ref(ctx) -+ del ctx, dummycallback -+ gc.collect() -+ self.assertIs(wr(), None) -+ -+ def test_cert_store_stats(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 0}) -+ ctx.load_cert_chain(CERTFILE) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 0}) -+ ctx.load_verify_locations(CERTFILE) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 1}) -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 1, 'crl': 0, 'x509': 2}) -+ -+ def test_get_ca_certs(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE -+ ctx.load_verify_locations(CERTFILE) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ self.assertEqual(ctx.get_ca_certs(), -+ [{'issuer': ((('organizationName', 'Root CA'),), -+ (('organizationalUnitName', 'http://www.cacert.org'),), -+ (('commonName', 'CA Cert Signing Authority'),), -+ (('emailAddress', 'support@cacert.org'),)), -+ 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'), -+ 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'), -+ 'serialNumber': '00', -+ 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',), -+ 'subject': ((('organizationName', 'Root CA'),), -+ (('organizationalUnitName', 'http://www.cacert.org'),), -+ (('commonName', 'CA Cert Signing Authority'),), -+ (('emailAddress', 'support@cacert.org'),)), -+ 'version': 3}]) -+ -+ with open(SVN_PYTHON_ORG_ROOT_CERT) as f: -+ pem = f.read() -+ der = ssl.PEM_cert_to_DER_cert(pem) -+ self.assertEqual(ctx.get_ca_certs(True), [der]) -+ -+ def test_load_default_certs(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs() -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs(ssl.Purpose.SERVER_AUTH) -+ ctx.load_default_certs() -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH) -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertRaises(TypeError, ctx.load_default_certs, None) -+ self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH') -+ -+ def test_create_default_context(self): -+ ctx = ssl.create_default_context() -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertTrue(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ -+ with open(SIGNING_CA) as f: -+ cadata = f.read().decode("ascii") -+ ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH, -+ cadata=cadata) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ -+ ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0), -+ getattr(ssl, "OP_SINGLE_DH_USE", 0), -+ ) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0), -+ getattr(ssl, "OP_SINGLE_ECDH_USE", 0), -+ ) -+ -+ def test__create_stdlib_context(self): -+ ctx = ssl._create_stdlib_context() -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertFalse(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1, -+ cert_reqs=ssl.CERT_REQUIRED, -+ check_hostname=True) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertTrue(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ def test_check_hostname(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertFalse(ctx.check_hostname) -+ -+ # Requires CERT_REQUIRED or CERT_OPTIONAL -+ with self.assertRaises(ValueError): -+ ctx.check_hostname = True -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ self.assertFalse(ctx.check_hostname) -+ ctx.check_hostname = True -+ self.assertTrue(ctx.check_hostname) -+ -+ ctx.verify_mode = ssl.CERT_OPTIONAL -+ ctx.check_hostname = True -+ self.assertTrue(ctx.check_hostname) -+ -+ # Cannot set CERT_NONE with check_hostname enabled -+ with self.assertRaises(ValueError): -+ ctx.verify_mode = ssl.CERT_NONE -+ ctx.check_hostname = False -+ self.assertFalse(ctx.check_hostname) -+ -+ -+class SSLErrorTests(unittest.TestCase): -+ -+ def test_str(self): -+ # The str() of a SSLError doesn't include the errno -+ e = ssl.SSLError(1, "foo") -+ self.assertEqual(str(e), "foo") -+ self.assertEqual(e.errno, 1) -+ # Same for a subclass -+ e = ssl.SSLZeroReturnError(1, "foo") -+ self.assertEqual(str(e), "foo") -+ self.assertEqual(e.errno, 1) -+ -+ def test_lib_reason(self): -+ # Test the library and reason attributes -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with self.assertRaises(ssl.SSLError) as cm: -+ ctx.load_dh_params(CERTFILE) -+ self.assertEqual(cm.exception.library, 'PEM') -+ self.assertEqual(cm.exception.reason, 'NO_START_LINE') -+ s = str(cm.exception) -+ self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s) -+ -+ def test_subclass(self): -+ # Check that the appropriate SSLError subclass is raised -+ # (this only tests one of them) -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with closing(socket.socket()) as s: -+ s.bind(("127.0.0.1", 0)) -+ s.listen(5) -+ c = socket.socket() -+ c.connect(s.getsockname()) -+ c.setblocking(False) -+ with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c: -+ with self.assertRaises(ssl.SSLWantReadError) as cm: -+ c.do_handshake() -+ s = str(cm.exception) -+ self.assertTrue(s.startswith("The operation did not complete (read)"), s) -+ # For compatibility -+ self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ) - - - class NetworkedTests(unittest.TestCase): - - def test_connect(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_NONE) -- s.connect(("svn.python.org", 443)) -- c = s.getpeercert() -- if c: -- self.fail("Peer cert %s shouldn't be here!") -- s.close() -- -- # this should fail because we have no verification certs -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_REQUIRED) - try: - s.connect(("svn.python.org", 443)) -- except ssl.SSLError: -- pass -+ self.assertEqual({}, s.getpeercert()) - finally: - s.close() - -+ # this should fail because we have no verification certs -+ s = ssl.wrap_socket(socket.socket(socket.AF_INET), -+ cert_reqs=ssl.CERT_REQUIRED) -+ self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed", -+ s.connect, ("svn.python.org", 443)) -+ s.close() -+ - # this should succeed because we specify the root cert - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) - try: - s.connect(("svn.python.org", 443)) -+ self.assertTrue(s.getpeercert()) - finally: - s.close() - - def test_connect_ex(self): - # Issue #11326: check connect_ex() implementation -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) -@@ -290,7 +1226,7 @@ class NetworkedTests(unittest.TestCase): - def test_non_blocking_connect_ex(self): - # Issue #11326: non-blocking connect_ex() should allow handshake - # to proceed after the socket gets ready. -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT, -@@ -307,13 +1243,10 @@ class NetworkedTests(unittest.TestCase): - try: - s.do_handshake() - break -- except ssl.SSLError as err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], [], 5.0) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], [], 5.0) -- else: -- raise -+ except ssl.SSLWantReadError: -+ select.select([s], [], [], 5.0) -+ except ssl.SSLWantWriteError: -+ select.select([], [s], [], 5.0) - # SSL established - self.assertTrue(s.getpeercert()) - finally: -@@ -322,7 +1255,7 @@ class NetworkedTests(unittest.TestCase): - def test_timeout_connect_ex(self): - # Issue #12065: on a timeout, connect_ex() should return the original - # errno (mimicking the behaviour of non-SSL sockets). -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT, -@@ -337,22 +1270,109 @@ class NetworkedTests(unittest.TestCase): - s.close() - - def test_connect_ex_error(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) - try: -- self.assertEqual(errno.ECONNREFUSED, -- s.connect_ex(("svn.python.org", 444))) -+ rc = s.connect_ex(("svn.python.org", 444)) -+ # Issue #19919: Windows machines or VMs hosted on Windows -+ # machines sometimes return EWOULDBLOCK. -+ self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK)) -+ finally: -+ s.close() -+ -+ def test_connect_with_context(self): -+ with support.transient_internet("svn.python.org"): -+ # Same as test_connect, but with a separately created context -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ self.assertEqual({}, s.getpeercert()) -+ finally: -+ s.close() -+ # Same with a server hostname -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET), -+ server_hostname="svn.python.org") -+ if ssl.HAS_SNI: -+ s.connect(("svn.python.org", 443)) -+ s.close() -+ else: -+ self.assertRaises(ValueError, s.connect, ("svn.python.org", 443)) -+ # This should fail because we have no verification certs -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed", -+ s.connect, ("svn.python.org", 443)) -+ s.close() -+ # This should succeed because we specify the root cert -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ -+ def test_connect_capath(self): -+ # Verify server certificates using the `capath` argument -+ # NOTE: the subject hashing algorithm has been changed between -+ # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must -+ # contain both versions of each certificate (same content, different -+ # filename) for this test to be portable across OpenSSL releases. -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=CAPATH) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ # Same with a bytes `capath` argument -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=BYTES_CAPATH) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) - finally: - s.close() - -+ def test_connect_cadata(self): -+ with open(CAFILE_CACERT) as f: -+ pem = f.read().decode('ascii') -+ der = ssl.PEM_cert_to_DER_cert(pem) -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(cadata=pem) -+ with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s: -+ s.connect(("svn.python.org", 443)) -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ -+ # same with DER -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(cadata=der) -+ with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s: -+ s.connect(("svn.python.org", 443)) -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ - @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") - def test_makefile_close(self): - # Issue #5238: creating a file-like object with makefile() shouldn't - # delay closing the underlying "real socket" (here tested with its - # file descriptor, hence skipping the test under Windows). -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) - ss.connect(("svn.python.org", 443)) - fd = ss.fileno() -@@ -368,7 +1388,7 @@ class NetworkedTests(unittest.TestCase): - self.assertEqual(e.exception.errno, errno.EBADF) - - def test_non_blocking_handshake(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = socket.socket(socket.AF_INET) - s.connect(("svn.python.org", 443)) - s.setblocking(False) -@@ -381,41 +1401,57 @@ class NetworkedTests(unittest.TestCase): - count += 1 - s.do_handshake() - break -- except ssl.SSLError, err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], []) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], []) -- else: -- raise -+ except ssl.SSLWantReadError: -+ select.select([s], [], []) -+ except ssl.SSLWantWriteError: -+ select.select([], [s], []) - s.close() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count) - - def test_get_server_certificate(self): -- with test_support.transient_internet("svn.python.org"): -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23) -- if not pem: -- self.fail("No server certificate on svn.python.org:443!") -+ def _test_get_server_certificate(host, port, cert=None): -+ with support.transient_internet(host): -+ pem = ssl.get_server_certificate((host, port)) -+ if not pem: -+ self.fail("No server certificate on %s:%s!" % (host, port)) - -- try: -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23, -- ca_certs=CERTFILE) -- except ssl.SSLError: -- #should fail -- pass -- else: -- self.fail("Got server certificate %s for svn.python.org!" % pem) -+ try: -+ pem = ssl.get_server_certificate((host, port), -+ ca_certs=CERTFILE) -+ except ssl.SSLError as x: -+ #should fail -+ if support.verbose: -+ sys.stdout.write("%s\n" % x) -+ else: -+ self.fail("Got server certificate %s for %s:%s!" % (pem, host, port)) -+ -+ pem = ssl.get_server_certificate((host, port), -+ ca_certs=cert) -+ if not pem: -+ self.fail("No server certificate on %s:%s!" % (host, port)) -+ if support.verbose: -+ sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem)) -+ -+ _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT) -+ if support.IPV6_ENABLED: -+ _test_get_server_certificate('ipv6.google.com', 443) - -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23, -- ca_certs=SVN_PYTHON_ORG_ROOT_CERT) -- if not pem: -- self.fail("No server certificate on svn.python.org:443!") -- if test_support.verbose: -- sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem) -+ def test_ciphers(self): -+ remote = ("svn.python.org", 443) -+ with support.transient_internet(remote[0]): -+ with closing(ssl.wrap_socket(socket.socket(socket.AF_INET), -+ cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s: -+ s.connect(remote) -+ with closing(ssl.wrap_socket(socket.socket(socket.AF_INET), -+ cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s: -+ s.connect(remote) -+ # Error checking can happen at instantiation or when connecting -+ with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -+ with closing(socket.socket(socket.AF_INET)) as sock: -+ s = ssl.wrap_socket(sock, -+ cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") -+ s.connect(remote) - - def test_algorithms(self): - # Issue #8484: all algorithms should be available when verifying a -@@ -423,17 +1459,21 @@ class NetworkedTests(unittest.TestCase): - # SHA256 was added in OpenSSL 0.9.8 - if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15): - self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION) -- self.skipTest("remote host needs SNI, only available on Python 3.2+") -- # NOTE: https://sha2.hboeck.de is another possible test host -+ # sha256.tbs-internet.com needs SNI to use the correct certificate -+ if not ssl.HAS_SNI: -+ self.skipTest("SNI needed for this test") -+ # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host) - remote = ("sha256.tbs-internet.com", 443) - sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem") -- with test_support.transient_internet("sha256.tbs-internet.com"): -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_REQUIRED, -- ca_certs=sha256_cert,) -+ with support.transient_internet("sha256.tbs-internet.com"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(sha256_cert) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET), -+ server_hostname="sha256.tbs-internet.com") - try: - s.connect(remote) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\nCipher with %r is %r\n" % - (remote, s.cipher())) - sys.stdout.write("Certificate is:\n%s\n" % -@@ -441,6 +1481,36 @@ class NetworkedTests(unittest.TestCase): - finally: - s.close() - -+ def test_get_ca_certs_capath(self): -+ # capath certs are loaded on request -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=CAPATH) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ self.assertEqual(len(ctx.get_ca_certs()), 1) -+ -+ @needs_sni -+ def test_context_setget(self): -+ # Check that the context of a connected socket can be replaced. -+ with support.transient_internet("svn.python.org"): -+ ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ s = socket.socket(socket.AF_INET) -+ with closing(ctx1.wrap_socket(s)) as ss: -+ ss.connect(("svn.python.org", 443)) -+ self.assertIs(ss.context, ctx1) -+ self.assertIs(ss._sslobj.context, ctx1) -+ ss.context = ctx2 -+ self.assertIs(ss.context, ctx2) -+ self.assertIs(ss._sslobj.context, ctx2) - - try: - import threading -@@ -449,6 +1519,8 @@ except ImportError: - else: - _have_threads = True - -+ from test.ssl_servers import make_https_server -+ - class ThreadedEchoServer(threading.Thread): - - class ConnectionHandler(threading.Thread): -@@ -457,48 +1529,51 @@ else: - with and without the SSL wrapper around the socket connection, so - that we can test the STARTTLS functionality.""" - -- def __init__(self, server, connsock): -+ def __init__(self, server, connsock, addr): - self.server = server - self.running = False - self.sock = connsock -+ self.addr = addr - self.sock.setblocking(1) - self.sslconn = None - threading.Thread.__init__(self) - self.daemon = True - -- def show_conn_details(self): -- if self.server.certreqs == ssl.CERT_REQUIRED: -- cert = self.sslconn.getpeercert() -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") -- cert_binary = self.sslconn.getpeercert(True) -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") -- cipher = self.sslconn.cipher() -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") -- - def wrap_conn(self): - try: -- self.sslconn = ssl.wrap_socket(self.sock, server_side=True, -- certfile=self.server.certificate, -- ssl_version=self.server.protocol, -- ca_certs=self.server.cacerts, -- cert_reqs=self.server.certreqs, -- ciphers=self.server.ciphers) -- except ssl.SSLError as e: -+ self.sslconn = self.server.context.wrap_socket( -+ self.sock, server_side=True) -+ self.server.selected_protocols.append(self.sslconn.selected_npn_protocol()) -+ except socket.error as e: -+ # We treat ConnectionResetError as though it were an -+ # SSLError - OpenSSL on Ubuntu abruptly closes the -+ # connection when asked to use an unsupported protocol. -+ # - # XXX Various errors can have happened here, for example - # a mismatching protocol version, an invalid certificate, - # or a low-level bug. This should be made more discriminating. -+ if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET: -+ raise - self.server.conn_errors.append(e) - if self.server.chatty: -- handle_error("\n server: bad connection attempt from " + -- str(self.sock.getpeername()) + ":\n") -- self.close() -+ handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") - self.running = False - self.server.stop() -+ self.close() - return False - else: -+ if self.server.context.verify_mode == ssl.CERT_REQUIRED: -+ cert = self.sslconn.getpeercert() -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") -+ cert_binary = self.sslconn.getpeercert(True) -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") -+ cipher = self.sslconn.cipher() -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") -+ sys.stdout.write(" server: selected protocol is now " -+ + str(self.sslconn.selected_npn_protocol()) + "\n") - return True - - def read(self): -@@ -517,48 +1592,53 @@ else: - if self.sslconn: - self.sslconn.close() - else: -- self.sock._sock.close() -+ self.sock.close() - - def run(self): - self.running = True - if not self.server.starttls_server: -- if isinstance(self.sock, ssl.SSLSocket): -- self.sslconn = self.sock -- elif not self.wrap_conn(): -+ if not self.wrap_conn(): - return -- self.show_conn_details() - while self.running: - try: - msg = self.read() -- if not msg: -+ stripped = msg.strip() -+ if not stripped: - # eof, so quit this handler - self.running = False - self.close() -- elif msg.strip() == 'over': -- if test_support.verbose and self.server.connectionchatty: -+ elif stripped == b'over': -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: client closed connection\n") - self.close() - return -- elif self.server.starttls_server and msg.strip() == 'STARTTLS': -- if test_support.verbose and self.server.connectionchatty: -+ elif (self.server.starttls_server and -+ stripped == b'STARTTLS'): -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: read STARTTLS from client, sending OK...\n") -- self.write("OK\n") -+ self.write(b"OK\n") - if not self.wrap_conn(): - return -- elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS': -- if test_support.verbose and self.server.connectionchatty: -+ elif (self.server.starttls_server and self.sslconn -+ and stripped == b'ENDTLS'): -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") -- self.write("OK\n") -- self.sslconn.unwrap() -+ self.write(b"OK\n") -+ self.sock = self.sslconn.unwrap() - self.sslconn = None -- if test_support.verbose and self.server.connectionchatty: -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: connection is now unencrypted...\n") -+ elif stripped == b'CB tls-unique': -+ if support.verbose and self.server.connectionchatty: -+ sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n") -+ data = self.sslconn.get_channel_binding("tls-unique") -+ self.write(repr(data).encode("us-ascii") + b"\n") - else: -- if (test_support.verbose and -+ if (support.verbose and - self.server.connectionchatty): - ctype = (self.sslconn and "encrypted") or "unencrypted" -- sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n" -- % (repr(msg), ctype, repr(msg.lower()), ctype)) -+ sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" -+ % (msg, ctype, msg.lower(), ctype)) - self.write(msg.lower()) - except ssl.SSLError: - if self.server.chatty: -@@ -569,36 +1649,34 @@ else: - # harness, we want to stop the server - self.server.stop() - -- def __init__(self, certificate, ssl_version=None, -+ def __init__(self, certificate=None, ssl_version=None, - certreqs=None, cacerts=None, - chatty=True, connectionchatty=False, starttls_server=False, -- wrap_accepting_socket=False, ciphers=None): -- -- if ssl_version is None: -- ssl_version = ssl.PROTOCOL_TLSv1 -- if certreqs is None: -- certreqs = ssl.CERT_NONE -- self.certificate = certificate -- self.protocol = ssl_version -- self.certreqs = certreqs -- self.cacerts = cacerts -- self.ciphers = ciphers -+ npn_protocols=None, ciphers=None, context=None): -+ if context: -+ self.context = context -+ else: -+ self.context = ssl.SSLContext(ssl_version -+ if ssl_version is not None -+ else ssl.PROTOCOL_TLSv1) -+ self.context.verify_mode = (certreqs if certreqs is not None -+ else ssl.CERT_NONE) -+ if cacerts: -+ self.context.load_verify_locations(cacerts) -+ if certificate: -+ self.context.load_cert_chain(certificate) -+ if npn_protocols: -+ self.context.set_npn_protocols(npn_protocols) -+ if ciphers: -+ self.context.set_ciphers(ciphers) - self.chatty = chatty - self.connectionchatty = connectionchatty - self.starttls_server = starttls_server - self.sock = socket.socket() -+ self.port = support.bind_port(self.sock) - self.flag = None -- if wrap_accepting_socket: -- self.sock = ssl.wrap_socket(self.sock, server_side=True, -- certfile=self.certificate, -- cert_reqs = self.certreqs, -- ca_certs = self.cacerts, -- ssl_version = self.protocol, -- ciphers = self.ciphers) -- if test_support.verbose and self.chatty: -- sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) -- self.port = test_support.bind_port(self.sock) - self.active = False -+ self.selected_protocols = [] - self.conn_errors = [] - threading.Thread.__init__(self) - self.daemon = True -@@ -626,10 +1704,10 @@ else: - while self.active: - try: - newconn, connaddr = self.sock.accept() -- if test_support.verbose and self.chatty: -+ if support.verbose and self.chatty: - sys.stdout.write(' server: new connection from ' -- + str(connaddr) + '\n') -- handler = self.ConnectionHandler(self, newconn) -+ + repr(connaddr) + '\n') -+ handler = self.ConnectionHandler(self, newconn, connaddr) - handler.start() - handler.join() - except socket.timeout: -@@ -648,11 +1726,12 @@ else: - class ConnectionHandler(asyncore.dispatcher_with_send): - - def __init__(self, conn, certfile): -- asyncore.dispatcher_with_send.__init__(self, conn) - self.socket = ssl.wrap_socket(conn, server_side=True, - certfile=certfile, - do_handshake_on_connect=False) -+ asyncore.dispatcher_with_send.__init__(self, self.socket) - self._ssl_accepting = True -+ self._do_ssl_handshake() - - def readable(self): - if isinstance(self.socket, ssl.SSLSocket): -@@ -663,12 +1742,11 @@ else: - def _do_ssl_handshake(self): - try: - self.socket.do_handshake() -- except ssl.SSLError, err: -- if err.args[0] in (ssl.SSL_ERROR_WANT_READ, -- ssl.SSL_ERROR_WANT_WRITE): -- return -- elif err.args[0] == ssl.SSL_ERROR_EOF: -- return self.handle_close() -+ except (ssl.SSLWantReadError, ssl.SSLWantWriteError): -+ return -+ except ssl.SSLEOFError: -+ return self.handle_close() -+ except ssl.SSLError: - raise - except socket.error, err: - if err.args[0] == errno.ECONNABORTED: -@@ -681,12 +1759,16 @@ else: - self._do_ssl_handshake() - else: - data = self.recv(1024) -- if data and data.strip() != 'over': -+ if support.verbose: -+ sys.stdout.write(" server: read %s from client\n" % repr(data)) -+ if not data: -+ self.close() -+ else: - self.send(data.lower()) - - def handle_close(self): - self.close() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" server: closed connection %s\n" % self.socket) - - def handle_error(self): -@@ -694,14 +1776,14 @@ else: - - def __init__(self, certfile): - self.certfile = certfile -- asyncore.dispatcher.__init__(self) -- self.create_socket(socket.AF_INET, socket.SOCK_STREAM) -- self.port = test_support.bind_port(self.socket) -+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ self.port = support.bind_port(sock, '') -+ asyncore.dispatcher.__init__(self, sock) - self.listen(5) - - def handle_accept(self): - sock_obj, addr = self.accept() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" server: new connection from %s:%s\n" %addr) - self.ConnectionHandler(sock_obj, self.certfile) - -@@ -725,13 +1807,13 @@ else: - return self - - def __exit__(self, *args): -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: stopping server.\n") - self.stop() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: joining server thread.\n") - self.join() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: successfully joined.\n") - - def start(self, flag=None): -@@ -743,103 +1825,15 @@ else: - if self.flag: - self.flag.set() - while self.active: -- asyncore.loop(0.05) -+ try: -+ asyncore.loop(1) -+ except: -+ pass - - def stop(self): - self.active = False - self.server.close() - -- class SocketServerHTTPSServer(threading.Thread): -- -- class HTTPSServer(HTTPServer): -- -- def __init__(self, server_address, RequestHandlerClass, certfile): -- HTTPServer.__init__(self, server_address, RequestHandlerClass) -- # we assume the certfile contains both private key and certificate -- self.certfile = certfile -- self.allow_reuse_address = True -- -- def __str__(self): -- return ('<%s %s:%s>' % -- (self.__class__.__name__, -- self.server_name, -- self.server_port)) -- -- def get_request(self): -- # override this to wrap socket with SSL -- sock, addr = self.socket.accept() -- sslconn = ssl.wrap_socket(sock, server_side=True, -- certfile=self.certfile) -- return sslconn, addr -- -- class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): -- # need to override translate_path to get a known root, -- # instead of using os.curdir, since the test could be -- # run from anywhere -- -- server_version = "TestHTTPS/1.0" -- -- root = None -- -- def translate_path(self, path): -- """Translate a /-separated PATH to the local filename syntax. -- -- Components that mean special things to the local file system -- (e.g. drive or directory names) are ignored. (XXX They should -- probably be diagnosed.) -- -- """ -- # abandon query parameters -- path = urlparse.urlparse(path)[2] -- path = os.path.normpath(urllib.unquote(path)) -- words = path.split('/') -- words = filter(None, words) -- path = self.root -- for word in words: -- drive, word = os.path.splitdrive(word) -- head, word = os.path.split(word) -- if word in self.root: continue -- path = os.path.join(path, word) -- return path -- -- def log_message(self, format, *args): -- -- # we override this to suppress logging unless "verbose" -- -- if test_support.verbose: -- sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % -- (self.server.server_address, -- self.server.server_port, -- self.request.cipher(), -- self.log_date_time_string(), -- format%args)) -- -- -- def __init__(self, certfile): -- self.flag = None -- self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0] -- self.server = self.HTTPSServer( -- (HOST, 0), self.RootedHTTPRequestHandler, certfile) -- self.port = self.server.server_port -- threading.Thread.__init__(self) -- self.daemon = True -- -- def __str__(self): -- return "<%s %s>" % (self.__class__.__name__, self.server) -- -- def start(self, flag=None): -- self.flag = flag -- threading.Thread.start(self) -- -- def run(self): -- if self.flag: -- self.flag.set() -- self.server.serve_forever(0.05) -- -- def stop(self): -- self.server.shutdown() -- -- - def bad_cert_test(certfile): - """ - Launch a server with CERT_REQUIRED, and check that trying to -@@ -847,74 +1841,74 @@ else: - """ - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_REQUIRED, -- cacerts=CERTFILE, chatty=False) -+ cacerts=CERTFILE, chatty=False, -+ connectionchatty=False) - with server: - try: -- s = ssl.wrap_socket(socket.socket(), -- certfile=certfile, -- ssl_version=ssl.PROTOCOL_TLSv1) -- s.connect((HOST, server.port)) -- except ssl.SSLError, x: -- if test_support.verbose: -- sys.stdout.write("\nSSLError is %s\n" % x[1]) -- except socket.error, x: -- if test_support.verbose: -- sys.stdout.write("\nsocket.error is %s\n" % x[1]) -+ with closing(socket.socket()) as sock: -+ s = ssl.wrap_socket(sock, -+ certfile=certfile, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ except ssl.SSLError as x: -+ if support.verbose: -+ sys.stdout.write("\nSSLError is %s\n" % x.args[1]) -+ except OSError as x: -+ if support.verbose: -+ sys.stdout.write("\nOSError is %s\n" % x.args[1]) -+ except OSError as x: -+ if x.errno != errno.ENOENT: -+ raise -+ if support.verbose: -+ sys.stdout.write("\OSError is %s\n" % str(x)) - else: - raise AssertionError("Use of invalid cert should have failed!") - -- def server_params_test(certfile, protocol, certreqs, cacertsfile, -- client_certfile, client_protocol=None, indata="FOO\n", -- ciphers=None, chatty=True, connectionchatty=False, -- wrap_accepting_socket=False): -+ def server_params_test(client_context, server_context, indata=b"FOO\n", -+ chatty=True, connectionchatty=False, sni_name=None): - """ - Launch a server, connect a client to it and try various reads - and writes. - """ -- server = ThreadedEchoServer(certfile, -- certreqs=certreqs, -- ssl_version=protocol, -- cacerts=cacertsfile, -- ciphers=ciphers, -+ stats = {} -+ server = ThreadedEchoServer(context=server_context, - chatty=chatty, -- connectionchatty=connectionchatty, -- wrap_accepting_socket=wrap_accepting_socket) -+ connectionchatty=False) - with server: -- # try to connect -- if client_protocol is None: -- client_protocol = protocol -- s = ssl.wrap_socket(socket.socket(), -- certfile=client_certfile, -- ca_certs=cacertsfile, -- ciphers=ciphers, -- cert_reqs=certreqs, -- ssl_version=client_protocol) -- s.connect((HOST, server.port)) -- for arg in [indata, bytearray(indata), memoryview(indata)]: -- if connectionchatty: -- if test_support.verbose: -- sys.stdout.write( -- " client: sending %s...\n" % (repr(arg))) -- s.write(arg) -- outdata = s.read() -+ with closing(client_context.wrap_socket(socket.socket(), -+ server_hostname=sni_name)) as s: -+ s.connect((HOST, server.port)) -+ for arg in [indata, bytearray(indata), memoryview(indata)]: -+ if connectionchatty: -+ if support.verbose: -+ sys.stdout.write( -+ " client: sending %r...\n" % indata) -+ s.write(arg) -+ outdata = s.read() -+ if connectionchatty: -+ if support.verbose: -+ sys.stdout.write(" client: read %r\n" % outdata) -+ if outdata != indata.lower(): -+ raise AssertionError( -+ "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n" -+ % (outdata[:20], len(outdata), -+ indata[:20].lower(), len(indata))) -+ s.write(b"over\n") - if connectionchatty: -- if test_support.verbose: -- sys.stdout.write(" client: read %s\n" % repr(outdata)) -- if outdata != indata.lower(): -- raise AssertionError( -- "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" -- % (outdata[:min(len(outdata),20)], len(outdata), -- indata[:min(len(indata),20)].lower(), len(indata))) -- s.write("over\n") -- if connectionchatty: -- if test_support.verbose: -- sys.stdout.write(" client: closing connection.\n") -- s.close() -+ if support.verbose: -+ sys.stdout.write(" client: closing connection.\n") -+ stats.update({ -+ 'compression': s.compression(), -+ 'cipher': s.cipher(), -+ 'peercert': s.getpeercert(), -+ 'client_npn_protocol': s.selected_npn_protocol() -+ }) -+ s.close() -+ stats['server_npn_protocols'] = server.selected_protocols -+ return stats - -- def try_protocol_combo(server_protocol, -- client_protocol, -- expect_success, -- certsreqs=None): -+ def try_protocol_combo(server_protocol, client_protocol, expect_success, -+ certsreqs=None, server_options=0, client_options=0): - if certsreqs is None: - certsreqs = ssl.CERT_NONE - certtype = { -@@ -922,19 +1916,30 @@ else: - ssl.CERT_OPTIONAL: "CERT_OPTIONAL", - ssl.CERT_REQUIRED: "CERT_REQUIRED", - }[certsreqs] -- if test_support.verbose: -+ if support.verbose: - formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n" - sys.stdout.write(formatstr % - (ssl.get_protocol_name(client_protocol), - ssl.get_protocol_name(server_protocol), - certtype)) -+ client_context = ssl.SSLContext(client_protocol) -+ client_context.options |= client_options -+ server_context = ssl.SSLContext(server_protocol) -+ server_context.options |= server_options -+ -+ # NOTE: we must enable "ALL" ciphers on the client, otherwise an -+ # SSLv23 client will send an SSLv3 hello (rather than SSLv2) -+ # starting from OpenSSL 1.0.0 (see issue #8322). -+ if client_context.protocol == ssl.PROTOCOL_SSLv23: -+ client_context.set_ciphers("ALL") -+ -+ for ctx in (client_context, server_context): -+ ctx.verify_mode = certsreqs -+ ctx.load_cert_chain(CERTFILE) -+ ctx.load_verify_locations(CERTFILE) - try: -- # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client -- # will send an SSLv3 hello (rather than SSLv2) starting from -- # OpenSSL 1.0.0 (see issue #8322). -- server_params_test(CERTFILE, server_protocol, certsreqs, -- CERTFILE, CERTFILE, client_protocol, -- ciphers="ALL", chatty=False) -+ server_params_test(client_context, server_context, -+ chatty=False, connectionchatty=False) - # Protocol mismatch can result in either an SSLError, or a - # "Connection reset by peer" error. - except ssl.SSLError: -@@ -953,75 +1958,38 @@ else: - - class ThreadedTests(unittest.TestCase): - -- def test_rude_shutdown(self): -- """A brutal shutdown of an SSL server should raise an IOError -- in the client when attempting handshake. -- """ -- listener_ready = threading.Event() -- listener_gone = threading.Event() -- -- s = socket.socket() -- port = test_support.bind_port(s, HOST) -- -- # `listener` runs in a thread. It sits in an accept() until -- # the main thread connects. Then it rudely closes the socket, -- # and sets Event `listener_gone` to let the main thread know -- # the socket is gone. -- def listener(): -- s.listen(5) -- listener_ready.set() -- s.accept() -- s.close() -- listener_gone.set() -- -- def connector(): -- listener_ready.wait() -- c = socket.socket() -- c.connect((HOST, port)) -- listener_gone.wait() -- try: -- ssl_sock = ssl.wrap_socket(c) -- except IOError: -- pass -- else: -- self.fail('connecting to closed SSL socket should have failed') -- -- t = threading.Thread(target=listener) -- t.start() -- try: -- connector() -- finally: -- t.join() -- - @skip_if_broken_ubuntu_ssl - def test_echo(self): - """Basic test of an SSL client connecting to a server""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, -- CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, -- chatty=True, connectionchatty=True) -+ for protocol in PROTOCOLS: -+ context = ssl.SSLContext(protocol) -+ context.load_cert_chain(CERTFILE) -+ server_params_test(context, context, -+ chatty=True, connectionchatty=True) - - def test_getpeercert(self): -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- s2 = socket.socket() -- server = ThreadedEchoServer(CERTFILE, -- certreqs=ssl.CERT_NONE, -- ssl_version=ssl.PROTOCOL_SSLv23, -- cacerts=CERTFILE, -- chatty=False) -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = ThreadedEchoServer(context=context, chatty=False) - with server: -- s = ssl.wrap_socket(socket.socket(), -- certfile=CERTFILE, -- ca_certs=CERTFILE, -- cert_reqs=ssl.CERT_REQUIRED, -- ssl_version=ssl.PROTOCOL_SSLv23) -+ s = context.wrap_socket(socket.socket(), -+ do_handshake_on_connect=False) - s.connect((HOST, server.port)) -+ # getpeercert() raise ValueError while the handshake isn't -+ # done. -+ with self.assertRaises(ValueError): -+ s.getpeercert() -+ s.do_handshake() - cert = s.getpeercert() - self.assertTrue(cert, "Can't get peer certificate.") - cipher = s.cipher() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(pprint.pformat(cert) + '\n') - sys.stdout.write("Connection cipher is " + str(cipher) + '.\n') - if 'subject' not in cert: -@@ -1032,8 +2000,94 @@ else: - self.fail( - "Missing or invalid 'organizationName' field in certificate subject; " - "should be 'Python Software Foundation'.") -+ self.assertIn('notBefore', cert) -+ self.assertIn('notAfter', cert) -+ before = ssl.cert_time_to_seconds(cert['notBefore']) -+ after = ssl.cert_time_to_seconds(cert['notAfter']) -+ self.assertLess(before, after) - s.close() - -+ @unittest.skipUnless(have_verify_flags(), -+ "verify_flags need OpenSSL > 0.9.8") -+ def test_crl_check(self): -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(SIGNING_CA) -+ self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT) -+ -+ # VERIFY_DEFAULT should pass -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails -+ context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF -+ -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ with self.assertRaisesRegexp(ssl.SSLError, -+ "certificate verify failed"): -+ s.connect((HOST, server.port)) -+ -+ # now load a CRL file. The CRL file is signed by the CA. -+ context.load_verify_locations(CRLFILE) -+ -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ @needs_sni -+ def test_check_hostname(self): -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.check_hostname = True -+ context.load_verify_locations(SIGNING_CA) -+ -+ # correct hostname should verify -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket(), -+ server_hostname="localhost")) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ # incorrect hostname should raise an exception -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket(), -+ server_hostname="invalid")) as s: -+ with self.assertRaisesRegexp(ssl.CertificateError, -+ "hostname 'invalid' doesn't match u?'localhost'"): -+ s.connect((HOST, server.port)) -+ -+ # missing server_hostname arg should cause an exception, too -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(socket.socket()) as s: -+ with self.assertRaisesRegexp(ValueError, -+ "check_hostname requires server_hostname"): -+ context.wrap_socket(s) -+ - def test_empty_cert(self): - """Connecting with an empty cert file""" - bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, -@@ -1051,25 +2105,84 @@ else: - bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, - "badkey.pem")) - -+ def test_rude_shutdown(self): -+ """A brutal shutdown of an SSL server should raise an OSError -+ in the client when attempting handshake. -+ """ -+ listener_ready = threading.Event() -+ listener_gone = threading.Event() -+ -+ s = socket.socket() -+ port = support.bind_port(s, HOST) -+ -+ # `listener` runs in a thread. It sits in an accept() until -+ # the main thread connects. Then it rudely closes the socket, -+ # and sets Event `listener_gone` to let the main thread know -+ # the socket is gone. -+ def listener(): -+ s.listen(5) -+ listener_ready.set() -+ newsock, addr = s.accept() -+ newsock.close() -+ s.close() -+ listener_gone.set() -+ -+ def connector(): -+ listener_ready.wait() -+ with closing(socket.socket()) as c: -+ c.connect((HOST, port)) -+ listener_gone.wait() -+ try: -+ ssl_sock = ssl.wrap_socket(c) -+ except ssl.SSLError: -+ pass -+ else: -+ self.fail('connecting to closed SSL socket should have failed') -+ -+ t = threading.Thread(target=listener) -+ t.start() -+ try: -+ connector() -+ finally: -+ t.join() -+ - @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), -+ "OpenSSL is compiled without SSLv2 support") - def test_protocol_sslv2(self): - """Connecting to an SSLv2 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- if not hasattr(ssl, 'PROTOCOL_SSLv2'): -- self.skipTest("PROTOCOL_SSLv2 needed") - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) -+ # SSLv23 client with specific SSL options -+ if no_sslv2_implies_sslv3_hello(): -+ # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv2) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1) - - @skip_if_broken_ubuntu_ssl - def test_protocol_sslv23(self): - """Connecting to an SSLv23 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try: -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) -+ except socket.error as x: -+ # this fails on some older versions of OpenSSL (0.9.7l, for instance) -+ if support.verbose: -+ sys.stdout.write( -+ " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" -+ % str(x)) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) -@@ -1082,22 +2195,38 @@ else: - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - -+ # Server with specific SSL options -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, -+ server_options=ssl.OP_NO_SSLv3) -+ # Will choose TLSv1 -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, -+ server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False, -+ server_options=ssl.OP_NO_TLSv1) -+ -+ - @skip_if_broken_ubuntu_ssl - def test_protocol_sslv3(self): - """Connecting to an SSLv3 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv3) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) -+ if no_sslv2_implies_sslv3_hello(): -+ # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True, -+ client_options=ssl.OP_NO_SSLv2) - - @skip_if_broken_ubuntu_ssl - def test_protocol_tlsv1(self): - """Connecting to a TLSv1 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) -@@ -1105,10 +2234,55 @@ else: - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1) -+ -+ @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"), -+ "TLS version 1.1 not supported.") -+ def test_protocol_tlsv1_1(self): -+ """Connecting to a TLSv1.1 server with various client options. -+ Testing against older TLS versions.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True) -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1_1) -+ -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) -+ -+ -+ @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"), -+ "TLS version 1.2 not supported.") -+ def test_protocol_tlsv1_2(self): -+ """Connecting to a TLSv1.2 server with various client options. -+ Testing against older TLS versions.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True, -+ server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2, -+ client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,) -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1_2) -+ -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False) - - def test_starttls(self): - """Switching from clear text to encrypted and back again.""" -- msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6") -+ msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6") - - server = ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_TLSv1, -@@ -1120,119 +2294,109 @@ else: - s = socket.socket() - s.setblocking(1) - s.connect((HOST, server.port)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - for indata in msgs: -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: sending %s...\n" % repr(indata)) -+ " client: sending %r...\n" % indata) - if wrapped: - conn.write(indata) - outdata = conn.read() - else: - s.send(indata) - outdata = s.recv(1024) -- if (indata == "STARTTLS" and -- outdata.strip().lower().startswith("ok")): -+ msg = outdata.strip().lower() -+ if indata == b"STARTTLS" and msg.startswith(b"ok"): - # STARTTLS ok, switch to secure mode -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server, starting TLS...\n" -- % repr(outdata)) -+ " client: read %r from server, starting TLS...\n" -+ % msg) - conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) - wrapped = True -- elif (indata == "ENDTLS" and -- outdata.strip().lower().startswith("ok")): -+ elif indata == b"ENDTLS" and msg.startswith(b"ok"): - # ENDTLS ok, switch back to clear text -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server, ending TLS...\n" -- % repr(outdata)) -+ " client: read %r from server, ending TLS...\n" -+ % msg) - s = conn.unwrap() - wrapped = False - else: -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server\n" % repr(outdata)) -- if test_support.verbose: -+ " client: read %r from server\n" % msg) -+ if support.verbose: - sys.stdout.write(" client: closing connection.\n") - if wrapped: -- conn.write("over\n") -+ conn.write(b"over\n") - else: -- s.send("over\n") -- s.close() -+ s.send(b"over\n") -+ if wrapped: -+ conn.close() -+ else: -+ s.close() - - def test_socketserver(self): - """Using a SocketServer to create and manage SSL connections.""" -- server = SocketServerHTTPSServer(CERTFILE) -- flag = threading.Event() -- server.start(flag) -- # wait for it to start -- flag.wait() -+ server = make_https_server(self, certfile=CERTFILE) - # try to connect -+ if support.verbose: -+ sys.stdout.write('\n') -+ with open(CERTFILE, 'rb') as f: -+ d1 = f.read() -+ d2 = '' -+ # now fetch the same data from the HTTPS server -+ url = 'https://%s:%d/%s' % ( -+ HOST, server.port, os.path.split(CERTFILE)[1]) -+ f = urllib.urlopen(url) - try: -- if test_support.verbose: -- sys.stdout.write('\n') -- with open(CERTFILE, 'rb') as f: -- d1 = f.read() -- d2 = '' -- # now fetch the same data from the HTTPS server -- url = 'https://127.0.0.1:%d/%s' % ( -- server.port, os.path.split(CERTFILE)[1]) -- with test_support.check_py3k_warnings(): -- f = urllib.urlopen(url) - dlen = f.info().getheader("content-length") - if dlen and (int(dlen) > 0): - d2 = f.read(int(dlen)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( - " client: read %d bytes from remote server '%s'\n" - % (len(d2), server)) -- f.close() -- self.assertEqual(d1, d2) - finally: -- server.stop() -- server.join() -- -- def test_wrapped_accept(self): -- """Check the accept() method on SSL sockets.""" -- if test_support.verbose: -- sys.stdout.write("\n") -- server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED, -- CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23, -- chatty=True, connectionchatty=True, -- wrap_accepting_socket=True) -+ f.close() -+ self.assertEqual(d1, d2) - - def test_asyncore_server(self): - """Check the example asyncore integration.""" - indata = "TEST MESSAGE of mixed case\n" - -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -+ -+ indata = b"FOO\n" - server = AsyncoreEchoServer(CERTFILE) - with server: - s = ssl.wrap_socket(socket.socket()) - s.connect(('127.0.0.1', server.port)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: sending %s...\n" % (repr(indata))) -+ " client: sending %r...\n" % indata) - s.write(indata) - outdata = s.read() -- if test_support.verbose: -- sys.stdout.write(" client: read %s\n" % repr(outdata)) -+ if support.verbose: -+ sys.stdout.write(" client: read %r\n" % outdata) - if outdata != indata.lower(): - self.fail( -- "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" -- % (outdata[:min(len(outdata),20)], len(outdata), -- indata[:min(len(indata),20)].lower(), len(indata))) -- s.write("over\n") -- if test_support.verbose: -+ "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n" -+ % (outdata[:20], len(outdata), -+ indata[:20].lower(), len(indata))) -+ s.write(b"over\n") -+ if support.verbose: - sys.stdout.write(" client: closing connection.\n") - s.close() -+ if support.verbose: -+ sys.stdout.write(" client: connection closed.\n") - - def test_recv_send(self): - """Test recv(), send() and friends.""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - - server = ThreadedEchoServer(CERTFILE, -@@ -1251,12 +2415,12 @@ else: - s.connect((HOST, server.port)) - # helper methods for standardising recv* method signatures - def _recv_into(): -- b = bytearray("\0"*100) -+ b = bytearray(b"\0"*100) - count = s.recv_into(b) - return b[:count] - - def _recvfrom_into(): -- b = bytearray("\0"*100) -+ b = bytearray(b"\0"*100) - count, addr = s.recvfrom_into(b) - return b[:count] - -@@ -1275,73 +2439,73 @@ else: - data_prefix = u"PREFIX_" - - for meth_name, send_meth, expect_success, args in send_methods: -- indata = data_prefix + meth_name -+ indata = (data_prefix + meth_name).encode('ascii') - try: -- send_meth(indata.encode('ASCII', 'strict'), *args) -+ send_meth(indata, *args) - outdata = s.read() -- outdata = outdata.decode('ASCII', 'strict') - if outdata != indata.lower(): - self.fail( -- "While sending with <<%s>> bad data " -- "<<%r>> (%d) received; " -- "expected <<%r>> (%d)\n" % ( -- meth_name, outdata[:20], len(outdata), -- indata[:20], len(indata) -+ "While sending with <<{name:s}>> bad data " -+ "<<{outdata:r}>> ({nout:d}) received; " -+ "expected <<{indata:r}>> ({nin:d})\n".format( -+ name=meth_name, outdata=outdata[:20], -+ nout=len(outdata), -+ indata=indata[:20], nin=len(indata) - ) - ) - except ValueError as e: - if expect_success: - self.fail( -- "Failed to send with method <<%s>>; " -- "expected to succeed.\n" % (meth_name,) -+ "Failed to send with method <<{name:s}>>; " -+ "expected to succeed.\n".format(name=meth_name) - ) - if not str(e).startswith(meth_name): - self.fail( -- "Method <<%s>> failed with unexpected " -- "exception message: %s\n" % ( -- meth_name, e -+ "Method <<{name:s}>> failed with unexpected " -+ "exception message: {exp:s}\n".format( -+ name=meth_name, exp=e - ) - ) - - for meth_name, recv_meth, expect_success, args in recv_methods: -- indata = data_prefix + meth_name -+ indata = (data_prefix + meth_name).encode('ascii') - try: -- s.send(indata.encode('ASCII', 'strict')) -+ s.send(indata) - outdata = recv_meth(*args) -- outdata = outdata.decode('ASCII', 'strict') - if outdata != indata.lower(): - self.fail( -- "While receiving with <<%s>> bad data " -- "<<%r>> (%d) received; " -- "expected <<%r>> (%d)\n" % ( -- meth_name, outdata[:20], len(outdata), -- indata[:20], len(indata) -+ "While receiving with <<{name:s}>> bad data " -+ "<<{outdata:r}>> ({nout:d}) received; " -+ "expected <<{indata:r}>> ({nin:d})\n".format( -+ name=meth_name, outdata=outdata[:20], -+ nout=len(outdata), -+ indata=indata[:20], nin=len(indata) - ) - ) - except ValueError as e: - if expect_success: - self.fail( -- "Failed to receive with method <<%s>>; " -- "expected to succeed.\n" % (meth_name,) -+ "Failed to receive with method <<{name:s}>>; " -+ "expected to succeed.\n".format(name=meth_name) - ) - if not str(e).startswith(meth_name): - self.fail( -- "Method <<%s>> failed with unexpected " -- "exception message: %s\n" % ( -- meth_name, e -+ "Method <<{name:s}>> failed with unexpected " -+ "exception message: {exp:s}\n".format( -+ name=meth_name, exp=e - ) - ) - # consume data - s.read() - -- s.write("over\n".encode("ASCII", "strict")) -+ s.write(b"over\n") - s.close() - - def test_handshake_timeout(self): - # Issue #5103: SSL handshake must respect the socket timeout - server = socket.socket(socket.AF_INET) - host = "127.0.0.1" -- port = test_support.bind_port(server) -+ port = support.bind_port(server) - started = threading.Event() - finish = False - -@@ -1355,6 +2519,8 @@ else: - # Let the socket hang around rather than having - # it closed by garbage collection. - conns.append(server.accept()[0]) -+ for sock in conns: -+ sock.close() - - t = threading.Thread(target=serve) - t.start() -@@ -1372,8 +2538,8 @@ else: - c.close() - try: - c = socket.socket(socket.AF_INET) -- c.settimeout(0.2) - c = ssl.wrap_socket(c) -+ c.settimeout(0.2) - # Will attempt handshake and time out - self.assertRaisesRegexp(ssl.SSLError, "timed out", - c.connect, (host, port)) -@@ -1384,59 +2550,384 @@ else: - t.join() - server.close() - -+ def test_server_accept(self): -+ # Issue #16357: accept() on a SSLSocket created through -+ # SSLContext.wrap_socket(). -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = socket.socket(socket.AF_INET) -+ host = "127.0.0.1" -+ port = support.bind_port(server) -+ server = context.wrap_socket(server, server_side=True) -+ -+ evt = threading.Event() -+ remote = [None] -+ peer = [None] -+ def serve(): -+ server.listen(5) -+ # Block on the accept and wait on the connection to close. -+ evt.set() -+ remote[0], peer[0] = server.accept() -+ remote[0].recv(1) -+ -+ t = threading.Thread(target=serve) -+ t.start() -+ # Client wait until server setup and perform a connect. -+ evt.wait() -+ client = context.wrap_socket(socket.socket()) -+ client.connect((host, port)) -+ client_addr = client.getsockname() -+ client.close() -+ t.join() -+ remote[0].close() -+ server.close() -+ # Sanity checks. -+ self.assertIsInstance(remote[0], ssl.SSLSocket) -+ self.assertEqual(peer[0], client_addr) -+ -+ def test_getpeercert_enotconn(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(context.wrap_socket(socket.socket())) as sock: -+ with self.assertRaises(socket.error) as cm: -+ sock.getpeercert() -+ self.assertEqual(cm.exception.errno, errno.ENOTCONN) -+ -+ def test_do_handshake_enotconn(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(context.wrap_socket(socket.socket())) as sock: -+ with self.assertRaises(socket.error) as cm: -+ sock.do_handshake() -+ self.assertEqual(cm.exception.errno, errno.ENOTCONN) -+ - def test_default_ciphers(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ try: -+ # Force a set of weak ciphers on our client context -+ context.set_ciphers("DES") -+ except ssl.SSLError: -+ self.skipTest("no DES cipher available") - with ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_SSLv23, - chatty=False) as server: -- sock = socket.socket() -- try: -- # Force a set of weak ciphers on our client socket -- try: -- s = ssl.wrap_socket(sock, -- ssl_version=ssl.PROTOCOL_SSLv23, -- ciphers="DES") -- except ssl.SSLError: -- self.skipTest("no DES cipher available") -- with self.assertRaises((OSError, ssl.SSLError)): -+ with closing(context.wrap_socket(socket.socket())) as s: -+ with self.assertRaises(ssl.SSLError): - s.connect((HOST, server.port)) -- finally: -- sock.close() - self.assertIn("no shared cipher", str(server.conn_errors[0])) - -+ @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") -+ def test_default_ecdh_curve(self): -+ # Issue #21015: elliptic curve-based Diffie Hellman key exchange -+ # should be enabled by default on SSL contexts. -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.load_cert_chain(CERTFILE) -+ # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled -+ # explicitly using the 'ECCdraft' cipher alias. Otherwise, -+ # our default cipher list should prefer ECDH-based ciphers -+ # automatically. -+ if ssl.OPENSSL_VERSION_INFO < (1, 0, 0): -+ context.set_ciphers("ECCdraft:ECDH") -+ with ThreadedEchoServer(context=context) as server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ self.assertIn("ECDH", s.cipher()[0]) -+ -+ @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES, -+ "'tls-unique' channel binding not available") -+ def test_tls_unique_channel_binding(self): -+ """Test tls-unique channel binding.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server = ThreadedEchoServer(CERTFILE, -+ certreqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1, -+ cacerts=CERTFILE, -+ chatty=True, -+ connectionchatty=False) -+ with server: -+ s = ssl.wrap_socket(socket.socket(), -+ server_side=False, -+ certfile=CERTFILE, -+ ca_certs=CERTFILE, -+ cert_reqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ # get the data -+ cb_data = s.get_channel_binding("tls-unique") -+ if support.verbose: -+ sys.stdout.write(" got channel binding data: {0!r}\n" -+ .format(cb_data)) -+ -+ # check if it is sane -+ self.assertIsNotNone(cb_data) -+ self.assertEqual(len(cb_data), 12) # True for TLSv1 -+ -+ # and compare with the peers version -+ s.write(b"CB tls-unique\n") -+ peer_data_repr = s.read().strip() -+ self.assertEqual(peer_data_repr, -+ repr(cb_data).encode("us-ascii")) -+ s.close() -+ -+ # now, again -+ s = ssl.wrap_socket(socket.socket(), -+ server_side=False, -+ certfile=CERTFILE, -+ ca_certs=CERTFILE, -+ cert_reqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ new_cb_data = s.get_channel_binding("tls-unique") -+ if support.verbose: -+ sys.stdout.write(" got another channel binding data: {0!r}\n" -+ .format(new_cb_data)) -+ # is it really unique -+ self.assertNotEqual(cb_data, new_cb_data) -+ self.assertIsNotNone(cb_data) -+ self.assertEqual(len(cb_data), 12) # True for TLSv1 -+ s.write(b"CB tls-unique\n") -+ peer_data_repr = s.read().strip() -+ self.assertEqual(peer_data_repr, -+ repr(new_cb_data).encode("us-ascii")) -+ s.close() -+ -+ def test_compression(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ if support.verbose: -+ sys.stdout.write(" got compression: {!r}\n".format(stats['compression'])) -+ self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' }) -+ -+ @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'), -+ "ssl.OP_NO_COMPRESSION needed for this test") -+ def test_compression_disabled(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ context.options |= ssl.OP_NO_COMPRESSION -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ self.assertIs(stats['compression'], None) -+ -+ def test_dh_params(self): -+ # Check we can get a connection with ephemeral Diffie-Hellman -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ context.load_dh_params(DHFILE) -+ context.set_ciphers("kEDH") -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ cipher = stats["cipher"][0] -+ parts = cipher.split("-") -+ if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: -+ self.fail("Non-DH cipher: " + cipher[0]) -+ -+ def test_selected_npn_protocol(self): -+ # selected_npn_protocol() is None unless NPN is used -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ self.assertIs(stats['client_npn_protocol'], None) -+ -+ @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test") -+ def test_npn_protocols(self): -+ server_protocols = ['http/1.1', 'spdy/2'] -+ protocol_tests = [ -+ (['http/1.1', 'spdy/2'], 'http/1.1'), -+ (['spdy/2', 'http/1.1'], 'http/1.1'), -+ (['spdy/2', 'test'], 'spdy/2'), -+ (['abc', 'def'], 'abc') -+ ] -+ for client_protocols, expected in protocol_tests: -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(CERTFILE) -+ server_context.set_npn_protocols(server_protocols) -+ client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ client_context.load_cert_chain(CERTFILE) -+ client_context.set_npn_protocols(client_protocols) -+ stats = server_params_test(client_context, server_context, -+ chatty=True, connectionchatty=True) -+ -+ msg = "failed trying %s (s) and %s (c).\n" \ -+ "was expecting %s, but got %%s from the %%s" \ -+ % (str(server_protocols), str(client_protocols), -+ str(expected)) -+ client_result = stats['client_npn_protocol'] -+ self.assertEqual(client_result, expected, msg % (client_result, "client")) -+ server_result = stats['server_npn_protocols'][-1] \ -+ if len(stats['server_npn_protocols']) else 'nothing' -+ self.assertEqual(server_result, expected, msg % (server_result, "server")) -+ -+ def sni_contexts(self): -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ other_context.load_cert_chain(SIGNED_CERTFILE2) -+ client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ client_context.verify_mode = ssl.CERT_REQUIRED -+ client_context.load_verify_locations(SIGNING_CA) -+ return server_context, other_context, client_context -+ -+ def check_common_name(self, stats, name): -+ cert = stats['peercert'] -+ self.assertIn((('commonName', name),), cert['subject']) -+ -+ @needs_sni -+ def test_sni_callback(self): -+ calls = [] -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def servername_cb(ssl_sock, server_name, initial_context): -+ calls.append((server_name, initial_context)) -+ if server_name is not None: -+ ssl_sock.context = other_context -+ server_context.set_servername_callback(servername_cb) -+ -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name='supermessage') -+ # The hostname was fetched properly, and the certificate was -+ # changed for the connection. -+ self.assertEqual(calls, [("supermessage", server_context)]) -+ # CERTFILE4 was selected -+ self.check_common_name(stats, 'fakehostname') -+ -+ calls = [] -+ # The callback is called with server_name=None -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name=None) -+ self.assertEqual(calls, [(None, server_context)]) -+ self.check_common_name(stats, 'localhost') -+ -+ # Check disabling the callback -+ calls = [] -+ server_context.set_servername_callback(None) -+ -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name='notfunny') -+ # Certificate didn't change -+ self.check_common_name(stats, 'localhost') -+ self.assertEqual(calls, []) -+ -+ @needs_sni -+ def test_sni_callback_alert(self): -+ # Returning a TLS alert is reflected to the connecting client -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_returning_alert(ssl_sock, server_name, initial_context): -+ return ssl.ALERT_DESCRIPTION_ACCESS_DENIED -+ server_context.set_servername_callback(cb_returning_alert) -+ -+ with self.assertRaises(ssl.SSLError) as cm: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED') -+ -+ @needs_sni -+ def test_sni_callback_raising(self): -+ # Raising fails the connection with a TLS handshake failure alert. -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_raising(ssl_sock, server_name, initial_context): -+ 1/0 -+ server_context.set_servername_callback(cb_raising) -+ -+ with self.assertRaises(ssl.SSLError) as cm, \ -+ support.captured_stderr() as stderr: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE') -+ self.assertIn("ZeroDivisionError", stderr.getvalue()) -+ -+ @needs_sni -+ def test_sni_callback_wrong_return_type(self): -+ # Returning the wrong return type terminates the TLS connection -+ # with an internal error alert. -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_wrong_return_type(ssl_sock, server_name, initial_context): -+ return "foo" -+ server_context.set_servername_callback(cb_wrong_return_type) -+ -+ with self.assertRaises(ssl.SSLError) as cm, \ -+ support.captured_stderr() as stderr: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR') -+ self.assertIn("TypeError", stderr.getvalue()) -+ -+ def test_read_write_after_close_raises_valuerror(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = ThreadedEchoServer(context=context, chatty=False) -+ -+ with server: -+ s = context.wrap_socket(socket.socket()) -+ s.connect((HOST, server.port)) -+ s.close() -+ -+ self.assertRaises(ValueError, s.read, 1024) -+ self.assertRaises(ValueError, s.write, b'hello') -+ - - def test_main(verbose=False): -- global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT -- CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, -- "keycert.pem") -- SVN_PYTHON_ORG_ROOT_CERT = os.path.join( -- os.path.dirname(__file__) or os.curdir, -- "https_svn_python_org_root.pem") -- NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir, -- "nokia.pem") -- NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir, -- "nullbytecert.pem") -- -- if (not os.path.exists(CERTFILE) or -- not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or -- not os.path.exists(NOKIACERT) or -- not os.path.exists(NULLBYTECERT)): -- raise test_support.TestFailed("Can't read certificate files!") -- -- tests = [BasicTests, BasicSocketTests] -- -- if test_support.is_resource_enabled('network'): -+ if support.verbose: -+ plats = { -+ 'Linux': platform.linux_distribution, -+ 'Mac': platform.mac_ver, -+ 'Windows': platform.win32_ver, -+ } -+ for name, func in plats.items(): -+ plat = func() -+ if plat and plat[0]: -+ plat = '%s %r' % (name, plat) -+ break -+ else: -+ plat = repr(platform.platform()) -+ print("test_ssl: testing with %r %r" % -+ (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO)) -+ print(" under %s" % plat) -+ print(" HAS_SNI = %r" % ssl.HAS_SNI) -+ print(" OP_ALL = 0x%8x" % ssl.OP_ALL) -+ try: -+ print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1) -+ except AttributeError: -+ pass -+ -+ for filename in [ -+ CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE, -+ ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY, -+ SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA, -+ BADCERT, BADKEY, EMPTYCERT]: -+ if not os.path.exists(filename): -+ raise support.TestFailed("Can't read certificate file %r" % filename) -+ -+ tests = [ContextTests, BasicSocketTests, SSLErrorTests] -+ -+ if support.is_resource_enabled('network'): - tests.append(NetworkedTests) - - if _have_threads: -- thread_info = test_support.threading_setup() -- if thread_info and test_support.is_resource_enabled('network'): -+ thread_info = support.threading_setup() -+ if thread_info: - tests.append(ThreadedTests) - - try: -- test_support.run_unittest(*tests) -+ support.run_unittest(*tests) - finally: - if _have_threads: -- test_support.threading_cleanup(*thread_info) -+ support.threading_cleanup(*thread_info) - - if __name__ == "__main__": - test_main() -diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py -index 695ac95..c1c8799 100644 ---- a/Lib/test/test_support.py -+++ b/Lib/test/test_support.py -@@ -39,7 +39,7 @@ __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", - "threading_cleanup", "reap_children", "cpython_only", - "check_impl_detail", "get_attribute", "py3k_bytes", - "import_fresh_module", "threading_cleanup", "reap_children", -- "strip_python_stderr"] -+ "strip_python_stderr", "IPV6_ENABLED"] - - class Error(Exception): - """Base class for regression test exceptions.""" -@@ -465,6 +465,23 @@ def bind_port(sock, host=HOST): - port = sock.getsockname()[1] - return port - -+def _is_ipv6_enabled(): -+ """Check whether IPv6 is enabled on this host.""" -+ if socket.has_ipv6: -+ sock = None -+ try: -+ sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) -+ sock.bind((HOSTv6, 0)) -+ return True -+ except OSError: -+ pass -+ finally: -+ if sock: -+ sock.close() -+ return False -+ -+IPV6_ENABLED = _is_ipv6_enabled() -+ - FUZZ = 1e-6 - - def fcmp(x, y): # fuzzy comparison function -diff --git a/Makefile.pre.in b/Makefile.pre.in -index bcd83bf..80a0926 100644 ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -930,8 +930,8 @@ PLATMACDIRS= plat-mac plat-mac/Carbon plat-mac/lib-scriptpackages \ - plat-mac/lib-scriptpackages/Terminal - PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages - LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ -- lib-tk/test/test_ttk site-packages test test/audiodata test/data \ -- test/cjkencodings test/decimaltestdata test/xmltestdata \ -+ lib-tk/test/test_ttk site-packages test test/audiodata test/capath \ -+ test/data test/cjkencodings test/decimaltestdata test/xmltestdata \ - test/imghdrdata \ - test/subprocessdata \ - test/tracedmodules \ -diff --git a/Modules/_ssl.c b/Modules/_ssl.c -index 752b033..8f4062b 100644 ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -14,22 +14,28 @@ - http://bugs.python.org/issue8108#msg102867 ? - */ - -+#define PY_SSIZE_T_CLEAN - #include "Python.h" - - #ifdef WITH_THREAD - #include "pythread.h" - - -+#define PySSL_BEGIN_ALLOW_THREADS_S(save) \ -+ do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) -+#define PySSL_END_ALLOW_THREADS_S(save) \ -+ do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } } while (0) - #define PySSL_BEGIN_ALLOW_THREADS { \ - PyThreadState *_save = NULL; \ -- if (_ssl_locks_count>0) {_save = PyEval_SaveThread();} --#define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)}; --#define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()}; --#define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ -- } -+ PySSL_BEGIN_ALLOW_THREADS_S(_save); -+#define PySSL_BLOCK_THREADS PySSL_END_ALLOW_THREADS_S(_save); -+#define PySSL_UNBLOCK_THREADS PySSL_BEGIN_ALLOW_THREADS_S(_save); -+#define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); } - - #else /* no WITH_THREAD */ - -+#define PySSL_BEGIN_ALLOW_THREADS_S(save) -+#define PySSL_END_ALLOW_THREADS_S(save) - #define PySSL_BEGIN_ALLOW_THREADS - #define PySSL_BLOCK_THREADS - #define PySSL_UNBLOCK_THREADS -@@ -37,6 +43,68 @@ - - #endif - -+/* Include symbols from _socket module */ -+#include "socketmodule.h" -+ -+#if defined(HAVE_POLL_H) -+#include -+#elif defined(HAVE_SYS_POLL_H) -+#include -+#endif -+ -+/* Include OpenSSL header files */ -+#include "openssl/rsa.h" -+#include "openssl/crypto.h" -+#include "openssl/x509.h" -+#include "openssl/x509v3.h" -+#include "openssl/pem.h" -+#include "openssl/ssl.h" -+#include "openssl/err.h" -+#include "openssl/rand.h" -+ -+/* SSL error object */ -+static PyObject *PySSLErrorObject; -+static PyObject *PySSLZeroReturnErrorObject; -+static PyObject *PySSLWantReadErrorObject; -+static PyObject *PySSLWantWriteErrorObject; -+static PyObject *PySSLSyscallErrorObject; -+static PyObject *PySSLEOFErrorObject; -+ -+/* Error mappings */ -+static PyObject *err_codes_to_names; -+static PyObject *err_names_to_codes; -+static PyObject *lib_codes_to_names; -+ -+struct py_ssl_error_code { -+ const char *mnemonic; -+ int library, reason; -+}; -+struct py_ssl_library_code { -+ const char *library; -+ int code; -+}; -+ -+/* Include generated data (error codes) */ -+#include "_ssl_data.h" -+ -+/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1 -+ http://www.openssl.org/news/changelog.html -+ */ -+#if OPENSSL_VERSION_NUMBER >= 0x10001000L -+# define HAVE_TLSv1_2 1 -+#else -+# define HAVE_TLSv1_2 0 -+#endif -+ -+/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f -+ * This includes the SSL_set_SSL_CTX() function. -+ */ -+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -+# define HAVE_SNI 1 -+#else -+# define HAVE_SNI 0 -+#endif -+ - enum py_ssl_error { - /* these mirror ssl.h */ - PY_SSL_ERROR_NONE, -@@ -49,6 +117,7 @@ enum py_ssl_error { - PY_SSL_ERROR_WANT_CONNECT, - /* start of non ssl.h errorcodes */ - PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ -+ PY_SSL_ERROR_NO_SOCKET, /* socket has been GC'd */ - PY_SSL_ERROR_INVALID_ERROR_CODE - }; - -@@ -64,35 +133,17 @@ enum py_ssl_cert_requirements { - }; - - enum py_ssl_version { --#ifndef OPENSSL_NO_SSL2 - PY_SSL_VERSION_SSL2, --#endif - PY_SSL_VERSION_SSL3=1, - PY_SSL_VERSION_SSL23, -+#if HAVE_TLSv1_2 -+ PY_SSL_VERSION_TLS1, -+ PY_SSL_VERSION_TLS1_1, -+ PY_SSL_VERSION_TLS1_2 -+#else - PY_SSL_VERSION_TLS1 --}; -- --/* Include symbols from _socket module */ --#include "socketmodule.h" -- --#if defined(HAVE_POLL_H) --#include --#elif defined(HAVE_SYS_POLL_H) --#include - #endif -- --/* Include OpenSSL header files */ --#include "openssl/rsa.h" --#include "openssl/crypto.h" --#include "openssl/x509.h" --#include "openssl/x509v3.h" --#include "openssl/pem.h" --#include "openssl/ssl.h" --#include "openssl/err.h" --#include "openssl/rand.h" -- --/* SSL error object */ --static PyObject *PySSLErrorObject; -+}; - - #ifdef WITH_THREAD - -@@ -114,27 +165,79 @@ static unsigned int _ssl_locks_count = 0; - # undef HAVE_OPENSSL_RAND - #endif - -+/* SSL_CTX_clear_options() and SSL_clear_options() were first added in -+ * OpenSSL 0.9.8m but do not appear in some 0.9.9-dev versions such the -+ * 0.9.9 from "May 2008" that NetBSD 5.0 uses. */ -+#if OPENSSL_VERSION_NUMBER >= 0x009080dfL && OPENSSL_VERSION_NUMBER != 0x00909000L -+# define HAVE_SSL_CTX_CLEAR_OPTIONS -+#else -+# undef HAVE_SSL_CTX_CLEAR_OPTIONS -+#endif -+ -+/* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for -+ * older SSL, but let's be safe */ -+#define PySSL_CB_MAXLEN 128 -+ -+/* SSL_get_finished got added to OpenSSL in 0.9.5 */ -+#if OPENSSL_VERSION_NUMBER >= 0x0090500fL -+# define HAVE_OPENSSL_FINISHED 1 -+#else -+# define HAVE_OPENSSL_FINISHED 0 -+#endif -+ -+/* ECDH support got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER < 0x0090800fL && !defined(OPENSSL_NO_ECDH) -+# define OPENSSL_NO_ECDH -+#endif -+ -+/* compression support got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER < 0x0090800fL && !defined(OPENSSL_NO_COMP) -+# define OPENSSL_NO_COMP -+#endif -+ -+/* X509_VERIFY_PARAM got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -+# define HAVE_OPENSSL_VERIFY_PARAM -+#endif -+ -+ -+typedef struct { -+ PyObject_HEAD -+ SSL_CTX *ctx; -+#ifdef OPENSSL_NPN_NEGOTIATED -+ char *npn_protocols; -+ int npn_protocols_len; -+#endif -+#ifndef OPENSSL_NO_TLSEXT -+ PyObject *set_hostname; -+#endif -+ int check_hostname; -+} PySSLContext; -+ - typedef struct { - PyObject_HEAD -- PySocketSockObject *Socket; /* Socket on which we're layered */ -- SSL_CTX* ctx; -- SSL* ssl; -- X509* peer_cert; -- char server[X509_NAME_MAXLEN]; -- char issuer[X509_NAME_MAXLEN]; -- int shutdown_seen_zero; -- --} PySSLObject; -- --static PyTypeObject PySSL_Type; --static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args); --static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args); -+ PySocketSockObject *Socket; -+ PyObject *ssl_sock; -+ SSL *ssl; -+ PySSLContext *ctx; /* weakref to SSL context */ -+ X509 *peer_cert; -+ char shutdown_seen_zero; -+ char handshake_done; -+ enum py_ssl_server_or_client socket_type; -+} PySSLSocket; -+ -+static PyTypeObject PySSLContext_Type; -+static PyTypeObject PySSLSocket_Type; -+ -+static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); -+static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); - static int check_socket_and_wait_for_timeout(PySocketSockObject *s, - int writing); --static PyObject *PySSL_peercert(PySSLObject *self, PyObject *args); --static PyObject *PySSL_cipher(PySSLObject *self); -+static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); -+static PyObject *PySSL_cipher(PySSLSocket *self); - --#define PySSLObject_Check(v) (Py_TYPE(v) == &PySSL_Type) -+#define PySSLContext_Check(v) (Py_TYPE(v) == &PySSLContext_Type) -+#define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) - - typedef enum { - SOCKET_IS_NONBLOCKING, -@@ -151,36 +254,140 @@ typedef enum { - #define ERRSTR1(x,y,z) (x ":" y ": " z) - #define ERRSTR(x) ERRSTR1("_ssl.c", STRINGIFY2(__LINE__), x) - --/* XXX It might be helpful to augment the error message generated -- below with the name of the SSL function that generated the error. -- I expect it's obvious most of the time. --*/ -+ -+/* -+ * SSL errors. -+ */ -+ -+PyDoc_STRVAR(SSLError_doc, -+"An error occurred in the SSL implementation."); -+ -+PyDoc_STRVAR(SSLZeroReturnError_doc, -+"SSL/TLS session closed cleanly."); -+ -+PyDoc_STRVAR(SSLWantReadError_doc, -+"Non-blocking SSL socket needs to read more data\n" -+"before the requested operation can be completed."); -+ -+PyDoc_STRVAR(SSLWantWriteError_doc, -+"Non-blocking SSL socket needs to write more data\n" -+"before the requested operation can be completed."); -+ -+PyDoc_STRVAR(SSLSyscallError_doc, -+"System error when attempting SSL operation."); -+ -+PyDoc_STRVAR(SSLEOFError_doc, -+"SSL/TLS connection terminated abruptly."); -+ - - static PyObject * --PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno) -+SSLError_str(PyEnvironmentErrorObject *self) - { -- PyObject *v; -- char buf[2048]; -- char *errstr; -+ if (self->strerror != NULL) { -+ Py_INCREF(self->strerror); -+ return self->strerror; -+ } -+ else -+ return PyObject_Str(self->args); -+} -+ -+static void -+fill_and_set_sslerror(PyObject *type, int ssl_errno, const char *errstr, -+ int lineno, unsigned long errcode) -+{ -+ PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL; -+ PyObject *init_value, *msg, *key; -+ -+ if (errcode != 0) { -+ int lib, reason; -+ -+ lib = ERR_GET_LIB(errcode); -+ reason = ERR_GET_REASON(errcode); -+ key = Py_BuildValue("ii", lib, reason); -+ if (key == NULL) -+ goto fail; -+ reason_obj = PyDict_GetItem(err_codes_to_names, key); -+ Py_DECREF(key); -+ if (reason_obj == NULL) { -+ /* XXX if reason < 100, it might reflect a library number (!!) */ -+ PyErr_Clear(); -+ } -+ key = PyLong_FromLong(lib); -+ if (key == NULL) -+ goto fail; -+ lib_obj = PyDict_GetItem(lib_codes_to_names, key); -+ Py_DECREF(key); -+ if (lib_obj == NULL) { -+ PyErr_Clear(); -+ } -+ if (errstr == NULL) -+ errstr = ERR_reason_error_string(errcode); -+ } -+ if (errstr == NULL) -+ errstr = "unknown error"; -+ -+ if (reason_obj && lib_obj) -+ msg = PyUnicode_FromFormat("[%S: %S] %s (_ssl.c:%d)", -+ lib_obj, reason_obj, errstr, lineno); -+ else if (lib_obj) -+ msg = PyUnicode_FromFormat("[%S] %s (_ssl.c:%d)", -+ lib_obj, errstr, lineno); -+ else -+ msg = PyUnicode_FromFormat("%s (_ssl.c:%d)", errstr, lineno); -+ if (msg == NULL) -+ goto fail; -+ -+ init_value = Py_BuildValue("iN", ssl_errno, msg); -+ if (init_value == NULL) -+ goto fail; -+ -+ err_value = PyObject_CallObject(type, init_value); -+ Py_DECREF(init_value); -+ if (err_value == NULL) -+ goto fail; -+ -+ if (reason_obj == NULL) -+ reason_obj = Py_None; -+ if (PyObject_SetAttrString(err_value, "reason", reason_obj)) -+ goto fail; -+ if (lib_obj == NULL) -+ lib_obj = Py_None; -+ if (PyObject_SetAttrString(err_value, "library", lib_obj)) -+ goto fail; -+ PyErr_SetObject(type, err_value); -+fail: -+ Py_XDECREF(err_value); -+} -+ -+static PyObject * -+PySSL_SetError(PySSLSocket *obj, int ret, char *filename, int lineno) -+{ -+ PyObject *type = PySSLErrorObject; -+ char *errstr = NULL; - int err; - enum py_ssl_error p = PY_SSL_ERROR_NONE; -+ unsigned long e = 0; - - assert(ret <= 0); -+ e = ERR_peek_last_error(); - - if (obj->ssl != NULL) { - err = SSL_get_error(obj->ssl, ret); - - switch (err) { - case SSL_ERROR_ZERO_RETURN: -- errstr = "TLS/SSL connection has been closed"; -+ errstr = "TLS/SSL connection has been closed (EOF)"; -+ type = PySSLZeroReturnErrorObject; - p = PY_SSL_ERROR_ZERO_RETURN; - break; - case SSL_ERROR_WANT_READ: - errstr = "The operation did not complete (read)"; -+ type = PySSLWantReadErrorObject; - p = PY_SSL_ERROR_WANT_READ; - break; - case SSL_ERROR_WANT_WRITE: - p = PY_SSL_ERROR_WANT_WRITE; -+ type = PySSLWantWriteErrorObject; - errstr = "The operation did not complete (write)"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: -@@ -193,213 +400,109 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno) - break; - case SSL_ERROR_SYSCALL: - { -- unsigned long e = ERR_get_error(); - if (e == 0) { -- if (ret == 0 || !obj->Socket) { -+ PySocketSockObject *s = obj->Socket; -+ if (ret == 0) { - p = PY_SSL_ERROR_EOF; -+ type = PySSLEOFErrorObject; - errstr = "EOF occurred in violation of protocol"; - } else if (ret == -1) { - /* underlying BIO reported an I/O error */ -+ Py_INCREF(s); - ERR_clear_error(); -- return obj->Socket->errorhandler(); -+ s->errorhandler(); -+ Py_DECREF(s); -+ return NULL; - } else { /* possible? */ - p = PY_SSL_ERROR_SYSCALL; -+ type = PySSLSyscallErrorObject; - errstr = "Some I/O error occurred"; - } - } else { - p = PY_SSL_ERROR_SYSCALL; -- /* XXX Protected by global interpreter lock */ -- errstr = ERR_error_string(e, NULL); - } - break; - } - case SSL_ERROR_SSL: - { -- unsigned long e = ERR_get_error(); - p = PY_SSL_ERROR_SSL; -- if (e != 0) -- /* XXX Protected by global interpreter lock */ -- errstr = ERR_error_string(e, NULL); -- else { /* possible? */ -+ if (e == 0) -+ /* possible? */ - errstr = "A failure in the SSL library occurred"; -- } - break; - } - default: - p = PY_SSL_ERROR_INVALID_ERROR_CODE; - errstr = "Invalid error code"; - } -- } else { -- errstr = ERR_error_string(ERR_peek_last_error(), NULL); - } -- PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); -+ fill_and_set_sslerror(type, p, errstr, lineno, e); - ERR_clear_error(); -- v = Py_BuildValue("(is)", p, buf); -- if (v != NULL) { -- PyErr_SetObject(PySSLErrorObject, v); -- Py_DECREF(v); -- } - return NULL; - } - - static PyObject * - _setSSLError (char *errstr, int errcode, char *filename, int lineno) { - -- char buf[2048]; -- PyObject *v; -- -- if (errstr == NULL) { -+ if (errstr == NULL) - errcode = ERR_peek_last_error(); -- errstr = ERR_error_string(errcode, NULL); -- } -- PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); -+ else -+ errcode = 0; -+ fill_and_set_sslerror(PySSLErrorObject, errcode, errstr, lineno, errcode); - ERR_clear_error(); -- v = Py_BuildValue("(is)", errcode, buf); -- if (v != NULL) { -- PyErr_SetObject(PySSLErrorObject, v); -- Py_DECREF(v); -- } - return NULL; - } - --static PySSLObject * --newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, -+/* -+ * SSL objects -+ */ -+ -+static PySSLSocket * -+newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, - enum py_ssl_server_or_client socket_type, -- enum py_ssl_cert_requirements certreq, -- enum py_ssl_version proto_version, -- char *cacerts_file, char *ciphers) -+ char *server_hostname, PyObject *ssl_sock) - { -- PySSLObject *self; -- char *errstr = NULL; -- int ret; -- int verification_mode; -- long options; -+ PySSLSocket *self; -+ SSL_CTX *ctx = sslctx->ctx; -+ long mode; - -- self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ -+ self = PyObject_New(PySSLSocket, &PySSLSocket_Type); - if (self == NULL) - return NULL; -- memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); -- memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); -+ - self->peer_cert = NULL; - self->ssl = NULL; -- self->ctx = NULL; - self->Socket = NULL; -+ self->ssl_sock = NULL; -+ self->ctx = sslctx; - self->shutdown_seen_zero = 0; -+ self->handshake_done = 0; -+ Py_INCREF(sslctx); - - /* Make sure the SSL error state is initialized */ - (void) ERR_get_state(); - ERR_clear_error(); - -- if ((key_file && !cert_file) || (!key_file && cert_file)) { -- errstr = ERRSTR("Both the key & certificate files " -- "must be specified"); -- goto fail; -- } -- -- if ((socket_type == PY_SSL_SERVER) && -- ((key_file == NULL) || (cert_file == NULL))) { -- errstr = ERRSTR("Both the key & certificate files " -- "must be specified for server-side operation"); -- goto fail; -- } -- -- PySSL_BEGIN_ALLOW_THREADS -- if (proto_version == PY_SSL_VERSION_TLS1) -- self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ -- else if (proto_version == PY_SSL_VERSION_SSL3) -- self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ --#ifndef OPENSSL_NO_SSL2 -- else if (proto_version == PY_SSL_VERSION_SSL2) -- self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ --#endif -- else if (proto_version == PY_SSL_VERSION_SSL23) -- self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ -- PySSL_END_ALLOW_THREADS -- -- if (self->ctx == NULL) { -- errstr = ERRSTR("Invalid SSL protocol variant specified."); -- goto fail; -- } -- -- if (ciphers != NULL) { -- ret = SSL_CTX_set_cipher_list(self->ctx, ciphers); -- if (ret == 0) { -- errstr = ERRSTR("No cipher can be selected."); -- goto fail; -- } -- } -- -- if (certreq != PY_SSL_CERT_NONE) { -- if (cacerts_file == NULL) { -- errstr = ERRSTR("No root certificates specified for " -- "verification of other-side certificates."); -- goto fail; -- } else { -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_load_verify_locations(self->ctx, -- cacerts_file, -- NULL); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail; -- } -- } -- } -- if (key_file) { -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, -- SSL_FILETYPE_PEM); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- _setSSLError(NULL, ret, __FILE__, __LINE__); -- goto fail; -- } -- -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_use_certificate_chain_file(self->ctx, -- cert_file); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- /* -- fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", -- ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); -- */ -- if (ERR_peek_last_error() != 0) { -- _setSSLError(NULL, ret, __FILE__, __LINE__); -- goto fail; -- } -- } -- } -- -- /* ssl compatibility */ -- options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -- if (proto_version != PY_SSL_VERSION_SSL2) -- options |= SSL_OP_NO_SSLv2; -- SSL_CTX_set_options(self->ctx, options); -- -- verification_mode = SSL_VERIFY_NONE; -- if (certreq == PY_SSL_CERT_OPTIONAL) -- verification_mode = SSL_VERIFY_PEER; -- else if (certreq == PY_SSL_CERT_REQUIRED) -- verification_mode = (SSL_VERIFY_PEER | -- SSL_VERIFY_FAIL_IF_NO_PEER_CERT); -- SSL_CTX_set_verify(self->ctx, verification_mode, -- NULL); /* set verify lvl */ -- - PySSL_BEGIN_ALLOW_THREADS -- self->ssl = SSL_new(self->ctx); /* New ssl struct */ -+ self->ssl = SSL_new(ctx); - PySSL_END_ALLOW_THREADS -- SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ -+ SSL_set_app_data(self->ssl,self); -+ SSL_set_fd(self->ssl, Py_SAFE_DOWNCAST(sock->sock_fd, SOCKET_T, int)); -+ mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; - #ifdef SSL_MODE_AUTO_RETRY -- SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); -+ mode |= SSL_MODE_AUTO_RETRY; -+#endif -+ SSL_set_mode(self->ssl, mode); -+ -+#if HAVE_SNI -+ if (server_hostname != NULL) -+ SSL_set_tlsext_host_name(self->ssl, server_hostname); - #endif - - /* If the socket is in non-blocking mode or timeout mode, set the BIO - * to non-blocking mode (blocking is the default) - */ -- if (Sock->sock_timeout >= 0.0) { -- /* Set both the read and write BIO's to non-blocking mode */ -+ if (sock->sock_timeout >= 0.0) { - BIO_set_nbio(SSL_get_rbio(self->ssl), 1); - BIO_set_nbio(SSL_get_wbio(self->ssl), 1); - } -@@ -411,65 +514,31 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, - SSL_set_accept_state(self->ssl); - PySSL_END_ALLOW_THREADS - -- self->Socket = Sock; -+ self->socket_type = socket_type; -+ self->Socket = sock; - Py_INCREF(self->Socket); -- return self; -- fail: -- if (errstr) -- PyErr_SetString(PySSLErrorObject, errstr); -- Py_DECREF(self); -- return NULL; --} -- --static PyObject * --PySSL_sslwrap(PyObject *self, PyObject *args) --{ -- PySocketSockObject *Sock; -- int server_side = 0; -- int verification_mode = PY_SSL_CERT_NONE; -- int protocol = PY_SSL_VERSION_SSL23; -- char *key_file = NULL; -- char *cert_file = NULL; -- char *cacerts_file = NULL; -- char *ciphers = NULL; -- -- if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap", -- PySocketModule.Sock_Type, -- &Sock, -- &server_side, -- &key_file, &cert_file, -- &verification_mode, &protocol, -- &cacerts_file, &ciphers)) -+ self->ssl_sock = PyWeakref_NewRef(ssl_sock, NULL); -+ if (self->ssl_sock == NULL) { -+ Py_DECREF(self); - return NULL; -- -- /* -- fprintf(stderr, -- "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " -- "protocol %d, certs %p\n", -- server_side, key_file, cert_file, verification_mode, -- protocol, cacerts_file); -- */ -- -- return (PyObject *) newPySSLObject(Sock, key_file, cert_file, -- server_side, verification_mode, -- protocol, cacerts_file, -- ciphers); -+ } -+ return self; - } - --PyDoc_STRVAR(ssl_doc, --"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n" --" cacertsfile, ciphers]) -> sslobject"); - - /* SSL object methods */ - --static PyObject *PySSL_SSLdo_handshake(PySSLObject *self) -+static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) - { - int ret; - int err; - int sockstate, nonblocking; -+ PySocketSockObject *sock = self->Socket; -+ -+ Py_INCREF(sock); - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -480,60 +549,48 @@ static PyObject *PySSL_SSLdo_handshake(PySSLObject *self) - ret = SSL_do_handshake(self->ssl); - err = SSL_get_error(self->ssl, ret); - PySSL_END_ALLOW_THREADS -- if(PyErr_CheckSignals()) { -- return NULL; -- } -+ if (PyErr_CheckSignals()) -+ goto error; - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("The handshake operation timed out")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket has been closed.")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket too large for select().")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); -+ Py_DECREF(sock); - if (ret < 1) - return PySSL_SetError(self, ret, __FILE__, __LINE__); - - if (self->peer_cert) - X509_free (self->peer_cert); - PySSL_BEGIN_ALLOW_THREADS -- if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) { -- X509_NAME_oneline(X509_get_subject_name(self->peer_cert), -- self->server, X509_NAME_MAXLEN); -- X509_NAME_oneline(X509_get_issuer_name(self->peer_cert), -- self->issuer, X509_NAME_MAXLEN); -- } -+ self->peer_cert = SSL_get_peer_certificate(self->ssl); - PySSL_END_ALLOW_THREADS -+ self->handshake_done = 1; - - Py_INCREF(Py_None); - return Py_None; --} -- --static PyObject * --PySSL_server(PySSLObject *self) --{ -- return PyString_FromString(self->server); --} - --static PyObject * --PySSL_issuer(PySSLObject *self) --{ -- return PyString_FromString(self->issuer); -+error: -+ Py_DECREF(sock); -+ return NULL; - } - - static PyObject * -@@ -639,8 +696,8 @@ _create_tuple_for_X509_NAME (X509_NAME *xname) - /* - fprintf(stderr, "RDN level %d, attribute %s: %s\n", - entry->set, -- PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), -- PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); -+ PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 0)), -+ PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 1))); - */ - if (attr == NULL) - goto fail1; -@@ -727,21 +784,24 @@ _get_peer_alt_names (X509 *certificate) { - /* now decode the altName */ - ext = X509_get_ext(certificate, i); - if(!(method = X509V3_EXT_get(ext))) { -- PyErr_SetString(PySSLErrorObject, -- ERRSTR("No method for internalizing subjectAltName!")); -+ PyErr_SetString -+ (PySSLErrorObject, -+ ERRSTR("No method for internalizing subjectAltName!")); - goto fail; - } - - p = ext->value->data; - if (method->it) -- names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, -- &p, -- ext->value->length, -- ASN1_ITEM_ptr(method->it))); -+ names = (GENERAL_NAMES*) -+ (ASN1_item_d2i(NULL, -+ &p, -+ ext->value->length, -+ ASN1_ITEM_ptr(method->it))); - else -- names = (GENERAL_NAMES*) (method->d2i(NULL, -- &p, -- ext->value->length)); -+ names = (GENERAL_NAMES*) -+ (method->d2i(NULL, -+ &p, -+ ext->value->length)); - - for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { - /* get a rendering of each name in the set of names */ -@@ -888,94 +948,212 @@ _get_peer_alt_names (X509 *certificate) { - } - - static PyObject * --_decode_certificate (X509 *certificate, int verbose) { -- -- PyObject *retval = NULL; -- BIO *biobuf = NULL; -- PyObject *peer; -- PyObject *peer_alt_names = NULL; -- PyObject *issuer; -- PyObject *version; -- PyObject *sn_obj; -- ASN1_INTEGER *serialNumber; -- char buf[2048]; -- int len; -- ASN1_TIME *notBefore, *notAfter; -- PyObject *pnotBefore, *pnotAfter; -- -- retval = PyDict_New(); -- if (retval == NULL) -- return NULL; -+_get_aia_uri(X509 *certificate, int nid) { -+ PyObject *lst = NULL, *ostr = NULL; -+ int i, result; -+ AUTHORITY_INFO_ACCESS *info; -+ -+ info = X509_get_ext_d2i(certificate, NID_info_access, NULL, NULL); -+ if ((info == NULL) || (sk_ACCESS_DESCRIPTION_num(info) == 0)) { -+ return Py_None; -+ } - -- peer = _create_tuple_for_X509_NAME( -- X509_get_subject_name(certificate)); -- if (peer == NULL) -- goto fail0; -- if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { -- Py_DECREF(peer); -- goto fail0; -+ if ((lst = PyList_New(0)) == NULL) { -+ goto fail; - } -- Py_DECREF(peer); - -- if (verbose) { -- issuer = _create_tuple_for_X509_NAME( -- X509_get_issuer_name(certificate)); -- if (issuer == NULL) -- goto fail0; -- if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { -- Py_DECREF(issuer); -- goto fail0; -- } -- Py_DECREF(issuer); -+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { -+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); -+ ASN1_IA5STRING *uri; - -- version = PyInt_FromLong(X509_get_version(certificate) + 1); -- if (PyDict_SetItemString(retval, "version", version) < 0) { -- Py_DECREF(version); -- goto fail0; -+ if ((OBJ_obj2nid(ad->method) != nid) || -+ (ad->location->type != GEN_URI)) { -+ continue; -+ } -+ uri = ad->location->d.uniformResourceIdentifier; -+ ostr = PyUnicode_FromStringAndSize((char *)uri->data, -+ uri->length); -+ if (ostr == NULL) { -+ goto fail; -+ } -+ result = PyList_Append(lst, ostr); -+ Py_DECREF(ostr); -+ if (result < 0) { -+ goto fail; - } -- Py_DECREF(version); - } -+ AUTHORITY_INFO_ACCESS_free(info); - -- /* get a memory buffer */ -- biobuf = BIO_new(BIO_s_mem()); -- -- if (verbose) { -+ /* convert to tuple or None */ -+ if (PyList_Size(lst) == 0) { -+ Py_DECREF(lst); -+ return Py_None; -+ } else { -+ PyObject *tup; -+ tup = PyList_AsTuple(lst); -+ Py_DECREF(lst); -+ return tup; -+ } - -- (void) BIO_reset(biobuf); -- serialNumber = X509_get_serialNumber(certificate); -- /* should not exceed 20 octets, 160 bits, so buf is big enough */ -- i2a_ASN1_INTEGER(biobuf, serialNumber); -- len = BIO_gets(biobuf, buf, sizeof(buf)-1); -- if (len < 0) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail1; -- } -- sn_obj = PyString_FromStringAndSize(buf, len); -- if (sn_obj == NULL) -- goto fail1; -- if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { -- Py_DECREF(sn_obj); -- goto fail1; -+ fail: -+ AUTHORITY_INFO_ACCESS_free(info); -+ Py_XDECREF(lst); -+ return NULL; -+} -+ -+static PyObject * -+_get_crl_dp(X509 *certificate) { -+ STACK_OF(DIST_POINT) *dps; -+ int i, j, result; -+ PyObject *lst; -+ -+#if OPENSSL_VERSION_NUMBER < 0x10001000L -+ dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, -+ NULL, NULL); -+#else -+ /* Calls x509v3_cache_extensions and sets up crldp */ -+ X509_check_ca(certificate); -+ dps = certificate->crldp; -+#endif -+ -+ if (dps == NULL) { -+ return Py_None; -+ } -+ -+ if ((lst = PyList_New(0)) == NULL) { -+ return NULL; -+ } -+ -+ for (i=0; i < sk_DIST_POINT_num(dps); i++) { -+ DIST_POINT *dp; -+ STACK_OF(GENERAL_NAME) *gns; -+ -+ dp = sk_DIST_POINT_value(dps, i); -+ gns = dp->distpoint->name.fullname; -+ -+ for (j=0; j < sk_GENERAL_NAME_num(gns); j++) { -+ GENERAL_NAME *gn; -+ ASN1_IA5STRING *uri; -+ PyObject *ouri; -+ -+ gn = sk_GENERAL_NAME_value(gns, j); -+ if (gn->type != GEN_URI) { -+ continue; -+ } -+ uri = gn->d.uniformResourceIdentifier; -+ ouri = PyUnicode_FromStringAndSize((char *)uri->data, -+ uri->length); -+ if (ouri == NULL) { -+ Py_DECREF(lst); -+ return NULL; -+ } -+ result = PyList_Append(lst, ouri); -+ Py_DECREF(ouri); -+ if (result < 0) { -+ Py_DECREF(lst); -+ return NULL; -+ } - } -+ } -+ /* convert to tuple or None */ -+ if (PyList_Size(lst) == 0) { -+ Py_DECREF(lst); -+ return Py_None; -+ } else { -+ PyObject *tup; -+ tup = PyList_AsTuple(lst); -+ Py_DECREF(lst); -+ return tup; -+ } -+} -+ -+static PyObject * -+_decode_certificate(X509 *certificate) { -+ -+ PyObject *retval = NULL; -+ BIO *biobuf = NULL; -+ PyObject *peer; -+ PyObject *peer_alt_names = NULL; -+ PyObject *issuer; -+ PyObject *version; -+ PyObject *sn_obj; -+ PyObject *obj; -+ ASN1_INTEGER *serialNumber; -+ char buf[2048]; -+ int len, result; -+ ASN1_TIME *notBefore, *notAfter; -+ PyObject *pnotBefore, *pnotAfter; -+ -+ retval = PyDict_New(); -+ if (retval == NULL) -+ return NULL; -+ -+ peer = _create_tuple_for_X509_NAME( -+ X509_get_subject_name(certificate)); -+ if (peer == NULL) -+ goto fail0; -+ if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { -+ Py_DECREF(peer); -+ goto fail0; -+ } -+ Py_DECREF(peer); -+ -+ issuer = _create_tuple_for_X509_NAME( -+ X509_get_issuer_name(certificate)); -+ if (issuer == NULL) -+ goto fail0; -+ if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { -+ Py_DECREF(issuer); -+ goto fail0; -+ } -+ Py_DECREF(issuer); -+ -+ version = PyLong_FromLong(X509_get_version(certificate) + 1); -+ if (version == NULL) -+ goto fail0; -+ if (PyDict_SetItemString(retval, "version", version) < 0) { -+ Py_DECREF(version); -+ goto fail0; -+ } -+ Py_DECREF(version); -+ -+ /* get a memory buffer */ -+ biobuf = BIO_new(BIO_s_mem()); -+ -+ (void) BIO_reset(biobuf); -+ serialNumber = X509_get_serialNumber(certificate); -+ /* should not exceed 20 octets, 160 bits, so buf is big enough */ -+ i2a_ASN1_INTEGER(biobuf, serialNumber); -+ len = BIO_gets(biobuf, buf, sizeof(buf)-1); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto fail1; -+ } -+ sn_obj = PyUnicode_FromStringAndSize(buf, len); -+ if (sn_obj == NULL) -+ goto fail1; -+ if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { - Py_DECREF(sn_obj); -+ goto fail1; -+ } -+ Py_DECREF(sn_obj); - -- (void) BIO_reset(biobuf); -- notBefore = X509_get_notBefore(certificate); -- ASN1_TIME_print(biobuf, notBefore); -- len = BIO_gets(biobuf, buf, sizeof(buf)-1); -- if (len < 0) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail1; -- } -- pnotBefore = PyString_FromStringAndSize(buf, len); -- if (pnotBefore == NULL) -- goto fail1; -- if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { -- Py_DECREF(pnotBefore); -- goto fail1; -- } -+ (void) BIO_reset(biobuf); -+ notBefore = X509_get_notBefore(certificate); -+ ASN1_TIME_print(biobuf, notBefore); -+ len = BIO_gets(biobuf, buf, sizeof(buf)-1); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto fail1; -+ } -+ pnotBefore = PyUnicode_FromStringAndSize(buf, len); -+ if (pnotBefore == NULL) -+ goto fail1; -+ if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { - Py_DECREF(pnotBefore); -+ goto fail1; - } -+ Py_DECREF(pnotBefore); - - (void) BIO_reset(biobuf); - notAfter = X509_get_notAfter(certificate); -@@ -1008,6 +1186,41 @@ _decode_certificate (X509 *certificate, int verbose) { - Py_DECREF(peer_alt_names); - } - -+ /* Authority Information Access: OCSP URIs */ -+ obj = _get_aia_uri(certificate, NID_ad_OCSP); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "OCSP", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ -+ obj = _get_aia_uri(certificate, NID_ad_ca_issuers); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "caIssuers", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ -+ /* CDP (CRL distribution points) */ -+ obj = _get_crl_dp(certificate); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "crlDistributionPoints", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ - BIO_free(biobuf); - return retval; - -@@ -1019,6 +1232,24 @@ _decode_certificate (X509 *certificate, int verbose) { - return NULL; - } - -+static PyObject * -+_certificate_to_der(X509 *certificate) -+{ -+ unsigned char *bytes_buf = NULL; -+ int len; -+ PyObject *retval; -+ -+ bytes_buf = NULL; -+ len = i2d_X509(certificate, &bytes_buf); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ /* this is actually an immutable bytes sequence */ -+ retval = PyBytes_FromStringAndSize((const char *) bytes_buf, len); -+ OPENSSL_free(bytes_buf); -+ return retval; -+} - - static PyObject * - PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { -@@ -1027,28 +1258,30 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { - char *filename = NULL; - X509 *x=NULL; - BIO *cert; -- int verbose = 1; - -- if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose)) -+ if (!PyArg_ParseTuple(args, "s:test_decode_certificate", &filename)) - return NULL; - - if ((cert=BIO_new(BIO_s_file())) == NULL) { -- PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Can't malloc memory to read file"); - goto fail0; - } - - if (BIO_read_filename(cert,filename) <= 0) { -- PyErr_SetString(PySSLErrorObject, "Can't open file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Can't open file"); - goto fail0; - } - - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); - if (x == NULL) { -- PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Error decoding PEM-encoded file"); - goto fail0; - } - -- retval = _decode_certificate(x, verbose); -+ retval = _decode_certificate(x); - X509_free(x); - - fail0: -@@ -1059,10 +1292,8 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { - - - static PyObject * --PySSL_peercert(PySSLObject *self, PyObject *args) -+PySSL_peercert(PySSLSocket *self, PyObject *args) - { -- PyObject *retval = NULL; -- int len; - int verification; - PyObject *binary_mode = Py_None; - int b; -@@ -1070,6 +1301,11 @@ PySSL_peercert(PySSLObject *self, PyObject *args) - if (!PyArg_ParseTuple(args, "|O:peer_certificate", &binary_mode)) - return NULL; - -+ if (!self->handshake_done) { -+ PyErr_SetString(PyExc_ValueError, -+ "handshake not done yet"); -+ return NULL; -+ } - if (!self->peer_cert) - Py_RETURN_NONE; - -@@ -1078,26 +1314,13 @@ PySSL_peercert(PySSLObject *self, PyObject *args) - return NULL; - if (b) { - /* return cert in DER-encoded format */ -- -- unsigned char *bytes_buf = NULL; -- -- bytes_buf = NULL; -- len = i2d_X509(self->peer_cert, &bytes_buf); -- if (len < 0) { -- PySSL_SetError(self, len, __FILE__, __LINE__); -- return NULL; -- } -- retval = PyString_FromStringAndSize((const char *) bytes_buf, len); -- OPENSSL_free(bytes_buf); -- return retval; -- -+ return _certificate_to_der(self->peer_cert); - } else { -- -- verification = SSL_CTX_get_verify_mode(self->ctx); -+ verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl)); - if ((verification & SSL_VERIFY_PEER) == 0) - return PyDict_New(); - else -- return _decode_certificate (self->peer_cert, 0); -+ return _decode_certificate(self->peer_cert); - } - } - -@@ -1113,7 +1336,7 @@ If the optional argument is True, returns a DER-encoded copy of the\n\ - peer certificate, or None if no certificate was provided. This will\n\ - return the certificate even if it wasn't validated."); - --static PyObject *PySSL_cipher (PySSLObject *self) { -+static PyObject *PySSL_cipher (PySSLSocket *self) { - - PyObject *retval, *v; - const SSL_CIPHER *current; -@@ -1140,7 +1363,7 @@ static PyObject *PySSL_cipher (PySSLObject *self) { - goto fail0; - PyTuple_SET_ITEM(retval, 0, v); - } -- cipher_protocol = SSL_CIPHER_get_version(current); -+ cipher_protocol = (char *) SSL_CIPHER_get_version(current); - if (cipher_protocol == NULL) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(retval, 1, Py_None); -@@ -1161,15 +1384,85 @@ static PyObject *PySSL_cipher (PySSLObject *self) { - return NULL; - } - --static void PySSL_dealloc(PySSLObject *self) -+#ifdef OPENSSL_NPN_NEGOTIATED -+static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { -+ const unsigned char *out; -+ unsigned int outlen; -+ -+ SSL_get0_next_proto_negotiated(self->ssl, -+ &out, &outlen); -+ -+ if (out == NULL) -+ Py_RETURN_NONE; -+ return PyUnicode_FromStringAndSize((char *) out, outlen); -+} -+#endif -+ -+static PyObject *PySSL_compression(PySSLSocket *self) { -+#ifdef OPENSSL_NO_COMP -+ Py_RETURN_NONE; -+#else -+ const COMP_METHOD *comp_method; -+ const char *short_name; -+ -+ if (self->ssl == NULL) -+ Py_RETURN_NONE; -+ comp_method = SSL_get_current_compression(self->ssl); -+ if (comp_method == NULL || comp_method->type == NID_undef) -+ Py_RETURN_NONE; -+ short_name = OBJ_nid2sn(comp_method->type); -+ if (short_name == NULL) -+ Py_RETURN_NONE; -+ return PyBytes_FromString(short_name); -+#endif -+} -+ -+static PySSLContext *PySSL_get_context(PySSLSocket *self, void *closure) { -+ Py_INCREF(self->ctx); -+ return self->ctx; -+} -+ -+static int PySSL_set_context(PySSLSocket *self, PyObject *value, -+ void *closure) { -+ -+ if (PyObject_TypeCheck(value, &PySSLContext_Type)) { -+#if !HAVE_SNI -+ PyErr_SetString(PyExc_NotImplementedError, "setting a socket's " -+ "context is not supported by your OpenSSL library"); -+ return -1; -+#else -+ Py_INCREF(value); -+ Py_DECREF(self->ctx); -+ self->ctx = (PySSLContext *) value; -+ SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); -+#endif -+ } else { -+ PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+PyDoc_STRVAR(PySSL_set_context_doc, -+"_setter_context(ctx)\n\ -+\ -+This changes the context associated with the SSLSocket. This is typically\n\ -+used from within a callback function set by the set_servername_callback\n\ -+on the SSLContext to change the certificate information associated with the\n\ -+SSLSocket before the cryptographic exchange handshake messages\n"); -+ -+ -+ -+static void PySSL_dealloc(PySSLSocket *self) - { - if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); - if (self->ssl) - SSL_free(self->ssl); -- if (self->ctx) -- SSL_CTX_free(self->ctx); - Py_XDECREF(self->Socket); -+ Py_XDECREF(self->ssl_sock); -+ Py_XDECREF(self->ctx); - PyObject_Del(self); - } - -@@ -1241,16 +1534,21 @@ normal_return: - return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; - } - --static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) -+static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) - { - Py_buffer buf; - int len; - int sockstate; - int err; - int nonblocking; -+ PySocketSockObject *sock = self->Socket; -+ -+ Py_INCREF(sock); - -- if (!PyArg_ParseTuple(args, "s*:write", &buf)) -+ if (!PyArg_ParseTuple(args, "s*:write", &buf)) { -+ Py_DECREF(sock); - return NULL; -+ } - - if (buf.len > INT_MAX) { - PyErr_Format(PyExc_OverflowError, -@@ -1259,11 +1557,11 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) - } - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); -@@ -1286,9 +1584,9 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) - goto error; - } - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } -@@ -1305,6 +1603,7 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - -+ Py_DECREF(sock); - PyBuffer_Release(&buf); - if (len > 0) - return PyInt_FromLong(len); -@@ -1312,6 +1611,7 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) - return PySSL_SetError(self, len, __FILE__, __LINE__); - - error: -+ Py_DECREF(sock); - PyBuffer_Release(&buf); - return NULL; - } -@@ -1322,7 +1622,7 @@ PyDoc_STRVAR(PySSL_SSLwrite_doc, - Writes the string s into the SSL object. Returns the number\n\ - of bytes written."); - --static PyObject *PySSL_SSLpending(PySSLObject *self) -+static PyObject *PySSL_SSLpending(PySSLSocket *self) - { - int count = 0; - -@@ -1341,23 +1641,46 @@ PyDoc_STRVAR(PySSL_SSLpending_doc, - Returns the number of already decrypted bytes available for read,\n\ - pending on the connection.\n"); - --static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) -+static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) - { -- PyObject *buf; -- int count = 0; -- int len = 1024; -+ PyObject *dest = NULL; -+ Py_buffer buf; -+ char *mem; -+ int len, count; -+ int buf_passed = 0; - int sockstate; - int err; - int nonblocking; -+ PySocketSockObject *sock = self->Socket; - -- if (!PyArg_ParseTuple(args, "|i:read", &len)) -- return NULL; -+ Py_INCREF(sock); - -- if (!(buf = PyString_FromStringAndSize((char *) 0, len))) -- return NULL; -+ buf.obj = NULL; -+ buf.buf = NULL; -+ if (!PyArg_ParseTuple(args, "i|w*:read", &len, &buf)) -+ goto error; -+ -+ if ((buf.buf == NULL) && (buf.obj == NULL)) { -+ dest = PyBytes_FromStringAndSize(NULL, len); -+ if (dest == NULL) -+ goto error; -+ mem = PyBytes_AS_STRING(dest); -+ } -+ else { -+ buf_passed = 1; -+ mem = buf.buf; -+ if (len <= 0 || len > buf.len) { -+ len = (int) buf.len; -+ if (buf.len != len) { -+ PyErr_SetString(PyExc_OverflowError, -+ "maximum length can't fit in a C 'int'"); -+ goto error; -+ } -+ } -+ } - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -1367,70 +1690,71 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) - PySSL_END_ALLOW_THREADS - - if (!count) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { -- if (SSL_get_shutdown(self->ssl) != -- SSL_RECEIVED_SHUTDOWN) -- { -- Py_DECREF(buf); -- PyErr_SetString(PySSLErrorObject, -- "Socket closed without SSL shutdown handshake"); -- return NULL; -- } else { -- /* should contain a zero-length string */ -- _PyString_Resize(&buf, 0); -- return buf; -- } -+ count = 0; -+ goto done; - } - } - do { - PySSL_BEGIN_ALLOW_THREADS -- count = SSL_read(self->ssl, PyString_AsString(buf), len); -+ count = SSL_read(self->ssl, mem, len); - err = SSL_get_error(self->ssl, count); - PySSL_END_ALLOW_THREADS -- if(PyErr_CheckSignals()) { -- Py_DECREF(buf); -- return NULL; -- } -+ if (PyErr_CheckSignals()) -+ goto error; - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else if ((err == SSL_ERROR_ZERO_RETURN) && - (SSL_get_shutdown(self->ssl) == - SSL_RECEIVED_SHUTDOWN)) - { -- _PyString_Resize(&buf, 0); -- return buf; -+ count = 0; -+ goto done; - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - if (count <= 0) { -- Py_DECREF(buf); -- return PySSL_SetError(self, count, __FILE__, __LINE__); -+ PySSL_SetError(self, count, __FILE__, __LINE__); -+ goto error; -+ } -+ -+done: -+ Py_DECREF(sock); -+ if (!buf_passed) { -+ _PyBytes_Resize(&dest, count); -+ return dest; - } -- if (count != len) -- _PyString_Resize(&buf, count); -- return buf; -+ else { -+ PyBuffer_Release(&buf); -+ return PyLong_FromLong(count); -+ } -+ -+error: -+ Py_DECREF(sock); -+ if (!buf_passed) -+ Py_XDECREF(dest); -+ else -+ PyBuffer_Release(&buf); -+ return NULL; - } - - PyDoc_STRVAR(PySSL_SSLread_doc, -@@ -1438,20 +1762,22 @@ PyDoc_STRVAR(PySSL_SSLread_doc, - \n\ - Read up to len bytes from the SSL socket."); - --static PyObject *PySSL_SSLshutdown(PySSLObject *self) -+static PyObject *PySSL_SSLshutdown(PySSLSocket *self) - { - int err, ssl_err, sockstate, nonblocking; - int zeros = 0; -+ PySocketSockObject *sock = self->Socket; - - /* Guard against closed socket */ -- if (self->Socket->sock_fd < 0) { -- PyErr_SetString(PySSLErrorObject, -- "Underlying socket has been closed."); -+ if (sock->sock_fd < 0) { -+ _setSSLError("Underlying socket connection gone", -+ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } -+ Py_INCREF(sock); - - /* Just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -1486,9 +1812,9 @@ static PyObject *PySSL_SSLshutdown(PySSLObject *self) - /* Possibly retry shutdown until timeout or failure */ - ssl_err = SSL_get_error(self->ssl, err); - if (ssl_err == SSL_ERROR_WANT_READ) -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - else if (ssl_err == SSL_ERROR_WANT_WRITE) -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - else - break; - if (sockstate == SOCKET_HAS_TIMED_OUT) { -@@ -1498,24 +1824,29 @@ static PyObject *PySSL_SSLshutdown(PySSLObject *self) - else - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); -- return NULL; -+ goto error; - } - else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); -- return NULL; -+ goto error; - } - else if (sockstate != SOCKET_OPERATION_OK) - /* Retain the SSL error code */ - break; - } - -- if (err < 0) -+ if (err < 0) { -+ Py_DECREF(sock); - return PySSL_SetError(self, err, __FILE__, __LINE__); -- else { -- Py_INCREF(self->Socket); -- return (PyObject *) (self->Socket); - } -+ else -+ /* It's already INCREF'ed */ -+ return (PyObject *) sock; -+ -+error: -+ Py_DECREF(sock); -+ return NULL; - } - - PyDoc_STRVAR(PySSL_SSLshutdown_doc, -@@ -1524,6 +1855,47 @@ PyDoc_STRVAR(PySSL_SSLshutdown_doc, - Does the SSL shutdown handshake with the remote end, and returns\n\ - the underlying socket object."); - -+#if HAVE_OPENSSL_FINISHED -+static PyObject * -+PySSL_tls_unique_cb(PySSLSocket *self) -+{ -+ PyObject *retval = NULL; -+ char buf[PySSL_CB_MAXLEN]; -+ size_t len; -+ -+ if (SSL_session_reused(self->ssl) ^ !self->socket_type) { -+ /* if session is resumed XOR we are the client */ -+ len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); -+ } -+ else { -+ /* if a new session XOR we are the server */ -+ len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); -+ } -+ -+ /* It cannot be negative in current OpenSSL version as of July 2011 */ -+ if (len == 0) -+ Py_RETURN_NONE; -+ -+ retval = PyBytes_FromStringAndSize(buf, len); -+ -+ return retval; -+} -+ -+PyDoc_STRVAR(PySSL_tls_unique_cb_doc, -+"tls_unique_cb() -> bytes\n\ -+\n\ -+Returns the 'tls-unique' channel binding data, as defined by RFC 5929.\n\ -+\n\ -+If the TLS handshake is not yet complete, None is returned"); -+ -+#endif /* HAVE_OPENSSL_FINISHED */ -+ -+static PyGetSetDef ssl_getsetlist[] = { -+ {"context", (getter) PySSL_get_context, -+ (setter) PySSL_set_context, PySSL_set_context_doc}, -+ {NULL}, /* sentinel */ -+}; -+ - static PyMethodDef PySSLMethods[] = { - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, -@@ -1532,66 +1904,1343 @@ static PyMethodDef PySSLMethods[] = { - PySSL_SSLread_doc}, - {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, - PySSL_SSLpending_doc}, -- {"server", (PyCFunction)PySSL_server, METH_NOARGS}, -- {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, -+#ifdef OPENSSL_NPN_NEGOTIATED -+ {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, -+#endif -+ {"compression", (PyCFunction)PySSL_compression, METH_NOARGS}, - {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, - PySSL_SSLshutdown_doc}, -+#if HAVE_OPENSSL_FINISHED -+ {"tls_unique_cb", (PyCFunction)PySSL_tls_unique_cb, METH_NOARGS, -+ PySSL_tls_unique_cb_doc}, -+#endif - {NULL, NULL} - }; - --static PyObject *PySSL_getattr(PySSLObject *self, char *name) --{ -- return Py_FindMethod(PySSLMethods, (PyObject *)self, name); --} -- --static PyTypeObject PySSL_Type = { -+static PyTypeObject PySSLSocket_Type = { - PyVarObject_HEAD_INIT(NULL, 0) -- "ssl.SSLContext", /*tp_name*/ -- sizeof(PySSLObject), /*tp_basicsize*/ -+ "_ssl._SSLSocket", /*tp_name*/ -+ sizeof(PySSLSocket), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PySSL_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ -- (getattrfunc)PySSL_getattr, /*tp_getattr*/ -+ 0, /*tp_getattr*/ - 0, /*tp_setattr*/ -- 0, /*tp_compare*/ -+ 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -+ 0, /*tp_call*/ -+ 0, /*tp_str*/ -+ 0, /*tp_getattro*/ -+ 0, /*tp_setattro*/ -+ 0, /*tp_as_buffer*/ -+ Py_TPFLAGS_DEFAULT, /*tp_flags*/ -+ 0, /*tp_doc*/ -+ 0, /*tp_traverse*/ -+ 0, /*tp_clear*/ -+ 0, /*tp_richcompare*/ -+ 0, /*tp_weaklistoffset*/ -+ 0, /*tp_iter*/ -+ 0, /*tp_iternext*/ -+ PySSLMethods, /*tp_methods*/ -+ 0, /*tp_members*/ -+ ssl_getsetlist, /*tp_getset*/ - }; - --#ifdef HAVE_OPENSSL_RAND - --/* helper routines for seeding the SSL PRNG */ -+/* -+ * _SSLContext objects -+ */ -+ - static PyObject * --PySSL_RAND_add(PyObject *self, PyObject *args) -+context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) - { -- char *buf; -- int len; -- double entropy; -+ char *kwlist[] = {"protocol", NULL}; -+ PySSLContext *self; -+ int proto_version = PY_SSL_VERSION_SSL23; -+ long options; -+ SSL_CTX *ctx = NULL; - -- if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) -+ if (!PyArg_ParseTupleAndKeywords( -+ args, kwds, "i:_SSLContext", kwlist, -+ &proto_version)) - return NULL; -- RAND_add(buf, len, entropy); -- Py_INCREF(Py_None); -- return Py_None; --} -- --PyDoc_STRVAR(PySSL_RAND_add_doc, --"RAND_add(string, entropy)\n\ --\n\ --Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\ --bound on the entropy contained in string. See RFC 1750."); - --static PyObject * --PySSL_RAND_status(PyObject *self) --{ -- return PyInt_FromLong(RAND_status()); -+ PySSL_BEGIN_ALLOW_THREADS -+ if (proto_version == PY_SSL_VERSION_TLS1) -+ ctx = SSL_CTX_new(TLSv1_method()); -+#if HAVE_TLSv1_2 -+ else if (proto_version == PY_SSL_VERSION_TLS1_1) -+ ctx = SSL_CTX_new(TLSv1_1_method()); -+ else if (proto_version == PY_SSL_VERSION_TLS1_2) -+ ctx = SSL_CTX_new(TLSv1_2_method()); -+#endif -+ else if (proto_version == PY_SSL_VERSION_SSL3) -+ ctx = SSL_CTX_new(SSLv3_method()); -+#ifndef OPENSSL_NO_SSL2 -+ else if (proto_version == PY_SSL_VERSION_SSL2) -+ ctx = SSL_CTX_new(SSLv2_method()); -+#endif -+ else if (proto_version == PY_SSL_VERSION_SSL23) -+ ctx = SSL_CTX_new(SSLv23_method()); -+ else -+ proto_version = -1; -+ PySSL_END_ALLOW_THREADS -+ -+ if (proto_version == -1) { -+ PyErr_SetString(PyExc_ValueError, -+ "invalid protocol version"); -+ return NULL; -+ } -+ if (ctx == NULL) { -+ PyErr_SetString(PySSLErrorObject, -+ "failed to allocate SSL context"); -+ return NULL; -+ } -+ -+ assert(type != NULL && type->tp_alloc != NULL); -+ self = (PySSLContext *) type->tp_alloc(type, 0); -+ if (self == NULL) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ self->ctx = ctx; -+#ifdef OPENSSL_NPN_NEGOTIATED -+ self->npn_protocols = NULL; -+#endif -+#ifndef OPENSSL_NO_TLSEXT -+ self->set_hostname = NULL; -+#endif -+ /* Don't check host name by default */ -+ self->check_hostname = 0; -+ /* Defaults */ -+ SSL_CTX_set_verify(self->ctx, SSL_VERIFY_NONE, NULL); -+ options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -+ if (proto_version != PY_SSL_VERSION_SSL2) -+ options |= SSL_OP_NO_SSLv2; -+ SSL_CTX_set_options(self->ctx, options); -+ -+#ifndef OPENSSL_NO_ECDH -+ /* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use -+ prime256v1 by default. This is Apache mod_ssl's initialization -+ policy, so we should be safe. */ -+#if defined(SSL_CTX_set_ecdh_auto) -+ SSL_CTX_set_ecdh_auto(self->ctx, 1); -+#else -+ { -+ EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); -+ SSL_CTX_set_tmp_ecdh(self->ctx, key); -+ EC_KEY_free(key); -+ } -+#endif -+#endif -+ -+#define SID_CTX "Python" -+ SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX, -+ sizeof(SID_CTX)); -+#undef SID_CTX -+ -+ return (PyObject *)self; -+} -+ -+static int -+context_traverse(PySSLContext *self, visitproc visit, void *arg) -+{ -+#ifndef OPENSSL_NO_TLSEXT -+ Py_VISIT(self->set_hostname); -+#endif -+ return 0; -+} -+ -+static int -+context_clear(PySSLContext *self) -+{ -+#ifndef OPENSSL_NO_TLSEXT -+ Py_CLEAR(self->set_hostname); -+#endif -+ return 0; -+} -+ -+static void -+context_dealloc(PySSLContext *self) -+{ -+ context_clear(self); -+ SSL_CTX_free(self->ctx); -+#ifdef OPENSSL_NPN_NEGOTIATED -+ PyMem_Free(self->npn_protocols); -+#endif -+ Py_TYPE(self)->tp_free(self); -+} -+ -+static PyObject * -+set_ciphers(PySSLContext *self, PyObject *args) -+{ -+ int ret; -+ const char *cipherlist; -+ -+ if (!PyArg_ParseTuple(args, "s:set_ciphers", &cipherlist)) -+ return NULL; -+ ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist); -+ if (ret == 0) { -+ /* Clearing the error queue is necessary on some OpenSSL versions, -+ otherwise the error will be reported again when another SSL call -+ is done. */ -+ ERR_clear_error(); -+ PyErr_SetString(PySSLErrorObject, -+ "No cipher can be selected."); -+ return NULL; -+ } -+ Py_RETURN_NONE; -+} -+ -+#ifdef OPENSSL_NPN_NEGOTIATED -+/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ -+static int -+_advertiseNPN_cb(SSL *s, -+ const unsigned char **data, unsigned int *len, -+ void *args) -+{ -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ -+ if (ssl_ctx->npn_protocols == NULL) { -+ *data = (unsigned char *) ""; -+ *len = 0; -+ } else { -+ *data = (unsigned char *) ssl_ctx->npn_protocols; -+ *len = ssl_ctx->npn_protocols_len; -+ } -+ -+ return SSL_TLSEXT_ERR_OK; -+} -+/* this callback gets passed to SSL_CTX_set_next_proto_select_cb */ -+static int -+_selectNPN_cb(SSL *s, -+ unsigned char **out, unsigned char *outlen, -+ const unsigned char *server, unsigned int server_len, -+ void *args) -+{ -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ -+ unsigned char *client = (unsigned char *) ssl_ctx->npn_protocols; -+ int client_len; -+ -+ if (client == NULL) { -+ client = (unsigned char *) ""; -+ client_len = 0; -+ } else { -+ client_len = ssl_ctx->npn_protocols_len; -+ } -+ -+ SSL_select_next_proto(out, outlen, -+ server, server_len, -+ client, client_len); -+ -+ return SSL_TLSEXT_ERR_OK; -+} -+#endif -+ -+static PyObject * -+_set_npn_protocols(PySSLContext *self, PyObject *args) -+{ -+#ifdef OPENSSL_NPN_NEGOTIATED -+ Py_buffer protos; -+ -+ if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos)) -+ return NULL; -+ -+ if (self->npn_protocols != NULL) { -+ PyMem_Free(self->npn_protocols); -+ } -+ -+ self->npn_protocols = PyMem_Malloc(protos.len); -+ if (self->npn_protocols == NULL) { -+ PyBuffer_Release(&protos); -+ return PyErr_NoMemory(); -+ } -+ memcpy(self->npn_protocols, protos.buf, protos.len); -+ self->npn_protocols_len = (int) protos.len; -+ -+ /* set both server and client callbacks, because the context can -+ * be used to create both types of sockets */ -+ SSL_CTX_set_next_protos_advertised_cb(self->ctx, -+ _advertiseNPN_cb, -+ self); -+ SSL_CTX_set_next_proto_select_cb(self->ctx, -+ _selectNPN_cb, -+ self); -+ -+ PyBuffer_Release(&protos); -+ Py_RETURN_NONE; -+#else -+ PyErr_SetString(PyExc_NotImplementedError, -+ "The NPN extension requires OpenSSL 1.0.1 or later."); -+ return NULL; -+#endif -+} -+ -+static PyObject * -+get_verify_mode(PySSLContext *self, void *c) -+{ -+ switch (SSL_CTX_get_verify_mode(self->ctx)) { -+ case SSL_VERIFY_NONE: -+ return PyLong_FromLong(PY_SSL_CERT_NONE); -+ case SSL_VERIFY_PEER: -+ return PyLong_FromLong(PY_SSL_CERT_OPTIONAL); -+ case SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT: -+ return PyLong_FromLong(PY_SSL_CERT_REQUIRED); -+ } -+ PyErr_SetString(PySSLErrorObject, -+ "invalid return value from SSL_CTX_get_verify_mode"); -+ return NULL; -+} -+ -+static int -+set_verify_mode(PySSLContext *self, PyObject *arg, void *c) -+{ -+ int n, mode; -+ if (!PyArg_Parse(arg, "i", &n)) -+ return -1; -+ if (n == PY_SSL_CERT_NONE) -+ mode = SSL_VERIFY_NONE; -+ else if (n == PY_SSL_CERT_OPTIONAL) -+ mode = SSL_VERIFY_PEER; -+ else if (n == PY_SSL_CERT_REQUIRED) -+ mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; -+ else { -+ PyErr_SetString(PyExc_ValueError, -+ "invalid value for verify_mode"); -+ return -1; -+ } -+ if (mode == SSL_VERIFY_NONE && self->check_hostname) { -+ PyErr_SetString(PyExc_ValueError, -+ "Cannot set verify_mode to CERT_NONE when " -+ "check_hostname is enabled."); -+ return -1; -+ } -+ SSL_CTX_set_verify(self->ctx, mode, NULL); -+ return 0; -+} -+ -+#ifdef HAVE_OPENSSL_VERIFY_PARAM -+static PyObject * -+get_verify_flags(PySSLContext *self, void *c) -+{ -+ X509_STORE *store; -+ unsigned long flags; -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ flags = X509_VERIFY_PARAM_get_flags(store->param); -+ return PyLong_FromUnsignedLong(flags); -+} -+ -+static int -+set_verify_flags(PySSLContext *self, PyObject *arg, void *c) -+{ -+ X509_STORE *store; -+ unsigned long new_flags, flags, set, clear; -+ -+ if (!PyArg_Parse(arg, "k", &new_flags)) -+ return -1; -+ store = SSL_CTX_get_cert_store(self->ctx); -+ flags = X509_VERIFY_PARAM_get_flags(store->param); -+ clear = flags & ~new_flags; -+ set = ~flags & new_flags; -+ if (clear) { -+ if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return -1; -+ } -+ } -+ if (set) { -+ if (!X509_VERIFY_PARAM_set_flags(store->param, set)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return -1; -+ } -+ } -+ return 0; -+} -+#endif -+ -+static PyObject * -+get_options(PySSLContext *self, void *c) -+{ -+ return PyLong_FromLong(SSL_CTX_get_options(self->ctx)); -+} -+ -+static int -+set_options(PySSLContext *self, PyObject *arg, void *c) -+{ -+ long new_opts, opts, set, clear; -+ if (!PyArg_Parse(arg, "l", &new_opts)) -+ return -1; -+ opts = SSL_CTX_get_options(self->ctx); -+ clear = opts & ~new_opts; -+ set = ~opts & new_opts; -+ if (clear) { -+#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS -+ SSL_CTX_clear_options(self->ctx, clear); -+#else -+ PyErr_SetString(PyExc_ValueError, -+ "can't clear options before OpenSSL 0.9.8m"); -+ return -1; -+#endif -+ } -+ if (set) -+ SSL_CTX_set_options(self->ctx, set); -+ return 0; -+} -+ -+static PyObject * -+get_check_hostname(PySSLContext *self, void *c) -+{ -+ return PyBool_FromLong(self->check_hostname); -+} -+ -+static int -+set_check_hostname(PySSLContext *self, PyObject *arg, void *c) -+{ -+ PyObject *py_check_hostname; -+ int check_hostname; -+ if (!PyArg_Parse(arg, "O", &py_check_hostname)) -+ return -1; -+ -+ check_hostname = PyObject_IsTrue(py_check_hostname); -+ if (check_hostname < 0) -+ return -1; -+ if (check_hostname && -+ SSL_CTX_get_verify_mode(self->ctx) == SSL_VERIFY_NONE) { -+ PyErr_SetString(PyExc_ValueError, -+ "check_hostname needs a SSL context with either " -+ "CERT_OPTIONAL or CERT_REQUIRED"); -+ return -1; -+ } -+ self->check_hostname = check_hostname; -+ return 0; -+} -+ -+ -+typedef struct { -+ PyThreadState *thread_state; -+ PyObject *callable; -+ char *password; -+ int size; -+ int error; -+} _PySSLPasswordInfo; -+ -+static int -+_pwinfo_set(_PySSLPasswordInfo *pw_info, PyObject* password, -+ const char *bad_type_error) -+{ -+ /* Set the password and size fields of a _PySSLPasswordInfo struct -+ from a unicode, bytes, or byte array object. -+ The password field will be dynamically allocated and must be freed -+ by the caller */ -+ PyObject *password_bytes = NULL; -+ const char *data = NULL; -+ Py_ssize_t size; -+ -+ if (PyUnicode_Check(password)) { -+ password_bytes = PyUnicode_AsEncodedString(password, NULL, NULL); -+ if (!password_bytes) { -+ goto error; -+ } -+ data = PyBytes_AS_STRING(password_bytes); -+ size = PyBytes_GET_SIZE(password_bytes); -+ } else if (PyBytes_Check(password)) { -+ data = PyBytes_AS_STRING(password); -+ size = PyBytes_GET_SIZE(password); -+ } else if (PyByteArray_Check(password)) { -+ data = PyByteArray_AS_STRING(password); -+ size = PyByteArray_GET_SIZE(password); -+ } else { -+ PyErr_SetString(PyExc_TypeError, bad_type_error); -+ goto error; -+ } -+ -+ if (size > (Py_ssize_t)INT_MAX) { -+ PyErr_Format(PyExc_ValueError, -+ "password cannot be longer than %d bytes", INT_MAX); -+ goto error; -+ } -+ -+ PyMem_Free(pw_info->password); -+ pw_info->password = PyMem_Malloc(size); -+ if (!pw_info->password) { -+ PyErr_SetString(PyExc_MemoryError, -+ "unable to allocate password buffer"); -+ goto error; -+ } -+ memcpy(pw_info->password, data, size); -+ pw_info->size = (int)size; -+ -+ Py_XDECREF(password_bytes); -+ return 1; -+ -+error: -+ Py_XDECREF(password_bytes); -+ return 0; -+} -+ -+static int -+_password_callback(char *buf, int size, int rwflag, void *userdata) -+{ -+ _PySSLPasswordInfo *pw_info = (_PySSLPasswordInfo*) userdata; -+ PyObject *fn_ret = NULL; -+ -+ PySSL_END_ALLOW_THREADS_S(pw_info->thread_state); -+ -+ if (pw_info->callable) { -+ fn_ret = PyObject_CallFunctionObjArgs(pw_info->callable, NULL); -+ if (!fn_ret) { -+ /* TODO: It would be nice to move _ctypes_add_traceback() into the -+ core python API, so we could use it to add a frame here */ -+ goto error; -+ } -+ -+ if (!_pwinfo_set(pw_info, fn_ret, -+ "password callback must return a string")) { -+ goto error; -+ } -+ Py_CLEAR(fn_ret); -+ } -+ -+ if (pw_info->size > size) { -+ PyErr_Format(PyExc_ValueError, -+ "password cannot be longer than %d bytes", size); -+ goto error; -+ } -+ -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); -+ memcpy(buf, pw_info->password, pw_info->size); -+ return pw_info->size; -+ -+error: -+ Py_XDECREF(fn_ret); -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); -+ pw_info->error = 1; -+ return -1; -+} -+ -+static PyObject * -+load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"certfile", "keyfile", "password", NULL}; -+ PyObject *password = NULL; -+ char *certfile_bytes = NULL, *keyfile_bytes = NULL; -+ pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; -+ void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; -+ _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 }; -+ int r; -+ -+ errno = 0; -+ ERR_clear_error(); -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, -+ "et|etO:load_cert_chain", kwlist, -+ Py_FileSystemDefaultEncoding, &certfile_bytes, -+ Py_FileSystemDefaultEncoding, &keyfile_bytes, -+ &password)) -+ return NULL; -+ if (password && password != Py_None) { -+ if (PyCallable_Check(password)) { -+ pw_info.callable = password; -+ } else if (!_pwinfo_set(&pw_info, password, -+ "password should be a string or callable")) { -+ goto error; -+ } -+ SSL_CTX_set_default_passwd_cb(self->ctx, _password_callback); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, &pw_info); -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_use_certificate_chain_file(self->ctx, certfile_bytes); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ if (pw_info.error) { -+ ERR_clear_error(); -+ /* the password callback has already set the error information */ -+ } -+ else if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_use_PrivateKey_file(self->ctx, -+ keyfile_bytes ? keyfile_bytes : certfile_bytes, -+ SSL_FILETYPE_PEM); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ if (pw_info.error) { -+ ERR_clear_error(); -+ /* the password callback has already set the error information */ -+ } -+ else if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_check_private_key(self->ctx); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto error; -+ } -+ SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); -+ PyMem_Free(pw_info.password); -+ Py_RETURN_NONE; -+ -+error: -+ SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); -+ PyMem_Free(pw_info.password); -+ PyMem_Free(keyfile_bytes); -+ PyMem_Free(certfile_bytes); -+ return NULL; -+} -+ -+/* internal helper function, returns -1 on error -+ */ -+static int -+_add_ca_certs(PySSLContext *self, void *data, Py_ssize_t len, -+ int filetype) -+{ -+ BIO *biobuf = NULL; -+ X509_STORE *store; -+ int retval = 0, err, loaded = 0; -+ -+ assert(filetype == SSL_FILETYPE_ASN1 || filetype == SSL_FILETYPE_PEM); -+ -+ if (len <= 0) { -+ PyErr_SetString(PyExc_ValueError, -+ "Empty certificate data"); -+ return -1; -+ } else if (len > INT_MAX) { -+ PyErr_SetString(PyExc_OverflowError, -+ "Certificate data is too long."); -+ return -1; -+ } -+ -+ biobuf = BIO_new_mem_buf(data, (int)len); -+ if (biobuf == NULL) { -+ _setSSLError("Can't allocate buffer", 0, __FILE__, __LINE__); -+ return -1; -+ } -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ assert(store != NULL); -+ -+ while (1) { -+ X509 *cert = NULL; -+ int r; -+ -+ if (filetype == SSL_FILETYPE_ASN1) { -+ cert = d2i_X509_bio(biobuf, NULL); -+ } else { -+ cert = PEM_read_bio_X509(biobuf, NULL, -+ self->ctx->default_passwd_callback, -+ self->ctx->default_passwd_callback_userdata); -+ } -+ if (cert == NULL) { -+ break; -+ } -+ r = X509_STORE_add_cert(store, cert); -+ X509_free(cert); -+ if (!r) { -+ err = ERR_peek_last_error(); -+ if ((ERR_GET_LIB(err) == ERR_LIB_X509) && -+ (ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) { -+ /* cert already in hash table, not an error */ -+ ERR_clear_error(); -+ } else { -+ break; -+ } -+ } -+ loaded++; -+ } -+ -+ err = ERR_peek_last_error(); -+ if ((filetype == SSL_FILETYPE_ASN1) && -+ (loaded > 0) && -+ (ERR_GET_LIB(err) == ERR_LIB_ASN1) && -+ (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) { -+ /* EOF ASN1 file, not an error */ -+ ERR_clear_error(); -+ retval = 0; -+ } else if ((filetype == SSL_FILETYPE_PEM) && -+ (loaded > 0) && -+ (ERR_GET_LIB(err) == ERR_LIB_PEM) && -+ (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { -+ /* EOF PEM file, not an error */ -+ ERR_clear_error(); -+ retval = 0; -+ } else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ retval = -1; -+ } -+ -+ BIO_free(biobuf); -+ return retval; -+} -+ -+ -+static PyObject * -+load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"cafile", "capath", "cadata", NULL}; -+ PyObject *cadata = NULL, *cafile = NULL, *capath = NULL; -+ PyObject *cafile_bytes = NULL, *capath_bytes = NULL; -+ const char *cafile_buf = NULL, *capath_buf = NULL; -+ int r = 0, ok = 1; -+ -+ errno = 0; -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, -+ "|OOO:load_verify_locations", kwlist, -+ &cafile, &capath, &cadata)) -+ return NULL; -+ -+ if (cafile == Py_None) -+ cafile = NULL; -+ if (capath == Py_None) -+ capath = NULL; -+ if (cadata == Py_None) -+ cadata = NULL; -+ -+ if (cafile == NULL && capath == NULL && cadata == NULL) { -+ PyErr_SetString(PyExc_TypeError, -+ "cafile, capath and cadata cannot be all omitted"); -+ goto error; -+ } -+ -+ if (cafile) { -+ cafile_bytes = PyString_AsEncodedObject( -+ cafile, Py_FileSystemDefaultEncoding, "strict"); -+ if (!cafile_bytes) { -+ goto error; -+ } -+ } -+ if (capath) { -+ capath_bytes = PyString_AsEncodedObject( -+ capath, Py_FileSystemDefaultEncoding, "strict"); -+ if (!capath_bytes) { -+ goto error; -+ } -+ } -+ -+ /* validata cadata type and load cadata */ -+ if (cadata) { -+ Py_buffer buf; -+ PyObject *cadata_ascii = NULL; -+ -+ if (!PyUnicode_Check(cadata) && PyObject_GetBuffer(cadata, &buf, PyBUF_SIMPLE) == 0) { -+ if (!PyBuffer_IsContiguous(&buf, 'C') || buf.ndim > 1) { -+ PyBuffer_Release(&buf); -+ PyErr_SetString(PyExc_TypeError, -+ "cadata should be a contiguous buffer with " -+ "a single dimension"); -+ goto error; -+ } -+ r = _add_ca_certs(self, buf.buf, buf.len, SSL_FILETYPE_ASN1); -+ PyBuffer_Release(&buf); -+ if (r == -1) { -+ goto error; -+ } -+ } else { -+ PyErr_Clear(); -+ cadata_ascii = PyUnicode_AsASCIIString(cadata); -+ if (cadata_ascii == NULL) { -+ PyErr_SetString(PyExc_TypeError, -+ "cadata should be a ASCII string or a " -+ "bytes-like object"); -+ goto error; -+ } -+ r = _add_ca_certs(self, -+ PyBytes_AS_STRING(cadata_ascii), -+ PyBytes_GET_SIZE(cadata_ascii), -+ SSL_FILETYPE_PEM); -+ Py_DECREF(cadata_ascii); -+ if (r == -1) { -+ goto error; -+ } -+ } -+ } -+ -+ /* load cafile or capath */ -+ if (cafile_bytes || capath_bytes) { -+ if (cafile) -+ cafile_buf = PyBytes_AS_STRING(cafile_bytes); -+ if (capath) -+ capath_buf = PyBytes_AS_STRING(capath_bytes); -+ PySSL_BEGIN_ALLOW_THREADS -+ r = SSL_CTX_load_verify_locations( -+ self->ctx, -+ cafile_buf, -+ capath_buf); -+ PySSL_END_ALLOW_THREADS -+ if (r != 1) { -+ ok = 0; -+ if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ } -+ goto end; -+ -+ error: -+ ok = 0; -+ end: -+ Py_XDECREF(cafile_bytes); -+ Py_XDECREF(capath_bytes); -+ if (ok) { -+ Py_RETURN_NONE; -+ } else { -+ return NULL; -+ } -+} -+ -+static PyObject * -+load_dh_params(PySSLContext *self, PyObject *filepath) -+{ -+ BIO *bio; -+ DH *dh; -+ char *path = PyBytes_AsString(filepath); -+ if (!path) { -+ return NULL; -+ } -+ -+ bio = BIO_new_file(path, "r"); -+ if (bio == NULL) { -+ ERR_clear_error(); -+ PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, filepath); -+ return NULL; -+ } -+ errno = 0; -+ PySSL_BEGIN_ALLOW_THREADS -+ dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); -+ BIO_free(bio); -+ PySSL_END_ALLOW_THREADS -+ if (dh == NULL) { -+ if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ return NULL; -+ } -+ if (SSL_CTX_set_tmp_dh(self->ctx, dh) == 0) -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ DH_free(dh); -+ Py_RETURN_NONE; -+} -+ -+static PyObject * -+context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"sock", "server_side", "server_hostname", "ssl_sock", NULL}; -+ PySocketSockObject *sock; -+ int server_side = 0; -+ char *hostname = NULL; -+ PyObject *hostname_obj, *ssl_sock = Py_None, *res; -+ -+ /* server_hostname is either None (or absent), or to be encoded -+ using the idna encoding. */ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i|O!O:_wrap_socket", kwlist, -+ PySocketModule.Sock_Type, -+ &sock, &server_side, -+ Py_TYPE(Py_None), &hostname_obj, -+ &ssl_sock)) { -+ PyErr_Clear(); -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!iet|O:_wrap_socket", kwlist, -+ PySocketModule.Sock_Type, -+ &sock, &server_side, -+ "idna", &hostname, &ssl_sock)) -+ return NULL; -+#if !HAVE_SNI -+ PyMem_Free(hostname); -+ PyErr_SetString(PyExc_ValueError, "server_hostname is not supported " -+ "by your OpenSSL library"); -+ return NULL; -+#endif -+ } -+ -+ res = (PyObject *) newPySSLSocket(self, sock, server_side, -+ hostname, ssl_sock); -+ if (hostname != NULL) -+ PyMem_Free(hostname); -+ return res; -+} -+ -+static PyObject * -+session_stats(PySSLContext *self, PyObject *unused) -+{ -+ int r; -+ PyObject *value, *stats = PyDict_New(); -+ if (!stats) -+ return NULL; -+ -+#define ADD_STATS(SSL_NAME, KEY_NAME) \ -+ value = PyLong_FromLong(SSL_CTX_sess_ ## SSL_NAME (self->ctx)); \ -+ if (value == NULL) \ -+ goto error; \ -+ r = PyDict_SetItemString(stats, KEY_NAME, value); \ -+ Py_DECREF(value); \ -+ if (r < 0) \ -+ goto error; -+ -+ ADD_STATS(number, "number"); -+ ADD_STATS(connect, "connect"); -+ ADD_STATS(connect_good, "connect_good"); -+ ADD_STATS(connect_renegotiate, "connect_renegotiate"); -+ ADD_STATS(accept, "accept"); -+ ADD_STATS(accept_good, "accept_good"); -+ ADD_STATS(accept_renegotiate, "accept_renegotiate"); -+ ADD_STATS(accept, "accept"); -+ ADD_STATS(hits, "hits"); -+ ADD_STATS(misses, "misses"); -+ ADD_STATS(timeouts, "timeouts"); -+ ADD_STATS(cache_full, "cache_full"); -+ -+#undef ADD_STATS -+ -+ return stats; -+ -+error: -+ Py_DECREF(stats); -+ return NULL; -+} -+ -+static PyObject * -+set_default_verify_paths(PySSLContext *self, PyObject *unused) -+{ -+ if (!SSL_CTX_set_default_verify_paths(self->ctx)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ Py_RETURN_NONE; -+} -+ -+#ifndef OPENSSL_NO_ECDH -+static PyObject * -+set_ecdh_curve(PySSLContext *self, PyObject *name) -+{ -+ char *name_bytes; -+ int nid; -+ EC_KEY *key; -+ -+ name_bytes = PyBytes_AsString(name); -+ if (!name_bytes) { -+ return NULL; -+ } -+ nid = OBJ_sn2nid(name_bytes); -+ if (nid == 0) { -+ PyErr_Format(PyExc_ValueError, -+ "unknown elliptic curve name %R", name); -+ return NULL; -+ } -+ key = EC_KEY_new_by_curve_name(nid); -+ if (key == NULL) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ SSL_CTX_set_tmp_ecdh(self->ctx, key); -+ EC_KEY_free(key); -+ Py_RETURN_NONE; -+} -+#endif -+ -+#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) -+static int -+_servername_callback(SSL *s, int *al, void *args) -+{ -+ int ret; -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ PySSLSocket *ssl; -+ PyObject *servername_o; -+ PyObject *servername_idna; -+ PyObject *result; -+ /* The high-level ssl.SSLSocket object */ -+ PyObject *ssl_socket; -+ const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); -+#ifdef WITH_THREAD -+ PyGILState_STATE gstate = PyGILState_Ensure(); -+#endif -+ -+ if (ssl_ctx->set_hostname == NULL) { -+ /* remove race condition in this the call back while if removing the -+ * callback is in progress */ -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return SSL_TLSEXT_ERR_OK; -+ } -+ -+ ssl = SSL_get_app_data(s); -+ assert(PySSLSocket_Check(ssl)); -+ ssl_socket = PyWeakref_GetObject(ssl->ssl_sock); -+ Py_INCREF(ssl_socket); -+ if (ssl_socket == Py_None) { -+ goto error; -+ } -+ -+ if (servername == NULL) { -+ result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, -+ Py_None, ssl_ctx, NULL); -+ } -+ else { -+ servername_o = PyBytes_FromString(servername); -+ if (servername_o == NULL) { -+ PyErr_WriteUnraisable((PyObject *) ssl_ctx); -+ goto error; -+ } -+ servername_idna = PyUnicode_FromEncodedObject(servername_o, "idna", NULL); -+ if (servername_idna == NULL) { -+ PyErr_WriteUnraisable(servername_o); -+ Py_DECREF(servername_o); -+ goto error; -+ } -+ Py_DECREF(servername_o); -+ result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, -+ servername_idna, ssl_ctx, NULL); -+ Py_DECREF(servername_idna); -+ } -+ Py_DECREF(ssl_socket); -+ -+ if (result == NULL) { -+ PyErr_WriteUnraisable(ssl_ctx->set_hostname); -+ *al = SSL_AD_HANDSHAKE_FAILURE; -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+ } -+ else { -+ if (result != Py_None) { -+ *al = (int) PyLong_AsLong(result); -+ if (PyErr_Occurred()) { -+ PyErr_WriteUnraisable(result); -+ *al = SSL_AD_INTERNAL_ERROR; -+ } -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+ } -+ else { -+ ret = SSL_TLSEXT_ERR_OK; -+ } -+ Py_DECREF(result); -+ } -+ -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return ret; -+ -+error: -+ Py_DECREF(ssl_socket); -+ *al = SSL_AD_INTERNAL_ERROR; -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return ret; -+} -+#endif -+ -+PyDoc_STRVAR(PySSL_set_servername_callback_doc, -+"set_servername_callback(method)\n\ -+\n\ -+This sets a callback that will be called when a server name is provided by\n\ -+the SSL/TLS client in the SNI extension.\n\ -+\n\ -+If the argument is None then the callback is disabled. The method is called\n\ -+with the SSLSocket, the server name as a string, and the SSLContext object.\n\ -+See RFC 6066 for details of the SNI extension."); -+ -+static PyObject * -+set_servername_callback(PySSLContext *self, PyObject *args) -+{ -+#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) -+ PyObject *cb; -+ -+ if (!PyArg_ParseTuple(args, "O", &cb)) -+ return NULL; -+ -+ Py_CLEAR(self->set_hostname); -+ if (cb == Py_None) { -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); -+ } -+ else { -+ if (!PyCallable_Check(cb)) { -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); -+ PyErr_SetString(PyExc_TypeError, -+ "not a callable object"); -+ return NULL; -+ } -+ Py_INCREF(cb); -+ self->set_hostname = cb; -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); -+ SSL_CTX_set_tlsext_servername_arg(self->ctx, self); -+ } -+ Py_RETURN_NONE; -+#else -+ PyErr_SetString(PyExc_NotImplementedError, -+ "The TLS extension servername callback, " -+ "SSL_CTX_set_tlsext_servername_callback, " -+ "is not in the current OpenSSL library."); -+ return NULL; -+#endif -+} -+ -+PyDoc_STRVAR(PySSL_get_stats_doc, -+"cert_store_stats() -> {'crl': int, 'x509_ca': int, 'x509': int}\n\ -+\n\ -+Returns quantities of loaded X.509 certificates. X.509 certificates with a\n\ -+CA extension and certificate revocation lists inside the context's cert\n\ -+store.\n\ -+NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -+been used at least once."); -+ -+static PyObject * -+cert_store_stats(PySSLContext *self) -+{ -+ X509_STORE *store; -+ X509_OBJECT *obj; -+ int x509 = 0, crl = 0, pkey = 0, ca = 0, i; -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { -+ obj = sk_X509_OBJECT_value(store->objs, i); -+ switch (obj->type) { -+ case X509_LU_X509: -+ x509++; -+ if (X509_check_ca(obj->data.x509)) { -+ ca++; -+ } -+ break; -+ case X509_LU_CRL: -+ crl++; -+ break; -+ case X509_LU_PKEY: -+ pkey++; -+ break; -+ default: -+ /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY. -+ * As far as I can tell they are internal states and never -+ * stored in a cert store */ -+ break; -+ } -+ } -+ return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl, -+ "x509_ca", ca); -+} -+ -+PyDoc_STRVAR(PySSL_get_ca_certs_doc, -+"get_ca_certs(binary_form=False) -> list of loaded certificate\n\ -+\n\ -+Returns a list of dicts with information of loaded CA certs. If the\n\ -+optional argument is True, returns a DER-encoded copy of the CA certificate.\n\ -+NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -+been used at least once."); -+ -+static PyObject * -+get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"binary_form", NULL}; -+ X509_STORE *store; -+ PyObject *ci = NULL, *rlist = NULL, *py_binary_mode = Py_False; -+ int i; -+ int binary_mode = 0; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:get_ca_certs", -+ kwlist, &py_binary_mode)) { -+ return NULL; -+ } -+ binary_mode = PyObject_IsTrue(py_binary_mode); -+ if (binary_mode < 0) { -+ return NULL; -+ } -+ -+ if ((rlist = PyList_New(0)) == NULL) { -+ return NULL; -+ } -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { -+ X509_OBJECT *obj; -+ X509 *cert; -+ -+ obj = sk_X509_OBJECT_value(store->objs, i); -+ if (obj->type != X509_LU_X509) { -+ /* not a x509 cert */ -+ continue; -+ } -+ /* CA for any purpose */ -+ cert = obj->data.x509; -+ if (!X509_check_ca(cert)) { -+ continue; -+ } -+ if (binary_mode) { -+ ci = _certificate_to_der(cert); -+ } else { -+ ci = _decode_certificate(cert); -+ } -+ if (ci == NULL) { -+ goto error; -+ } -+ if (PyList_Append(rlist, ci) == -1) { -+ goto error; -+ } -+ Py_CLEAR(ci); -+ } -+ return rlist; -+ -+ error: -+ Py_XDECREF(ci); -+ Py_XDECREF(rlist); -+ return NULL; -+} -+ -+ -+static PyGetSetDef context_getsetlist[] = { -+ {"check_hostname", (getter) get_check_hostname, -+ (setter) set_check_hostname, NULL}, -+ {"options", (getter) get_options, -+ (setter) set_options, NULL}, -+#ifdef HAVE_OPENSSL_VERIFY_PARAM -+ {"verify_flags", (getter) get_verify_flags, -+ (setter) set_verify_flags, NULL}, -+#endif -+ {"verify_mode", (getter) get_verify_mode, -+ (setter) set_verify_mode, NULL}, -+ {NULL}, /* sentinel */ -+}; -+ -+static struct PyMethodDef context_methods[] = { -+ {"_wrap_socket", (PyCFunction) context_wrap_socket, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"set_ciphers", (PyCFunction) set_ciphers, -+ METH_VARARGS, NULL}, -+ {"_set_npn_protocols", (PyCFunction) _set_npn_protocols, -+ METH_VARARGS, NULL}, -+ {"load_cert_chain", (PyCFunction) load_cert_chain, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"load_dh_params", (PyCFunction) load_dh_params, -+ METH_O, NULL}, -+ {"load_verify_locations", (PyCFunction) load_verify_locations, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"session_stats", (PyCFunction) session_stats, -+ METH_NOARGS, NULL}, -+ {"set_default_verify_paths", (PyCFunction) set_default_verify_paths, -+ METH_NOARGS, NULL}, -+#ifndef OPENSSL_NO_ECDH -+ {"set_ecdh_curve", (PyCFunction) set_ecdh_curve, -+ METH_O, NULL}, -+#endif -+ {"set_servername_callback", (PyCFunction) set_servername_callback, -+ METH_VARARGS, PySSL_set_servername_callback_doc}, -+ {"cert_store_stats", (PyCFunction) cert_store_stats, -+ METH_NOARGS, PySSL_get_stats_doc}, -+ {"get_ca_certs", (PyCFunction) get_ca_certs, -+ METH_VARARGS | METH_KEYWORDS, PySSL_get_ca_certs_doc}, -+ {NULL, NULL} /* sentinel */ -+}; -+ -+static PyTypeObject PySSLContext_Type = { -+ PyVarObject_HEAD_INIT(NULL, 0) -+ "_ssl._SSLContext", /*tp_name*/ -+ sizeof(PySSLContext), /*tp_basicsize*/ -+ 0, /*tp_itemsize*/ -+ (destructor)context_dealloc, /*tp_dealloc*/ -+ 0, /*tp_print*/ -+ 0, /*tp_getattr*/ -+ 0, /*tp_setattr*/ -+ 0, /*tp_reserved*/ -+ 0, /*tp_repr*/ -+ 0, /*tp_as_number*/ -+ 0, /*tp_as_sequence*/ -+ 0, /*tp_as_mapping*/ -+ 0, /*tp_hash*/ -+ 0, /*tp_call*/ -+ 0, /*tp_str*/ -+ 0, /*tp_getattro*/ -+ 0, /*tp_setattro*/ -+ 0, /*tp_as_buffer*/ -+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -+ 0, /*tp_doc*/ -+ (traverseproc) context_traverse, /*tp_traverse*/ -+ (inquiry) context_clear, /*tp_clear*/ -+ 0, /*tp_richcompare*/ -+ 0, /*tp_weaklistoffset*/ -+ 0, /*tp_iter*/ -+ 0, /*tp_iternext*/ -+ context_methods, /*tp_methods*/ -+ 0, /*tp_members*/ -+ context_getsetlist, /*tp_getset*/ -+ 0, /*tp_base*/ -+ 0, /*tp_dict*/ -+ 0, /*tp_descr_get*/ -+ 0, /*tp_descr_set*/ -+ 0, /*tp_dictoffset*/ -+ 0, /*tp_init*/ -+ 0, /*tp_alloc*/ -+ context_new, /*tp_new*/ -+}; -+ -+ -+ -+#ifdef HAVE_OPENSSL_RAND -+ -+/* helper routines for seeding the SSL PRNG */ -+static PyObject * -+PySSL_RAND_add(PyObject *self, PyObject *args) -+{ -+ char *buf; -+ Py_ssize_t len, written; -+ double entropy; -+ -+ if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) -+ return NULL; -+ do { -+ if (len >= INT_MAX) { -+ written = INT_MAX; -+ } else { -+ written = len; -+ } -+ RAND_add(buf, (int)written, entropy); -+ buf += written; -+ len -= written; -+ } while (len); -+ Py_INCREF(Py_None); -+ return Py_None; -+} -+ -+PyDoc_STRVAR(PySSL_RAND_add_doc, -+"RAND_add(string, entropy)\n\ -+\n\ -+Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\ -+bound on the entropy contained in string. See RFC 1750."); -+ -+static PyObject * -+PySSL_RAND_status(PyObject *self) -+{ -+ return PyLong_FromLong(RAND_status()); - } - - PyDoc_STRVAR(PySSL_RAND_status_doc, -@@ -1630,21 +3279,413 @@ fails or if it does not provide enough data to seed PRNG."); - #endif /* HAVE_OPENSSL_RAND */ - - -+PyDoc_STRVAR(PySSL_get_default_verify_paths_doc, -+"get_default_verify_paths() -> tuple\n\ -+\n\ -+Return search paths and environment vars that are used by SSLContext's\n\ -+set_default_verify_paths() to load default CAs. The values are\n\ -+'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'."); -+ -+static PyObject * -+PySSL_get_default_verify_paths(PyObject *self) -+{ -+ PyObject *ofile_env = NULL; -+ PyObject *ofile = NULL; -+ PyObject *odir_env = NULL; -+ PyObject *odir = NULL; -+ -+#define convert(info, target) { \ -+ const char *tmp = (info); \ -+ target = NULL; \ -+ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ -+ else { target = PyBytes_FromString(tmp); } \ -+ if (!target) goto error; \ -+ } while(0) -+ -+ convert(X509_get_default_cert_file_env(), ofile_env); -+ convert(X509_get_default_cert_file(), ofile); -+ convert(X509_get_default_cert_dir_env(), odir_env); -+ convert(X509_get_default_cert_dir(), odir); -+#undef convert -+ -+ return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -+ -+ error: -+ Py_XDECREF(ofile_env); -+ Py_XDECREF(ofile); -+ Py_XDECREF(odir_env); -+ Py_XDECREF(odir); -+ return NULL; -+} -+ -+static PyObject* -+asn1obj2py(ASN1_OBJECT *obj) -+{ -+ int nid; -+ const char *ln, *sn; -+ char buf[100]; -+ Py_ssize_t buflen; -+ -+ nid = OBJ_obj2nid(obj); -+ if (nid == NID_undef) { -+ PyErr_Format(PyExc_ValueError, "Unknown object"); -+ return NULL; -+ } -+ sn = OBJ_nid2sn(nid); -+ ln = OBJ_nid2ln(nid); -+ buflen = OBJ_obj2txt(buf, sizeof(buf), obj, 1); -+ if (buflen < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ if (buflen) { -+ return Py_BuildValue("isss#", nid, sn, ln, buf, buflen); -+ } else { -+ return Py_BuildValue("issO", nid, sn, ln, Py_None); -+ } -+} -+ -+PyDoc_STRVAR(PySSL_txt2obj_doc, -+"txt2obj(txt, name=False) -> (nid, shortname, longname, oid)\n\ -+\n\ -+Lookup NID, short name, long name and OID of an ASN1_OBJECT. By default\n\ -+objects are looked up by OID. With name=True short and long name are also\n\ -+matched."); -+ -+static PyObject* -+PySSL_txt2obj(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"txt", "name", NULL}; -+ PyObject *result = NULL; -+ char *txt; -+ PyObject *pyname = Py_None; -+ int name = 0; -+ ASN1_OBJECT *obj; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O:txt2obj", -+ kwlist, &txt, &pyname)) { -+ return NULL; -+ } -+ name = PyObject_IsTrue(pyname); -+ if (name < 0) -+ return NULL; -+ obj = OBJ_txt2obj(txt, name ? 0 : 1); -+ if (obj == NULL) { -+ PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt); -+ return NULL; -+ } -+ result = asn1obj2py(obj); -+ ASN1_OBJECT_free(obj); -+ return result; -+} -+ -+PyDoc_STRVAR(PySSL_nid2obj_doc, -+"nid2obj(nid) -> (nid, shortname, longname, oid)\n\ -+\n\ -+Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID."); -+ -+static PyObject* -+PySSL_nid2obj(PyObject *self, PyObject *args) -+{ -+ PyObject *result = NULL; -+ int nid; -+ ASN1_OBJECT *obj; -+ -+ if (!PyArg_ParseTuple(args, "i:nid2obj", &nid)) { -+ return NULL; -+ } -+ if (nid < NID_undef) { -+ PyErr_SetString(PyExc_ValueError, "NID must be positive."); -+ return NULL; -+ } -+ obj = OBJ_nid2obj(nid); -+ if (obj == NULL) { -+ PyErr_Format(PyExc_ValueError, "unknown NID %i", nid); -+ return NULL; -+ } -+ result = asn1obj2py(obj); -+ ASN1_OBJECT_free(obj); -+ return result; -+} -+ -+#ifdef _MSC_VER -+ -+static PyObject* -+certEncodingType(DWORD encodingType) -+{ -+ static PyObject *x509_asn = NULL; -+ static PyObject *pkcs_7_asn = NULL; -+ -+ if (x509_asn == NULL) { -+ x509_asn = PyUnicode_InternFromString("x509_asn"); -+ if (x509_asn == NULL) -+ return NULL; -+ } -+ if (pkcs_7_asn == NULL) { -+ pkcs_7_asn = PyUnicode_InternFromString("pkcs_7_asn"); -+ if (pkcs_7_asn == NULL) -+ return NULL; -+ } -+ switch(encodingType) { -+ case X509_ASN_ENCODING: -+ Py_INCREF(x509_asn); -+ return x509_asn; -+ case PKCS_7_ASN_ENCODING: -+ Py_INCREF(pkcs_7_asn); -+ return pkcs_7_asn; -+ default: -+ return PyLong_FromLong(encodingType); -+ } -+} -+ -+static PyObject* -+parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags) -+{ -+ CERT_ENHKEY_USAGE *usage; -+ DWORD size, error, i; -+ PyObject *retval; -+ -+ if (!CertGetEnhancedKeyUsage(pCertCtx, flags, NULL, &size)) { -+ error = GetLastError(); -+ if (error == CRYPT_E_NOT_FOUND) { -+ Py_RETURN_TRUE; -+ } -+ return PyErr_SetFromWindowsErr(error); -+ } -+ -+ usage = (CERT_ENHKEY_USAGE*)PyMem_Malloc(size); -+ if (usage == NULL) { -+ return PyErr_NoMemory(); -+ } -+ -+ /* Now get the actual enhanced usage property */ -+ if (!CertGetEnhancedKeyUsage(pCertCtx, flags, usage, &size)) { -+ PyMem_Free(usage); -+ error = GetLastError(); -+ if (error == CRYPT_E_NOT_FOUND) { -+ Py_RETURN_TRUE; -+ } -+ return PyErr_SetFromWindowsErr(error); -+ } -+ retval = PySet_New(NULL); -+ if (retval == NULL) { -+ goto error; -+ } -+ for (i = 0; i < usage->cUsageIdentifier; ++i) { -+ if (usage->rgpszUsageIdentifier[i]) { -+ PyObject *oid; -+ int err; -+ oid = PyUnicode_FromString(usage->rgpszUsageIdentifier[i]); -+ if (oid == NULL) { -+ Py_CLEAR(retval); -+ goto error; -+ } -+ err = PySet_Add(retval, oid); -+ Py_DECREF(oid); -+ if (err == -1) { -+ Py_CLEAR(retval); -+ goto error; -+ } -+ } -+ } -+ error: -+ PyMem_Free(usage); -+ return retval; -+} -+ -+PyDoc_STRVAR(PySSL_enum_certificates_doc, -+"enum_certificates(store_name) -> []\n\ -+\n\ -+Retrieve certificates from Windows' cert store. store_name may be one of\n\ -+'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -+The function returns a list of (bytes, encoding_type, trust) tuples. The\n\ -+encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -+PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the\n\ -+boolean True."); -+ -+static PyObject * -+PySSL_enum_certificates(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"store_name", NULL}; -+ char *store_name; -+ HCERTSTORE hStore = NULL; -+ PCCERT_CONTEXT pCertCtx = NULL; -+ PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; -+ PyObject *result = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates", -+ kwlist, &store_name)) { -+ return NULL; -+ } -+ result = PyList_New(0); -+ if (result == NULL) { -+ return NULL; -+ } -+ hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); -+ if (hStore == NULL) { -+ Py_DECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ -+ while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) { -+ cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded, -+ pCertCtx->cbCertEncoded); -+ if (!cert) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((enc = certEncodingType(pCertCtx->dwCertEncodingType)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ keyusage = parseKeyUsage(pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); -+ if (keyusage == Py_True) { -+ Py_DECREF(keyusage); -+ keyusage = parseKeyUsage(pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); -+ } -+ if (keyusage == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((tup = PyTuple_New(3)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ PyTuple_SET_ITEM(tup, 0, cert); -+ cert = NULL; -+ PyTuple_SET_ITEM(tup, 1, enc); -+ enc = NULL; -+ PyTuple_SET_ITEM(tup, 2, keyusage); -+ keyusage = NULL; -+ if (PyList_Append(result, tup) < 0) { -+ Py_CLEAR(result); -+ break; -+ } -+ Py_CLEAR(tup); -+ } -+ if (pCertCtx) { -+ /* loop ended with an error, need to clean up context manually */ -+ CertFreeCertificateContext(pCertCtx); -+ } -+ -+ /* In error cases cert, enc and tup may not be NULL */ -+ Py_XDECREF(cert); -+ Py_XDECREF(enc); -+ Py_XDECREF(keyusage); -+ Py_XDECREF(tup); -+ -+ if (!CertCloseStore(hStore, 0)) { -+ /* This error case might shadow another exception.*/ -+ Py_XDECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ return result; -+} -+ -+PyDoc_STRVAR(PySSL_enum_crls_doc, -+"enum_crls(store_name) -> []\n\ -+\n\ -+Retrieve CRLs from Windows' cert store. store_name may be one of\n\ -+'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -+The function returns a list of (bytes, encoding_type) tuples. The\n\ -+encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -+PKCS_7_ASN_ENCODING."); -+ -+static PyObject * -+PySSL_enum_crls(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"store_name", NULL}; -+ char *store_name; -+ HCERTSTORE hStore = NULL; -+ PCCRL_CONTEXT pCrlCtx = NULL; -+ PyObject *crl = NULL, *enc = NULL, *tup = NULL; -+ PyObject *result = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls", -+ kwlist, &store_name)) { -+ return NULL; -+ } -+ result = PyList_New(0); -+ if (result == NULL) { -+ return NULL; -+ } -+ hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); -+ if (hStore == NULL) { -+ Py_DECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ -+ while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) { -+ crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded, -+ pCrlCtx->cbCrlEncoded); -+ if (!crl) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((enc = certEncodingType(pCrlCtx->dwCertEncodingType)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((tup = PyTuple_New(2)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ PyTuple_SET_ITEM(tup, 0, crl); -+ crl = NULL; -+ PyTuple_SET_ITEM(tup, 1, enc); -+ enc = NULL; -+ -+ if (PyList_Append(result, tup) < 0) { -+ Py_CLEAR(result); -+ break; -+ } -+ Py_CLEAR(tup); -+ } -+ if (pCrlCtx) { -+ /* loop ended with an error, need to clean up context manually */ -+ CertFreeCRLContext(pCrlCtx); -+ } -+ -+ /* In error cases cert, enc and tup may not be NULL */ -+ Py_XDECREF(crl); -+ Py_XDECREF(enc); -+ Py_XDECREF(tup); -+ -+ if (!CertCloseStore(hStore, 0)) { -+ /* This error case might shadow another exception.*/ -+ Py_XDECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ return result; -+} -+ -+#endif /* _MSC_VER */ -+ - /* List of functions exported by this module. */ - - static PyMethodDef PySSL_methods[] = { -- {"sslwrap", PySSL_sslwrap, -- METH_VARARGS, ssl_doc}, - {"_test_decode_cert", PySSL_test_decode_certificate, - METH_VARARGS}, - #ifdef HAVE_OPENSSL_RAND - {"RAND_add", PySSL_RAND_add, METH_VARARGS, - PySSL_RAND_add_doc}, -- {"RAND_egd", PySSL_RAND_egd, METH_O, -+ {"RAND_egd", PySSL_RAND_egd, METH_VARARGS, - PySSL_RAND_egd_doc}, - {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, - PySSL_RAND_status_doc}, - #endif -+ {"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths, -+ METH_NOARGS, PySSL_get_default_verify_paths_doc}, -+#ifdef _MSC_VER -+ {"enum_certificates", (PyCFunction)PySSL_enum_certificates, -+ METH_VARARGS | METH_KEYWORDS, PySSL_enum_certificates_doc}, -+ {"enum_crls", (PyCFunction)PySSL_enum_crls, -+ METH_VARARGS | METH_KEYWORDS, PySSL_enum_crls_doc}, -+#endif -+ {"txt2obj", (PyCFunction)PySSL_txt2obj, -+ METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc}, -+ {"nid2obj", (PyCFunction)PySSL_nid2obj, -+ METH_VARARGS, PySSL_nid2obj_doc}, - {NULL, NULL} /* Sentinel */ - }; - -@@ -1672,16 +3713,17 @@ _ssl_thread_id_function (void) { - } - #endif - --static void _ssl_thread_locking_function (int mode, int n, const char *file, int line) { -+static void _ssl_thread_locking_function -+ (int mode, int n, const char *file, int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data -- structures that will be implicitly shared whenever multiple threads -- use OpenSSL.) Multi-threaded applications will crash at random if -- it is not set. -+ structures that will be implicitly shared whenever multiple -+ threads use OpenSSL.) Multi-threaded applications will -+ crash at random if it is not set. - -- locking_function() must be able to handle up to CRYPTO_num_locks() -- different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and -- releases it otherwise. -+ locking_function() must be able to handle up to -+ CRYPTO_num_locks() different mutex locks. It sets the n-th -+ lock if mode & CRYPTO_LOCK, and releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. -@@ -1705,10 +3747,11 @@ static int _setup_ssl_threads(void) { - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = (PyThread_type_lock *) -- malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); -+ PyMem_Malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); - if (_ssl_locks == NULL) - return 0; -- memset(_ssl_locks, 0, sizeof(PyThread_type_lock) * _ssl_locks_count); -+ memset(_ssl_locks, 0, -+ sizeof(PyThread_type_lock) * _ssl_locks_count); - for (i = 0; i < _ssl_locks_count; i++) { - _ssl_locks[i] = PyThread_allocate_lock(); - if (_ssl_locks[i] == NULL) { -@@ -1716,7 +3759,7 @@ static int _setup_ssl_threads(void) { - for (j = 0; j < i; j++) { - PyThread_free_lock(_ssl_locks[j]); - } -- free(_ssl_locks); -+ PyMem_Free(_ssl_locks); - return 0; - } - } -@@ -1736,14 +3779,39 @@ PyDoc_STRVAR(module_doc, - "Implementation module for SSL socket operations. See the socket module\n\ - for documentation."); - -+ -+ -+ -+static void -+parse_openssl_version(unsigned long libver, -+ unsigned int *major, unsigned int *minor, -+ unsigned int *fix, unsigned int *patch, -+ unsigned int *status) -+{ -+ *status = libver & 0xF; -+ libver >>= 4; -+ *patch = libver & 0xFF; -+ libver >>= 8; -+ *fix = libver & 0xFF; -+ libver >>= 8; -+ *minor = libver & 0xFF; -+ libver >>= 8; -+ *major = libver & 0xFF; -+} -+ - PyMODINIT_FUNC - init_ssl(void) - { - PyObject *m, *d, *r; - unsigned long libver; - unsigned int major, minor, fix, patch, status; -+ struct py_ssl_error_code *errcode; -+ struct py_ssl_library_code *libcode; - -- Py_TYPE(&PySSL_Type) = &PyType_Type; -+ if (PyType_Ready(&PySSLContext_Type) < 0) -+ return; -+ if (PyType_Ready(&PySSLSocket_Type) < 0) -+ return; - - m = Py_InitModule3("_ssl", PySSL_methods, module_doc); - if (m == NULL) -@@ -1766,15 +3834,53 @@ init_ssl(void) - OpenSSL_add_all_algorithms(); - - /* Add symbols to module dict */ -- PySSLErrorObject = PyErr_NewException("ssl.SSLError", -- PySocketModule.error, -- NULL); -+ PySSLErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLError", SSLError_doc, -+ PySocketModule.error, NULL); - if (PySSLErrorObject == NULL) - return; -- if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0) -+ ((PyTypeObject *)PySSLErrorObject)->tp_str = (reprfunc)SSLError_str; -+ -+ PySSLZeroReturnErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLZeroReturnError", SSLZeroReturnError_doc, -+ PySSLErrorObject, NULL); -+ PySSLWantReadErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLWantReadError", SSLWantReadError_doc, -+ PySSLErrorObject, NULL); -+ PySSLWantWriteErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLWantWriteError", SSLWantWriteError_doc, -+ PySSLErrorObject, NULL); -+ PySSLSyscallErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLSyscallError", SSLSyscallError_doc, -+ PySSLErrorObject, NULL); -+ PySSLEOFErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLEOFError", SSLEOFError_doc, -+ PySSLErrorObject, NULL); -+ if (PySSLZeroReturnErrorObject == NULL -+ || PySSLWantReadErrorObject == NULL -+ || PySSLWantWriteErrorObject == NULL -+ || PySSLSyscallErrorObject == NULL -+ || PySSLEOFErrorObject == NULL) -+ return; -+ -+ ((PyTypeObject *)PySSLZeroReturnErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLWantReadErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLWantWriteErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLSyscallErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLEOFErrorObject)->tp_str = (reprfunc)SSLError_str; -+ -+ if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLZeroReturnError", PySSLZeroReturnErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLWantReadError", PySSLWantReadErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLWantWriteError", PySSLWantWriteErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLSyscallError", PySSLSyscallErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLEOFError", PySSLEOFErrorObject) != 0) -+ return; -+ if (PyDict_SetItemString(d, "_SSLContext", -+ (PyObject *)&PySSLContext_Type) != 0) - return; -- if (PyDict_SetItemString(d, "SSLType", -- (PyObject *)&PySSL_Type) != 0) -+ if (PyDict_SetItemString(d, "_SSLSocket", -+ (PyObject *)&PySSLSocket_Type) != 0) - return; - PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - PY_SSL_ERROR_ZERO_RETURN); -@@ -1802,6 +3908,66 @@ init_ssl(void) - PY_SSL_CERT_OPTIONAL); - PyModule_AddIntConstant(m, "CERT_REQUIRED", - PY_SSL_CERT_REQUIRED); -+ /* CRL verification for verification_flags */ -+ PyModule_AddIntConstant(m, "VERIFY_DEFAULT", -+ 0); -+ PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_LEAF", -+ X509_V_FLAG_CRL_CHECK); -+ PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_CHAIN", -+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); -+ PyModule_AddIntConstant(m, "VERIFY_X509_STRICT", -+ X509_V_FLAG_X509_STRICT); -+ -+ /* Alert Descriptions from ssl.h */ -+ /* note RESERVED constants no longer intended for use have been removed */ -+ /* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */ -+ -+#define ADD_AD_CONSTANT(s) \ -+ PyModule_AddIntConstant(m, "ALERT_DESCRIPTION_"#s, \ -+ SSL_AD_##s) -+ -+ ADD_AD_CONSTANT(CLOSE_NOTIFY); -+ ADD_AD_CONSTANT(UNEXPECTED_MESSAGE); -+ ADD_AD_CONSTANT(BAD_RECORD_MAC); -+ ADD_AD_CONSTANT(RECORD_OVERFLOW); -+ ADD_AD_CONSTANT(DECOMPRESSION_FAILURE); -+ ADD_AD_CONSTANT(HANDSHAKE_FAILURE); -+ ADD_AD_CONSTANT(BAD_CERTIFICATE); -+ ADD_AD_CONSTANT(UNSUPPORTED_CERTIFICATE); -+ ADD_AD_CONSTANT(CERTIFICATE_REVOKED); -+ ADD_AD_CONSTANT(CERTIFICATE_EXPIRED); -+ ADD_AD_CONSTANT(CERTIFICATE_UNKNOWN); -+ ADD_AD_CONSTANT(ILLEGAL_PARAMETER); -+ ADD_AD_CONSTANT(UNKNOWN_CA); -+ ADD_AD_CONSTANT(ACCESS_DENIED); -+ ADD_AD_CONSTANT(DECODE_ERROR); -+ ADD_AD_CONSTANT(DECRYPT_ERROR); -+ ADD_AD_CONSTANT(PROTOCOL_VERSION); -+ ADD_AD_CONSTANT(INSUFFICIENT_SECURITY); -+ ADD_AD_CONSTANT(INTERNAL_ERROR); -+ ADD_AD_CONSTANT(USER_CANCELLED); -+ ADD_AD_CONSTANT(NO_RENEGOTIATION); -+ /* Not all constants are in old OpenSSL versions */ -+#ifdef SSL_AD_UNSUPPORTED_EXTENSION -+ ADD_AD_CONSTANT(UNSUPPORTED_EXTENSION); -+#endif -+#ifdef SSL_AD_CERTIFICATE_UNOBTAINABLE -+ ADD_AD_CONSTANT(CERTIFICATE_UNOBTAINABLE); -+#endif -+#ifdef SSL_AD_UNRECOGNIZED_NAME -+ ADD_AD_CONSTANT(UNRECOGNIZED_NAME); -+#endif -+#ifdef SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE -+ ADD_AD_CONSTANT(BAD_CERTIFICATE_STATUS_RESPONSE); -+#endif -+#ifdef SSL_AD_BAD_CERTIFICATE_HASH_VALUE -+ ADD_AD_CONSTANT(BAD_CERTIFICATE_HASH_VALUE); -+#endif -+#ifdef SSL_AD_UNKNOWN_PSK_IDENTITY -+ ADD_AD_CONSTANT(UNKNOWN_PSK_IDENTITY); -+#endif -+ -+#undef ADD_AD_CONSTANT - - /* protocol versions */ - #ifndef OPENSSL_NO_SSL2 -@@ -1814,6 +3980,109 @@ init_ssl(void) - PY_SSL_VERSION_SSL23); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", - PY_SSL_VERSION_TLS1); -+#if HAVE_TLSv1_2 -+ PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_1", -+ PY_SSL_VERSION_TLS1_1); -+ PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2", -+ PY_SSL_VERSION_TLS1_2); -+#endif -+ -+ /* protocol options */ -+ PyModule_AddIntConstant(m, "OP_ALL", -+ SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); -+ PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2); -+ PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); -+#if HAVE_TLSv1_2 -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1); -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2); -+#endif -+ PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE", -+ SSL_OP_CIPHER_SERVER_PREFERENCE); -+ PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE); -+#ifdef SSL_OP_SINGLE_ECDH_USE -+ PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE); -+#endif -+#ifdef SSL_OP_NO_COMPRESSION -+ PyModule_AddIntConstant(m, "OP_NO_COMPRESSION", -+ SSL_OP_NO_COMPRESSION); -+#endif -+ -+#if HAVE_SNI -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_SNI", r); -+ -+#if HAVE_OPENSSL_FINISHED -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_TLS_UNIQUE", r); -+ -+#ifdef OPENSSL_NO_ECDH -+ r = Py_False; -+#else -+ r = Py_True; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_ECDH", r); -+ -+#ifdef OPENSSL_NPN_NEGOTIATED -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_NPN", r); -+ -+ /* Mappings for error codes */ -+ err_codes_to_names = PyDict_New(); -+ err_names_to_codes = PyDict_New(); -+ if (err_codes_to_names == NULL || err_names_to_codes == NULL) -+ return; -+ errcode = error_codes; -+ while (errcode->mnemonic != NULL) { -+ PyObject *mnemo, *key; -+ mnemo = PyUnicode_FromString(errcode->mnemonic); -+ key = Py_BuildValue("ii", errcode->library, errcode->reason); -+ if (mnemo == NULL || key == NULL) -+ return; -+ if (PyDict_SetItem(err_codes_to_names, key, mnemo)) -+ return; -+ if (PyDict_SetItem(err_names_to_codes, mnemo, key)) -+ return; -+ Py_DECREF(key); -+ Py_DECREF(mnemo); -+ errcode++; -+ } -+ if (PyModule_AddObject(m, "err_codes_to_names", err_codes_to_names)) -+ return; -+ if (PyModule_AddObject(m, "err_names_to_codes", err_names_to_codes)) -+ return; -+ -+ lib_codes_to_names = PyDict_New(); -+ if (lib_codes_to_names == NULL) -+ return; -+ libcode = library_codes; -+ while (libcode->library != NULL) { -+ PyObject *mnemo, *key; -+ key = PyLong_FromLong(libcode->code); -+ mnemo = PyUnicode_FromString(libcode->library); -+ if (key == NULL || mnemo == NULL) -+ return; -+ if (PyDict_SetItem(lib_codes_to_names, key, mnemo)) -+ return; -+ Py_DECREF(key); -+ Py_DECREF(mnemo); -+ libcode++; -+ } -+ if (PyModule_AddObject(m, "lib_codes_to_names", lib_codes_to_names)) -+ return; - - /* OpenSSL version */ - /* SSLeay() gives us the version of the library linked against, -@@ -1825,15 +4094,7 @@ init_ssl(void) - return; - if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) - return; -- status = libver & 0xF; -- libver >>= 4; -- patch = libver & 0xFF; -- libver >>= 8; -- fix = libver & 0xFF; -- libver >>= 8; -- minor = libver & 0xFF; -- libver >>= 8; -- major = libver & 0xFF; -+ parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); - r = Py_BuildValue("IIIII", major, minor, fix, patch, status); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) - return; -@@ -1841,4 +4102,9 @@ init_ssl(void) - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) - return; - -+ libver = OPENSSL_VERSION_NUMBER; -+ parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); -+ r = Py_BuildValue("IIIII", major, minor, fix, patch, status); -+ if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r)) -+ return; - } -diff --git a/Modules/_ssl_data.h b/Modules/_ssl_data.h -new file mode 100644 -index 0000000..81a8d7b ---- /dev/null -+++ b/Modules/_ssl_data.h -@@ -0,0 +1,1653 @@ -+/* File generated by Tools/ssl/make_ssl_data.py */ -+/* Generated on 2012-05-16T23:56:40.981382 */ -+ -+static struct py_ssl_library_code library_codes[] = { -+ {"PEM", ERR_LIB_PEM}, -+ {"SSL", ERR_LIB_SSL}, -+ {"X509", ERR_LIB_X509}, -+ { NULL } -+}; -+ -+static struct py_ssl_error_code error_codes[] = { -+ #ifdef PEM_R_BAD_BASE64_DECODE -+ {"BAD_BASE64_DECODE", ERR_LIB_PEM, PEM_R_BAD_BASE64_DECODE}, -+ #else -+ {"BAD_BASE64_DECODE", ERR_LIB_PEM, 100}, -+ #endif -+ #ifdef PEM_R_BAD_DECRYPT -+ {"BAD_DECRYPT", ERR_LIB_PEM, PEM_R_BAD_DECRYPT}, -+ #else -+ {"BAD_DECRYPT", ERR_LIB_PEM, 101}, -+ #endif -+ #ifdef PEM_R_BAD_END_LINE -+ {"BAD_END_LINE", ERR_LIB_PEM, PEM_R_BAD_END_LINE}, -+ #else -+ {"BAD_END_LINE", ERR_LIB_PEM, 102}, -+ #endif -+ #ifdef PEM_R_BAD_IV_CHARS -+ {"BAD_IV_CHARS", ERR_LIB_PEM, PEM_R_BAD_IV_CHARS}, -+ #else -+ {"BAD_IV_CHARS", ERR_LIB_PEM, 103}, -+ #endif -+ #ifdef PEM_R_BAD_MAGIC_NUMBER -+ {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER}, -+ #else -+ {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, 116}, -+ #endif -+ #ifdef PEM_R_BAD_PASSWORD_READ -+ {"BAD_PASSWORD_READ", ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ}, -+ #else -+ {"BAD_PASSWORD_READ", ERR_LIB_PEM, 104}, -+ #endif -+ #ifdef PEM_R_BAD_VERSION_NUMBER -+ {"BAD_VERSION_NUMBER", ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER}, -+ #else -+ {"BAD_VERSION_NUMBER", ERR_LIB_PEM, 117}, -+ #endif -+ #ifdef PEM_R_BIO_WRITE_FAILURE -+ {"BIO_WRITE_FAILURE", ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE}, -+ #else -+ {"BIO_WRITE_FAILURE", ERR_LIB_PEM, 118}, -+ #endif -+ #ifdef PEM_R_CIPHER_IS_NULL -+ {"CIPHER_IS_NULL", ERR_LIB_PEM, PEM_R_CIPHER_IS_NULL}, -+ #else -+ {"CIPHER_IS_NULL", ERR_LIB_PEM, 127}, -+ #endif -+ #ifdef PEM_R_ERROR_CONVERTING_PRIVATE_KEY -+ {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY}, -+ #else -+ {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, 115}, -+ #endif -+ #ifdef PEM_R_EXPECTING_PRIVATE_KEY_BLOB -+ {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB}, -+ #else -+ {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, 119}, -+ #endif -+ #ifdef PEM_R_EXPECTING_PUBLIC_KEY_BLOB -+ {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB}, -+ #else -+ {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, 120}, -+ #endif -+ #ifdef PEM_R_INCONSISTENT_HEADER -+ {"INCONSISTENT_HEADER", ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER}, -+ #else -+ {"INCONSISTENT_HEADER", ERR_LIB_PEM, 121}, -+ #endif -+ #ifdef PEM_R_KEYBLOB_HEADER_PARSE_ERROR -+ {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR}, -+ #else -+ {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, 122}, -+ #endif -+ #ifdef PEM_R_KEYBLOB_TOO_SHORT -+ {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT}, -+ #else -+ {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, 123}, -+ #endif -+ #ifdef PEM_R_NOT_DEK_INFO -+ {"NOT_DEK_INFO", ERR_LIB_PEM, PEM_R_NOT_DEK_INFO}, -+ #else -+ {"NOT_DEK_INFO", ERR_LIB_PEM, 105}, -+ #endif -+ #ifdef PEM_R_NOT_ENCRYPTED -+ {"NOT_ENCRYPTED", ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED}, -+ #else -+ {"NOT_ENCRYPTED", ERR_LIB_PEM, 106}, -+ #endif -+ #ifdef PEM_R_NOT_PROC_TYPE -+ {"NOT_PROC_TYPE", ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE}, -+ #else -+ {"NOT_PROC_TYPE", ERR_LIB_PEM, 107}, -+ #endif -+ #ifdef PEM_R_NO_START_LINE -+ {"NO_START_LINE", ERR_LIB_PEM, PEM_R_NO_START_LINE}, -+ #else -+ {"NO_START_LINE", ERR_LIB_PEM, 108}, -+ #endif -+ #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD -+ {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, PEM_R_PROBLEMS_GETTING_PASSWORD}, -+ #else -+ {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, 109}, -+ #endif -+ #ifdef PEM_R_PUBLIC_KEY_NO_RSA -+ {"PUBLIC_KEY_NO_RSA", ERR_LIB_PEM, PEM_R_PUBLIC_KEY_NO_RSA}, -+ #else -+ {"PUBLIC_KEY_NO_RSA", ERR_LIB_PEM, 110}, -+ #endif -+ #ifdef PEM_R_PVK_DATA_TOO_SHORT -+ {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT}, -+ #else -+ {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, 124}, -+ #endif -+ #ifdef PEM_R_PVK_TOO_SHORT -+ {"PVK_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT}, -+ #else -+ {"PVK_TOO_SHORT", ERR_LIB_PEM, 125}, -+ #endif -+ #ifdef PEM_R_READ_KEY -+ {"READ_KEY", ERR_LIB_PEM, PEM_R_READ_KEY}, -+ #else -+ {"READ_KEY", ERR_LIB_PEM, 111}, -+ #endif -+ #ifdef PEM_R_SHORT_HEADER -+ {"SHORT_HEADER", ERR_LIB_PEM, PEM_R_SHORT_HEADER}, -+ #else -+ {"SHORT_HEADER", ERR_LIB_PEM, 112}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_CIPHER -+ {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER}, -+ #else -+ {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, 113}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_ENCRYPTION -+ {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION}, -+ #else -+ {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, 114}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_KEY_COMPONENTS -+ {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS}, -+ #else -+ {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, 126}, -+ #endif -+ #ifdef SSL_R_APP_DATA_IN_HANDSHAKE -+ {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, SSL_R_APP_DATA_IN_HANDSHAKE}, -+ #else -+ {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, 100}, -+ #endif -+ #ifdef SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT -+ {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT}, -+ #else -+ {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, 272}, -+ #endif -+ #ifdef SSL_R_BAD_ALERT_RECORD -+ {"BAD_ALERT_RECORD", ERR_LIB_SSL, SSL_R_BAD_ALERT_RECORD}, -+ #else -+ {"BAD_ALERT_RECORD", ERR_LIB_SSL, 101}, -+ #endif -+ #ifdef SSL_R_BAD_AUTHENTICATION_TYPE -+ {"BAD_AUTHENTICATION_TYPE", ERR_LIB_SSL, SSL_R_BAD_AUTHENTICATION_TYPE}, -+ #else -+ {"BAD_AUTHENTICATION_TYPE", ERR_LIB_SSL, 102}, -+ #endif -+ #ifdef SSL_R_BAD_CHANGE_CIPHER_SPEC -+ {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC}, -+ #else -+ {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, 103}, -+ #endif -+ #ifdef SSL_R_BAD_CHECKSUM -+ {"BAD_CHECKSUM", ERR_LIB_SSL, SSL_R_BAD_CHECKSUM}, -+ #else -+ {"BAD_CHECKSUM", ERR_LIB_SSL, 104}, -+ #endif -+ #ifdef SSL_R_BAD_DATA_RETURNED_BY_CALLBACK -+ {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK}, -+ #else -+ {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, 106}, -+ #endif -+ #ifdef SSL_R_BAD_DECOMPRESSION -+ {"BAD_DECOMPRESSION", ERR_LIB_SSL, SSL_R_BAD_DECOMPRESSION}, -+ #else -+ {"BAD_DECOMPRESSION", ERR_LIB_SSL, 107}, -+ #endif -+ #ifdef SSL_R_BAD_DH_G_LENGTH -+ {"BAD_DH_G_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_G_LENGTH}, -+ #else -+ {"BAD_DH_G_LENGTH", ERR_LIB_SSL, 108}, -+ #endif -+ #ifdef SSL_R_BAD_DH_PUB_KEY_LENGTH -+ {"BAD_DH_PUB_KEY_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_PUB_KEY_LENGTH}, -+ #else -+ {"BAD_DH_PUB_KEY_LENGTH", ERR_LIB_SSL, 109}, -+ #endif -+ #ifdef SSL_R_BAD_DH_P_LENGTH -+ {"BAD_DH_P_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_P_LENGTH}, -+ #else -+ {"BAD_DH_P_LENGTH", ERR_LIB_SSL, 110}, -+ #endif -+ #ifdef SSL_R_BAD_DIGEST_LENGTH -+ {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DIGEST_LENGTH}, -+ #else -+ {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, 111}, -+ #endif -+ #ifdef SSL_R_BAD_DSA_SIGNATURE -+ {"BAD_DSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_DSA_SIGNATURE}, -+ #else -+ {"BAD_DSA_SIGNATURE", ERR_LIB_SSL, 112}, -+ #endif -+ #ifdef SSL_R_BAD_ECC_CERT -+ {"BAD_ECC_CERT", ERR_LIB_SSL, SSL_R_BAD_ECC_CERT}, -+ #else -+ {"BAD_ECC_CERT", ERR_LIB_SSL, 304}, -+ #endif -+ #ifdef SSL_R_BAD_ECDSA_SIGNATURE -+ {"BAD_ECDSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_ECDSA_SIGNATURE}, -+ #else -+ {"BAD_ECDSA_SIGNATURE", ERR_LIB_SSL, 305}, -+ #endif -+ #ifdef SSL_R_BAD_ECPOINT -+ {"BAD_ECPOINT", ERR_LIB_SSL, SSL_R_BAD_ECPOINT}, -+ #else -+ {"BAD_ECPOINT", ERR_LIB_SSL, 306}, -+ #endif -+ #ifdef SSL_R_BAD_HANDSHAKE_LENGTH -+ {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_LENGTH}, -+ #else -+ {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, 332}, -+ #endif -+ #ifdef SSL_R_BAD_HELLO_REQUEST -+ {"BAD_HELLO_REQUEST", ERR_LIB_SSL, SSL_R_BAD_HELLO_REQUEST}, -+ #else -+ {"BAD_HELLO_REQUEST", ERR_LIB_SSL, 105}, -+ #endif -+ #ifdef SSL_R_BAD_LENGTH -+ {"BAD_LENGTH", ERR_LIB_SSL, SSL_R_BAD_LENGTH}, -+ #else -+ {"BAD_LENGTH", ERR_LIB_SSL, 271}, -+ #endif -+ #ifdef SSL_R_BAD_MAC_DECODE -+ {"BAD_MAC_DECODE", ERR_LIB_SSL, SSL_R_BAD_MAC_DECODE}, -+ #else -+ {"BAD_MAC_DECODE", ERR_LIB_SSL, 113}, -+ #endif -+ #ifdef SSL_R_BAD_MAC_LENGTH -+ {"BAD_MAC_LENGTH", ERR_LIB_SSL, SSL_R_BAD_MAC_LENGTH}, -+ #else -+ {"BAD_MAC_LENGTH", ERR_LIB_SSL, 333}, -+ #endif -+ #ifdef SSL_R_BAD_MESSAGE_TYPE -+ {"BAD_MESSAGE_TYPE", ERR_LIB_SSL, SSL_R_BAD_MESSAGE_TYPE}, -+ #else -+ {"BAD_MESSAGE_TYPE", ERR_LIB_SSL, 114}, -+ #endif -+ #ifdef SSL_R_BAD_PACKET_LENGTH -+ {"BAD_PACKET_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PACKET_LENGTH}, -+ #else -+ {"BAD_PACKET_LENGTH", ERR_LIB_SSL, 115}, -+ #endif -+ #ifdef SSL_R_BAD_PROTOCOL_VERSION_NUMBER -+ {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER}, -+ #else -+ {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, 116}, -+ #endif -+ #ifdef SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH -+ {"BAD_PSK_IDENTITY_HINT_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH}, -+ #else -+ {"BAD_PSK_IDENTITY_HINT_LENGTH", ERR_LIB_SSL, 316}, -+ #endif -+ #ifdef SSL_R_BAD_RESPONSE_ARGUMENT -+ {"BAD_RESPONSE_ARGUMENT", ERR_LIB_SSL, SSL_R_BAD_RESPONSE_ARGUMENT}, -+ #else -+ {"BAD_RESPONSE_ARGUMENT", ERR_LIB_SSL, 117}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_DECRYPT -+ {"BAD_RSA_DECRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_DECRYPT}, -+ #else -+ {"BAD_RSA_DECRYPT", ERR_LIB_SSL, 118}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_ENCRYPT -+ {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_ENCRYPT}, -+ #else -+ {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, 119}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_E_LENGTH -+ {"BAD_RSA_E_LENGTH", ERR_LIB_SSL, SSL_R_BAD_RSA_E_LENGTH}, -+ #else -+ {"BAD_RSA_E_LENGTH", ERR_LIB_SSL, 120}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_MODULUS_LENGTH -+ {"BAD_RSA_MODULUS_LENGTH", ERR_LIB_SSL, SSL_R_BAD_RSA_MODULUS_LENGTH}, -+ #else -+ {"BAD_RSA_MODULUS_LENGTH", ERR_LIB_SSL, 121}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_SIGNATURE -+ {"BAD_RSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_RSA_SIGNATURE}, -+ #else -+ {"BAD_RSA_SIGNATURE", ERR_LIB_SSL, 122}, -+ #endif -+ #ifdef SSL_R_BAD_SIGNATURE -+ {"BAD_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_SIGNATURE}, -+ #else -+ {"BAD_SIGNATURE", ERR_LIB_SSL, 123}, -+ #endif -+ #ifdef SSL_R_BAD_SSL_FILETYPE -+ {"BAD_SSL_FILETYPE", ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE}, -+ #else -+ {"BAD_SSL_FILETYPE", ERR_LIB_SSL, 124}, -+ #endif -+ #ifdef SSL_R_BAD_SSL_SESSION_ID_LENGTH -+ {"BAD_SSL_SESSION_ID_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SSL_SESSION_ID_LENGTH}, -+ #else -+ {"BAD_SSL_SESSION_ID_LENGTH", ERR_LIB_SSL, 125}, -+ #endif -+ #ifdef SSL_R_BAD_STATE -+ {"BAD_STATE", ERR_LIB_SSL, SSL_R_BAD_STATE}, -+ #else -+ {"BAD_STATE", ERR_LIB_SSL, 126}, -+ #endif -+ #ifdef SSL_R_BAD_WRITE_RETRY -+ {"BAD_WRITE_RETRY", ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY}, -+ #else -+ {"BAD_WRITE_RETRY", ERR_LIB_SSL, 127}, -+ #endif -+ #ifdef SSL_R_BIO_NOT_SET -+ {"BIO_NOT_SET", ERR_LIB_SSL, SSL_R_BIO_NOT_SET}, -+ #else -+ {"BIO_NOT_SET", ERR_LIB_SSL, 128}, -+ #endif -+ #ifdef SSL_R_BLOCK_CIPHER_PAD_IS_WRONG -+ {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG}, -+ #else -+ {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, 129}, -+ #endif -+ #ifdef SSL_R_BN_LIB -+ {"BN_LIB", ERR_LIB_SSL, SSL_R_BN_LIB}, -+ #else -+ {"BN_LIB", ERR_LIB_SSL, 130}, -+ #endif -+ #ifdef SSL_R_CA_DN_LENGTH_MISMATCH -+ {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CA_DN_LENGTH_MISMATCH}, -+ #else -+ {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, 131}, -+ #endif -+ #ifdef SSL_R_CA_DN_TOO_LONG -+ {"CA_DN_TOO_LONG", ERR_LIB_SSL, SSL_R_CA_DN_TOO_LONG}, -+ #else -+ {"CA_DN_TOO_LONG", ERR_LIB_SSL, 132}, -+ #endif -+ #ifdef SSL_R_CCS_RECEIVED_EARLY -+ {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY}, -+ #else -+ {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, 133}, -+ #endif -+ #ifdef SSL_R_CERTIFICATE_VERIFY_FAILED -+ {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED}, -+ #else -+ {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, 134}, -+ #endif -+ #ifdef SSL_R_CERT_LENGTH_MISMATCH -+ {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CERT_LENGTH_MISMATCH}, -+ #else -+ {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, 135}, -+ #endif -+ #ifdef SSL_R_CHALLENGE_IS_DIFFERENT -+ {"CHALLENGE_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_CHALLENGE_IS_DIFFERENT}, -+ #else -+ {"CHALLENGE_IS_DIFFERENT", ERR_LIB_SSL, 136}, -+ #endif -+ #ifdef SSL_R_CIPHER_CODE_WRONG_LENGTH -+ {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, SSL_R_CIPHER_CODE_WRONG_LENGTH}, -+ #else -+ {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, 137}, -+ #endif -+ #ifdef SSL_R_CIPHER_OR_HASH_UNAVAILABLE -+ {"CIPHER_OR_HASH_UNAVAILABLE", ERR_LIB_SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE}, -+ #else -+ {"CIPHER_OR_HASH_UNAVAILABLE", ERR_LIB_SSL, 138}, -+ #endif -+ #ifdef SSL_R_CIPHER_TABLE_SRC_ERROR -+ {"CIPHER_TABLE_SRC_ERROR", ERR_LIB_SSL, SSL_R_CIPHER_TABLE_SRC_ERROR}, -+ #else -+ {"CIPHER_TABLE_SRC_ERROR", ERR_LIB_SSL, 139}, -+ #endif -+ #ifdef SSL_R_CLIENTHELLO_TLSEXT -+ {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_CLIENTHELLO_TLSEXT}, -+ #else -+ {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, 226}, -+ #endif -+ #ifdef SSL_R_COMPRESSED_LENGTH_TOO_LONG -+ {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_COMPRESSED_LENGTH_TOO_LONG}, -+ #else -+ {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, 140}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_DISABLED -+ {"COMPRESSION_DISABLED", ERR_LIB_SSL, SSL_R_COMPRESSION_DISABLED}, -+ #else -+ {"COMPRESSION_DISABLED", ERR_LIB_SSL, 343}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_FAILURE -+ {"COMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_COMPRESSION_FAILURE}, -+ #else -+ {"COMPRESSION_FAILURE", ERR_LIB_SSL, 141}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE -+ {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE}, -+ #else -+ {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, 307}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_LIBRARY_ERROR -+ {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR}, -+ #else -+ {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, 142}, -+ #endif -+ #ifdef SSL_R_CONNECTION_ID_IS_DIFFERENT -+ {"CONNECTION_ID_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_CONNECTION_ID_IS_DIFFERENT}, -+ #else -+ {"CONNECTION_ID_IS_DIFFERENT", ERR_LIB_SSL, 143}, -+ #endif -+ #ifdef SSL_R_CONNECTION_TYPE_NOT_SET -+ {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, SSL_R_CONNECTION_TYPE_NOT_SET}, -+ #else -+ {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, 144}, -+ #endif -+ #ifdef SSL_R_COOKIE_MISMATCH -+ {"COOKIE_MISMATCH", ERR_LIB_SSL, SSL_R_COOKIE_MISMATCH}, -+ #else -+ {"COOKIE_MISMATCH", ERR_LIB_SSL, 308}, -+ #endif -+ #ifdef SSL_R_DATA_BETWEEN_CCS_AND_FINISHED -+ {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED}, -+ #else -+ {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, 145}, -+ #endif -+ #ifdef SSL_R_DATA_LENGTH_TOO_LONG -+ {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG}, -+ #else -+ {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, 146}, -+ #endif -+ #ifdef SSL_R_DECRYPTION_FAILED -+ {"DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED}, -+ #else -+ {"DECRYPTION_FAILED", ERR_LIB_SSL, 147}, -+ #endif -+ #ifdef SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC -+ {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC}, -+ #else -+ {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, 281}, -+ #endif -+ #ifdef SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG -+ {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG}, -+ #else -+ {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, 148}, -+ #endif -+ #ifdef SSL_R_DIGEST_CHECK_FAILED -+ {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, SSL_R_DIGEST_CHECK_FAILED}, -+ #else -+ {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, 149}, -+ #endif -+ #ifdef SSL_R_DTLS_MESSAGE_TOO_BIG -+ {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, SSL_R_DTLS_MESSAGE_TOO_BIG}, -+ #else -+ {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, 334}, -+ #endif -+ #ifdef SSL_R_DUPLICATE_COMPRESSION_ID -+ {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID}, -+ #else -+ {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, 309}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT -+ {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT}, -+ #else -+ {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", ERR_LIB_SSL, 317}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_NOT_FOR_SIGNING -+ {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING}, -+ #else -+ {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, 318}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE -+ {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE}, -+ #else -+ {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", ERR_LIB_SSL, 322}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE -+ {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE}, -+ #else -+ {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, 323}, -+ #endif -+ #ifdef SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER -+ {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER}, -+ #else -+ {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, 310}, -+ #endif -+ #ifdef SSL_R_ENCRYPTED_LENGTH_TOO_LONG -+ {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG}, -+ #else -+ {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, 150}, -+ #endif -+ #ifdef SSL_R_ERROR_GENERATING_TMP_RSA_KEY -+ {"ERROR_GENERATING_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_ERROR_GENERATING_TMP_RSA_KEY}, -+ #else -+ {"ERROR_GENERATING_TMP_RSA_KEY", ERR_LIB_SSL, 282}, -+ #endif -+ #ifdef SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST -+ {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST}, -+ #else -+ {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, 151}, -+ #endif -+ #ifdef SSL_R_EXCESSIVE_MESSAGE_SIZE -+ {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE}, -+ #else -+ {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, 152}, -+ #endif -+ #ifdef SSL_R_EXTRA_DATA_IN_MESSAGE -+ {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, SSL_R_EXTRA_DATA_IN_MESSAGE}, -+ #else -+ {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, 153}, -+ #endif -+ #ifdef SSL_R_GOT_A_FIN_BEFORE_A_CCS -+ {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS}, -+ #else -+ {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, 154}, -+ #endif -+ #ifdef SSL_R_HTTPS_PROXY_REQUEST -+ {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, SSL_R_HTTPS_PROXY_REQUEST}, -+ #else -+ {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, 155}, -+ #endif -+ #ifdef SSL_R_HTTP_REQUEST -+ {"HTTP_REQUEST", ERR_LIB_SSL, SSL_R_HTTP_REQUEST}, -+ #else -+ {"HTTP_REQUEST", ERR_LIB_SSL, 156}, -+ #endif -+ #ifdef SSL_R_ILLEGAL_PADDING -+ {"ILLEGAL_PADDING", ERR_LIB_SSL, SSL_R_ILLEGAL_PADDING}, -+ #else -+ {"ILLEGAL_PADDING", ERR_LIB_SSL, 283}, -+ #endif -+ #ifdef SSL_R_INCONSISTENT_COMPRESSION -+ {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, SSL_R_INCONSISTENT_COMPRESSION}, -+ #else -+ {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, 340}, -+ #endif -+ #ifdef SSL_R_INVALID_CHALLENGE_LENGTH -+ {"INVALID_CHALLENGE_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_CHALLENGE_LENGTH}, -+ #else -+ {"INVALID_CHALLENGE_LENGTH", ERR_LIB_SSL, 158}, -+ #endif -+ #ifdef SSL_R_INVALID_COMMAND -+ {"INVALID_COMMAND", ERR_LIB_SSL, SSL_R_INVALID_COMMAND}, -+ #else -+ {"INVALID_COMMAND", ERR_LIB_SSL, 280}, -+ #endif -+ #ifdef SSL_R_INVALID_COMPRESSION_ALGORITHM -+ {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_INVALID_COMPRESSION_ALGORITHM}, -+ #else -+ {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, 341}, -+ #endif -+ #ifdef SSL_R_INVALID_PURPOSE -+ {"INVALID_PURPOSE", ERR_LIB_SSL, SSL_R_INVALID_PURPOSE}, -+ #else -+ {"INVALID_PURPOSE", ERR_LIB_SSL, 278}, -+ #endif -+ #ifdef SSL_R_INVALID_STATUS_RESPONSE -+ {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_INVALID_STATUS_RESPONSE}, -+ #else -+ {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, 328}, -+ #endif -+ #ifdef SSL_R_INVALID_TICKET_KEYS_LENGTH -+ {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH}, -+ #else -+ {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, 325}, -+ #endif -+ #ifdef SSL_R_INVALID_TRUST -+ {"INVALID_TRUST", ERR_LIB_SSL, SSL_R_INVALID_TRUST}, -+ #else -+ {"INVALID_TRUST", ERR_LIB_SSL, 279}, -+ #endif -+ #ifdef SSL_R_KEY_ARG_TOO_LONG -+ {"KEY_ARG_TOO_LONG", ERR_LIB_SSL, SSL_R_KEY_ARG_TOO_LONG}, -+ #else -+ {"KEY_ARG_TOO_LONG", ERR_LIB_SSL, 284}, -+ #endif -+ #ifdef SSL_R_KRB5 -+ {"KRB5", ERR_LIB_SSL, SSL_R_KRB5}, -+ #else -+ {"KRB5", ERR_LIB_SSL, 285}, -+ #endif -+ #ifdef SSL_R_KRB5_C_CC_PRINC -+ {"KRB5_C_CC_PRINC", ERR_LIB_SSL, SSL_R_KRB5_C_CC_PRINC}, -+ #else -+ {"KRB5_C_CC_PRINC", ERR_LIB_SSL, 286}, -+ #endif -+ #ifdef SSL_R_KRB5_C_GET_CRED -+ {"KRB5_C_GET_CRED", ERR_LIB_SSL, SSL_R_KRB5_C_GET_CRED}, -+ #else -+ {"KRB5_C_GET_CRED", ERR_LIB_SSL, 287}, -+ #endif -+ #ifdef SSL_R_KRB5_C_INIT -+ {"KRB5_C_INIT", ERR_LIB_SSL, SSL_R_KRB5_C_INIT}, -+ #else -+ {"KRB5_C_INIT", ERR_LIB_SSL, 288}, -+ #endif -+ #ifdef SSL_R_KRB5_C_MK_REQ -+ {"KRB5_C_MK_REQ", ERR_LIB_SSL, SSL_R_KRB5_C_MK_REQ}, -+ #else -+ {"KRB5_C_MK_REQ", ERR_LIB_SSL, 289}, -+ #endif -+ #ifdef SSL_R_KRB5_S_BAD_TICKET -+ {"KRB5_S_BAD_TICKET", ERR_LIB_SSL, SSL_R_KRB5_S_BAD_TICKET}, -+ #else -+ {"KRB5_S_BAD_TICKET", ERR_LIB_SSL, 290}, -+ #endif -+ #ifdef SSL_R_KRB5_S_INIT -+ {"KRB5_S_INIT", ERR_LIB_SSL, SSL_R_KRB5_S_INIT}, -+ #else -+ {"KRB5_S_INIT", ERR_LIB_SSL, 291}, -+ #endif -+ #ifdef SSL_R_KRB5_S_RD_REQ -+ {"KRB5_S_RD_REQ", ERR_LIB_SSL, SSL_R_KRB5_S_RD_REQ}, -+ #else -+ {"KRB5_S_RD_REQ", ERR_LIB_SSL, 292}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_EXPIRED -+ {"KRB5_S_TKT_EXPIRED", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_EXPIRED}, -+ #else -+ {"KRB5_S_TKT_EXPIRED", ERR_LIB_SSL, 293}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_NYV -+ {"KRB5_S_TKT_NYV", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_NYV}, -+ #else -+ {"KRB5_S_TKT_NYV", ERR_LIB_SSL, 294}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_SKEW -+ {"KRB5_S_TKT_SKEW", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_SKEW}, -+ #else -+ {"KRB5_S_TKT_SKEW", ERR_LIB_SSL, 295}, -+ #endif -+ #ifdef SSL_R_LENGTH_MISMATCH -+ {"LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH}, -+ #else -+ {"LENGTH_MISMATCH", ERR_LIB_SSL, 159}, -+ #endif -+ #ifdef SSL_R_LENGTH_TOO_SHORT -+ {"LENGTH_TOO_SHORT", ERR_LIB_SSL, SSL_R_LENGTH_TOO_SHORT}, -+ #else -+ {"LENGTH_TOO_SHORT", ERR_LIB_SSL, 160}, -+ #endif -+ #ifdef SSL_R_LIBRARY_BUG -+ {"LIBRARY_BUG", ERR_LIB_SSL, SSL_R_LIBRARY_BUG}, -+ #else -+ {"LIBRARY_BUG", ERR_LIB_SSL, 274}, -+ #endif -+ #ifdef SSL_R_LIBRARY_HAS_NO_CIPHERS -+ {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS}, -+ #else -+ {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, 161}, -+ #endif -+ #ifdef SSL_R_MESSAGE_TOO_LONG -+ {"MESSAGE_TOO_LONG", ERR_LIB_SSL, SSL_R_MESSAGE_TOO_LONG}, -+ #else -+ {"MESSAGE_TOO_LONG", ERR_LIB_SSL, 296}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_DSA_CERT -+ {"MISSING_DH_DSA_CERT", ERR_LIB_SSL, SSL_R_MISSING_DH_DSA_CERT}, -+ #else -+ {"MISSING_DH_DSA_CERT", ERR_LIB_SSL, 162}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_KEY -+ {"MISSING_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_DH_KEY}, -+ #else -+ {"MISSING_DH_KEY", ERR_LIB_SSL, 163}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_RSA_CERT -+ {"MISSING_DH_RSA_CERT", ERR_LIB_SSL, SSL_R_MISSING_DH_RSA_CERT}, -+ #else -+ {"MISSING_DH_RSA_CERT", ERR_LIB_SSL, 164}, -+ #endif -+ #ifdef SSL_R_MISSING_DSA_SIGNING_CERT -+ {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_DSA_SIGNING_CERT}, -+ #else -+ {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, 165}, -+ #endif -+ #ifdef SSL_R_MISSING_EXPORT_TMP_DH_KEY -+ {"MISSING_EXPORT_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_EXPORT_TMP_DH_KEY}, -+ #else -+ {"MISSING_EXPORT_TMP_DH_KEY", ERR_LIB_SSL, 166}, -+ #endif -+ #ifdef SSL_R_MISSING_EXPORT_TMP_RSA_KEY -+ {"MISSING_EXPORT_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_MISSING_EXPORT_TMP_RSA_KEY}, -+ #else -+ {"MISSING_EXPORT_TMP_RSA_KEY", ERR_LIB_SSL, 167}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_CERTIFICATE -+ {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, -+ #else -+ {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, 168}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_ENCRYPTING_CERT -+ {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_ENCRYPTING_CERT}, -+ #else -+ {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, 169}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_SIGNING_CERT -+ {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_SIGNING_CERT}, -+ #else -+ {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, 170}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_DH_KEY -+ {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_DH_KEY}, -+ #else -+ {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, 171}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_ECDH_KEY -+ {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_ECDH_KEY}, -+ #else -+ {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, 311}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_RSA_KEY -+ {"MISSING_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_RSA_KEY}, -+ #else -+ {"MISSING_TMP_RSA_KEY", ERR_LIB_SSL, 172}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_RSA_PKEY -+ {"MISSING_TMP_RSA_PKEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_RSA_PKEY}, -+ #else -+ {"MISSING_TMP_RSA_PKEY", ERR_LIB_SSL, 173}, -+ #endif -+ #ifdef SSL_R_MISSING_VERIFY_MESSAGE -+ {"MISSING_VERIFY_MESSAGE", ERR_LIB_SSL, SSL_R_MISSING_VERIFY_MESSAGE}, -+ #else -+ {"MISSING_VERIFY_MESSAGE", ERR_LIB_SSL, 174}, -+ #endif -+ #ifdef SSL_R_NON_SSLV2_INITIAL_PACKET -+ {"NON_SSLV2_INITIAL_PACKET", ERR_LIB_SSL, SSL_R_NON_SSLV2_INITIAL_PACKET}, -+ #else -+ {"NON_SSLV2_INITIAL_PACKET", ERR_LIB_SSL, 175}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATES_RETURNED -+ {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATES_RETURNED}, -+ #else -+ {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, 176}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_ASSIGNED -+ {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED}, -+ #else -+ {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, 177}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_RETURNED -+ {"NO_CERTIFICATE_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_RETURNED}, -+ #else -+ {"NO_CERTIFICATE_RETURNED", ERR_LIB_SSL, 178}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_SET -+ {"NO_CERTIFICATE_SET", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET}, -+ #else -+ {"NO_CERTIFICATE_SET", ERR_LIB_SSL, 179}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_SPECIFIED -+ {"NO_CERTIFICATE_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SPECIFIED}, -+ #else -+ {"NO_CERTIFICATE_SPECIFIED", ERR_LIB_SSL, 180}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_AVAILABLE -+ {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_CIPHERS_AVAILABLE}, -+ #else -+ {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, 181}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_PASSED -+ {"NO_CIPHERS_PASSED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_PASSED}, -+ #else -+ {"NO_CIPHERS_PASSED", ERR_LIB_SSL, 182}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_SPECIFIED -+ {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_SPECIFIED}, -+ #else -+ {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, 183}, -+ #endif -+ #ifdef SSL_R_NO_CIPHER_LIST -+ {"NO_CIPHER_LIST", ERR_LIB_SSL, SSL_R_NO_CIPHER_LIST}, -+ #else -+ {"NO_CIPHER_LIST", ERR_LIB_SSL, 184}, -+ #endif -+ #ifdef SSL_R_NO_CIPHER_MATCH -+ {"NO_CIPHER_MATCH", ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH}, -+ #else -+ {"NO_CIPHER_MATCH", ERR_LIB_SSL, 185}, -+ #endif -+ #ifdef SSL_R_NO_CLIENT_CERT_METHOD -+ {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_METHOD}, -+ #else -+ {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, 331}, -+ #endif -+ #ifdef SSL_R_NO_CLIENT_CERT_RECEIVED -+ {"NO_CLIENT_CERT_RECEIVED", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_RECEIVED}, -+ #else -+ {"NO_CLIENT_CERT_RECEIVED", ERR_LIB_SSL, 186}, -+ #endif -+ #ifdef SSL_R_NO_COMPRESSION_SPECIFIED -+ {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_COMPRESSION_SPECIFIED}, -+ #else -+ {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, 187}, -+ #endif -+ #ifdef SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER -+ {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER}, -+ #else -+ {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, 330}, -+ #endif -+ #ifdef SSL_R_NO_METHOD_SPECIFIED -+ {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_METHOD_SPECIFIED}, -+ #else -+ {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, 188}, -+ #endif -+ #ifdef SSL_R_NO_PRIVATEKEY -+ {"NO_PRIVATEKEY", ERR_LIB_SSL, SSL_R_NO_PRIVATEKEY}, -+ #else -+ {"NO_PRIVATEKEY", ERR_LIB_SSL, 189}, -+ #endif -+ #ifdef SSL_R_NO_PRIVATE_KEY_ASSIGNED -+ {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED}, -+ #else -+ {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, 190}, -+ #endif -+ #ifdef SSL_R_NO_PROTOCOLS_AVAILABLE -+ {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_PROTOCOLS_AVAILABLE}, -+ #else -+ {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, 191}, -+ #endif -+ #ifdef SSL_R_NO_PUBLICKEY -+ {"NO_PUBLICKEY", ERR_LIB_SSL, SSL_R_NO_PUBLICKEY}, -+ #else -+ {"NO_PUBLICKEY", ERR_LIB_SSL, 192}, -+ #endif -+ #ifdef SSL_R_NO_RENEGOTIATION -+ {"NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_NO_RENEGOTIATION}, -+ #else -+ {"NO_RENEGOTIATION", ERR_LIB_SSL, 339}, -+ #endif -+ #ifdef SSL_R_NO_REQUIRED_DIGEST -+ {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, SSL_R_NO_REQUIRED_DIGEST}, -+ #else -+ {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, 324}, -+ #endif -+ #ifdef SSL_R_NO_SHARED_CIPHER -+ {"NO_SHARED_CIPHER", ERR_LIB_SSL, SSL_R_NO_SHARED_CIPHER}, -+ #else -+ {"NO_SHARED_CIPHER", ERR_LIB_SSL, 193}, -+ #endif -+ #ifdef SSL_R_NO_VERIFY_CALLBACK -+ {"NO_VERIFY_CALLBACK", ERR_LIB_SSL, SSL_R_NO_VERIFY_CALLBACK}, -+ #else -+ {"NO_VERIFY_CALLBACK", ERR_LIB_SSL, 194}, -+ #endif -+ #ifdef SSL_R_NULL_SSL_CTX -+ {"NULL_SSL_CTX", ERR_LIB_SSL, SSL_R_NULL_SSL_CTX}, -+ #else -+ {"NULL_SSL_CTX", ERR_LIB_SSL, 195}, -+ #endif -+ #ifdef SSL_R_NULL_SSL_METHOD_PASSED -+ {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, SSL_R_NULL_SSL_METHOD_PASSED}, -+ #else -+ {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, 196}, -+ #endif -+ #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED -+ {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, -+ #else -+ {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, 197}, -+ #endif -+ #ifdef SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED -+ {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED}, -+ #else -+ {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, 344}, -+ #endif -+ #ifdef SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE -+ {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE}, -+ #else -+ {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, 297}, -+ #endif -+ #ifdef SSL_R_OPAQUE_PRF_INPUT_TOO_LONG -+ {"OPAQUE_PRF_INPUT_TOO_LONG", ERR_LIB_SSL, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG}, -+ #else -+ {"OPAQUE_PRF_INPUT_TOO_LONG", ERR_LIB_SSL, 327}, -+ #endif -+ #ifdef SSL_R_PACKET_LENGTH_TOO_LONG -+ {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PACKET_LENGTH_TOO_LONG}, -+ #else -+ {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, 198}, -+ #endif -+ #ifdef SSL_R_PARSE_TLSEXT -+ {"PARSE_TLSEXT", ERR_LIB_SSL, SSL_R_PARSE_TLSEXT}, -+ #else -+ {"PARSE_TLSEXT", ERR_LIB_SSL, 227}, -+ #endif -+ #ifdef SSL_R_PATH_TOO_LONG -+ {"PATH_TOO_LONG", ERR_LIB_SSL, SSL_R_PATH_TOO_LONG}, -+ #else -+ {"PATH_TOO_LONG", ERR_LIB_SSL, 270}, -+ #endif -+ #ifdef SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE -+ {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE}, -+ #else -+ {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, 199}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR -+ {"PEER_ERROR", ERR_LIB_SSL, SSL_R_PEER_ERROR}, -+ #else -+ {"PEER_ERROR", ERR_LIB_SSL, 200}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_CERTIFICATE -+ {"PEER_ERROR_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_ERROR_CERTIFICATE}, -+ #else -+ {"PEER_ERROR_CERTIFICATE", ERR_LIB_SSL, 201}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_NO_CERTIFICATE -+ {"PEER_ERROR_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_ERROR_NO_CERTIFICATE}, -+ #else -+ {"PEER_ERROR_NO_CERTIFICATE", ERR_LIB_SSL, 202}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_NO_CIPHER -+ {"PEER_ERROR_NO_CIPHER", ERR_LIB_SSL, SSL_R_PEER_ERROR_NO_CIPHER}, -+ #else -+ {"PEER_ERROR_NO_CIPHER", ERR_LIB_SSL, 203}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE -+ {"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE}, -+ #else -+ {"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", ERR_LIB_SSL, 204}, -+ #endif -+ #ifdef SSL_R_PRE_MAC_LENGTH_TOO_LONG -+ {"PRE_MAC_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PRE_MAC_LENGTH_TOO_LONG}, -+ #else -+ {"PRE_MAC_LENGTH_TOO_LONG", ERR_LIB_SSL, 205}, -+ #endif -+ #ifdef SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS -+ {"PROBLEMS_MAPPING_CIPHER_FUNCTIONS", ERR_LIB_SSL, SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS}, -+ #else -+ {"PROBLEMS_MAPPING_CIPHER_FUNCTIONS", ERR_LIB_SSL, 206}, -+ #endif -+ #ifdef SSL_R_PROTOCOL_IS_SHUTDOWN -+ {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN}, -+ #else -+ {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, 207}, -+ #endif -+ #ifdef SSL_R_PSK_IDENTITY_NOT_FOUND -+ {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, SSL_R_PSK_IDENTITY_NOT_FOUND}, -+ #else -+ {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, 223}, -+ #endif -+ #ifdef SSL_R_PSK_NO_CLIENT_CB -+ {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, SSL_R_PSK_NO_CLIENT_CB}, -+ #else -+ {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, 224}, -+ #endif -+ #ifdef SSL_R_PSK_NO_SERVER_CB -+ {"PSK_NO_SERVER_CB", ERR_LIB_SSL, SSL_R_PSK_NO_SERVER_CB}, -+ #else -+ {"PSK_NO_SERVER_CB", ERR_LIB_SSL, 225}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_ENCRYPT_ERROR -+ {"PUBLIC_KEY_ENCRYPT_ERROR", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_ENCRYPT_ERROR}, -+ #else -+ {"PUBLIC_KEY_ENCRYPT_ERROR", ERR_LIB_SSL, 208}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_IS_NOT_RSA -+ {"PUBLIC_KEY_IS_NOT_RSA", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_IS_NOT_RSA}, -+ #else -+ {"PUBLIC_KEY_IS_NOT_RSA", ERR_LIB_SSL, 209}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_NOT_RSA -+ {"PUBLIC_KEY_NOT_RSA", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_NOT_RSA}, -+ #else -+ {"PUBLIC_KEY_NOT_RSA", ERR_LIB_SSL, 210}, -+ #endif -+ #ifdef SSL_R_READ_BIO_NOT_SET -+ {"READ_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_READ_BIO_NOT_SET}, -+ #else -+ {"READ_BIO_NOT_SET", ERR_LIB_SSL, 211}, -+ #endif -+ #ifdef SSL_R_READ_TIMEOUT_EXPIRED -+ {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, SSL_R_READ_TIMEOUT_EXPIRED}, -+ #else -+ {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, 312}, -+ #endif -+ #ifdef SSL_R_READ_WRONG_PACKET_TYPE -+ {"READ_WRONG_PACKET_TYPE", ERR_LIB_SSL, SSL_R_READ_WRONG_PACKET_TYPE}, -+ #else -+ {"READ_WRONG_PACKET_TYPE", ERR_LIB_SSL, 212}, -+ #endif -+ #ifdef SSL_R_RECORD_LENGTH_MISMATCH -+ {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_RECORD_LENGTH_MISMATCH}, -+ #else -+ {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, 213}, -+ #endif -+ #ifdef SSL_R_RECORD_TOO_LARGE -+ {"RECORD_TOO_LARGE", ERR_LIB_SSL, SSL_R_RECORD_TOO_LARGE}, -+ #else -+ {"RECORD_TOO_LARGE", ERR_LIB_SSL, 214}, -+ #endif -+ #ifdef SSL_R_RECORD_TOO_SMALL -+ {"RECORD_TOO_SMALL", ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL}, -+ #else -+ {"RECORD_TOO_SMALL", ERR_LIB_SSL, 298}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG -+ {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, SSL_R_RENEGOTIATE_EXT_TOO_LONG}, -+ #else -+ {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, 335}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATION_ENCODING_ERR -+ {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, SSL_R_RENEGOTIATION_ENCODING_ERR}, -+ #else -+ {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, 336}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATION_MISMATCH -+ {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, SSL_R_RENEGOTIATION_MISMATCH}, -+ #else -+ {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, 337}, -+ #endif -+ #ifdef SSL_R_REQUIRED_CIPHER_MISSING -+ {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_CIPHER_MISSING}, -+ #else -+ {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, 215}, -+ #endif -+ #ifdef SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING -+ {"REQUIRED_COMPRESSSION_ALGORITHM_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING}, -+ #else -+ {"REQUIRED_COMPRESSSION_ALGORITHM_MISSING", ERR_LIB_SSL, 342}, -+ #endif -+ #ifdef SSL_R_REUSE_CERT_LENGTH_NOT_ZERO -+ {"REUSE_CERT_LENGTH_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CERT_LENGTH_NOT_ZERO}, -+ #else -+ {"REUSE_CERT_LENGTH_NOT_ZERO", ERR_LIB_SSL, 216}, -+ #endif -+ #ifdef SSL_R_REUSE_CERT_TYPE_NOT_ZERO -+ {"REUSE_CERT_TYPE_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CERT_TYPE_NOT_ZERO}, -+ #else -+ {"REUSE_CERT_TYPE_NOT_ZERO", ERR_LIB_SSL, 217}, -+ #endif -+ #ifdef SSL_R_REUSE_CIPHER_LIST_NOT_ZERO -+ {"REUSE_CIPHER_LIST_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CIPHER_LIST_NOT_ZERO}, -+ #else -+ {"REUSE_CIPHER_LIST_NOT_ZERO", ERR_LIB_SSL, 218}, -+ #endif -+ #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING -+ {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING}, -+ #else -+ {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, 345}, -+ #endif -+ #ifdef SSL_R_SERVERHELLO_TLSEXT -+ {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_SERVERHELLO_TLSEXT}, -+ #else -+ {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, 275}, -+ #endif -+ #ifdef SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED -+ {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED}, -+ #else -+ {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, 277}, -+ #endif -+ #ifdef SSL_R_SHORT_READ -+ {"SHORT_READ", ERR_LIB_SSL, SSL_R_SHORT_READ}, -+ #else -+ {"SHORT_READ", ERR_LIB_SSL, 219}, -+ #endif -+ #ifdef SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE -+ {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE}, -+ #else -+ {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, 220}, -+ #endif -+ #ifdef SSL_R_SSL23_DOING_SESSION_ID_REUSE -+ {"SSL23_DOING_SESSION_ID_REUSE", ERR_LIB_SSL, SSL_R_SSL23_DOING_SESSION_ID_REUSE}, -+ #else -+ {"SSL23_DOING_SESSION_ID_REUSE", ERR_LIB_SSL, 221}, -+ #endif -+ #ifdef SSL_R_SSL2_CONNECTION_ID_TOO_LONG -+ {"SSL2_CONNECTION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL2_CONNECTION_ID_TOO_LONG}, -+ #else -+ {"SSL2_CONNECTION_ID_TOO_LONG", ERR_LIB_SSL, 299}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT -+ {"SSL3_EXT_INVALID_ECPOINTFORMAT", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT}, -+ #else -+ {"SSL3_EXT_INVALID_ECPOINTFORMAT", ERR_LIB_SSL, 321}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME -+ {"SSL3_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME}, -+ #else -+ {"SSL3_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, 319}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE -+ {"SSL3_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE}, -+ #else -+ {"SSL3_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, 320}, -+ #endif -+ #ifdef SSL_R_SSL3_SESSION_ID_TOO_LONG -+ {"SSL3_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL3_SESSION_ID_TOO_LONG}, -+ #else -+ {"SSL3_SESSION_ID_TOO_LONG", ERR_LIB_SSL, 300}, -+ #endif -+ #ifdef SSL_R_SSL3_SESSION_ID_TOO_SHORT -+ {"SSL3_SESSION_ID_TOO_SHORT", ERR_LIB_SSL, SSL_R_SSL3_SESSION_ID_TOO_SHORT}, -+ #else -+ {"SSL3_SESSION_ID_TOO_SHORT", ERR_LIB_SSL, 222}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE -+ {"SSLV3_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, 1042}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_BAD_RECORD_MAC -+ {"SSLV3_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_RECORD_MAC}, -+ #else -+ {"SSLV3_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, 1020}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED -+ {"SSLV3_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, 1045}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED -+ {"SSLV3_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, 1044}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN -+ {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, 1046}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE -+ {"SSLV3_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE}, -+ #else -+ {"SSLV3_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, 1030}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE -+ {"SSLV3_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE}, -+ #else -+ {"SSLV3_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, 1040}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER -+ {"SSLV3_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER}, -+ #else -+ {"SSLV3_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, 1047}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_NO_CERTIFICATE -+ {"SSLV3_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_NO_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, 1041}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE -+ {"SSLV3_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE}, -+ #else -+ {"SSLV3_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, 1010}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE -+ {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, 1043}, -+ #endif -+ #ifdef SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION -+ {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION}, -+ #else -+ {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, 228}, -+ #endif -+ #ifdef SSL_R_SSL_HANDSHAKE_FAILURE -+ {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE}, -+ #else -+ {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, 229}, -+ #endif -+ #ifdef SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS -+ {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS}, -+ #else -+ {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, 230}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CALLBACK_FAILED -+ {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED}, -+ #else -+ {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, 301}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CONFLICT -+ {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONFLICT}, -+ #else -+ {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, 302}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG -+ {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG}, -+ #else -+ {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, 273}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH -+ {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH}, -+ #else -+ {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, 303}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_IS_DIFFERENT -+ {"SSL_SESSION_ID_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_IS_DIFFERENT}, -+ #else -+ {"SSL_SESSION_ID_IS_DIFFERENT", ERR_LIB_SSL, 231}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_ACCESS_DENIED -+ {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_ACCESS_DENIED}, -+ #else -+ {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, 1049}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECODE_ERROR -+ {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECODE_ERROR}, -+ #else -+ {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, 1050}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECRYPTION_FAILED -+ {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED}, -+ #else -+ {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, 1021}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECRYPT_ERROR -+ {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPT_ERROR}, -+ #else -+ {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, 1051}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION -+ {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION}, -+ #else -+ {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, 1060}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY -+ {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY}, -+ #else -+ {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, 1071}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_INTERNAL_ERROR -+ {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INTERNAL_ERROR}, -+ #else -+ {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, 1080}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_NO_RENEGOTIATION -+ {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION}, -+ #else -+ {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, 1100}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_PROTOCOL_VERSION -+ {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION}, -+ #else -+ {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, 1070}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_RECORD_OVERFLOW -+ {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW}, -+ #else -+ {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, 1022}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA -+ {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_CA}, -+ #else -+ {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, 1048}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_USER_CANCELLED -+ {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_USER_CANCELLED}, -+ #else -+ {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, 1090}, -+ #endif -+ #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE -+ {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE}, -+ #else -+ {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, 1114}, -+ #endif -+ #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE -+ {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE}, -+ #else -+ {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, 1113}, -+ #endif -+ #ifdef SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE -+ {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE}, -+ #else -+ {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, 1111}, -+ #endif -+ #ifdef SSL_R_TLSV1_UNRECOGNIZED_NAME -+ {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, SSL_R_TLSV1_UNRECOGNIZED_NAME}, -+ #else -+ {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, 1112}, -+ #endif -+ #ifdef SSL_R_TLSV1_UNSUPPORTED_EXTENSION -+ {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV1_UNSUPPORTED_EXTENSION}, -+ #else -+ {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, 1110}, -+ #endif -+ #ifdef SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER -+ {"TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER", ERR_LIB_SSL, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER}, -+ #else -+ {"TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER", ERR_LIB_SSL, 232}, -+ #endif -+ #ifdef SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST -+ {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST}, -+ #else -+ {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, 157}, -+ #endif -+ #ifdef SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST -+ {"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST", ERR_LIB_SSL, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST}, -+ #else -+ {"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST", ERR_LIB_SSL, 233}, -+ #endif -+ #ifdef SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG -+ {"TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG}, -+ #else -+ {"TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, 234}, -+ #endif -+ #ifdef SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER -+ {"TRIED_TO_USE_UNSUPPORTED_CIPHER", ERR_LIB_SSL, SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER}, -+ #else -+ {"TRIED_TO_USE_UNSUPPORTED_CIPHER", ERR_LIB_SSL, 235}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_DECODE_DH_CERTS -+ {"UNABLE_TO_DECODE_DH_CERTS", ERR_LIB_SSL, SSL_R_UNABLE_TO_DECODE_DH_CERTS}, -+ #else -+ {"UNABLE_TO_DECODE_DH_CERTS", ERR_LIB_SSL, 236}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_DECODE_ECDH_CERTS -+ {"UNABLE_TO_DECODE_ECDH_CERTS", ERR_LIB_SSL, SSL_R_UNABLE_TO_DECODE_ECDH_CERTS}, -+ #else -+ {"UNABLE_TO_DECODE_ECDH_CERTS", ERR_LIB_SSL, 313}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY -+ {"UNABLE_TO_EXTRACT_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY}, -+ #else -+ {"UNABLE_TO_EXTRACT_PUBLIC_KEY", ERR_LIB_SSL, 237}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_DH_PARAMETERS -+ {"UNABLE_TO_FIND_DH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_DH_PARAMETERS", ERR_LIB_SSL, 238}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS -+ {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, 314}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS -+ {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, 239}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_SSL_METHOD -+ {"UNABLE_TO_FIND_SSL_METHOD", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_SSL_METHOD}, -+ #else -+ {"UNABLE_TO_FIND_SSL_METHOD", ERR_LIB_SSL, 240}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES -+ {"UNABLE_TO_LOAD_SSL2_MD5_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL2_MD5_ROUTINES", ERR_LIB_SSL, 241}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES -+ {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", ERR_LIB_SSL, 242}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES -+ {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", ERR_LIB_SSL, 243}, -+ #endif -+ #ifdef SSL_R_UNEXPECTED_MESSAGE -+ {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE}, -+ #else -+ {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, 244}, -+ #endif -+ #ifdef SSL_R_UNEXPECTED_RECORD -+ {"UNEXPECTED_RECORD", ERR_LIB_SSL, SSL_R_UNEXPECTED_RECORD}, -+ #else -+ {"UNEXPECTED_RECORD", ERR_LIB_SSL, 245}, -+ #endif -+ #ifdef SSL_R_UNINITIALIZED -+ {"UNINITIALIZED", ERR_LIB_SSL, SSL_R_UNINITIALIZED}, -+ #else -+ {"UNINITIALIZED", ERR_LIB_SSL, 276}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_ALERT_TYPE -+ {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_ALERT_TYPE}, -+ #else -+ {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, 246}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CERTIFICATE_TYPE -+ {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE}, -+ #else -+ {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, 247}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CIPHER_RETURNED -+ {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_RETURNED}, -+ #else -+ {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, 248}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CIPHER_TYPE -+ {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_TYPE}, -+ #else -+ {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, 249}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE -+ {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE}, -+ #else -+ {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, 250}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_PKEY_TYPE -+ {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_PKEY_TYPE}, -+ #else -+ {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, 251}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_PROTOCOL -+ {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, SSL_R_UNKNOWN_PROTOCOL}, -+ #else -+ {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, 252}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_REMOTE_ERROR_TYPE -+ {"UNKNOWN_REMOTE_ERROR_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_REMOTE_ERROR_TYPE}, -+ #else -+ {"UNKNOWN_REMOTE_ERROR_TYPE", ERR_LIB_SSL, 253}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_SSL_VERSION -+ {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNKNOWN_SSL_VERSION}, -+ #else -+ {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, 254}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_STATE -+ {"UNKNOWN_STATE", ERR_LIB_SSL, SSL_R_UNKNOWN_STATE}, -+ #else -+ {"UNKNOWN_STATE", ERR_LIB_SSL, 255}, -+ #endif -+ #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED -+ {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED}, -+ #else -+ {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, 338}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_CIPHER -+ {"UNSUPPORTED_CIPHER", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CIPHER}, -+ #else -+ {"UNSUPPORTED_CIPHER", ERR_LIB_SSL, 256}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM -+ {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, -+ #else -+ {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, 257}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_DIGEST_TYPE -+ {"UNSUPPORTED_DIGEST_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_DIGEST_TYPE}, -+ #else -+ {"UNSUPPORTED_DIGEST_TYPE", ERR_LIB_SSL, 326}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_ELLIPTIC_CURVE -+ {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE}, -+ #else -+ {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, 315}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_PROTOCOL -+ {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, SSL_R_UNSUPPORTED_PROTOCOL}, -+ #else -+ {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, 258}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_SSL_VERSION -+ {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION}, -+ #else -+ {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, 259}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_STATUS_TYPE -+ {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_STATUS_TYPE}, -+ #else -+ {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, 329}, -+ #endif -+ #ifdef SSL_R_WRITE_BIO_NOT_SET -+ {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_WRITE_BIO_NOT_SET}, -+ #else -+ {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, 260}, -+ #endif -+ #ifdef SSL_R_WRONG_CIPHER_RETURNED -+ {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_WRONG_CIPHER_RETURNED}, -+ #else -+ {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, 261}, -+ #endif -+ #ifdef SSL_R_WRONG_MESSAGE_TYPE -+ {"WRONG_MESSAGE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_MESSAGE_TYPE}, -+ #else -+ {"WRONG_MESSAGE_TYPE", ERR_LIB_SSL, 262}, -+ #endif -+ #ifdef SSL_R_WRONG_NUMBER_OF_KEY_BITS -+ {"WRONG_NUMBER_OF_KEY_BITS", ERR_LIB_SSL, SSL_R_WRONG_NUMBER_OF_KEY_BITS}, -+ #else -+ {"WRONG_NUMBER_OF_KEY_BITS", ERR_LIB_SSL, 263}, -+ #endif -+ #ifdef SSL_R_WRONG_SIGNATURE_LENGTH -+ {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_LENGTH}, -+ #else -+ {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, 264}, -+ #endif -+ #ifdef SSL_R_WRONG_SIGNATURE_SIZE -+ {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_SIZE}, -+ #else -+ {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, 265}, -+ #endif -+ #ifdef SSL_R_WRONG_SSL_VERSION -+ {"WRONG_SSL_VERSION", ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION}, -+ #else -+ {"WRONG_SSL_VERSION", ERR_LIB_SSL, 266}, -+ #endif -+ #ifdef SSL_R_WRONG_VERSION_NUMBER -+ {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER}, -+ #else -+ {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, 267}, -+ #endif -+ #ifdef SSL_R_X509_LIB -+ {"X509_LIB", ERR_LIB_SSL, SSL_R_X509_LIB}, -+ #else -+ {"X509_LIB", ERR_LIB_SSL, 268}, -+ #endif -+ #ifdef SSL_R_X509_VERIFICATION_SETUP_PROBLEMS -+ {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS}, -+ #else -+ {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, 269}, -+ #endif -+ #ifdef X509_R_BAD_X509_FILETYPE -+ {"BAD_X509_FILETYPE", ERR_LIB_X509, X509_R_BAD_X509_FILETYPE}, -+ #else -+ {"BAD_X509_FILETYPE", ERR_LIB_X509, 100}, -+ #endif -+ #ifdef X509_R_BASE64_DECODE_ERROR -+ {"BASE64_DECODE_ERROR", ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR}, -+ #else -+ {"BASE64_DECODE_ERROR", ERR_LIB_X509, 118}, -+ #endif -+ #ifdef X509_R_CANT_CHECK_DH_KEY -+ {"CANT_CHECK_DH_KEY", ERR_LIB_X509, X509_R_CANT_CHECK_DH_KEY}, -+ #else -+ {"CANT_CHECK_DH_KEY", ERR_LIB_X509, 114}, -+ #endif -+ #ifdef X509_R_CERT_ALREADY_IN_HASH_TABLE -+ {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE}, -+ #else -+ {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, 101}, -+ #endif -+ #ifdef X509_R_ERR_ASN1_LIB -+ {"ERR_ASN1_LIB", ERR_LIB_X509, X509_R_ERR_ASN1_LIB}, -+ #else -+ {"ERR_ASN1_LIB", ERR_LIB_X509, 102}, -+ #endif -+ #ifdef X509_R_INVALID_DIRECTORY -+ {"INVALID_DIRECTORY", ERR_LIB_X509, X509_R_INVALID_DIRECTORY}, -+ #else -+ {"INVALID_DIRECTORY", ERR_LIB_X509, 113}, -+ #endif -+ #ifdef X509_R_INVALID_FIELD_NAME -+ {"INVALID_FIELD_NAME", ERR_LIB_X509, X509_R_INVALID_FIELD_NAME}, -+ #else -+ {"INVALID_FIELD_NAME", ERR_LIB_X509, 119}, -+ #endif -+ #ifdef X509_R_INVALID_TRUST -+ {"INVALID_TRUST", ERR_LIB_X509, X509_R_INVALID_TRUST}, -+ #else -+ {"INVALID_TRUST", ERR_LIB_X509, 123}, -+ #endif -+ #ifdef X509_R_KEY_TYPE_MISMATCH -+ {"KEY_TYPE_MISMATCH", ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH}, -+ #else -+ {"KEY_TYPE_MISMATCH", ERR_LIB_X509, 115}, -+ #endif -+ #ifdef X509_R_KEY_VALUES_MISMATCH -+ {"KEY_VALUES_MISMATCH", ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH}, -+ #else -+ {"KEY_VALUES_MISMATCH", ERR_LIB_X509, 116}, -+ #endif -+ #ifdef X509_R_LOADING_CERT_DIR -+ {"LOADING_CERT_DIR", ERR_LIB_X509, X509_R_LOADING_CERT_DIR}, -+ #else -+ {"LOADING_CERT_DIR", ERR_LIB_X509, 103}, -+ #endif -+ #ifdef X509_R_LOADING_DEFAULTS -+ {"LOADING_DEFAULTS", ERR_LIB_X509, X509_R_LOADING_DEFAULTS}, -+ #else -+ {"LOADING_DEFAULTS", ERR_LIB_X509, 104}, -+ #endif -+ #ifdef X509_R_METHOD_NOT_SUPPORTED -+ {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED}, -+ #else -+ {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, 124}, -+ #endif -+ #ifdef X509_R_NO_CERT_SET_FOR_US_TO_VERIFY -+ {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY}, -+ #else -+ {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, 105}, -+ #endif -+ #ifdef X509_R_PUBLIC_KEY_DECODE_ERROR -+ {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_DECODE_ERROR}, -+ #else -+ {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, 125}, -+ #endif -+ #ifdef X509_R_PUBLIC_KEY_ENCODE_ERROR -+ {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR}, -+ #else -+ {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, 126}, -+ #endif -+ #ifdef X509_R_SHOULD_RETRY -+ {"SHOULD_RETRY", ERR_LIB_X509, X509_R_SHOULD_RETRY}, -+ #else -+ {"SHOULD_RETRY", ERR_LIB_X509, 106}, -+ #endif -+ #ifdef X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN -+ {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN}, -+ #else -+ {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, 107}, -+ #endif -+ #ifdef X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY -+ {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY}, -+ #else -+ {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, 108}, -+ #endif -+ #ifdef X509_R_UNKNOWN_KEY_TYPE -+ {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE}, -+ #else -+ {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, 117}, -+ #endif -+ #ifdef X509_R_UNKNOWN_NID -+ {"UNKNOWN_NID", ERR_LIB_X509, X509_R_UNKNOWN_NID}, -+ #else -+ {"UNKNOWN_NID", ERR_LIB_X509, 109}, -+ #endif -+ #ifdef X509_R_UNKNOWN_PURPOSE_ID -+ {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID}, -+ #else -+ {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, 121}, -+ #endif -+ #ifdef X509_R_UNKNOWN_TRUST_ID -+ {"UNKNOWN_TRUST_ID", ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID}, -+ #else -+ {"UNKNOWN_TRUST_ID", ERR_LIB_X509, 120}, -+ #endif -+ #ifdef X509_R_UNSUPPORTED_ALGORITHM -+ {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM}, -+ #else -+ {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, 111}, -+ #endif -+ #ifdef X509_R_WRONG_LOOKUP_TYPE -+ {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE}, -+ #else -+ {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, 112}, -+ #endif -+ #ifdef X509_R_WRONG_TYPE -+ {"WRONG_TYPE", ERR_LIB_X509, X509_R_WRONG_TYPE}, -+ #else -+ {"WRONG_TYPE", ERR_LIB_X509, 122}, -+ #endif -+ { NULL } -+}; -diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py -new file mode 100755 -index 0000000..10244d1 ---- /dev/null -+++ b/Tools/ssl/make_ssl_data.py -@@ -0,0 +1,68 @@ -+#! /usr/bin/env python3 -+ -+""" -+This script should be called *manually* when we want to upgrade SSLError -+`library` and `reason` mnemnonics to a more recent OpenSSL version. -+ -+It takes two arguments: -+- the path to the OpenSSL include files' directory -+ (e.g. openssl-1.0.1-beta3/include/openssl/) -+- the path to the C file to be generated -+ (probably Modules/_ssl_data.h) -+""" -+ -+import datetime -+import os -+import re -+import sys -+ -+ -+def parse_error_codes(h_file, prefix): -+ pat = re.compile(r"#define\W+(%s([\w]+))\W+(\d+)\b" % re.escape(prefix)) -+ codes = [] -+ with open(h_file, "r", encoding="latin1") as f: -+ for line in f: -+ match = pat.search(line) -+ if match: -+ code, name, num = match.groups() -+ num = int(num) -+ codes.append((code, name, num)) -+ return codes -+ -+if __name__ == "__main__": -+ openssl_inc = sys.argv[1] -+ outfile = sys.argv[2] -+ use_stdout = outfile == '-' -+ f = sys.stdout if use_stdout else open(outfile, "w") -+ error_libraries = ( -+ # (library code, mnemonic, error prefix, header file) -+ ('ERR_LIB_PEM', 'PEM', 'PEM_R_', 'pem.h'), -+ ('ERR_LIB_SSL', 'SSL', 'SSL_R_', 'ssl.h'), -+ ('ERR_LIB_X509', 'X509', 'X509_R_', 'x509.h'), -+ ) -+ def w(l): -+ f.write(l + "\n") -+ w("/* File generated by Tools/ssl/make_ssl_data.py */") -+ w("/* Generated on %s */" % datetime.datetime.now().isoformat()) -+ w("") -+ -+ w("static struct py_ssl_library_code library_codes[] = {") -+ for libcode, mnemo, _, _ in error_libraries: -+ w(' {"%s", %s},' % (mnemo, libcode)) -+ w(' { NULL }') -+ w('};') -+ w("") -+ -+ w("static struct py_ssl_error_code error_codes[] = {") -+ for libcode, _, prefix, h_file in error_libraries: -+ codes = parse_error_codes(os.path.join(openssl_inc, h_file), prefix) -+ for code, name, num in sorted(codes): -+ w(' #ifdef %s' % (code)) -+ w(' {"%s", %s, %s},' % (name, libcode, code)) -+ w(' #else') -+ w(' {"%s", %s, %d},' % (name, libcode, num)) -+ w(' #endif') -+ w(' { NULL }') -+ w('};') -+ if not use_stdout: -+ f.close() -diff --git a/Tools/ssl/test_multiple_versions.py b/Tools/ssl/test_multiple_versions.py -new file mode 100644 -index 0000000..fc7a967 ---- /dev/null -+++ b/Tools/ssl/test_multiple_versions.py -@@ -0,0 +1,241 @@ -+#./python -+"""Run Python tests with multiple installations of OpenSSL -+ -+The script -+ -+ (1) downloads OpenSSL tar bundle -+ (2) extracts it to ../openssl/src/openssl-VERSION/ -+ (3) compiles OpenSSL -+ (4) installs OpenSSL into ../openssl/VERSION/ -+ (5) forces a recompilation of Python modules using the -+ header and library files from ../openssl/VERSION/ -+ (6) runs Python's test suite -+ -+The script must be run with Python's build directory as current working -+directory: -+ -+ ./python Tools/ssl/test_multiple_versions.py -+ -+The script uses LD_RUN_PATH, LD_LIBRARY_PATH, CPPFLAGS and LDFLAGS to bend -+search paths for header files and shared libraries. It's known to work on -+Linux with GCC 4.x. -+ -+(c) 2013 Christian Heimes -+""" -+import logging -+import os -+import tarfile -+import shutil -+import subprocess -+import sys -+from urllib import urlopen -+ -+log = logging.getLogger("multissl") -+ -+OPENSSL_VERSIONS = [ -+ "0.9.7m", "0.9.8i", "0.9.8l", "0.9.8m", "0.9.8y", "1.0.0k", "1.0.1e" -+] -+FULL_TESTS = [ -+ "test_asyncio", "test_ftplib", "test_hashlib", "test_httplib", -+ "test_imaplib", "test_nntplib", "test_poplib", "test_smtplib", -+ "test_smtpnet", "test_urllib2_localnet", "test_venv" -+] -+MINIMAL_TESTS = ["test_ssl", "test_hashlib"] -+CADEFAULT = True -+HERE = os.path.abspath(os.getcwd()) -+DEST_DIR = os.path.abspath(os.path.join(HERE, os.pardir, "openssl")) -+ -+ -+class BuildSSL(object): -+ url_template = "https://www.openssl.org/source/openssl-{}.tar.gz" -+ -+ module_files = ["Modules/_ssl.c", -+ "Modules/socketmodule.c", -+ "Modules/_hashopenssl.c"] -+ -+ def __init__(self, version, openssl_compile_args=(), destdir=DEST_DIR): -+ self._check_python_builddir() -+ self.version = version -+ self.openssl_compile_args = openssl_compile_args -+ # installation directory -+ self.install_dir = os.path.join(destdir, version) -+ # source file -+ self.src_file = os.path.join(destdir, "src", -+ "openssl-{}.tar.gz".format(version)) -+ # build directory (removed after install) -+ self.build_dir = os.path.join(destdir, "src", -+ "openssl-{}".format(version)) -+ -+ @property -+ def openssl_cli(self): -+ """openssl CLI binary""" -+ return os.path.join(self.install_dir, "bin", "openssl") -+ -+ @property -+ def openssl_version(self): -+ """output of 'bin/openssl version'""" -+ env = os.environ.copy() -+ env["LD_LIBRARY_PATH"] = self.lib_dir -+ cmd = [self.openssl_cli, "version"] -+ return self._subprocess_output(cmd, env=env) -+ -+ @property -+ def pyssl_version(self): -+ """Value of ssl.OPENSSL_VERSION""" -+ env = os.environ.copy() -+ env["LD_LIBRARY_PATH"] = self.lib_dir -+ cmd = ["./python", "-c", "import ssl; print(ssl.OPENSSL_VERSION)"] -+ return self._subprocess_output(cmd, env=env) -+ -+ @property -+ def include_dir(self): -+ return os.path.join(self.install_dir, "include") -+ -+ @property -+ def lib_dir(self): -+ return os.path.join(self.install_dir, "lib") -+ -+ @property -+ def has_openssl(self): -+ return os.path.isfile(self.openssl_cli) -+ -+ @property -+ def has_src(self): -+ return os.path.isfile(self.src_file) -+ -+ def _subprocess_call(self, cmd, stdout=subprocess.DEVNULL, env=None, -+ **kwargs): -+ log.debug("Call '{}'".format(" ".join(cmd))) -+ return subprocess.check_call(cmd, stdout=stdout, env=env, **kwargs) -+ -+ def _subprocess_output(self, cmd, env=None, **kwargs): -+ log.debug("Call '{}'".format(" ".join(cmd))) -+ out = subprocess.check_output(cmd, env=env) -+ return out.strip().decode("utf-8") -+ -+ def _check_python_builddir(self): -+ if not os.path.isfile("python") or not os.path.isfile("setup.py"): -+ raise ValueError("Script must be run in Python build directory") -+ -+ def _download_openssl(self): -+ """Download OpenSSL source dist""" -+ src_dir = os.path.dirname(self.src_file) -+ if not os.path.isdir(src_dir): -+ os.makedirs(src_dir) -+ url = self.url_template.format(self.version) -+ log.info("Downloading OpenSSL from {}".format(url)) -+ req = urlopen(url, cadefault=CADEFAULT) -+ # KISS, read all, write all -+ data = req.read() -+ log.info("Storing {}".format(self.src_file)) -+ with open(self.src_file, "wb") as f: -+ f.write(data) -+ -+ def _unpack_openssl(self): -+ """Unpack tar.gz bundle""" -+ # cleanup -+ if os.path.isdir(self.build_dir): -+ shutil.rmtree(self.build_dir) -+ os.makedirs(self.build_dir) -+ -+ tf = tarfile.open(self.src_file) -+ base = "openssl-{}/".format(self.version) -+ # force extraction into build dir -+ members = tf.getmembers() -+ for member in members: -+ if not member.name.startswith(base): -+ raise ValueError(member.name) -+ member.name = member.name[len(base):] -+ log.info("Unpacking files to {}".format(self.build_dir)) -+ tf.extractall(self.build_dir, members) -+ -+ def _build_openssl(self): -+ """Now build openssl""" -+ log.info("Running build in {}".format(self.install_dir)) -+ cwd = self.build_dir -+ cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] -+ cmd.extend(self.openssl_compile_args) -+ self._subprocess_call(cmd, cwd=cwd) -+ self._subprocess_call(["make"], cwd=cwd) -+ -+ def _install_openssl(self, remove=True): -+ self._subprocess_call(["make", "install"], cwd=self.build_dir) -+ if remove: -+ shutil.rmtree(self.build_dir) -+ -+ def install_openssl(self): -+ if not self.has_openssl: -+ if not self.has_src: -+ self._download_openssl() -+ else: -+ log.debug("Already has src {}".format(self.src_file)) -+ self._unpack_openssl() -+ self._build_openssl() -+ self._install_openssl() -+ else: -+ log.info("Already has installation {}".format(self.install_dir)) -+ # validate installation -+ version = self.openssl_version -+ if self.version not in version: -+ raise ValueError(version) -+ -+ def touch_pymods(self): -+ # force a rebuild of all modules that use OpenSSL APIs -+ for fname in self.module_files: -+ os.utime(fname) -+ -+ def recompile_pymods(self): -+ log.info("Using OpenSSL build from {}".format(self.build_dir)) -+ # overwrite header and library search paths -+ env = os.environ.copy() -+ env["CPPFLAGS"] = "-I{}".format(self.include_dir) -+ env["LDFLAGS"] = "-L{}".format(self.lib_dir) -+ # set rpath -+ env["LD_RUN_PATH"] = self.lib_dir -+ -+ log.info("Rebuilding Python modules") -+ self.touch_pymods() -+ cmd = ["./python", "setup.py", "build"] -+ self._subprocess_call(cmd, env=env) -+ -+ def check_pyssl(self): -+ version = self.pyssl_version -+ if self.version not in version: -+ raise ValueError(version) -+ -+ def run_pytests(self, *args): -+ cmd = ["./python", "-m", "test"] -+ cmd.extend(args) -+ self._subprocess_call(cmd, stdout=None) -+ -+ def run_python_tests(self, *args): -+ self.recompile_pymods() -+ self.check_pyssl() -+ self.run_pytests(*args) -+ -+ -+def main(*args): -+ builders = [] -+ for version in OPENSSL_VERSIONS: -+ if version in ("0.9.8i", "0.9.8l"): -+ openssl_compile_args = ("no-asm",) -+ else: -+ openssl_compile_args = () -+ builder = BuildSSL(version, openssl_compile_args) -+ builder.install_openssl() -+ builders.append(builder) -+ -+ for builder in builders: -+ builder.run_python_tests(*args) -+ # final touch -+ builder.touch_pymods() -+ -+ -+if __name__ == "__main__": -+ logging.basicConfig(level=logging.INFO, -+ format="*** %(levelname)s %(message)s") -+ args = sys.argv[1:] -+ if not args: -+ args = ["-unetwork", "-v"] -+ args.extend(FULL_TESTS) -+ main(*args) diff --git a/00197-unicode_fromformat.patch b/00197-unicode_fromformat.patch deleted file mode 100644 index 95031d5..0000000 --- a/00197-unicode_fromformat.patch +++ /dev/null @@ -1,208 +0,0 @@ -diff -r 847a0e74c4cc Lib/test/test_unicode.py ---- a/Lib/test/test_unicode.py Sun Jul 20 21:26:04 2014 -0700 -+++ b/Lib/test/test_unicode.py Tue Jul 22 00:13:24 2014 +0200 -@@ -1659,6 +1659,122 @@ class UnicodeTest( - self.assertEqual("%s" % u, u'__unicode__ overridden') - self.assertEqual("{}".format(u), '__unicode__ overridden') - -+ # Test PyUnicode_FromFormat() -+ def test_from_format(self): -+ test_support.import_module('ctypes') -+ from ctypes import ( -+ pythonapi, py_object, sizeof, -+ c_int, c_long, c_longlong, c_ssize_t, -+ c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) -+ if sys.maxunicode == 0xffff: -+ name = "PyUnicodeUCS2_FromFormat" -+ else: -+ name = "PyUnicodeUCS4_FromFormat" -+ _PyUnicode_FromFormat = getattr(pythonapi, name) -+ _PyUnicode_FromFormat.restype = py_object -+ -+ def PyUnicode_FromFormat(format, *args): -+ cargs = tuple( -+ py_object(arg) if isinstance(arg, unicode) else arg -+ for arg in args) -+ return _PyUnicode_FromFormat(format, *cargs) -+ -+ def check_format(expected, format, *args): -+ text = PyUnicode_FromFormat(format, *args) -+ self.assertEqual(expected, text) -+ -+ # ascii format, non-ascii argument -+ check_format(u'ascii\x7f=unicode\xe9', -+ b'ascii\x7f=%U', u'unicode\xe9') -+ -+ # non-ascii format, ascii argument: ensure that PyUnicode_FromFormatV() -+ # raises an error -+ #self.assertRaisesRegex(ValueError, -+ # '^PyUnicode_FromFormatV\(\) expects an ASCII-encoded format ' -+ # 'string, got a non-ASCII byte: 0xe9$', -+ # PyUnicode_FromFormat, b'unicode\xe9=%s', u'ascii') -+ -+ # test "%c" -+ check_format(u'\uabcd', -+ b'%c', c_int(0xabcd)) -+ if sys.maxunicode > 0xffff: -+ check_format(u'\U0010ffff', -+ b'%c', c_int(0x10ffff)) -+ with self.assertRaises(OverflowError): -+ PyUnicode_FromFormat(b'%c', c_int(0x110000)) -+ # Issue #18183 -+ if sys.maxunicode > 0xffff: -+ check_format(u'\U00010000\U00100000', -+ b'%c%c', c_int(0x10000), c_int(0x100000)) -+ -+ # test "%" -+ check_format(u'%', -+ b'%') -+ check_format(u'%', -+ b'%%') -+ check_format(u'%s', -+ b'%%s') -+ check_format(u'[%]', -+ b'[%%]') -+ check_format(u'%abc', -+ b'%%%s', b'abc') -+ -+ # test %S -+ check_format(u"repr=abc", -+ b'repr=%S', u'abc') -+ -+ # test %R -+ check_format(u"repr=u'abc'", -+ b'repr=%R', u'abc') -+ -+ # test integer formats (%i, %d, %u) -+ check_format(u'010', -+ b'%03i', c_int(10)) -+ check_format(u'0010', -+ b'%0.4i', c_int(10)) -+ check_format(u'-123', -+ b'%i', c_int(-123)) -+ check_format(u'-123', -+ b'%li', c_long(-123)) -+ check_format(u'-123', -+ b'%zi', c_ssize_t(-123)) -+ -+ check_format(u'-123', -+ b'%d', c_int(-123)) -+ check_format(u'-123', -+ b'%ld', c_long(-123)) -+ check_format(u'-123', -+ b'%zd', c_ssize_t(-123)) -+ -+ check_format(u'123', -+ b'%u', c_uint(123)) -+ check_format(u'123', -+ b'%lu', c_ulong(123)) -+ check_format(u'123', -+ b'%zu', c_size_t(123)) -+ -+ # test long output -+ PyUnicode_FromFormat(b'%p', c_void_p(-1)) -+ -+ # test %V -+ check_format(u'repr=abc', -+ b'repr=%V', u'abc', b'xyz') -+ check_format(u'repr=\xe4\xba\xba\xe6\xb0\x91', -+ b'repr=%V', None, b'\xe4\xba\xba\xe6\xb0\x91') -+ check_format(u'repr=abc\xff', -+ b'repr=%V', None, b'abc\xff') -+ -+ # not supported: copy the raw format string. these tests are just here -+ # to check for crashs and should not be considered as specifications -+ check_format(u'%s', -+ b'%1%s', b'abc') -+ check_format(u'%1abc', -+ b'%1abc') -+ check_format(u'%+i', -+ b'%+i', c_int(10)) -+ check_format(u'%s', -+ b'%.%s', b'abc') -+ - @test_support.cpython_only - def test_encode_decimal(self): - from _testcapi import unicode_encodedecimal -diff -r 847a0e74c4cc Objects/unicodeobject.c ---- a/Objects/unicodeobject.c Sun Jul 20 21:26:04 2014 -0700 -+++ b/Objects/unicodeobject.c Tue Jul 22 00:13:24 2014 +0200 -@@ -690,7 +690,12 @@ makefmt(char *fmt, int longflag, int siz - *fmt = '\0'; - } - --#define appendstring(string) {for (copy = string;*copy;) *s++ = *copy++;} -+#define appendstring(string) \ -+ do { \ -+ for (copy = string;*copy; copy++) { \ -+ *s++ = (unsigned char)*copy; \ -+ } \ -+ } while (0) - - PyObject * - PyUnicode_FromFormatV(const char *format, va_list vargs) -@@ -845,7 +850,7 @@ PyUnicode_FromFormatV(const char *format - str = PyObject_Str(obj); - if (!str) - goto fail; -- n += PyUnicode_GET_SIZE(str); -+ n += PyString_GET_SIZE(str); - /* Remember the str and switch to the next slot */ - *callresult++ = str; - break; -@@ -925,12 +930,12 @@ PyUnicode_FromFormatV(const char *format - } - /* handle the long flag, but only for %ld and %lu. - others can be added when necessary. */ -- if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) { -+ if (*f == 'l' && (f[1] == 'd' || f[1] == 'i' || f[1] == 'u')) { - longflag = 1; - ++f; - } - /* handle the size_t flag. */ -- if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { -+ if (*f == 'z' && (f[1] == 'd' || f[1] == 'i' || f[1] == 'u')) { - size_tflag = 1; - ++f; - } -@@ -939,8 +944,9 @@ PyUnicode_FromFormatV(const char *format - case 'c': - *s++ = va_arg(vargs, int); - break; -+ case 'i': - case 'd': -- makefmt(fmt, longflag, size_tflag, zeropad, width, precision, 'd'); -+ makefmt(fmt, longflag, size_tflag, zeropad, width, precision, *f); - if (longflag) - sprintf(realbuffer, fmt, va_arg(vargs, long)); - else if (size_tflag) -@@ -959,11 +965,6 @@ PyUnicode_FromFormatV(const char *format - sprintf(realbuffer, fmt, va_arg(vargs, unsigned int)); - appendstring(realbuffer); - break; -- case 'i': -- makefmt(fmt, 0, 0, zeropad, width, precision, 'i'); -- sprintf(realbuffer, fmt, va_arg(vargs, int)); -- appendstring(realbuffer); -- break; - case 'x': - makefmt(fmt, 0, 0, zeropad, width, precision, 'x'); - sprintf(realbuffer, fmt, va_arg(vargs, int)); -@@ -1006,15 +1007,10 @@ PyUnicode_FromFormatV(const char *format - case 'S': - case 'R': - { -- Py_UNICODE *ucopy; -- Py_ssize_t usize; -- Py_ssize_t upos; -+ const char *str = PyString_AS_STRING(*callresult); - /* unused, since we already have the result */ - (void) va_arg(vargs, PyObject *); -- ucopy = PyUnicode_AS_UNICODE(*callresult); -- usize = PyUnicode_GET_SIZE(*callresult); -- for (upos = 0; upos forget it */ - Py_DECREF(*callresult); - /* switch to next unicode()/repr() result */ diff --git a/00198-add-rewheel-module.patch b/00198-add-rewheel-module.patch new file mode 100644 index 0000000..7da66a4 --- /dev/null +++ b/00198-add-rewheel-module.patch @@ -0,0 +1,230 @@ +diff -Nur Python-3.4.1/Lib/ensurepip/__init__.py Python-3.4.1-rewheel/Lib/ensurepip/__init__.py +--- Python-3.4.1/Lib/ensurepip/__init__.py 2014-08-21 10:49:30.792695824 +0200 ++++ Python-3.4.1-rewheel/Lib/ensurepip/__init__.py 2014-08-21 10:10:41.958341726 +0200 +@@ -7,6 +7,7 @@ import pkgutil + import shutil + import sys + import tempfile ++from ensurepip import rewheel + + + __all__ = ["version", "bootstrap"] +@@ -43,6 +44,8 @@ + + # Install the bundled software + import pip ++ if args[0] in ["install", "list", "wheel"]: ++ args.append('--pre') + pip.main(args) + + +@@ -93,21 +96,40 @@ def bootstrap(root=None, upgrade=False, + # omit pip and easy_install + os.environ["ENSUREPIP_OPTIONS"] = "install" + ++ whls = [] ++ rewheel_dir = None ++ # try to see if we have system-wide versions of _PROJECTS ++ dep_records = rewheel.find_system_records([p[0] for p in _PROJECTS]) ++ # TODO: check if system-wide versions are the newest ones ++ # if --upgrade is used? ++ if all(dep_records): ++ # if we have all _PROJECTS installed system-wide, we'll recreate ++ # wheels from them and install those ++ rewheel_dir = tempfile.TemporaryDirectory() ++ for dr in dep_records: ++ new_whl = rewheel.rewheel_from_record(dr, rewheel_dir.name) ++ whls.append(os.path.join(rewheel_dir.name, new_whl)) ++ else: ++ # if we don't have all the _PROJECTS installed system-wide, ++ # let's just fall back to bundled wheels ++ for project, version in _PROJECTS: ++ whl = os.path.join( ++ os.path.dirname(__file__), ++ "_bundled", ++ "{}-{}-py2.py3-none-any.whl".format(project, version) ++ ) ++ whls.append(whl) ++ + tmpdir = tempfile.mkdtemp() + try: + # Put our bundled wheels into a temporary directory and construct the + # additional paths that need added to sys.path + additional_paths = [] +- for project, version in _PROJECTS: +- wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version) +- whl = pkgutil.get_data( +- "ensurepip", +- "_bundled/{}".format(wheel_name), +- ) +- with open(os.path.join(tmpdir, wheel_name), "wb") as fp: +- fp.write(whl) +- +- additional_paths.append(os.path.join(tmpdir, wheel_name)) ++ for whl in whls: ++ shutil.copy(whl, tmpdir) ++ additional_paths.append(os.path.join(tmpdir, os.path.basename(whl))) ++ if rewheel_dir: ++ rewheel_dir.cleanup() + + # Construct the arguments to be passed to the pip command + args = ["install", "--no-index", "--find-links", tmpdir] +diff -Nur Python-3.4.1/Makefile.pre.in Python-3.4.1-rewheel/Makefile.pre.in +--- Python-3.4.1/Makefile.pre.in 2014-08-21 10:49:31.512695040 +0200 ++++ Python-3.4.1-rewheel/Makefile.pre.in 2014-08-21 10:10:41.961341722 +0200 +@@ -976,7 +976,7 @@ LIBSUBDIRS= lib-tk lib-tk/test lib-tk/te + test/tracedmodules \ + encodings compiler hotshot \ + email email/mime email/test email/test/data \ +- ensurepip ensurepip/_bundled \ ++ ensurepip ensurepip/_bundled ensurepip/rewheel\ + json json/tests \ + sqlite3 sqlite3/test \ + logging bsddb bsddb/test csv importlib wsgiref \ +diff -ru --new-file Python-2.7.9rc1-rewheel/Lib/ensurepip/rewheel/__init__.py Python-2.7.9rc1/Lib/ensurepip/rewheel/__init__.py +--- Python-2.7.9rc1-rewheel/Lib/ensurepip/rewheel/__init__.py 1970-01-01 01:00:00.000000000 +0100 ++++ Python-2.7.9rc1/Lib/ensurepip/rewheel/__init__.py 2014-12-08 11:29:34.215237317 +0100 +@@ -0,0 +1,143 @@ ++import argparse ++import codecs ++import csv ++import email.parser ++import os ++import io ++import re ++import site ++import subprocess ++import sys ++import zipfile ++ ++def run(): ++ parser = argparse.ArgumentParser(description='Recreate wheel of package with given RECORD.') ++ parser.add_argument('record_path', ++ help='Path to RECORD file') ++ parser.add_argument('-o', '--output-dir', ++ help='Dir where to place the wheel, defaults to current working dir.', ++ dest='outdir', ++ default=os.path.curdir) ++ ++ ns = parser.parse_args() ++ retcode = 0 ++ try: ++ print(rewheel_from_record(**vars(ns))) ++ except BaseException as e: ++ print('Failed: {}'.format(e)) ++ retcode = 1 ++ sys.exit(1) ++ ++def find_system_records(projects): ++ """Return list of paths to RECORD files for system-installed projects. ++ ++ If a project is not installed, the resulting list contains None instead ++ of a path to its RECORD ++ """ ++ records = [] ++ # get system site-packages dirs ++ sys_sitepack = site.getsitepackages([sys.base_prefix, sys.base_exec_prefix]) ++ sys_sitepack = [sp for sp in sys_sitepack if os.path.exists(sp)] ++ # try to find all projects in all system site-packages ++ for project in projects: ++ path = None ++ for sp in sys_sitepack: ++ dist_info_re = os.path.join(sp, project) + '-[^\{0}]+\.dist-info'.format(os.sep) ++ candidates = [os.path.join(sp, p) for p in os.listdir(sp)] ++ # filter out candidate dirs based on the above regexp ++ filtered = [c for c in candidates if re.match(dist_info_re, c)] ++ # if we have 0 or 2 or more dirs, something is wrong... ++ if len(filtered) == 1: ++ path = filtered[0] ++ if path is not None: ++ records.append(os.path.join(path, 'RECORD')) ++ else: ++ records.append(None) ++ return records ++ ++def rewheel_from_record(record_path, outdir): ++ """Recreates a whee of package with given record_path and returns path ++ to the newly created wheel.""" ++ site_dir = os.path.dirname(os.path.dirname(record_path)) ++ record_relpath = record_path[len(site_dir):].strip(os.path.sep) ++ to_write, to_omit = get_records_to_pack(site_dir, record_relpath) ++ new_wheel_name = get_wheel_name(record_path) ++ new_wheel_path = os.path.join(outdir, new_wheel_name + '.whl') ++ ++ new_wheel = zipfile.ZipFile(new_wheel_path, mode='w', compression=zipfile.ZIP_DEFLATED) ++ # we need to write a new record with just the files that we will write, ++ # e.g. not binaries and *.pyc/*.pyo files ++ new_record = io.StringIO() ++ writer = csv.writer(new_record) ++ ++ # handle files that we can write straight away ++ for f, sha_hash, size in to_write: ++ new_wheel.write(os.path.join(site_dir, f), arcname=f) ++ writer.writerow([f, sha_hash,size]) ++ ++ # rewrite the old wheel file with a new computed one ++ writer.writerow([record_relpath, '', '']) ++ new_wheel.writestr(record_relpath, new_record.getvalue()) ++ ++ new_wheel.close() ++ ++ return new_wheel.filename ++ ++def get_wheel_name(record_path): ++ """Return proper name of the wheel, without .whl.""" ++ ++ wheel_info_path = os.path.join(os.path.dirname(record_path), 'WHEEL') ++ with codecs.open(wheel_info_path, encoding='utf-8') as wheel_info_file: ++ wheel_info = email.parser.Parser().parsestr(wheel_info_file.read()) ++ ++ metadata_path = os.path.join(os.path.dirname(record_path), 'METADATA') ++ with codecs.open(metadata_path, encoding='utf-8') as metadata_file: ++ metadata = email.parser.Parser().parsestr(metadata_file.read()) ++ ++ # construct name parts according to wheel spec ++ distribution = metadata.get('Name') ++ version = metadata.get('Version') ++ build_tag = '' # nothing for now ++ lang_tag = [] ++ for t in wheel_info.get_all('Tag'): ++ lang_tag.append(t.split('-')[0]) ++ lang_tag = '.'.join(lang_tag) ++ abi_tag, plat_tag = wheel_info.get('Tag').split('-')[1:3] ++ # leave out build tag, if it is empty ++ to_join = filter(None, [distribution, version, build_tag, lang_tag, abi_tag, plat_tag]) ++ return '-'.join(list(to_join)) ++ ++def get_records_to_pack(site_dir, record_relpath): ++ """Accepts path of sitedir and path of RECORD file relative to it. ++ Returns two lists: ++ - list of files that can be written to new RECORD straight away ++ - list of files that shouldn't be written or need some processing ++ (pyc and pyo files, scripts) ++ """ ++ record_file_path = os.path.join(site_dir, record_relpath) ++ with codecs.open(record_file_path, encoding='utf-8') as record_file: ++ record_contents = record_file.read() ++ # temporary fix for https://github.com/pypa/pip/issues/1376 ++ # we need to ignore files under ".data" directory ++ data_dir = os.path.dirname(record_relpath).strip(os.path.sep) ++ data_dir = data_dir[:-len('dist-info')] + 'data' ++ ++ to_write = [] ++ to_omit = [] ++ for l in record_contents.splitlines(): ++ spl = l.split(',') ++ if len(spl) == 3: ++ # new record will omit (or write differently): ++ # - abs paths, paths with ".." (entry points), ++ # - pyc+pyo files ++ # - the old RECORD file ++ # TODO: is there any better way to recognize an entry point? ++ if os.path.isabs(spl[0]) or spl[0].startswith('..') or \ ++ spl[0].endswith('.pyc') or spl[0].endswith('.pyo') or \ ++ spl[0] == record_relpath or spl[0].startswith(data_dir): ++ to_omit.append(spl) ++ else: ++ to_write.append(spl) ++ else: ++ pass # bad RECORD or empty line ++ return to_write, to_omit diff --git a/python-2.7.3-debug-build.patch b/python-2.7.3-debug-build.patch index ee0b2a2..c8e8fea 100644 --- a/python-2.7.3-debug-build.patch +++ b/python-2.7.3-debug-build.patch @@ -193,14 +193,14 @@ diff -up Python-2.7.6/Misc/python-config.in.debug-build Python-2.7.6/Misc/python --- Python-2.7.6/Misc/python-config.in.debug-build 2013-11-10 08:36:41.000000000 +0100 +++ Python-2.7.6/Misc/python-config.in 2014-01-29 14:13:08.816888470 +0100 @@ -45,7 +45,7 @@ for opt in opt_flags: + print ' '.join(flags) elif opt in ('--libs', '--ldflags'): - libs = getvar('LIBS').split() + getvar('SYSLIBS').split() -- libs.append('-lpython'+pyver) -+ libs.append('-lpython' + pyver + (sys.pydebug and "_d" or "")) +- libs = ['-lpython' + pyver] ++ libs = ['-lpython' + pyver + (sys.pydebug and "_d" or "")] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() # add the prefix/lib/pythonX.Y/config dir, but only if there is no - # shared library in prefix/lib/. - if opt == '--ldflags': diff -up Python-2.7.6/Modules/makesetup.debug-build Python-2.7.6/Modules/makesetup --- Python-2.7.6/Modules/makesetup.debug-build 2013-11-10 08:36:41.000000000 +0100 +++ Python-2.7.6/Modules/makesetup 2014-01-29 14:13:08.817888407 +0100 diff --git a/python.spec b/python.spec index 8e3a6c4..2e34041 100644 --- a/python.spec +++ b/python.spec @@ -2,6 +2,8 @@ # Conditionals and other variables controlling the build # ====================================================== +%global with_rewheel 1 + %{!?__python_ver:%global __python_ver EMPTY} #global __python_ver 27 %global unicode ucs4 @@ -105,8 +107,8 @@ Summary: An interpreted, interactive, object-oriented programming language Name: %{python} # Remember to also rebase python-docs when changing this: -Version: 2.7.8 -Release: 10%{?dist} +Version: 2.7.9 +Release: 1%{?dist} License: Python Group: Development/Languages Requires: %{python}-libs%{?_isa} = %{version}-%{release} @@ -164,6 +166,11 @@ BuildRequires: valgrind-devel BuildRequires: zlib-devel +%if 0%{?with_rewheel} +BuildRequires: python-setuptools +BuildRequires: python-pip +%endif + # ======================= @@ -888,11 +895,17 @@ Patch193: 00193-enable-loading-sqlite-extensions.patch # http://bugs.python.org/issue21308 # Backport of ssl module from python3 -Patch196: 00196-ssl-backport.patch +# FIXED UPSTREAM +# Patch196: 00196-ssl-backport.patch # http://bugs.python.org/issue22023 # Patch seg fault in unicodeobject.c -Patch197: 00197-unicode_fromformat.patch +# FIXED UPSTREAM +# Patch197: 00197-unicode_fromformat.patch + +%if 0%{with_rewheel} +Patch198: 00198-add-rewheel-module.patch +%endif # (New patches go here ^^^) # @@ -1251,8 +1264,11 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c %patch193 -p1 # 00194: upstream as of Python 2.7.7 #%patch195 -p1 -%patch196 -p1 -%patch197 -p1 +# 00196: upstream as of Python 2.7.9 +# 00197: upstream as of Python 2.7.9 +%if 0%{with_rewheel} +%patch198 -p1 +%endif # This shouldn't be necesarry, but is right now (2.2a3) @@ -1893,6 +1909,16 @@ rm -fr %{buildroot} %doc systemtap-example.stp pyfuntop.stp %endif +%dir %{pylibdir}/ensurepip/ +%{pylibdir}/ensurepip/*.py* +%exclude %{pylibdir}/ensurepip/_bundled + +%if 0%{?with_rewheel} +%dir %{pylibdir}/ensurepip/rewheel/ +%{pylibdir}/ensurepip/rewheel/*.py* +%endif + + %files devel %defattr(-,root,root,-) %{_libdir}/pkgconfig/python-%{pybasever}.pc @@ -2091,6 +2117,12 @@ rm -fr %{buildroot} # ====================================================== %changelog +* Thu Dec 11 2014 Matej Stuchlik - 2.7.9-1 +- Update to 2.7.9 +- Refreshed patches: #55, #137, #146, #153, #156, #198 +- Dropped patches: #196, #197 +- Added the rewheel module + * Mon Nov 24 2014 Matej Stuchlik - 2.7.8-10 - Improve python2_version macros diff --git a/sources b/sources index 9163c53..a7b1f8e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -d235bdfa75b8396942e360a70487ee00 Python-2.7.8.tar.xz +38d530f7efc373d64a8fb1637e3baaa7 Python-2.7.9.tar.xz