Skip to content

Commit

Permalink
Small cleanups, some test infrastructure, and a first passing test
Browse files Browse the repository at this point in the history
  • Loading branch information
njsmith committed Apr 10, 2017
1 parent 8eb9651 commit 383db08
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 18 deletions.
51 changes: 33 additions & 18 deletions trio/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,46 @@
from . import _streams
from . import _sync

from ssl import (
SSLError, SSLZeroReturnError, SSLSyscallError, SSLEOFError,
CertificateError, create_default_context, match_hostname,
cert_time_to_seconds, DER_cert_to_PEM_cert, PEM_cert_to_DER_cert,
get_default_verify_paths, enum_certificates, enum_crls, VerifyMode,
VerifyFlags, Options, AlertDescription, SSLErrorNumber, SSLContext,
Purpose,
)
try:
# 3.6+ only:
from ssl import SSLSession
except ImportError:
pass
__all__ = ["SSLStream"]

def _reexport(name):
globals()[name] = getattr(_stdlib_socket, name)
globals()[name] = getattr(_stdlib_ssl, name)
__all__.append(name)

for _name in [
"SSLError", "SSLZeroReturnError", "SSLSyscallError", "SSLEOFError",
"CertificateError", "create_default_context", "match_hostname",
"cert_time_to_seconds", "DER_cert_to_PEM_cert", "PEM_cert_to_DER_cert",
"get_default_verify_paths", "SSLContext", "Purpose",
]:
_reexport(_name)


# Windows only
try:
for _name in ["enum_certificates", "enum_crls"]:
_reexport(_name)
except AttributeError:
pass

try:
# 3.6+ only:
for _name in [
"SSLSession", "VerifyMode", "VerifyFlags", "Options",
"AlertDescription", "SSLErrorNumber",
]:
_reexport(_name)
except AttributeError:
pass

for _name in _stdlib_ssl.__dict__.keys():
if _name == _name.upper():
_reexport(_name)

# XX add suppress_ragged_eofs option?
# or maybe actually make an option that means "I want the variant of the
# protocol that doesn't do EOFs", so it ignores lack from the other side and
# also doesn't send them.

class SSLStream(_streams.Stream):
def __init__(
Expand Down Expand Up @@ -89,9 +106,7 @@ def __setattr__(self, name, value):
def __dir__(self):
return super().__dir__() + list(self._forwarded)

@property
def can_send_eof(self):
return False
can_send_eof = False

async def send_eof(self):
raise RuntimeError("the TLS protocol does not support send_eof")
Expand Down Expand Up @@ -180,6 +195,6 @@ async def graceful_close(self):
try:
await self.unwrap()
await self.wrapped_stream.graceful_close()
except _core.Cancelled:
except:
self.forceful_close()
raise
50 changes: 50 additions & 0 deletions trio/tests/test_ssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pytest

from pathlib import Path
import threading
import socket as stdlib_socket
import ssl as stdlib_ssl

from .. import _core
from .. import ssl as tssl
from .. import socket as tsocket

from ..testing import assert_yields, wait_all_tasks_blocked


_cert_dir = Path(__file__).parent / "test_ssl_certs"
CA = str(_cert_dir / "trio-test-CA.pem")
CERT1 = str(_cert_dir / "trio-test-1.pem")
CERT2 = str(_cert_dir / "trio-test-2.pem")


def ssl_echo_server(sock, ctx):
wrapped = ctx.wrap_socket(sock, server_side=True)
while True:
data = wrapped.recv(1024)
if not data:
# graceful shutdown
wrapped.unwrap()
return
wrapped.sendall(data)


async def test_ssl_simple():
a, b = stdlib_socket.socketpair()
with a, b:
a = tsocket.from_stdlib_socket(a)
server_ctx = stdlib_ssl.create_default_context(
stdlib_ssl.Purpose.CLIENT_AUTH,
)
server_ctx.load_cert_chain(CERT1)
t = threading.Thread(target=ssl_echo_server, args=(b, server_ctx))
t.start()

client_ctx = stdlib_ssl.create_default_context(cafile=CA)
s = tssl.SSLStream(
a, client_ctx, server_hostname="trio-test-1.example.org")
await s.sendall(b"x")
assert await s.recv(10) == b"x"

await s.graceful_close()
t.join()
53 changes: 53 additions & 0 deletions trio/tests/test_ssl_certs/make-test-certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash

# This file generates 3 .pem files that we use in the test suite.
#
# trio-test-CA.pem contains the public key for a root CA certificate.
#
# trio-test-{1,2}.pem contain, concatenated in order:
# - a private key
# - a certificate signed by our CA claiming that this is the key for the host
# "trio-test-$N.example.org"
# - the root CA certificate again (to complete the cert chain)
#
# End result is that if you do
#
# ssl.create_default_context(cafile="trio-test-CA.pem")
#
# then your SSLContext will trust the trio-test-{1,2} certificates.
#
# And if you do
#
# sslcontext.load_cert_chain("trio-test-1.pem")
#
# then you can claim to be trio-test-1.example.org.

set -uxe -o pipefail

# Generate a self-signed 2048-bit RSA key as our signing root
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 99999 \
-subj '/O=Trio test CA' \
-keyout trio-test-CA.key -out trio-test-CA.pem

for CERT in 1 2; do
# Create a key and CSR.
#
# Our tests only use one name, so CN= is enough. (Otherwise we would need
# to use subjectAltNames=, which *replaces* CN=.)
openssl req -new -newkey rsa:2048 -nodes -sha256 \
-subj "/CN=trio-test-${CERT}.example.org" \
-keyout trio-test-${CERT}.key -out trio-test-${CERT}.csr
# Use the CSR and CA to sign the key, generating a certificate
openssl x509 -req -in trio-test-${CERT}.csr -sha256 -days 99999 \
-CA trio-test-CA.pem -CAkey trio-test-CA.key \
-set_serial ${CERT} \
-out trio-test-${CERT}.crt
# Combine key/cert/root-CA into a single file for convenience
# (see https://docs.python.org/3/library/ssl.html#ssl-certificates)
cat trio-test-${CERT}.key trio-test-${CERT}.crt trio-test-CA.pem \
> trio-test-${CERT}.pem
rm -f trio-test-${CERT}.{csr,key,crt}
done

# We don't need the signing key anymore, remove it to reduce clutter
rm -f trio-test-CA.key
64 changes: 64 additions & 0 deletions trio/tests/test_ssl_certs/trio-test-1.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDZ8yz1OrHX7aHp
Erfa1ds8kmYfqYomjgy5wDsGdb8i1gF4uxhHCRDQtNZANVOVXI7R3TMchA1GMxzA
ZYDuBDuEUsqTktbTEBNb4GjOhyMu1fF4dX/tMxf7GB+flTx178eE2exTOZLmSmBa
2laoDVe3CrBAYE7nZtBF630jKKKMsUuIl0CbFRHajpoqM3e3CeCo4KcbBzgujRA3
AsVV6y5qhMH2zqLkOYaurVUfEkdjqoHFgj1VbjWpkTbrXAxPwW6v/uZK056bHgBg
go03RyWexaPapsF2oUm2JNdSN3z7MP0umKphO2n9icyGt9Bmkm2AKs3dA45VLPXh
+NohluqJAgMBAAECggEARlfWCtAG1ko8F52S+W5MdCBMFawCiq8OLGV+p3cZWYT4
tJ6uFz81ziaPf+m2MF7POazK8kksf5u/i9k245s6GlseRsL90uE9XknvibjUAinK
5bYGs+fptYDzs+3WtbnOC3LKc5IBd5JJxwjxLwwfY1RvzldHIChu0CJRISfcTsvR
occ8hXdeft7svNymvTuwQd05u1yjzL4RwF8Be76i17j5+jDsrAaUKdxxwGNAyOU7
OKrUY6G851T6NUGgC19iXAJ1wN9tVGIR5QOs3J/s6dCctnX5tN8Di7prkXCKvVlm
vhpC8XWWG+c3LhS90wmEBvKS0AfUeoPDHxMOLyzKgQKBgQD07lZRO0nsc38+PVaI
NrvlP90Q8OgbwMIC52jmSZK3b5YSh3TrllsbCg6hzUk1SAJsa3qi7B1vq36Fd+rG
LGDRW9xY0cfShLhzqvZWi45zU/RYnEcWHOuXQshLikx1DWUpg2KbLSVT2/lyvzmn
QgM1Te8CSxW5vrBRVfluXoJuEwKBgQDjzLAbwk/wdjITKlQtirtsJEzWi3LGuUrg
Z2kMz+0ztUU5d1oFL9B5xh0CwK8bpK9kYnoVZSy/r5+mGHqyz1eKaDdAXIR13nC0
g7aZbTZzbt2btvuNZc3NCzRffHF3sCqp8a+oCryHyITjZcA+WYeU8nG0TQ5O8Zgr
Skbo1JGocwKBgQC4jCx1oFqe0pd5afYdREBnB6ul7B63apHEZmBfw+fMV0OYSoAK
Uovq37UOrQMQJmXNE16gC5BSZ8E5B5XaI+3/UVvBgK8zK9VfMd3Sb+yxcPyXF4lo
W/oXSrZoVJgvShyDHv/ZNDb/7KsTjon+QHryWvpPnAuOnON1JXZ/dq6ICQKBgCZF
AukG8esR0EPL/qxP/ECksIvyjWu5QU0F0m4mmFDxiRmoZWUtrTZoBAOsXz6johuZ
N61Ue/oQBSAgSKy1jJ1h+LZFVLOAlSqeXhTUditaWryINyaADdz+nuPTwjQ7Uk+O
nNX8R8P/+eNB+tP+snphaJzDvT2h9NCA//ypiXblAoGAJoLmotPI+P3KIRVzESL0
DAsVmeijtXE3H+R4nwqUDQbBbFKx0/u2pbON+D5C9llaGiuUp9H+awtwQRYhToeX
CNguwWrcpuhFOCeXDHDWF/0NIZYD2wBMxjF/eUarvoLaT4Gi0yyWh5ExIKOW4bFk
EojUPSJ3gomOUp5bIFcSmSU=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICrzCCAZcCAQEwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UECgwMVHJpbyB0ZXN0
IENBMCAXDTE3MDQwOTEwMDcyMVoYDzIyOTEwMTIyMTAwNzIxWjAiMSAwHgYDVQQD
DBd0cmlvLXRlc3QtMS5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBANnzLPU6sdftoekSt9rV2zySZh+piiaODLnAOwZ1vyLWAXi7GEcJ
ENC01kA1U5VcjtHdMxyEDUYzHMBlgO4EO4RSypOS1tMQE1vgaM6HIy7V8Xh1f+0z
F/sYH5+VPHXvx4TZ7FM5kuZKYFraVqgNV7cKsEBgTudm0EXrfSMoooyxS4iXQJsV
EdqOmiozd7cJ4KjgpxsHOC6NEDcCxVXrLmqEwfbOouQ5hq6tVR8SR2OqgcWCPVVu
NamRNutcDE/Bbq/+5krTnpseAGCCjTdHJZ7Fo9qmwXahSbYk11I3fPsw/S6YqmE7
af2JzIa30GaSbYAqzd0DjlUs9eH42iGW6okCAwEAATANBgkqhkiG9w0BAQsFAAOC
AQEAlRNA96H88lVnzlpQUYt0pwpoy7B3/CDe8Uvl41thKEfTjb+SIo95F4l+fi+l
jISWSonAYXRMNqymPMXl2ir0NigxfvvrcjggER3khASIs0l1ICwTNTv2a40NnFY6
ZjTaBeSZ/lAi7191AkENDYvMl3aGhb6kALVIbos4/5LvJYF/UXvQfrjriLWZq/I3
WkvduU9oSi0EA4Jt9aAhblsgDHMBL0+LU8Nl1tgzy2/NePcJWjzBRQDlF8uxCQ+2
LesZongKQ+lebS4eYbNs0s810h8hrOEcn7VWn7FfxZRkjeaKIst2FCHmdr5JJgxj
8fw+s7l2UkrNURAJ4IRNQvPB+w==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAe6gAwIBAgIJAIUF+wna+nuzMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
BAoMDFRyaW8gdGVzdCBDQTAgFw0xNzA0MDkxMDA3MjFaGA8yMjkxMDEyMjEwMDcy
MVowFzEVMBMGA1UECgwMVHJpbyB0ZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAyhE82Cbq+2c2f9M+vj2f9v+z+0+bMZDUVPSXhBDiRdKubt+K
f9vY+ZH3ze1sm0iNgO6xU3OsDTlzO5z0TpsvEEbs0wgsJDUXD7Y8Fb1zH2jaVCro
Y6KcVfFZvD96zsVCnZy0vMsYJw20iIL0RNCtr17lXWVxd17OoVy91djFD9v/cixu
LRIr+N7pa8BDLUQUO/g0ui9YSC9Wgf67mr93KXKPGwjTHBGdjeZeex198j5aZjZR
lkPH/9g5d3hP7EI0EAIMDVd4dvwNJgZzv+AZINbKLAkQyE9AAm+xQ7qBSvdfAvKq
N/fwaFevmyrxUBcfoQxSpds8njWDb3dQzCn7ywIDAQABo1MwUTAdBgNVHQ4EFgQU
JiilveozF8Qpyy2fS3wV4foVRCswHwYDVR0jBBgwFoAUJiilveozF8Qpyy2fS3wV
4foVRCswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkcthPjkJ
+npvMKyQtUx7CSVcT4Ar0jHrvfPSg17ipyLv+MhSTIbS2VwhSYXxNmu+oBWKuYUs
BnNxly3+SOcs+dTP3GBMng91SBsz5hhbP4ws8uUtCvYJauzeHbeY67R14RT8Ws/b
mP6HDiybN7zy6LOKGCiz+sCoJqVZG/yBYO87iQsTTyNttgoG27yUSvzP07EQwUa5
F9dI9Wn+4b5wP2ofMCu3asTbKXjfFbz3w5OkRgpGYhC4jhDdOw/819+01R9//GrM
54Gme03yDAAM7nGihr1Xtld3dp2gLuqv0WgxKBqvG5X+nCbr2WamscAP5qz149vo
y6Hq6P4mm2GmZw==
-----END CERTIFICATE-----
64 changes: 64 additions & 0 deletions trio/tests/test_ssl_certs/trio-test-2.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+BbLK+Pp0Qvbh
jQKmI/2R1YD3hTn1ppS6XMO/k2En/kU7wxjW48nl5vvwdmeII76Kd/I625DgyJLk
ihVltPggBnk5zHps1E4Drz65gp12tgfGJhX/QF5sx+Uza7WJvUmkySEDPXbpwWsd
fXcwuy8QmS6vXAlGske6pCqilQJqpvJXoO9Z7RPtS32WG2x5FYc7hHxDw6Fwo0ZE
1mZ4aXKMrwjr5SnqEq+5m8qs37aCK5unBFV63vcPBb/qyy3ouKYOMB1qV7biMQHe
u25psNtDW/9xdbQ8IUeHrH+cTarofRQ2yJeizOxbUuphx1IhwKU7EDEc+C4ERy4F
AwHlPro/AgMBAAECggEBAKhYig7SR6jqjqhCcf9Y0VP679fZ+wBLxWXZuz4lRqTU
2udYL9BpXDxGyBs/+vccm7k3DK3iSdcrOyAnyU8i5dQRiCKRqkByUm9nOU3GjtRV
7ks5ALHzh/QdoExO9zUBMpY/7fRd5tSvG8OznP3aR5cP7tFC26D7XxrWSENjehGb
MMrvzTV45DKlrDQ59c5+MzNZABxWK4wlX7plzHEzObfWewZsJp9dhHxVRL0Qd3e4
pJ1ciIY6AcL2DQogPpVCr3Z9HBgBSMAvmq53EWXliFVEeySHk0trE1YUVuT3Od36
aDcMjUofDNnH9dTAOcdfuphNW1YvaBd21lFZR8Qr1ckCgYEA5yUNFmzwMWip6CxQ
rA+UyNBfAakz6F5WrMAqFPw90ir5HlAlC1C14FXevb+TIRZioXbwkQvwZMJpapcq
ER0Om/qn3MoizJ53Q4nG4yq1FEd1G7se+6C4LVLSclweHMjtgH5sodr4SzMqsZTA
T9cQA+SMfdR00y0Hwi4pjMY0/zUCgYEA0nSg45X7RKQ4DRiH0OnhPnQfX+ei+m1Q
OFvuIUwhNUCMaMSb/Z7ne660O1u5vkMgtG0WB5udyphy8K2Xrr2ldZ+oN1yWEmmJ
c1l1RjUmwbhoSaAdCpPlThIXZp969hccmB5UrviSgot6hT5i82P8yiql4ba0FWfv
O56yOo6NPiMCgYAe3iPRStsIviFyj/h2Ad6ssqb9Ycs8zNxmVYNJKiZXWsXJ9on7
6NthChak4GCVmpexWGDn/eAslInfYjCL+IVq7x5breLX0JG8wzl8PMfR3XkWKvcI
Q35VDypre0HKNksBTeDT/JoL8NlSvbqw7teErZDVfPnc+bZ/iAqkchPBwQKBgCqc
/u7WMZiGf+r26pk8oiUZMjkjF/cJJ1MiGieX2KmFtmiIVuWVxV1f1JKoUgXaZcbi
x7Emq16YW72sCKiTMeuNNmxvTNvRjslSddKPdJeJFWTDDN5Vb/rM4vwekrE9oMaU
baU4I8JXJ6nPJg4OUuNEm24GppQnBWPXEFOXBbZtAoGBAIz4c0MynYfYoXdt/PPv
ILRJt4JEIkuEeCnT4VSLQUIivysKTP/2sXfNDpwBNarTvnQMG0Uo2h0AAhGYRO7F
2u7//As6CQZES8dPiEw+CBPxDvpqK1MKLOwBy3UXO2XWdfjNzNylh627dD69a+qo
xqzEiNrm5s+7WF+O//UyqTk8
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICrzCCAZcCAQIwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UECgwMVHJpbyB0ZXN0
IENBMCAXDTE3MDQwOTEwMDcyMVoYDzIyOTEwMTIyMTAwNzIxWjAiMSAwHgYDVQQD
DBd0cmlvLXRlc3QtMi5leGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAL4Fssr4+nRC9uGNAqYj/ZHVgPeFOfWmlLpcw7+TYSf+RTvDGNbj
yeXm+/B2Z4gjvop38jrbkODIkuSKFWW0+CAGeTnMemzUTgOvPrmCnXa2B8YmFf9A
XmzH5TNrtYm9SaTJIQM9dunBax19dzC7LxCZLq9cCUayR7qkKqKVAmqm8leg71nt
E+1LfZYbbHkVhzuEfEPDoXCjRkTWZnhpcoyvCOvlKeoSr7mbyqzftoIrm6cEVXre
9w8Fv+rLLei4pg4wHWpXtuIxAd67bmmw20Nb/3F1tDwhR4esf5xNquh9FDbIl6LM
7FtS6mHHUiHApTsQMRz4LgRHLgUDAeU+uj8CAwEAATANBgkqhkiG9w0BAQsFAAOC
AQEAqAaGJLCmhzuEDFxFsluiowV8AmI/U7PAxtjU/I3C1q3qsmz4AkW1RWde3iYv
wN6tTGOv2Ygy98sp0kaHzyUM5i1VOEInuRjkCAu8H9klAfwIcXZ5IAnGvthdrONO
vq21Kh3ylaW7u/gqfbJtu4PjsTBu0RBjFL4kxq3+IjF/Qo1HuT3FhyqEYC4It93g
G9kma3omUKATFe4gDUMzxQP+DCC0//5BnYvalzH+hzo5h8rAd53KA0a1CmnhS+jE
rDu5o7uYZ3cDikG0ukxkAIc9Is2jb7GU9Hq/2ct0722t4yqnSzrByoY8lDWq4+x4
gQCn+qIhwjffxZaeNbcpBjTMtw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAe6gAwIBAgIJAIUF+wna+nuzMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
BAoMDFRyaW8gdGVzdCBDQTAgFw0xNzA0MDkxMDA3MjFaGA8yMjkxMDEyMjEwMDcy
MVowFzEVMBMGA1UECgwMVHJpbyB0ZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAyhE82Cbq+2c2f9M+vj2f9v+z+0+bMZDUVPSXhBDiRdKubt+K
f9vY+ZH3ze1sm0iNgO6xU3OsDTlzO5z0TpsvEEbs0wgsJDUXD7Y8Fb1zH2jaVCro
Y6KcVfFZvD96zsVCnZy0vMsYJw20iIL0RNCtr17lXWVxd17OoVy91djFD9v/cixu
LRIr+N7pa8BDLUQUO/g0ui9YSC9Wgf67mr93KXKPGwjTHBGdjeZeex198j5aZjZR
lkPH/9g5d3hP7EI0EAIMDVd4dvwNJgZzv+AZINbKLAkQyE9AAm+xQ7qBSvdfAvKq
N/fwaFevmyrxUBcfoQxSpds8njWDb3dQzCn7ywIDAQABo1MwUTAdBgNVHQ4EFgQU
JiilveozF8Qpyy2fS3wV4foVRCswHwYDVR0jBBgwFoAUJiilveozF8Qpyy2fS3wV
4foVRCswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkcthPjkJ
+npvMKyQtUx7CSVcT4Ar0jHrvfPSg17ipyLv+MhSTIbS2VwhSYXxNmu+oBWKuYUs
BnNxly3+SOcs+dTP3GBMng91SBsz5hhbP4ws8uUtCvYJauzeHbeY67R14RT8Ws/b
mP6HDiybN7zy6LOKGCiz+sCoJqVZG/yBYO87iQsTTyNttgoG27yUSvzP07EQwUa5
F9dI9Wn+4b5wP2ofMCu3asTbKXjfFbz3w5OkRgpGYhC4jhDdOw/819+01R9//GrM
54Gme03yDAAM7nGihr1Xtld3dp2gLuqv0WgxKBqvG5X+nCbr2WamscAP5qz149vo
y6Hq6P4mm2GmZw==
-----END CERTIFICATE-----
19 changes: 19 additions & 0 deletions trio/tests/test_ssl_certs/trio-test-CA.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDBjCCAe6gAwIBAgIJAIUF+wna+nuzMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV
BAoMDFRyaW8gdGVzdCBDQTAgFw0xNzA0MDkxMDA3MjFaGA8yMjkxMDEyMjEwMDcy
MVowFzEVMBMGA1UECgwMVHJpbyB0ZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAyhE82Cbq+2c2f9M+vj2f9v+z+0+bMZDUVPSXhBDiRdKubt+K
f9vY+ZH3ze1sm0iNgO6xU3OsDTlzO5z0TpsvEEbs0wgsJDUXD7Y8Fb1zH2jaVCro
Y6KcVfFZvD96zsVCnZy0vMsYJw20iIL0RNCtr17lXWVxd17OoVy91djFD9v/cixu
LRIr+N7pa8BDLUQUO/g0ui9YSC9Wgf67mr93KXKPGwjTHBGdjeZeex198j5aZjZR
lkPH/9g5d3hP7EI0EAIMDVd4dvwNJgZzv+AZINbKLAkQyE9AAm+xQ7qBSvdfAvKq
N/fwaFevmyrxUBcfoQxSpds8njWDb3dQzCn7ywIDAQABo1MwUTAdBgNVHQ4EFgQU
JiilveozF8Qpyy2fS3wV4foVRCswHwYDVR0jBBgwFoAUJiilveozF8Qpyy2fS3wV
4foVRCswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkcthPjkJ
+npvMKyQtUx7CSVcT4Ar0jHrvfPSg17ipyLv+MhSTIbS2VwhSYXxNmu+oBWKuYUs
BnNxly3+SOcs+dTP3GBMng91SBsz5hhbP4ws8uUtCvYJauzeHbeY67R14RT8Ws/b
mP6HDiybN7zy6LOKGCiz+sCoJqVZG/yBYO87iQsTTyNttgoG27yUSvzP07EQwUa5
F9dI9Wn+4b5wP2ofMCu3asTbKXjfFbz3w5OkRgpGYhC4jhDdOw/819+01R9//GrM
54Gme03yDAAM7nGihr1Xtld3dp2gLuqv0WgxKBqvG5X+nCbr2WamscAP5qz149vo
y6Hq6P4mm2GmZw==
-----END CERTIFICATE-----

0 comments on commit 383db08

Please sign in to comment.