Commit 71a4ee3e authored by Benjamin Peterson's avatar Benjamin Peterson

backport many ssl features from Python 3 (closes #21308)

A contribution of Alex Gaynor and David Reid with the generous support of
Rackspace. May God have mercy on their souls.
parent aed7f8b7
......@@ -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
<ssl-nonblocking>` 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
<ssl-nonblocking>` 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 "<stdin>", line 1, in <module>
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
<http://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. 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
<http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6>`_
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-nonblocking>`.
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
<http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html>`_.
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
<http://www.openssl.org/docs/apps/ciphers.html#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
<http://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. 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_* <ALERT_DESCRIPTION_INTERNAL_ERROR>` 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 <http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html>`_
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
<http://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html>`_ 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 <http://www.thawte.com/roots/>`_, `Verisign
<http://www.verisign.com/support/roots.html>`_, `Positive SSL
<http://www.PositiveSSL.com/ssl-certificate-support/cert_installation/UTN-USERFirst-Hardware.crt>`_
(used by python.org), `Equifax and GeoTrust
<http://www.geotrust.com/resources/root_certificates/index.asp>`_.
-----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', '<unsupported>'),
('DNS', 'linuxfr.org'),
('othername', '<unsupported>'),
('DNS', 'dev.linuxfr.org'),
('othername', '<unsupported>'),
('DNS', 'prod.linuxfr.org'),
('othername', '<unsupported>'),
('DNS', 'alpha.linuxfr.org'),
('othername', '<unsupported>'),
('DNS', '*.linuxfr.org'),
('othername', '<unsupported>')),
'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 <http://www.openssl.org/docs/apps/ciphers.html#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 <http://www.ietf.org/rfc/rfc3280>`_
Housley et. al.
`RFC 4366: Transport Layer Security (TLS) Extensions <http://www.ietf.org/rfc/rfc4366>`_
Blake-Wilson et. al.
`RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <http://www.ietf.org/rfc/rfc5246>`_
T. Dierks et. al.
`RFC 6066: Transport Layer Security (TLS) Extensions <http://www.ietf.org/rfc/rfc6066>`_
D. Eastlake
`IANA TLS: Transport Layer Security (TLS) Parameters <http://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_
IANA
# 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):
......
-----BEGIN CERTIFICATE-----
MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD
VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv
bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy
dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X
DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw
EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l
dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT
EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw
L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN
BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX
9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4=
-----END CERTIFICATE-----
-----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-----
-----BEGIN CERTIFICATE-----
MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD
VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv
bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy
dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X
DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw
EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l
dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT
EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw
L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN
BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX
9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4=
-----END CERTIFICATE-----
-----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-----
-----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.
-----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-----
-----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-----
-----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-----
"""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'])
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-----
-----BEGIN X509 CRL-----
MIIBpjCBjwIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJYWTEmMCQGA1UE
CgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNVBAMMDW91ci1j
YS1zZXJ2ZXIXDTEzMTEyMTE3MDg0N1oXDTIzMDkzMDE3MDg0N1qgDjAMMAoGA1Ud
FAQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQCNJXC2mVKauEeN3LlQ3ZtM5gkH3ExH
+i4bmJjtJn497WwvvoIeUdrmVXgJQR93RtV37hZwN0SXMLlNmUZPH4rHhihayw4m
unCzVj/OhCCY7/TPjKuJ1O/0XhaLBpBVjQN7R/1ujoRKbSia/CD3vcn7Fqxzw7LK
fSRCKRGTj1CZiuxrphtFchwALXSiFDy9mr2ZKhImcyq1PydfgEzU78APpOkMQsIC
UNJ/cf3c9emzf+dUtcMEcejQ3mynBo4eIGg1EW42bz4q4hSjzQlKcBV0muw5qXhc
HOxH2iTFhQ7SrvVuK/dM14rYM4B5mSX3nRC1kNmXpS9j3wJDhuwmjHed
-----END X509 CRL-----
# 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-----
-----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-----
-----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 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-----
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)
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -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
......
......@@ -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 \
......
......@@ -19,6 +19,9 @@ Core and Builtins
Library
-------
- Issue #21308: Backport numerous features from Python's ssl module. This is
part of PEP 466.
- Issue #15696: Add a __sizeof__ implementation for mmap objects on Windows.
- Issue #8797: Raise HTTPError on failed Basic Authentication immediately.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* 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 }
};
#! /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()
#./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 <christian@python.org>
"""
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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment