SSL: Handle wildcards in Subject Alternative Names
Closes-Bug: #1259528 Change-Id: Iedc2b98d47f1f9433a4cfd77e07f7f86bae806c1
This commit is contained in:
@@ -343,15 +343,20 @@ class VerifiedHTTPSConnection(HTTPSConnection):
|
|||||||
connecting to, ie that the certificate's Common Name
|
connecting to, ie that the certificate's Common Name
|
||||||
or a Subject Alternative Name matches 'host'.
|
or a Subject Alternative Name matches 'host'.
|
||||||
"""
|
"""
|
||||||
common_name = x509.get_subject().commonName
|
def check_match(name):
|
||||||
|
# Directly match the name
|
||||||
# First see if we can match the CN
|
if name == host:
|
||||||
if common_name == host:
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Support single wildcard matching
|
# Support single wildcard matching
|
||||||
if common_name.startswith('*.') and host.find('.') > 0:
|
if name.startswith('*.') and host.find('.') > 0:
|
||||||
if common_name[2:] == host.split('.', 1)[1]:
|
if name[2:] == host.split('.', 1)[1]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
common_name = x509.get_subject().commonName
|
||||||
|
|
||||||
|
# First see if we can match the CN
|
||||||
|
if check_match(common_name):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Also try Subject Alternative Names for a match
|
# Also try Subject Alternative Names for a match
|
||||||
@@ -361,7 +366,8 @@ class VerifiedHTTPSConnection(HTTPSConnection):
|
|||||||
if ext.get_short_name() == 'subjectAltName':
|
if ext.get_short_name() == 'subjectAltName':
|
||||||
san_list = str(ext)
|
san_list = str(ext)
|
||||||
for san in ''.join(san_list.split()).split(','):
|
for san in ''.join(san_list.split()).split(','):
|
||||||
if san == "DNS:%s" % host:
|
if san.startswith('DNS:'):
|
||||||
|
if check_match(san.split(':', 1)[1]):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Server certificate does not match host
|
# Server certificate does not match host
|
||||||
|
@@ -165,6 +165,34 @@ class TestVerifiedHTTPSConnection(testtools.TestCase):
|
|||||||
except Exception:
|
except Exception:
|
||||||
self.fail('Unexpected exception.')
|
self.fail('Unexpected exception.')
|
||||||
|
|
||||||
|
def test_ssl_cert_subject_alt_name_wildcard(self):
|
||||||
|
"""
|
||||||
|
Test certificate: wildcard SAN match
|
||||||
|
"""
|
||||||
|
cert_file = os.path.join(TEST_VAR_DIR, 'wildcard-san-certificate.crt')
|
||||||
|
cert = crypto.load_certificate(crypto.FILETYPE_PEM,
|
||||||
|
file(cert_file).read())
|
||||||
|
# The expected cert should have CN=0.0.0.0
|
||||||
|
self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
|
||||||
|
try:
|
||||||
|
conn = http.VerifiedHTTPSConnection('alt1.example.com', 0)
|
||||||
|
conn.verify_callback(None, cert, 0, 0, 1)
|
||||||
|
except Exception:
|
||||||
|
self.fail('Unexpected exception.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = http.VerifiedHTTPSConnection('alt2.example.com', 0)
|
||||||
|
conn.verify_callback(None, cert, 0, 0, 1)
|
||||||
|
except Exception:
|
||||||
|
self.fail('Unexpected exception.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = http.VerifiedHTTPSConnection('alt3.example.net', 0)
|
||||||
|
conn.verify_callback(None, cert, 0, 0, 1)
|
||||||
|
self.fail('Failed to raise assertion.')
|
||||||
|
except exc.SSLCertificateError:
|
||||||
|
pass
|
||||||
|
|
||||||
def test_ssl_cert_mismatch(self):
|
def test_ssl_cert_mismatch(self):
|
||||||
"""
|
"""
|
||||||
Test certificate: bogus host
|
Test certificate: bogus host
|
||||||
|
54
tests/var/wildcard-san-certificate.crt
Normal file
54
tests/var/wildcard-san-certificate.crt
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#Certificate:
|
||||||
|
# Data:
|
||||||
|
# Version: 3 (0x2)
|
||||||
|
# Serial Number: 11990626514780340979 (0xa66743493fdcc2f3)
|
||||||
|
# Signature Algorithm: sha1WithRSAEncryption
|
||||||
|
# Issuer: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack Test Unit, CN=0.0.0.0
|
||||||
|
# Validity
|
||||||
|
# Not Before: Dec 10 15:31:22 2013 GMT
|
||||||
|
# Not After : Nov 16 15:31:22 2113 GMT
|
||||||
|
# Subject: C=US, ST=CA, L=State1, O=Openstack Test Org, OU=Openstack Test Unit, CN=0.0.0.0
|
||||||
|
# Subject Public Key Info:
|
||||||
|
# Public Key Algorithm: rsaEncryption
|
||||||
|
# Public-Key: (2048 bit)
|
||||||
|
# Modulus:
|
||||||
|
# 00:ca:6b:07:73:53:24:45:74:05:a5:2a:27:bd:3e:
|
||||||
|
# .
|
||||||
|
# .
|
||||||
|
# .
|
||||||
|
# Exponent: 65537 (0x10001)
|
||||||
|
# X509v3 extensions:
|
||||||
|
# X509v3 Key Usage:
|
||||||
|
# Key Encipherment, Data Encipherment
|
||||||
|
# X509v3 Extended Key Usage:
|
||||||
|
# TLS Web Server Authentication
|
||||||
|
# X509v3 Subject Alternative Name:
|
||||||
|
# DNS:foo.example.net, DNS:*.example.com
|
||||||
|
# Signature Algorithm: sha1WithRSAEncryption
|
||||||
|
# 7e:41:69:da:f4:3c:06:d6:83:c6:f2:db:df:37:f1:ac:fa:f5:
|
||||||
|
# .
|
||||||
|
# .
|
||||||
|
# .
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDxDCCAqygAwIBAgIJAKZnQ0k/3MLzMA0GCSqGSIb3DQEBBQUAMHgxCzAJBgNV
|
||||||
|
BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEBxMGU3RhdGUxMRswGQYDVQQKExJP
|
||||||
|
cGVuc3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsTE09wZW5zdGFjayBUZXN0IFVuaXQx
|
||||||
|
EDAOBgNVBAMTBzAuMC4wLjAwIBcNMTMxMjEwMTUzMTIyWhgPMjExMzExMTYxNTMx
|
||||||
|
MjJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEBxMGU3RhdGUx
|
||||||
|
MRswGQYDVQQKExJPcGVuc3RhY2sgVGVzdCBPcmcxHDAaBgNVBAsTE09wZW5zdGFj
|
||||||
|
ayBUZXN0IFVuaXQxEDAOBgNVBAMTBzAuMC4wLjAwggEiMA0GCSqGSIb3DQEBAQUA
|
||||||
|
A4IBDwAwggEKAoIBAQDKawdzUyRFdAWlKie9Pn10j7frffN+z1gEMluK2CtDEwv9
|
||||||
|
kbD4uS/Kz4dujfTx03mdyNfiMVlOM+YJm/qeLLSdJyFyvZ9Y3WmJ+vT2RGlMMhLd
|
||||||
|
/wEnMRrTYLL39pwI6z+gyw+4D78Pyv/OXy02IA6WtVEefYSx1vmVngb3pL+iBzhO
|
||||||
|
8CZXNI6lqrFhh+Hr4iMkYMtY1vTnwezAL6p64E/ZAFNPYCEJlacESTLQ4VZYniHc
|
||||||
|
QTgnE1czlI1vxlIk1KDXAzUGeeopZecRih9qlTxtOpklqEciQEE+sHtPcvyvdRE9
|
||||||
|
Bdyx5rNSALLIcXs0ViJE1RPlw3fjdBoDIOygqvX1AgMBAAGjTzBNMAsGA1UdDwQE
|
||||||
|
AwIEMDATBgNVHSUEDDAKBggrBgEFBQcDATApBgNVHREEIjAggg9mb28uZXhhbXBs
|
||||||
|
ZS5uZXSCDSouZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAH5Badr0PAbW
|
||||||
|
g8by29838az69Raul5IkpZQ5V3O1NaNNWxvmF1q8zFFqqGK5ktXJAwGiwnYEBb30
|
||||||
|
Zfrr+eFIEERzBthSJkWlP8NG+2ooMyg50femp+asAvW+KYYefJW8KaXTsznMsAFy
|
||||||
|
z1agcWVYVZ4H9PwunEYn/rM1krLEe4Cagsw5nmf8VqZg+hHtw930q8cRzgDsZdfA
|
||||||
|
jVK6dWdmzmLCUTL1GKCeNriDw1jIeFvNufC+Q3orH7xBx4VL+NV5ORWdNY/B8q1b
|
||||||
|
mFHdzbuZX6v39+2ww6aZqG2orfxUocc/5Ox6fXqenKPI3moeHS6Ktesq7sEQSJ6H
|
||||||
|
QZFsTuT/124=
|
||||||
|
-----END CERTIFICATE-----
|
Reference in New Issue
Block a user