Commit 8cc949e5 authored by Julien Puydt's avatar Julien Puydt

Update upstream source from tag 'upstream/6.5.0+ds'

Update to upstream version '6.5.0+ds'
with Debian dir a86984ba80d608caafce9d871c97561426cbf3dd
parents 67029dbf a24c6d23
ref-names: tag: v6.4.0
ref-names: HEAD -> master, tag: v6.5.0
......@@ -28,7 +28,7 @@ repos:
- id: check-symlinks
- id: check-yaml
- id: detect-private-key
exclude: cheroot/test/test.pem
exclude: cheroot/test/(test.pem|ssl/*)
- id: requirements-txt-fixer
- repo: git://github.com/chewse/pre-commit-mirrors-pydocstyle
......
......@@ -54,7 +54,7 @@ _base_envs:
language: generic
before_install:
- brew install zlib readline
- brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/cac0ae5/Formula/pyenv.rb || brew upgrade pyenv
- brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/pyenv.rb || brew upgrade pyenv
- &ensure_pyenv_preloaded |
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
......
v6.5.0
======
- :cp-issue:`1001` via :pr:`52` and :pr:`108`: Add support for
validating client certificates.
v6.4.0
======
......
......@@ -67,6 +67,21 @@ class BuiltinSSLAdapter(Adapter):
ciphers = None
"""The ciphers list of SSL."""
CERT_KEY_TO_ENV = {
'subject': 'SSL_CLIENT_S_DN',
'issuer': 'SSL_CLIENT_I_DN'
}
CERT_KEY_TO_LDAP_CODE = {
'countryName': 'C',
'stateOrProvinceName': 'ST',
'localityName': 'L',
'organizationName': 'O',
'organizationalUnitName': 'OU',
'commonName': 'CN',
'emailAddress': 'Email',
}
def __init__(
self, certificate, private_key, certificate_chain=None,
ciphers=None):
......@@ -155,8 +170,34 @@ class BuiltinSSLAdapter(Adapter):
# SSL_VERSION_INTERFACE string The mod_ssl program version
# SSL_VERSION_LIBRARY string The OpenSSL program version
}
if self.context and self.context.verify_mode != ssl.CERT_NONE:
client_cert = sock.getpeercert()
if client_cert:
for cert_key, env_var in self.CERT_KEY_TO_ENV.items():
ssl_environ.update(
self.env_dn_dict(env_var, client_cert.get(cert_key)))
return ssl_environ
def env_dn_dict(self, env_prefix, cert_value):
"""Return a dict of WSGI environment variables for a client cert DN.
E.g. SSL_CLIENT_S_DN_CN, SSL_CLIENT_S_DN_C, etc.
See SSL_CLIENT_S_DN_x509 at
https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#envvars.
"""
if not cert_value:
return {}
env = {}
for rdn in cert_value:
for attr_name, val in rdn:
attr_code = self.CERT_KEY_TO_LDAP_CODE.get(attr_name)
if attr_code:
env['%s_%s' % (env_prefix, attr_code)] = val
return env
def makefile(self, sock, mode='r', bufsize=DEFAULT_BUFFER_SIZE):
"""Return socket file object."""
return MakeFile(sock, mode, bufsize)
-----BEGIN CERTIFICATE-----
MIIFlzCCA3+gAwIBAgIJAPYshx+wivLoMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJYWDEMMAoGA1UEBxMDWFhYMREwDwYDVQQKEwhDaGVy
cnlQeTAeFw0xMDEwMDQxOTAxNDJaFw0yMDEwMDExOTAxNDJaMDsxCzAJBgNVBAYT
AlVTMQswCQYDVQQIEwJYWDEMMAoGA1UEBxMDWFhYMREwDwYDVQQKEwhDaGVycnlQ
eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKzWr8dvyn1Nsq2xRFpM
+Ockg99V0/OAD6SrzrI9Uf//BcSotbooDyvUJ1Z2iW9wOfIj5MQ0juNpu4AlfyTa
cPZPDrbf/wJkjWj+2UIrImZOrWVmtsRb+OJi2cH1yjibvMfn8BTxhW9P03jUb1O7
V6Lnnp1XktJM9vZWLhtoKDwIYNzsG/S1WUX4OfBu/QofrPTeBBCFV7Q/6V3FCa9P
aBijXhuzlt3D9YMxiL4Uu18Mk/KgzReOBCDrTftatbZpdHnB0s9Oq3ZwuF1SbcT0
lAw2MLguuA1j8RmaaqmoNNogsiyQpXY06ef3Skom86mkiXmOIgyX6IQ/BXhFoH4i
96vv3SptD43g6TFMjvWEBlJIWDBNCxGNnCbHNj70MCLJ1KeW0KUUc6WTxB2ADYif
Ifpo1UR2g0KQjHhLhdWDU4aCqj3S/n23Ho7Q4cD36VPdoknMaDJs+7UDJ4B9b+eZ
L0IYcLhqtSHPVdxxYejS1GLNXWizcwmJV3z1tA+1g0jTRA70Ee6SdMOxlnEf4ACT
IdwcC8xQWh0j4rgqT4Z1EYmP+iukjh029Ge4rASaBkbyRJ1ALESdxr5nAryq8wxj
/XVwgOMU5O4zuANggvq8GGAyrixcPJB+f8AYhdHp0yjKuUNJ2YbH1G3Dlg8hqyNA
uNc88jG8nc1EKd8/OHQnabZVAgMBAAGjgZ0wgZowHQYDVR0OBBYEFDYQnybvD5dR
D8rLKlXPZifiWPEYMGsGA1UdIwRkMGKAFDYQnybvD5dRD8rLKlXPZifiWPEYoT+k
PTA7MQswCQYDVQQGEwJVUzELMAkGA1UECBMCWFgxDDAKBgNVBAcTA1hYWDERMA8G
A1UEChMIQ2hlcnJ5UHmCCQD2LIcfsIry6DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
DQEBBQUAA4ICAQCSlMKC7WUxee3QvXNPW08Q86IzcwAZqKNZy2+ZyqUPUYzeaFW8
exTDELv8yMj0C5VjprmdIrhsMKXZSA8D8/JuUZgHUruLLXn/Dc4HRFa79cVxW9yx
YM6weTgdNnBBtdi+Qz3Sc9UiIOlr5YzoZq2qTZw2u8ogLx9iPPrbg8Qiurx8WJse
rzb1iqoqSLV/RpaktKNkgQpqao4TrDkxjgtuiKyMj7DKRgTz2sWwKdpPtXLCYIz2
Xc/jxjj1xFHbKMCHxdjgYCrGUzHBUV8LhyNrii573L1Bxedi/7Jdr2IMkiEWuyus
QthB+CGwCGUzm/nh/AVsnG2YNCRraiK1FWuq1FawudYM0eoozWIdk0lU9IR1jgNi
y8LCQD/8d3E8EJ/dkP8o4mvmOeYko7QTb7gCNdT06YierNTi8DCZ31iggQfxOH0P
eW1siKumG1wztEoPan/nbTsJchhqpfY6qN2YikH/6cQGR0b9tDJZe/BF7mdRXq8d
vF4HIIOAn6xCK1/TdUbmCp6MaUYdWHM4MoAWbf592j9oER/EIc603DYjdDBTUVO3
pYPbVg1SWINvKzTTEFFXtOvJNt5dFxFlARMcUR034Au62EMOTvC3/7bQcy0nEPTV
G50UvRgwvNrr3D2el/jurDaHdJBQ90qUnAnI56uW7puyKvMPFXS1q2bsvQ==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIE8DCCAtgCAQMwDQYJKoZIhvcNAQEFBQAwOzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAlhYMQwwCgYDVQQHEwNYWFgxETAPBgNVBAoTCENoZXJyeVB5MB4XDTEwMTAw
NTE2NDkwNVoXDTIwMTAwMjE2NDkwNVowQTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
AlhYMREwDwYDVQQKEwhDaGVycnlQeTESMBAGA1UEAxMJbG9jYWxob3N0MIICIjAN
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAymPRfUID7S9YAy36CqGg1JEXGYnf
/u6CN/6OnTTLbWjQLzUaVy2gjqqVXXamZv9x4dVv7JLYl4RZ5fX72HGmcIP2tyDW
cRLizmoKlo7Ih8k5Z66u4qFp7ebQrEma0WZvlqKUFrX2ataaJIm51809YJXZXK3G
2gdwJyjPeCK9B8RkCqRTpiSxR38e3iSvpsqkwqqoxNcZAE2z2VV0c+p9HcwEeNN9
3ZQEdYkA4ni6U6tnJ5v17CaJwvF7mVfxydsoHU7qH8lE5R3mBN6BgZMjZtwOWDFw
3grUFBiS9F7NiMxNvnykwr4WTn7fc6hSm/Rvls12ALElIDd5qe9GpnPXJH3OMG87
BHxa0DRuM7e6yw/dpBlMcfzyo1um7xe9DJJnc63hwQdc1agjr5zzkZWkv4I/4j88
gmgKjcEa4PbpmyZ8E8uNsPSO9Vy7csel+A7IwHiiArVfoel6dor34km6KYIN2uq7
P04djTOy+KR0ry+OwCo2vTkjPcd7S5Ta7rVsfGo3wxpxysTCDtBA6lMMd0otIZiE
Hz2Z89sHS6ZebYM2yvLcxvFYp6w8id4ETcRLoITP5+TCUWedZ+tuixygZrcqfQFF
WHlpGTlBO765xvH11rzFKDZSVrXwGpo82qHcFCw0imkXnKSoFUIX+EK97TK4RtBs
kpNSll1e+d7XokECAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAUdqrvx74A1pLYkHp
bhxHMuMEsg1m0eWVLrM9VN2lUTcDPySYmWmeT8ywOZWUCKyDfc7hBhRwyQbfYkoQ
FbgDebvrLQvXvTCWIv5paFq4d05oSiBvvQb0KHmw9gDsDne77dYetUUTupyI1YYV
70bIcZYk27jOSSZa7rFyZvJxO1vc1eBb+w8Wm0i6vWERUDIBI8hcSvGPiWt+/VCB
feGIYiJN6xyYg3/Yi6OgzZLGGiJxhJiHvlA7BkTR7TSlIrskbipBydWeRrU/d9TS
OOwviIlw0hGdBSsOgqzfNal1x8KXIJ87rdn6LwOp1m3k1T1QcgXYp5Xv6dYeJYYJ
/KJ8dOCnh5lRmc/y6dgV3V/U2iT7co8TQjhYANAa+0YhNMflrhbGYfv8TcarWv4v
eE1eUMgKCTAdqQix5e5yXtimOqM+ubsV1Oo64AUdguy1EyDGpQf8py5Ps0YpfQms
S2FMskUuEkYRvZQgvp4jtlYpBfc9yojFrHO320tepwfrD4+T6w6pbhEiR8T5oagu
cARuXtn4fuVFUu49sx4Hs8X1gtLS4HjPAYQveB+ZQuysn8O3JWKz9eBQ/JIVjeh1
2Ggv9gO8PMO175g4ePAZa6uSl39tCOtNBf0YdZCi4XmJn+FzDNec7eLTv7oognCG
VCp+fSm/1V5FLqnelUk1NTMbwYg=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIE8TCCAtkCAgRjMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlVTMQswCQYD
VQQIEwJYWDEMMAoGA1UEBxMDWFhYMREwDwYDVQQKEwhDaGVycnlQeTAeFw0xMDEw
MDgxNjQwMTRaFw0yMDEwMDUxNjQwMTRaMEExCzAJBgNVBAYTAlVTMQswCQYDVQQI
EwJYWDERMA8GA1UEChMIQ2hlcnJ5UHkxEjAQBgNVBAMTCTEyNy4wLjAuMTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMpj0X1CA+0vWAMt+gqhoNSRFxmJ
3/7ugjf+jp00y21o0C81GlctoI6qlV12pmb/ceHVb+yS2JeEWeX1+9hxpnCD9rcg
1nES4s5qCpaOyIfJOWeuruKhae3m0KxJmtFmb5ailBa19mrWmiSJudfNPWCV2Vyt
xtoHcCcoz3givQfEZAqkU6YksUd/Ht4kr6bKpMKqqMTXGQBNs9lVdHPqfR3MBHjT
fd2UBHWJAOJ4ulOrZyeb9ewmicLxe5lX8cnbKB1O6h/JROUd5gTegYGTI2bcDlgx
cN4K1BQYkvRezYjMTb58pMK+Fk5+33OoUpv0b5bNdgCxJSA3eanvRqZz1yR9zjBv
OwR8WtA0bjO3ussP3aQZTHH88qNbpu8XvQySZ3Ot4cEHXNWoI6+c85GVpL+CP+I/
PIJoCo3BGuD26ZsmfBPLjbD0jvVcu3LHpfgOyMB4ogK1X6HpenaK9+JJuimCDdrq
uz9OHY0zsvikdK8vjsAqNr05Iz3He0uU2u61bHxqN8MaccrEwg7QQOpTDHdKLSGY
hB89mfPbB0umXm2DNsry3MbxWKesPIneBE3ES6CEz+fkwlFnnWfrboscoGa3Kn0B
RVh5aRk5QTu+ucbx9da8xSg2Ula18BqaPNqh3BQsNIppF5ykqBVCF/hCve0yuEbQ
bJKTUpZdXvne16JBAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAJpdyMHD7nsrd7dA
r1wDdUg8nXOq0ZJAcheMIakUNhjzymn4XF/o8KhPykuPdHFilOgqAT6CAM//hFDO
tzROsq74wB6ICxerPsuDIppxhbSRuVYbFlr2aUXRUQZIWNAjvTnOfLhAy+i8BVlS
8mEdQrqYLpg1RJhRWT7crSMAex4IIZzSnblFs1yo3Hx97eIgHViTBxGfsSMtvdie
ZOWbKV9ueYkgxN8t8b9qDlhiaaASoFP8f3kktmKtk+8yxBA1jiPA9sYPL5sqvdP0
ZF0ul6mo0I6H01ITkXPF0RlNScHVS+ryouIOaWXe80mHtuGwYiAFADTab0WsmIXm
dRoUFX3yRAc1tJnUJwbHUkZWwI6rU3b6dHmfuaUq06i2MhpdW+awhycCRExKdxCm
jdTzqlYVoJj0ARXIQqV5wS5EZ+T3pFoykV3mvYaqlBbogfyt+LoPoVmPpPzXG/DX
ihxaGAmcvENatdwAfqP9ycZCcXKmfLf7amwyekS6qZ6nUgGeRBQNA34mrIxg/Yij
yzfVhnMJ7Mi7fzLxZrF59N2uIV2y/6oH6eMakJ6kniCexgTh8EoADF4JQqHGvIfX
c/HBoU3BAlXDYuzZVpL6uAhJwDbqyKMqUVvGTfnM65PSoAtjbyre1Tk6WtgcgD+q
ycDjzcNUsA9fv/zBCS1QbYPIrVyh
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE8zCCAtsCAivjMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlVTMQswCQYD
VQQIEwJYWDEMMAoGA1UEBxMDWFhYMREwDwYDVQQKEwhDaGVycnlQeTAeFw0xMDEw
MDgxNjQwMzBaFw0yMDEwMDUxNjQwMzBaMEMxCzAJBgNVBAYTAlVTMQswCQYDVQQI
EwJYWDERMA8GA1UEChMIQ2hlcnJ5UHkxFDASBgNVBAMUCyoubG9jYWxob3N0MIIC
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAymPRfUID7S9YAy36CqGg1JEX
GYnf/u6CN/6OnTTLbWjQLzUaVy2gjqqVXXamZv9x4dVv7JLYl4RZ5fX72HGmcIP2
tyDWcRLizmoKlo7Ih8k5Z66u4qFp7ebQrEma0WZvlqKUFrX2ataaJIm51809YJXZ
XK3G2gdwJyjPeCK9B8RkCqRTpiSxR38e3iSvpsqkwqqoxNcZAE2z2VV0c+p9HcwE
eNN93ZQEdYkA4ni6U6tnJ5v17CaJwvF7mVfxydsoHU7qH8lE5R3mBN6BgZMjZtwO
WDFw3grUFBiS9F7NiMxNvnykwr4WTn7fc6hSm/Rvls12ALElIDd5qe9GpnPXJH3O
MG87BHxa0DRuM7e6yw/dpBlMcfzyo1um7xe9DJJnc63hwQdc1agjr5zzkZWkv4I/
4j88gmgKjcEa4PbpmyZ8E8uNsPSO9Vy7csel+A7IwHiiArVfoel6dor34km6KYIN
2uq7P04djTOy+KR0ry+OwCo2vTkjPcd7S5Ta7rVsfGo3wxpxysTCDtBA6lMMd0ot
IZiEHz2Z89sHS6ZebYM2yvLcxvFYp6w8id4ETcRLoITP5+TCUWedZ+tuixygZrcq
fQFFWHlpGTlBO765xvH11rzFKDZSVrXwGpo82qHcFCw0imkXnKSoFUIX+EK97TK4
RtBskpNSll1e+d7XokECAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAPPJULe6zpVta
ihGI3j9ALaXbfCAarHCRbzwhFu6YzcmQ76H4Ec1yq/Gt/dhE+UrUXEe1sUMUgQYm
LyBqppkHbA0m+ehvGg5Rbe/R9ZDp2Q1JzI39YLqDgY3MHIkO6TST6Ps94X0Udn6N
VxA2gQRu0vI9/e7zWxSg+RkR+X60AYkcJNy+h+PZewTFQoUyAiBWRjrqDzGqiNuC
WRCX7vE5TqRq6f62zYCC/rnUDbUae80Cf4aTsNHJWdtljijCY/bzsmvOp+mrq7j6
XEa6uvdS/obvze8/xiFizEbCz9z8UUWTcKq2CiOEQzl8LAlBIbrLJQSKoGH6L+oM
J+Cwe4itpBe7shgRfaPfC7avwCiJkMY13yBBPfzQ9vTbl9MOg5gTlFUEdl/DHTuw
1HLmJzAWsfxyBeggt76oeuKytFmXrqOoCQhd/EF113ykrg3I9Crf1x4kjk/AYbjN
LqLVvsChNYtO7lNjW+dUsqptq4meCVWh/HY1Znk2yVsI2coBgiBkIIrBNfoTxYFX
0iBxpIp8XL+Y22DiUV6owbErPCy8qUvPmgHa7OF8G1koN4vubEHtfegZEjGLcMZG
SbIo4cZZ/EmZHSzGilyGVvpV9zYRQfs8sruHhy4BOGS2EFyrJcOVOhLHEODZFMDH
PzR1WeCLFQAYsgHr3Y7HHk0ljgBHIUY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE4jCCAsoCAQIwDQYJKoZIhvcNAQEFBQAwLTELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAlhYMREwDwYDVQQKEwhDaGVycnlQeTAeFw0xMDEwMDQxOTExMzZaFw0yMDEw
MDExOTExMzZaMEExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJYWDERMA8GA1UEChMI
Q2hlcnJ5UHkxEjAQBgNVBAMTCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMpj0X1CA+0vWAMt+gqhoNSRFxmJ3/7ugjf+jp00y21o0C81
GlctoI6qlV12pmb/ceHVb+yS2JeEWeX1+9hxpnCD9rcg1nES4s5qCpaOyIfJOWeu
ruKhae3m0KxJmtFmb5ailBa19mrWmiSJudfNPWCV2VytxtoHcCcoz3givQfEZAqk
U6YksUd/Ht4kr6bKpMKqqMTXGQBNs9lVdHPqfR3MBHjTfd2UBHWJAOJ4ulOrZyeb
9ewmicLxe5lX8cnbKB1O6h/JROUd5gTegYGTI2bcDlgxcN4K1BQYkvRezYjMTb58
pMK+Fk5+33OoUpv0b5bNdgCxJSA3eanvRqZz1yR9zjBvOwR8WtA0bjO3ussP3aQZ
THH88qNbpu8XvQySZ3Ot4cEHXNWoI6+c85GVpL+CP+I/PIJoCo3BGuD26ZsmfBPL
jbD0jvVcu3LHpfgOyMB4ogK1X6HpenaK9+JJuimCDdrquz9OHY0zsvikdK8vjsAq
Nr05Iz3He0uU2u61bHxqN8MaccrEwg7QQOpTDHdKLSGYhB89mfPbB0umXm2DNsry
3MbxWKesPIneBE3ES6CEz+fkwlFnnWfrboscoGa3Kn0BRVh5aRk5QTu+ucbx9da8
xSg2Ula18BqaPNqh3BQsNIppF5ykqBVCF/hCve0yuEbQbJKTUpZdXvne16JBAgMB
AAEwDQYJKoZIhvcNAQEFBQADggIBABJ6kQ5SLRMVrDiA4MSGNdZ2/5DdaGQ8U5ai
wjZ+JPu/efhiOkSSdFJCDXXJphAmGHWOTzGWc/NjgEJ2hswixsMS1nYxrP+abGjb
I+Nw0KOLynd2++hlS7JIVUzBzZsu5aE0QHQtg9bYRt2Sw94LDpiUvpmDSid10coQ
au444fNxeXVixZdyJxEyS5b5KXB0p3xHL7My4wZ8/bM/TPHyoe4qVJM5egSrw0Oz
LItyNVJ8akc9gfwOgX8SzRG75T15IuCojnhKKRiaHJMahRQO3u+JB4+gA4hGk0Rx
JQferTzQM/goYMSq3mQcKUbgsEf3wUmFWJDnkJAXgLHeZh1Oawug9VsGlCxS+IJ3
Mj9hoPI4RYrMOGI8EUXBrXWhxhhi2A1LR+o4/+O5IrVBp298vEpO+EWHb9/lbt2F
gpU5jZcRR+M76MdVHF5X4RD+rE97vRZofR7bfhxmvJ+LeForbJk3u0arCLD6LHfG
TtUGsRWdABQuB/ZvRNYe6KWCxvuVTwTLayYNwbPr5qRCs4fHww6vRJGvDC5fqdIQ
7aqRvwrKq2w7dMIZK0BiVEtOiBoHcKhvzD3yfi/OkqaoPbIodN5C65g2prHjwyD0
uCqynSHHjP3qycXLLaChrYSftNwvBSJKKfbCyY/MGU7lOydkpkiFvsGXW8elC7On
Dvhc259l
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE9DCCAtwCAQQwDQYJKoZIhvcNAQEFBQAwOzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAlhYMQwwCgYDVQQHEwNYWFgxETAPBgNVBAoTCENoZXJyeVB5MB4XDTEwMTAw
NDE5MTAzOVoXDTIwMTAwMTE5MTAzOVowRTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
AlhYMREwDwYDVQQKEwhDaGVycnlQeTEWMBQGA1UEAxQNbm90X2xvY2FsaG9zdDCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMpj0X1CA+0vWAMt+gqhoNSR
FxmJ3/7ugjf+jp00y21o0C81GlctoI6qlV12pmb/ceHVb+yS2JeEWeX1+9hxpnCD
9rcg1nES4s5qCpaOyIfJOWeuruKhae3m0KxJmtFmb5ailBa19mrWmiSJudfNPWCV
2VytxtoHcCcoz3givQfEZAqkU6YksUd/Ht4kr6bKpMKqqMTXGQBNs9lVdHPqfR3M
BHjTfd2UBHWJAOJ4ulOrZyeb9ewmicLxe5lX8cnbKB1O6h/JROUd5gTegYGTI2bc
DlgxcN4K1BQYkvRezYjMTb58pMK+Fk5+33OoUpv0b5bNdgCxJSA3eanvRqZz1yR9
zjBvOwR8WtA0bjO3ussP3aQZTHH88qNbpu8XvQySZ3Ot4cEHXNWoI6+c85GVpL+C
P+I/PIJoCo3BGuD26ZsmfBPLjbD0jvVcu3LHpfgOyMB4ogK1X6HpenaK9+JJuimC
Ddrquz9OHY0zsvikdK8vjsAqNr05Iz3He0uU2u61bHxqN8MaccrEwg7QQOpTDHdK
LSGYhB89mfPbB0umXm2DNsry3MbxWKesPIneBE3ES6CEz+fkwlFnnWfrboscoGa3
Kn0BRVh5aRk5QTu+ucbx9da8xSg2Ula18BqaPNqh3BQsNIppF5ykqBVCF/hCve0y
uEbQbJKTUpZdXvne16JBAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBABOSv3BiRC7K
oZXdLuEIWsAyzt5Ir4aRDqXZxIlFhcek2hs9AB+aNOcRLM6o+FR/ynXiUjftBJYL
lHUsYzXt0xIxrxH8W2SgTgyY2ZxMXq15c1mDWZUeM+lejuBMII1qNTUblb9vy0sl
xf3JmsrIUk7Ji+0eMY2ZI7eMCYLN3akdzixI4Qb5UgyKoRBqWrTnTomB0SnCqEiv
md4BG5ifKJjGtr01xJXcTmwa80v8ANmLz1WS4no4lyau2Yf30KGxEJ2nvIiV4Nhs
2iD/cnJYPcMkqFTKodt9JVLDCiec4Gh1HkN0VWy1XyEZvZasfO2/kFcYS8Pg9xTQ
2w0/9VxckWx8JA54GYovhVYIYfEDZgIICf4EGIhljGX5K0gQ/jJc9Rx4dYjmKItx
Js/js+CDLOOErnXJ7ZexArvwyRdbVQZC2PsdK7HcWnKYvjf8x4bGFSzmB/SLVnYL
mx6ygRhdlftobhB2RnXDPtHzU28SiGGG90zzjvZoV2LdNgHttcwzjPbMU2gRXvcM
wUFdk+xvEhjuwct6ZmZG5MbBbyXllGHoU8VadvQiK1ufrhcBdla6vaNhyNebuB1t
P+N+T1Xe7jnjcVSkgQjT4W6du4gif4q3wFQcXuW4WtHua5b6JibQ5kNoOcct+sV7
ZGrvlNC+PcYw1dFtI6I7ANWrdGmuGD9w
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE8DCCAtgCAQEwDQYJKoZIhvcNAQEFBQAwOzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgTAlhYMQwwCgYDVQQHEwNYWFgxETAPBgNVBAoTCENoZXJyeVB5MB4XDTEwMTAw
NTE2NTU0NFoXDTIwMTAwMjE2NTU0NFowQTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
AlhYMREwDwYDVQQKEwhDaGVycnlQeTESMBAGA1UEAxMJbG9jYWxob3N0MIICIjAN
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5LKNLY3Il4TFKigGvRqu3RXHvU/T
9wrNyD/SCkUFFP/kTophyFoFyLu1jhmw6YQQfr7Q8rpvH2wXR/l7wvlr2HzfOXZH
TA9vUsZLdAo07thYRPzLOAANKjVDmn6/dzyfeGxmpmxYlEioRtYuYDqpUoAM5V7s
6B7aoW4llWi2rrRn8h6yAGlRrvoAUc/gOugOFzCVerQ6OFvY54YDUEkK/HqhpD70
grYh9DdNKiNbHaDBDlQ1WEON/N4tTY1KFvYcHo67U5dkxweNQmUBZQYkp2fAO6FA
FOfQahXjvO7QpoIYU00XjF61YBKNplTQhWH7x9ZAIzdSedhu2e6yZqLc/5wgw9lD
pYeNqvTGK28UF+9JjvoYoI3T5//CDxrQjTZlhiW7NF1gnapaQR/uwB9AoFierEGI
dEX5ob8Hv0V8hPhCiJUypQj0tvhGuCwAktf6jtlsWNMGrD4IpE1LEcPzhGbDZBs7
i0J9chmXaklPed+enTpHCrLzhY7ImRzrnRnfceIkRQCL3TRvWJO+JeQ1Nahiw7m+
S7jie63cLwiLMgFqcqMu7s0Yt7qrnA4Rg39B2KCdDMw1pAkoU4HMOY5x/8Lvsukz
3y9IJHN5i+GbPQDN+RdAA4nFTNA9au+j/YJZETw61PUmbx8YdLfnOXyr+/JL/rQ+
VIAHHMur+dO6qp8CAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAfnA62cflmXJ6fLpi
wp0egKb4CgQK8Kc8qio4U7X76Fhp3YQFQu8FZu+h2EAqwOuuYFZD4PzjdVA2DgTc
+OcIiKX0K3+KRuAzlhQ1jGxVcXjAQD6oHQdd6bFh8HbnBa3MJqtTx0U3wzEuIpXi
3Nxjb79mFkVhjWFoj9gKa1l8KPqZGePr4iJZzmmPah/GoaPGJrD6RwTu+8BSjiQi
FPmmZF7IauMoY2lKGloSNRd6FFiCSvtiTzkIvoL6pjOz2o5QFborEp5myF8z95n9
UbrFB80JMhLDcxD6F4AInL8Mz6N8g32dgz8DgVXp93pRwWoeUlY+DQSZ7qBsIt2U
U/gK6sTu7XnYX3JFTAkyBcU9xBMEgZiLLxzTGNYdzK1BDeHm9GVabqpRtc4acsEi
diWGq6RGhe9o4VoYj0OzBHkI95ZJExK2tcO5DKpbXkpZOK1zTZaMNyW043UkO7FT
/AXy90aO3aQXGnb9OR+14zbSXk8u0vaVwhPbzHMcQ4JVxaU2acLLSK94rdz+t/oR
wIIjcST1eyvVb0y1C5TlZR6jIEfcZdRcdzGbGk2+Pi8Pv7HN1F5uoZy9UQmqqOD7
b6qOGuymiC59o7jHmND+By3L51XqWzpPyyeAZv7WeAln93idRVjEhDYiWDfeFePV
H7+ZxbdpJ4BDgCwYBaFYyFReMcw=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
"""HTTPS Tests."""
# -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 :
import os
import pytest
import ssl
from cheroot.ssl.builtin import BuiltinSSLAdapter
from cheroot.test import helper
import cheroot
import ddt
def create_wsgi_server(**conf):
"""Create test server."""
ssl_adapter = BuiltinSSLAdapter(
certificate=conf.pop('certificate'),
private_key=conf.pop('private_key'),
certificate_chain=conf.pop('certificate_chain'))
ssl_adapter.context.verify_mode = conf.pop('verify_mode', ssl.CERT_NONE)
server = cheroot.wsgi.Server(**conf)
server.ssl_adapter = ssl_adapter
return server
def ssl_file(filename):
"""Return path to given ssl file."""
return os.path.join('cheroot/test/ssl/', filename)
class HTTPSTestBase(object):
"""Base class for HTTPS tests."""
available_servers = {'wsgi': create_wsgi_server}
config = {
'certificate': 'cheroot/test/ssl/server.cert',
'private_key': 'cheroot/test/ssl/server.key',
'certificate_chain': 'cheroot/test/ssl/ca.cert',
}
script_name = '/hello'
ssl_context = None
@classmethod
def setup_server(cls):
"""Set up the test server."""
class Root(helper.Controller):
def hello(req, resp):
return 'Hello world!'
handlers = {'/hello': hello}
cls.httpserver.wsgi_app = Root()
def setUp(self):
"""Set up."""
super(HTTPSTestBase, self).setUp()
self.ssl_context = ssl.create_default_context(
cafile='cheroot/test/ssl/ca.cert')
self.ssl_context.check_hostname = False
def getPage(self, *args, **kw):
"""Fetch the page."""
return super(HTTPSTestBase, self).getPage(
self.script_name, *args,
raise_subcls=ssl.SSLError, **kw)
def set_client_cert(self, name):
"""Set client cert."""
self.ssl_context.load_cert_chain(ssl_file(name + '.cert'),
keyfile=ssl_file('client.key'))
def assert_allowed(self, client_cert):
"""Assert test page can be fetched when given client cert is used."""
self.set_client_cert(client_cert)
self.getPage()
self.assertStatus('200 OK')
def assert_reject(self, client_cert):
"""Assert test page cannot be fetched.
And an SSLError is raised when the given client cert is used.
"""
self.set_client_cert(client_cert)
with pytest.raises(ssl.SSLError) as context:
self.getPage()
return context
@ddt.ddt
class ClientCertRequiredTests(HTTPSTestBase, helper.CherootWebCase):
"""Test expected outcomes when client cert is required."""
@classmethod
def setup_class(cls):
"""Set up for tests."""
cls.config.update({'verify_mode': ssl.CERT_REQUIRED})
super(ClientCertRequiredTests, cls).setup_class()
@ddt.data('client', 'client_ip', 'client_wildcard', 'client_wrong_host')
def test_allow(self, client_cert):
"""Test that the given client cert is allowed to connect."""
self.assert_allowed(client_cert)
def test_reject_wrong_ca(self):
"""Test that the given client cert is not allowed to connect."""
context = self.assert_reject('client_wrong_ca')
assert 'tlsv1 alert unknown ca' in str(context.value)
@ddt.ddt
class ClientCertOptionalTests(HTTPSTestBase, helper.CherootWebCase):
"""Test expected outcomes when client cert is optional."""
@classmethod
def setup_class(cls):
"""Set up for tests."""
cls.config.update({'verify_mode': ssl.CERT_OPTIONAL})
super(ClientCertOptionalTests, cls).setup_class()
@ddt.data('client', 'client_ip', 'client_wildcard', 'client_wrong_host')
def test_allow(self, client_cert):
"""Test that the given client cert is allowed to connect."""
self.assert_allowed(client_cert)
def test_reject_wrong_ca(self):
"""Test that the given client cert is not allowed to connect."""
context = self.assert_reject('client_wrong_ca')
assert 'tlsv1 alert unknown ca' in str(context.value)
@ddt.ddt
class ClientCertIgnoredTests(HTTPSTestBase, helper.CherootWebCase):
"""Test expected outcomes when client cert is ignored."""
@classmethod
def setup_class(cls):
"""Set up for tests."""
cls.config.update({'verify_mode': ssl.CERT_NONE})
super(ClientCertIgnoredTests, cls).setup_class()
@ddt.data('client', 'client_ip', 'client_wildcard', 'client_wrong_host',
'client_wrong_ca')
def test_allow(self, client_cert):
"""Test that the given client cert is allowed to connect."""
self.assert_allowed(client_cert)
......@@ -106,6 +106,7 @@ class WebCase(unittest.TestCase):
scheme = 'http'
url = None
ssl_context = None
status = None
headers = None
......@@ -205,7 +206,7 @@ class WebCase(unittest.TestCase):
start = time.time()
result = openURL(url, headers, method, body, self.HOST, self.PORT,
self.HTTP_CONN, protocol or self.PROTOCOL,
raise_subcls)
raise_subcls, ssl_context=self.ssl_context)
self.time = time.time() - start
self.status, self.headers, self.body = result
......@@ -467,7 +468,7 @@ def shb(response):
def openURL(url, headers=None, method='GET', body=None,
host='127.0.0.1', port=8000, http_conn=http_client.HTTPConnection,
protocol='HTTP/1.1', raise_subcls=None):
protocol='HTTP/1.1', raise_subcls=None, ssl_context=None):
"""
Open the given HTTP resource and return status, headers, and body.
......@@ -486,7 +487,10 @@ def openURL(url, headers=None, method='GET', body=None,
if hasattr(http_conn, 'host'):
conn = http_conn
else:
conn = http_conn(interface(host), port)
kw = {}
if ssl_context:
kw['context'] = ssl_context
conn = http_conn(interface(host), port, **kw)
conn._http_vsn_str = protocol
conn._http_vsn = int(''.join([x for x in protocol if x.isdigit()]))
......
......@@ -61,6 +61,7 @@ params = dict(
'collective.checkdocs',
],
'testing': [
'ddt',
'pytest>=2.8',
'pytest-sugar',
'pytest-testmon>=0.9.7',
......
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