Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 58ddc9d

Browse files
committed
Issue #8109: The ssl module now has support for server-side SNI, thanks to a :meth:SSLContext.set_servername_callback method.
Patch by Daniel Black.
1 parent 3c9850a commit 58ddc9d

11 files changed

Lines changed: 881 additions & 42 deletions

File tree

Doc/library/ssl.rst

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,19 @@ Constants
533533

534534
.. versionadded:: 3.2
535535

536+
.. data:: ALERT_DESCRIPTION_HANDSHAKE_FAILURE
537+
ALERT_DESCRIPTION_INTERNAL_ERROR
538+
ALERT_DESCRIPTION_*
539+
540+
Alert Descriptions from :rfc:`5246` and others. The `IANA TLS Alert Registry
541+
<http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6>`_
542+
contains this list and references to the RFCs where their meaning is defined.
543+
544+
Used as the return value of the callback function in
545+
:meth:`SSLContext.set_servername_callback`.
546+
547+
.. versionadded:: 3.4
548+
536549

537550
SSL Sockets
538551
-----------
@@ -780,6 +793,55 @@ to speed up repeated connections from the same clients.
780793

781794
.. versionadded:: 3.3
782795

796+
.. method:: SSLContext.set_servername_callback(server_name_callback)
797+
798+
Register a callback function that will be called after the TLS Client Hello
799+
handshake message has been received by the SSL/TLS server when the TLS client
800+
specifies a server name indication. The server name indication mechanism
801+
is specified in :rfc:`6066` section 3 - Server Name Indication.
802+
803+
Only one callback can be set per ``SSLContext``. If *server_name_callback*
804+
is ``None`` then the callback is disabled. Calling this function a
805+
subsequent time will disable the previously registered callback.
806+
807+
The callback function, *server_name_callback*, will be called with three
808+
arguments; the first being the :class:`ssl.SSLSocket`, the second is a string
809+
that represents the server name that the client is intending to communicate
810+
and the third argument is the original :class:`SSLContext`. The server name
811+
argument is the IDNA decoded server name.
812+
813+
A typical use of this callback is to change the :class:`ssl.SSLSocket`'s
814+
:attr:`SSLSocket.context` attribute to a new object of type
815+
:class:`SSLContext` representing a certificate chain that matches the server
816+
name.
817+
818+
Due to the early negotiation phase of the TLS connection, only limited
819+
methods and attributes are usable like
820+
:meth:`SSLSocket.selected_npn_protocol` and :attr:`SSLSocket.context`.
821+
:meth:`SSLSocket.getpeercert`, :meth:`SSLSocket.getpeercert`,
822+
:meth:`SSLSocket.cipher` and :meth:`SSLSocket.compress` methods require that
823+
the TLS connection has progressed beyond the TLS Client Hello and therefore
824+
will not contain return meaningful values nor can they be called safely.
825+
826+
The *server_name_callback* function must return ``None`` to allow the
827+
the TLS negotiation to continue. If a TLS failure is required, a constant
828+
:const:`ALERT_DESCRIPTION_* <ALERT_DESCRIPTION_INTERNAL_ERROR>` can be
829+
returned. Other return values will result in a TLS fatal error with
830+
:const:`ALERT_DESCRIPTION_INTERNAL_ERROR`.
831+
832+
If there is a IDNA decoding error on the server name, the TLS connection
833+
will terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS
834+
alert message to the client.
835+
836+
If an exception is raised from the *server_name_callback* function the TLS
837+
connection will terminate with a fatal TLS alert message
838+
:const:`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`.
839+
840+
This method will raise :exc:`NotImplementedError` if the OpenSSL library
841+
had OPENSSL_NO_TLSEXT defined when it was built.
842+
843+
.. versionadded:: 3.4
844+
783845
.. method:: SSLContext.load_dh_params(dhfile)
784846

785847
Load the key generation parameters for Diffie-Helman (DH) key exchange.
@@ -1313,3 +1375,12 @@ use the ``openssl ciphers`` command on your system.
13131375

13141376
`RFC 4366: Transport Layer Security (TLS) Extensions <http://www.ietf.org/rfc/rfc4366>`_
13151377
Blake-Wilson et. al.
1378+
1379+
`RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <http://www.ietf.org/rfc/rfc5246>`_
1380+
T. Dierks et. al.
1381+
1382+
`RFC 6066: Transport Layer Security (TLS) Extensions <http://www.ietf.org/rfc/rfc6066>`_
1383+
D. Eastlake
1384+
1385+
`IANA TLS: Transport Layer Security (TLS) Parameters <http://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_
1386+
IANA

Lib/ssl.py

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,37 @@
5252
PROTOCOL_SSLv3
5353
PROTOCOL_SSLv23
5454
PROTOCOL_TLSv1
55+
56+
The following constants identify various SSL alert message descriptions as per
57+
http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6
58+
59+
ALERT_DESCRIPTION_CLOSE_NOTIFY
60+
ALERT_DESCRIPTION_UNEXPECTED_MESSAGE
61+
ALERT_DESCRIPTION_BAD_RECORD_MAC
62+
ALERT_DESCRIPTION_RECORD_OVERFLOW
63+
ALERT_DESCRIPTION_DECOMPRESSION_FAILURE
64+
ALERT_DESCRIPTION_HANDSHAKE_FAILURE
65+
ALERT_DESCRIPTION_BAD_CERTIFICATE
66+
ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE
67+
ALERT_DESCRIPTION_CERTIFICATE_REVOKED
68+
ALERT_DESCRIPTION_CERTIFICATE_EXPIRED
69+
ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN
70+
ALERT_DESCRIPTION_ILLEGAL_PARAMETER
71+
ALERT_DESCRIPTION_UNKNOWN_CA
72+
ALERT_DESCRIPTION_ACCESS_DENIED
73+
ALERT_DESCRIPTION_DECODE_ERROR
74+
ALERT_DESCRIPTION_DECRYPT_ERROR
75+
ALERT_DESCRIPTION_PROTOCOL_VERSION
76+
ALERT_DESCRIPTION_INSUFFICIENT_SECURITY
77+
ALERT_DESCRIPTION_INTERNAL_ERROR
78+
ALERT_DESCRIPTION_USER_CANCELLED
79+
ALERT_DESCRIPTION_NO_RENEGOTIATION
80+
ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION
81+
ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE
82+
ALERT_DESCRIPTION_UNRECOGNIZED_NAME
83+
ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE
84+
ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE
85+
ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY
5586
"""
5687

5788
import textwrap
@@ -66,35 +97,24 @@
6697
SSLSyscallError, SSLEOFError,
6798
)
6899
from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
69-
from _ssl import (
70-
OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1,
71-
OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_DH_USE
72-
)
73-
try:
74-
from _ssl import OP_NO_COMPRESSION
75-
except ImportError:
76-
pass
77-
try:
78-
from _ssl import OP_SINGLE_ECDH_USE
79-
except ImportError:
80-
pass
81100
from _ssl import RAND_status, RAND_egd, RAND_add, RAND_bytes, RAND_pseudo_bytes
82-
from _ssl import (
83-
SSL_ERROR_ZERO_RETURN,
84-
SSL_ERROR_WANT_READ,
85-
SSL_ERROR_WANT_WRITE,
86-
SSL_ERROR_WANT_X509_LOOKUP,
87-
SSL_ERROR_SYSCALL,
88-
SSL_ERROR_SSL,
89-
SSL_ERROR_WANT_CONNECT,
90-
SSL_ERROR_EOF,
91-
SSL_ERROR_INVALID_ERROR_CODE,
92-
)
101+
102+
def _import_symbols(prefix):
103+
for n in dir(_ssl):
104+
if n.startswith(prefix):
105+
globals()[n] = getattr(_ssl, n)
106+
107+
_import_symbols('OP_')
108+
_import_symbols('ALERT_DESCRIPTION_')
109+
_import_symbols('SSL_ERROR_')
110+
93111
from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN
112+
94113
from _ssl import (PROTOCOL_SSLv3, PROTOCOL_SSLv23,
95114
PROTOCOL_TLSv1)
96115
from _ssl import _OPENSSL_API_VERSION
97116

117+
98118
_PROTOCOL_NAMES = {
99119
PROTOCOL_TLSv1: "TLSv1",
100120
PROTOCOL_SSLv23: "SSLv23",
@@ -190,7 +210,7 @@ class SSLContext(_SSLContext):
190210
"""An SSLContext holds various SSL-related configuration options and
191211
data, such as certificates and possibly a private key."""
192212

193-
__slots__ = ('protocol',)
213+
__slots__ = ('protocol', '__weakref__')
194214

195215
def __new__(cls, protocol, *args, **kwargs):
196216
self = _SSLContext.__new__(cls, protocol)
@@ -238,7 +258,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
238258
_context=None):
239259

240260
if _context:
241-
self.context = _context
261+
self._context = _context
242262
else:
243263
if server_side and not certfile:
244264
raise ValueError("certfile must be specified for server-side "
@@ -247,16 +267,16 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
247267
raise ValueError("certfile must be specified")
248268
if certfile and not keyfile:
249269
keyfile = certfile
250-
self.context = SSLContext(ssl_version)
251-
self.context.verify_mode = cert_reqs
270+
self._context = SSLContext(ssl_version)
271+
self._context.verify_mode = cert_reqs
252272
if ca_certs:
253-
self.context.load_verify_locations(ca_certs)
273+
self._context.load_verify_locations(ca_certs)
254274
if certfile:
255-
self.context.load_cert_chain(certfile, keyfile)
275+
self._context.load_cert_chain(certfile, keyfile)
256276
if npn_protocols:
257-
self.context.set_npn_protocols(npn_protocols)
277+
self._context.set_npn_protocols(npn_protocols)
258278
if ciphers:
259-
self.context.set_ciphers(ciphers)
279+
self._context.set_ciphers(ciphers)
260280
self.keyfile = keyfile
261281
self.certfile = certfile
262282
self.cert_reqs = cert_reqs
@@ -298,7 +318,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
298318
if connected:
299319
# create the SSL object
300320
try:
301-
self._sslobj = self.context._wrap_socket(self, server_side,
321+
self._sslobj = self._context._wrap_socket(self, server_side,
302322
server_hostname)
303323
if do_handshake_on_connect:
304324
timeout = self.gettimeout()
@@ -310,6 +330,14 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
310330
except OSError as x:
311331
self.close()
312332
raise x
333+
@property
334+
def context(self):
335+
return self._context
336+
337+
@context.setter
338+
def context(self, ctx):
339+
self._context = ctx
340+
self._sslobj.context = ctx
313341

314342
def dup(self):
315343
raise NotImplemented("Can't dup() %s instances" %

Lib/test/keycert3.pem

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMLgD0kAKDb5cFyP
3+
jbwNfR5CtewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM
4+
9z2j1OlaN+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZ
5+
aggEdkj1TsSsv1zWIYKlPIjlvhuxAgMBAAECgYA0aH+T2Vf3WOPv8KdkcJg6gCRe
6+
yJKXOWgWRcicx/CUzOEsTxmFIDPLxqAWA3k7v0B+3vjGw5Y9lycV/5XqXNoQI14j
7+
y09iNsumds13u5AKkGdTJnZhQ7UKdoVHfuP44ZdOv/rJ5/VD6F4zWywpe90pcbK+
8+
AWDVtusgGQBSieEl1QJBAOyVrUG5l2yoUBtd2zr/kiGm/DYyXlIthQO/A3/LngDW
9+
5/ydGxVsT7lAVOgCsoT+0L4efTh90PjzW8LPQrPBWVMCQQDS3h/FtYYd5lfz+FNL
10+
9CEe1F1w9l8P749uNUD0g317zv1tatIqVCsQWHfVHNdVvfQ+vSFw38OORO00Xqs9
11+
1GJrAkBkoXXEkxCZoy4PteheO/8IWWLGGr6L7di6MzFl1lIqwT6D8L9oaV2vynFT
12+
DnKop0pa09Unhjyw57KMNmSE2SUJAkEArloTEzpgRmCq4IK2/NpCeGdHS5uqRlbh
13+
1VIa/xGps7EWQl5Mn8swQDel/YP3WGHTjfx7pgSegQfkyaRtGpZ9OQJAa9Vumj8m
14+
JAAtI0Bnga8hgQx7BhTQY4CadDxyiRGOGYhwUzYVCqkb2sbVRH9HnwUaJT7cWBY3
15+
RnJdHOMXWem7/w==
16+
-----END PRIVATE KEY-----
17+
Certificate:
18+
Data:
19+
Version: 1 (0x0)
20+
Serial Number: 12723342612721443281 (0xb09264b1f2da21d1)
21+
Signature Algorithm: sha1WithRSAEncryption
22+
Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server
23+
Validity
24+
Not Before: Jan 4 19:47:07 2013 GMT
25+
Not After : Nov 13 19:47:07 2022 GMT
26+
Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=localhost
27+
Subject Public Key Info:
28+
Public Key Algorithm: rsaEncryption
29+
Public-Key: (1024 bit)
30+
Modulus:
31+
00:c2:e0:0f:49:00:28:36:f9:70:5c:8f:8d:bc:0d:
32+
7d:1e:42:b5:ec:1d:5c:2f:a4:31:70:16:0f:c0:cb:
33+
c6:24:d3:be:13:16:ee:a5:67:97:03:a6:df:a9:99:
34+
96:cc:c7:2a:fb:11:7f:4e:65:4f:8a:5e:82:21:4c:
35+
f7:3d:a3:d4:e9:5a:37:e7:22:fd:7e:cd:53:6d:93:
36+
34:de:9c:ad:84:a2:37:be:c5:8d:82:4f:e3:ae:23:
37+
f3:be:a7:75:2c:72:0f:ea:f3:ca:cd:fc:e9:3f:b5:
38+
af:56:99:6a:08:04:76:48:f5:4e:c4:ac:bf:5c:d6:
39+
21:82:a5:3c:88:e5:be:1b:b1
40+
Exponent: 65537 (0x10001)
41+
Signature Algorithm: sha1WithRSAEncryption
42+
2f:42:5f:a3:09:2c:fa:51:88:c7:37:7f:ea:0e:63:f0:a2:9a:
43+
e5:5a:e2:c8:20:f0:3f:60:bc:c8:0f:b6:c6:76:ce:db:83:93:
44+
f5:a3:33:67:01:8e:04:cd:00:9a:73:fd:f3:35:86:fa:d7:13:
45+
e2:46:c6:9d:c0:29:53:d4:a9:90:b8:77:4b:e6:83:76:e4:92:
46+
d6:9c:50:cf:43:d0:c6:01:77:61:9a:de:9b:70:f7:72:cd:59:
47+
00:31:69:d9:b4:ca:06:9c:6d:c3:c7:80:8c:68:e6:b5:a2:f8:
48+
ef:1d:bb:16:9f:77:77:ef:87:62:22:9b:4d:69:a4:3a:1a:f1:
49+
21:5e:8c:32:ac:92:fd:15:6b:18:c2:7f:15:0d:98:30:ca:75:
50+
8f:1a:71:df:da:1d:b2:ef:9a:e8:2d:2e:02:fd:4a:3c:aa:96:
51+
0b:06:5d:35:b3:3d:24:87:4b:e0:b0:58:60:2f:45:ac:2e:48:
52+
8a:b0:99:10:65:27:ff:cc:b1:d8:fd:bd:26:6b:b9:0c:05:2a:
53+
f4:45:63:35:51:07:ed:83:85:fe:6f:69:cb:bb:40:a8:ae:b6:
54+
3b:56:4a:2d:a4:ed:6d:11:2c:4d:ed:17:24:fd:47:bc:d3:41:
55+
a2:d3:06:fe:0c:90:d8:d8:94:26:c4:ff:cc:a1:d8:42:77:eb:
56+
fc:a9:94:71
57+
-----BEGIN CERTIFICATE-----
58+
MIICpDCCAYwCCQCwkmSx8toh0TANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY
59+
WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV
60+
BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3
61+
WjBfMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV
62+
BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRIwEAYDVQQDEwlsb2NhbGhv
63+
c3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMLgD0kAKDb5cFyPjbwNfR5C
64+
tewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM9z2j1Ola
65+
N+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZaggEdkj1
66+
TsSsv1zWIYKlPIjlvhuxAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAC9CX6MJLPpR
67+
iMc3f+oOY/CimuVa4sgg8D9gvMgPtsZ2ztuDk/WjM2cBjgTNAJpz/fM1hvrXE+JG
68+
xp3AKVPUqZC4d0vmg3bkktacUM9D0MYBd2Ga3ptw93LNWQAxadm0ygacbcPHgIxo
69+
5rWi+O8duxafd3fvh2Iim01ppDoa8SFejDKskv0VaxjCfxUNmDDKdY8acd/aHbLv
70+
mugtLgL9SjyqlgsGXTWzPSSHS+CwWGAvRawuSIqwmRBlJ//Msdj9vSZruQwFKvRF
71+
YzVRB+2Dhf5vacu7QKiutjtWSi2k7W0RLE3tFyT9R7zTQaLTBv4MkNjYlCbE/8yh
72+
2EJ36/yplHE=
73+
-----END CERTIFICATE-----

Lib/test/keycert4.pem

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK5UQiMI5VkNs2Qv
3+
L7gUaiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2
4+
NkX0ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1
5+
L2OQhEx1GM6RydHdgX69G64LXcY5AgMBAAECgYAhsRMfJkb9ERLMl/oG/5sLQu9L
6+
pWDKt6+ZwdxzlZbggQ85CMYshjLKIod2DLL/sLf2x1PRXyRG131M1E3k8zkkz6de
7+
R1uDrIN/x91iuYzfLQZGh8bMY7Yjd2eoroa6R/7DjpElGejLxOAaDWO0ST2IFQy9
8+
myTGS2jSM97wcXfsSQJBANP3jelJoS5X6BRjTSneY21wcocxVuQh8pXpErALVNsT
9+
drrFTeaBuZp7KvbtnIM5g2WRNvaxLZlAY/hXPJvi6ncCQQDSix1cebml6EmPlEZS
10+
Mm8gwI2F9ufUunwJmBJcz826Do0ZNGByWDAM/JQZH4FX4GfAFNuj8PUb+GQfadkx
11+
i1DPAkEA0lVsNHojvuDsIo8HGuzarNZQT2beWjJ1jdxh9t7HrTx7LIps6rb/fhOK
12+
Zs0R6gVAJaEbcWAPZ2tFyECInAdnsQJAUjaeXXjuxFkjOFym5PvqpvhpivEx78Bu
13+
JPTr3rAKXmfGMxxfuOa0xK1wSyshP6ZR/RBn/+lcXPKubhHQDOegwwJAJF1DBQnN
14+
+/tLmOPULtDwfP4Zixn+/8GmGOahFoRcu6VIGHmRilJTn6MOButw7Glv2YdeC6l/
15+
e83Gq6ffLVfKNQ==
16+
-----END PRIVATE KEY-----
17+
Certificate:
18+
Data:
19+
Version: 1 (0x0)
20+
Serial Number: 12723342612721443282 (0xb09264b1f2da21d2)
21+
Signature Algorithm: sha1WithRSAEncryption
22+
Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server
23+
Validity
24+
Not Before: Jan 4 19:47:07 2013 GMT
25+
Not After : Nov 13 19:47:07 2022 GMT
26+
Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=fakehostname
27+
Subject Public Key Info:
28+
Public Key Algorithm: rsaEncryption
29+
Public-Key: (1024 bit)
30+
Modulus:
31+
00:ae:54:42:23:08:e5:59:0d:b3:64:2f:2f:b8:14:
32+
6a:20:dd:15:eb:cd:51:74:63:53:80:c7:01:ed:d9:
33+
cf:36:0b:64:d1:3a:f6:1f:60:3b:d5:42:49:2d:7a:
34+
b4:9e:5f:4f:95:44:bb:41:19:c8:6a:f4:7b:75:76:
35+
36:45:f4:66:85:34:1d:cf:d4:69:8e:2a:c7:b2:c7:
36+
9a:7e:52:61:9a:48:c6:12:67:91:fe:d2:c8:72:4a:
37+
d7:35:1a:1a:55:34:fc:bc:58:a8:8b:86:0a:d1:79:
38+
76:ac:75:2f:63:90:84:4c:75:18:ce:91:c9:d1:dd:
39+
81:7e:bd:1b:ae:0b:5d:c6:39
40+
Exponent: 65537 (0x10001)
41+
Signature Algorithm: sha1WithRSAEncryption
42+
ad:45:8a:8e:ef:c6:ef:04:41:5c:2c:4a:84:dc:02:76:0c:d0:
43+
66:0f:f0:16:04:58:4d:fd:68:b7:b8:d3:a8:41:a5:5c:3c:6f:
44+
65:3c:d1:f8:ce:43:35:e7:41:5f:53:3d:c9:2c:c3:7d:fc:56:
45+
4a:fa:47:77:38:9d:bb:97:28:0a:3b:91:19:7f:bc:74:ae:15:
46+
6b:bd:20:36:67:45:a5:1e:79:d7:75:e6:89:5c:6d:54:84:d1:
47+
95:d7:a7:b4:33:3c:af:37:c4:79:8f:5e:75:dc:75:c2:18:fb:
48+
61:6f:2d:dc:38:65:5b:ba:67:28:d0:88:d7:8d:b9:23:5a:8e:
49+
e8:c6:bb:db:ce:d5:b8:41:2a:ce:93:08:b6:95:ad:34:20:18:
50+
d5:3b:37:52:74:50:0b:07:2c:b0:6d:a4:4c:7b:f4:e0:fd:d1:
51+
af:17:aa:20:cd:62:e3:f0:9d:37:69:db:41:bd:d4:1c:fb:53:
52+
20:da:88:9d:76:26:67:ce:01:90:a7:80:1d:a9:5b:39:73:68:
53+
54:0a:d1:2a:03:1b:8f:3c:43:5d:5d:c4:51:f1:a7:e7:11:da:
54+
31:2c:49:06:af:04:f4:b8:3c:99:c4:20:b9:06:36:a2:00:92:
55+
61:1d:0c:6d:24:05:e2:82:e1:47:db:a0:5f:ba:b9:fb:ba:fa:
56+
49:12:1e:ce
57+
-----BEGIN CERTIFICATE-----
58+
MIICpzCCAY8CCQCwkmSx8toh0jANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY
59+
WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV
60+
BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3
61+
WjBiMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV
62+
BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRUwEwYDVQQDEwxmYWtlaG9z
63+
dG5hbWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK5UQiMI5VkNs2QvL7gU
64+
aiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2NkX0
65+
ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1L2OQ
66+
hEx1GM6RydHdgX69G64LXcY5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAK1Fio7v
67+
xu8EQVwsSoTcAnYM0GYP8BYEWE39aLe406hBpVw8b2U80fjOQzXnQV9TPcksw338
68+
Vkr6R3c4nbuXKAo7kRl/vHSuFWu9IDZnRaUeedd15olcbVSE0ZXXp7QzPK83xHmP
69+
XnXcdcIY+2FvLdw4ZVu6ZyjQiNeNuSNajujGu9vO1bhBKs6TCLaVrTQgGNU7N1J0
70+
UAsHLLBtpEx79OD90a8XqiDNYuPwnTdp20G91Bz7UyDaiJ12JmfOAZCngB2pWzlz
71+
aFQK0SoDG488Q11dxFHxp+cR2jEsSQavBPS4PJnEILkGNqIAkmEdDG0kBeKC4Ufb
72+
oF+6ufu6+kkSHs4=
73+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)