Permalink
Browse files

Tests and fixes for CertificateData.verify_server

  • Loading branch information...
1 parent 72c48be commit 72b77fcc8dd68ce810f0837991290fb0aeed2485 @Jajcus committed Sep 6, 2011
View
@@ -77,13 +77,14 @@ def get_jids(self):
"""
result = []
if ("XmppAddr" in self.alt_names or "DNS" in self.alt_names
- or "SRVName" in alt_names):
+ or "SRVName" in self.alt_names):
addrs = self.alt_names.get("XmppAddr", [])
addrs += [ addr for addr in self.alt_names.get("DNS", [])
if not addr.startswith("*.") ]
addrs += [ addr.split(".", 1)[1] for addr
in self.alt_names.get("SRVName", [])
- if addr.startswith("_xmpp-server.") ]
+ if (addr.startswith("_xmpp-server.")
+ or addr.startswith("_xmpp-client."))]
warn_bad = True
elif self.common_names:
addrs = [addr for addr in self.common_names
@@ -115,21 +116,44 @@ def verify_server(self, server_name, srv_type = 'xmpp-client'):
:Return: `True` if the certificate is valid for given name, `False`
otherwise.
"""
- # TODO: wildcards
server_jid = JID(server_name)
if "XmppAddr" not in self.alt_names and "DNS" not in self.alt_names \
and "SRV" not in self.alt_names:
return self.verify_jid_against_common_name(server_jid)
- for name in self.alt_names.get("DNS", []) + self.alt_names.get(
- "XmppAddr", []):
+ names = [name for name in self.alt_names.get("DNS", [])
+ if not name.startswith(u"*.")]
+ names += self.alt_names.get("XmppAddr", [])
+ for name in names:
+ logger.debug("checking {0!r} against {1!r}".format(server_jid,
+ name))
try:
jid = JID(name)
except ValueError:
+ logger.debug("Not a valid JID: {0!r}".format(name))
continue
if jid == server_jid:
+ logger.debug("Match!")
+ return True
+ if srv_type and self.verify_jid_against_srv_name(server_jid, srv_type):
+ return True
+ wildcards = [name[2:] for name in self.alt_names.get("DNS", [])
+ if name.startswith("*.")]
+ if not wildcards or not "." in server_jid.domain:
+ return False
+ logger.debug("checking {0!r} against wildcard domains: {1!r}"
+ .format(server_jid, wildcards))
+ server_domain = JID(domain = server_jid.domain.split(".", 1)[1])
+ for domain in wildcards:
+ logger.debug("checking {0!r} against {1!r}".format(server_domain,
+ domain))
+ try:
+ jid = JID(domain)
+ except ValueError:
+ logger.debug("Not a valid JID: {0!r}".format(name))
+ continue
+ if jid == server_domain:
+ logger.debug("Match!")
return True
- if srv_type:
- return self.verify_jid_against_srv_name(jid, srv_type)
return False
def verify_jid_against_common_name(self, jid):
@@ -167,14 +191,19 @@ def verify_jid_against_srv_name(self, jid, srv_type):
"""
srv_prefix = u"_" + srv_type + u"."
srv_prefix_l = len(srv_prefix)
- for srv in self.alt_names.get("SRV", []):
+ for srv in self.alt_names.get("SRVName", []):
+ logger.debug("checking {0!r} against {1!r}".format(jid,
+ srv))
if not srv.startswith(srv_prefix):
+ logger.debug("{0!r} does not start with {1!r}"
+ .format(srv, srv_prefix))
continue
try:
srv_jid = JID(srv[srv_prefix_l:])
except ValueError:
continue
if srv_jid == jid:
+ logger.debug("Match!")
return True
return False
@@ -362,7 +391,8 @@ class ASN1CertificateData(CertificateData):
_cert_asn1_type = None
@classmethod
def from_ssl_socket(cls, ssl_socket):
-
+ """Get certificate data from an SSL socket.
+ """
try:
data = ssl_socket.getpeercert(True)
except AttributeError:
View
@@ -34,10 +34,10 @@ def socket_with_cert(cert_path, key_path, cacert_path, server_cert = True):
addr = listen_sock.getsockname()
def thread_func():
try:
- sock, addr = listen_sock.accept()
- sock.setblocking(True)
+ sock = listen_sock.accept()[0]
+ sock.setblocking(True) # pylint: disable=E1101
try:
- ssl_sock = ssl.wrap_socket(sock, key_path, cert_path,
+ ssl.wrap_socket(sock, key_path, cert_path,
server_side = server_cert, ca_certs = cacert_path)
finally:
sock.close()
@@ -63,8 +63,8 @@ class TestCertFunctions(unittest.TestCase):
@unittest.skipUnless("lo-network" in _support.RESOURCES,
"network usage disabled")
def test_get_certificate_from_ssl_socket(self):
- socket = socket_with_cert("server.pem", "server-key.pem", "ca.pem")
- cert = get_certificate_from_ssl_socket(socket)
+ sock = socket_with_cert("server.pem", "server-key.pem", "ca.pem")
+ cert = get_certificate_from_ssl_socket(sock)
self.assertIsNotNone(cert)
if HAVE_PYASN1:
self.assertIsInstance(cert, ASN1CertificateData)
@@ -96,8 +96,8 @@ class TestBasicCertificateData(unittest.TestCase):
def load_certificate(name, server_cert = True):
cert_file = name + ".pem"
key_file = name + "-key.pem"
- socket = socket_with_cert(cert_file, key_file, "ca.pem", server_cert)
- return BasicCertificateData.from_ssl_socket(socket)
+ sock = socket_with_cert(cert_file, key_file, "ca.pem", server_cert)
+ return BasicCertificateData.from_ssl_socket(sock)
def test_server_cert_fields(self):
cert = self.load_certificate("server", True)
@@ -118,6 +118,16 @@ def test_server_cert_fields(self):
u"commonName=server.example.org")
self.assertEqual(cert.get_jids(), [JID("server.example.org")])
+ def test_verify_server(self):
+ cert = self.load_certificate("server", True)
+ self.assertTrue(cert.verify_server(u"server.example.org"))
+ self.assertTrue(cert.verify_server(JID(u"server.example.org")))
+ self.assertFalse(cert.verify_server(u"wrong.example.org"))
+ self.assertFalse(cert.verify_server(JID(u"wrong.example.org")))
+ self.assertFalse(cert.verify_server(u"example.org"))
+ self.assertFalse(cert.verify_server(u"sub.server.example.org"))
+
+
def test_client_cert_fields(self):
cert = self.load_certificate("client", False)
self.assertEqual(cert.subject_name, (
@@ -154,8 +164,8 @@ def test_server1_cert_fields(self):
u"*.wild.example.org"])
if not isinstance(cert, BasicCertificateData):
self.assertEqual(list(cert.alt_names["SRVName"]),
- [u"_xmpp-server.srv1.example.org",
- u"_xmpp-server.srv2.example.org"])
+ [u"_xmpp-client.client-srv.example.org",
+ u"_xmpp-server.server-srv.example.org"])
self.assertEqual(list(cert.alt_names["XmppAddr"]),
[u"xmppaddr1.example.org",
u"xmppaddr2.example.org"])
@@ -164,8 +174,8 @@ def test_server1_cert_fields(self):
u"commonName=common-name.example.org")
jids = [JID("dns1.example.org"), JID("dns2.example.org")]
if not isinstance(cert, BasicCertificateData):
- jids += [
- JID("srv1.example.org"), JID("srv2.example.org"),
+ jids += [ JID("client-srv.example.org"),
+ JID("server-srv.example.org"),
JID("xmppaddr1.example.org"), JID("xmppaddr2.example.org")]
self.assertEqual(set(cert.get_jids()), set(jids))
@@ -192,6 +202,23 @@ def test_client1_cert_fields(self):
self.assertEqual(cert.get_jids(), [JID("user1@server.example.org"),
JID("user2@server.example.org")])
+ def test_verify_server1_wrong(self):
+ cert = self.load_certificate("server1", True)
+ self.assertFalse(cert.verify_server(u"common-name.example.org"))
+ self.assertFalse(cert.verify_server(u"example.org"))
+ self.assertFalse(cert.verify_server(u"bad.example.org"))
+ self.assertFalse(cert.verify_server(u"wild.example.org"))
+ self.assertFalse(cert.verify_server(u"sub.sub.wild.example.org"))
+ self.assertFalse(cert.verify_server(u"client-srv.example.org",
+ "xmpp-server"))
+ self.assertFalse(cert.verify_server(u"server-srv.example.org"))
+ self.assertFalse(cert.verify_server(u"server-srv.example.org",
+ "xmpp-client"))
+
+ def test_verify_server1_dns(self):
+ cert = self.load_certificate("server1", True)
+ self.assertTrue(cert.verify_server(u"dns1.example.org"))
+ self.assertTrue(cert.verify_server(u"dns2.example.org"))
@unittest.skipUnless(HAVE_PYASN1, "No pyasn1")
class TestASN1CertificateData(TestBasicCertificateData):
@@ -200,6 +227,24 @@ def load_certificate(name, server_cert = True):
cert_file = os.path.join(_support.DATA_DIR, name + ".pem")
return ASN1CertificateData.from_file(cert_file)
+ def test_verify_server1_srv(self):
+ cert = self.load_certificate("server1", True)
+ self.assertTrue(cert.verify_server(u"client-srv.example.org"))
+ self.assertTrue(cert.verify_server(u"client-srv.example.org",
+ "xmpp-client"))
+ self.assertTrue(cert.verify_server(u"server-srv.example.org",
+ "xmpp-server"))
+
+ def test_verify_server1_xmppaddr(self):
+ cert = self.load_certificate("server1", True)
+ self.assertTrue(cert.verify_server(u"xmppaddr1.example.org"))
+ self.assertTrue(cert.verify_server(u"xmppaddr2.example.org"))
+
+ def test_verify_server1_wildcard(self):
+ cert = self.load_certificate("server1", True)
+ self.assertTrue(cert.verify_server(u"sub.wild.example.org"))
+ self.assertTrue(cert.verify_server(u"somethinelse.wild.example.org"))
+
# pylint: disable=W0611
from pyxmpp2.test._support import load_tests, setup_logging
@@ -20,4 +20,4 @@ commonName = common-name.example.org
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-subjectAltName=DNS:dns1.example.org,DNS:dns2.example.org,DNS:*.wild.example.org,otherName:1.3.6.1.5.5.7.8.7;IA5:_xmpp-server.srv1.example.org,otherName:1.3.6.1.5.5.7.8.7;IA5:_xmpp-server.srv2.example.org,otherName:1.3.6.1.5.5.7.8.5;UTF8:xmppaddr1.example.org,otherName:1.3.6.1.5.5.7.8.5;UTF8:xmppaddr2.example.org
+subjectAltName=DNS:dns1.example.org,DNS:dns2.example.org,DNS:*.wild.example.org,otherName:1.3.6.1.5.5.7.8.7;IA5:_xmpp-client.client-srv.example.org,otherName:1.3.6.1.5.5.7.8.7;IA5:_xmpp-server.server-srv.example.org,otherName:1.3.6.1.5.5.7.8.5;UTF8:xmppaddr1.example.org,otherName:1.3.6.1.5.5.7.8.5;UTF8:xmppaddr2.example.org
@@ -1,16 +1,16 @@
-----BEGIN PRIVATE KEY-----
-MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPh+eXefG213bE4i
-eFZbJIdwCP/8WbSX7oVCKfZ1+cLiwVNlsn0ixLdXxVx25C3g0cfZThsGfU6Y+GsT
-52eI0OYh2P9GfnLwQcFuQS+O2fKUgfjFAGLl9rsNuJoOV2YCvXRiniCKZDtXbU65
-8KbmOkvjx/sMi4lVAvZAVqBHn9qfAgMBAAECgYEA9RAFyqrm6bX04bms471O8SLU
-PWApN6j+Wf0+VQlUH5ZxAkYxGKfJSOcOhHnb3kLxoB32oUBtI65Ij5E5jSmomNsX
-2MLvAE6lsYl6761yFwT95gxn6d088A7OQMbOX14r84k+OjCVRaEfuSa9aRV3prqe
-LnVnyqGmHLPE78CNcEECQQD+p/nvPQUlIy78yKbQk1p3zlbQ3zIvZwn9HuZzlDqR
-anisvJ8//iQMxaAQJ4ViS0LqDXegygK+IsJxS/UDr1ztAkEA+c4sboPM7WmrcpgG
-ywHIqQ5XOfHC9dhcYdIziXbwEyMQyyLMbOh9jV3n3VCH0lMeMmW25fLEb9WX/vIx
-T80wOwJBAN/snR39rjSFx5+IYQcvS3HmAvkQCnUcSfBF56biRM3xrcNW6UHAG7sP
-XDxYRDW2sFRXG0ZL3DWNIyW1APIIldECQCcqNvcgvOlgDtxJj48WeYJf2Dcie2GW
-CW3gyem8dwlZDxH6I7jTfpPCbE7biF/mXi6imdlVhYzPHSSAjlCnp+8CQQCrcVSX
-6bLxT00A5FlhCaptxHzvE2kK3GdDmUpNzk5KqNh2V39z6uP/sKNnsl46BUe+FSox
-W+Ny81+Ut1nyOaoY
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL21NBD6yNUqJAmY
+j9/VXbZJ64l7V8xDdDeZR/hERgRYys2ntGRNelFe4sXJ76pn6AefiF4x1N64Jq9U
+wAavNMuQj26aVN/R1enMmlbWgte8UQnKbEBGArN7wddZYmn9h/87PNQrXA5/qNR1
+n6Ad6OOzfZdtffR9Qdg98wCQELWVAgMBAAECgYEAk9qUd99dg3XSnIABMkzTOu2l
+24L8TMEN5P9cLkzX3S9u8JYSbFJOUPkI+WqHlmJhXv+hgviHlgYkcGY3O352QA9C
+5Zqsm4jO2e7/3ttnVsIJ0jiVS1bHDy+DrgIjSUDVtwdzQ7FRiZhxXKeO9bKd0geO
+fxMWwEjHhuSradVBp8ECQQD67UfvKtNtMtlDQs2M4MDR217oomAytER/Umy5bLbD
+TbT/5WD+mR6Ukmig9jHuZgQC138SKg4dcGM7aGLj+4hdAkEAwYsSXMQx1dMiq6J3
+LZhqaG1JRwMfQW8uh5Ub0/ebkgrHBfkUTk4k8dvi4TlEUWT1k0a0ZpC87YltVKVE
+U3GumQJBAM2f7mfOV23P0nys3JaKg1g1hYPrtBs44DzaBaC5ttc68Y0VojNgtM+Z
+XsYwmeA7lyPhBg+TiPeU5qyDMS6ULD0CQHNVerXJPKFdVlXNVRPYteBQ78/fbmrB
+5IprMtAXx585yOwoSA95xc5S6Fqqk6mlbio7ghl0uwEaWgqNCbBoGFECQDrcRBba
+ie2C6cKHhRMd4eFEEMzXL0rbKg+hS/EjCm+NLrQEiyMWso+OPAYVhnrgLgCQZvxQ
+O892Z/3u/TDSkRQ=
-----END PRIVATE KEY-----
@@ -1,17 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
-MIICozCCAgwCAQAwSDEPMA0GA1UECgwGUHlYTVBQMRMwEQYDVQQLDApVbml0IFRl
+MIICrzCCAhgCAQAwSDEPMA0GA1UECgwGUHlYTVBQMRMwEQYDVQQLDApVbml0IFRl
c3RzMSAwHgYDVQQDDBdjb21tb24tbmFtZS5leGFtcGxlLm9yZzCBnzANBgkqhkiG
-9w0BAQEFAAOBjQAwgYkCgYEA+H55d58bbXdsTiJ4Vlskh3AI//xZtJfuhUIp9nX5
-wuLBU2WyfSLEt1fFXHbkLeDRx9lOGwZ9Tpj4axPnZ4jQ5iHY/0Z+cvBBwW5BL47Z
-8pSB+MUAYuX2uw24mg5XZgK9dGKeIIpkO1dtTrnwpuY6S+PH+wyLiVUC9kBWoEef
-2p8CAwEAAaCCARkwggEVBgkqhkiG9w0BCQ4xggEGMIIBAjAJBgNVHRMEAjAAMAsG
-A1UdDwQEAwIF4DCB5wYDVR0RBIHfMIHcghBkbnMxLmV4YW1wbGUub3JnghBkbnMy
-LmV4YW1wbGUub3JnghIqLndpbGQuZXhhbXBsZS5vcmegKwYIKwYBBQUHCAegHxYd
-X3htcHAtc2VydmVyLnNydjEuZXhhbXBsZS5vcmegKwYIKwYBBQUHCAegHxYdX3ht
-cHAtc2VydmVyLnNydjIuZXhhbXBsZS5vcmegIwYIKwYBBQUHCAWgFwwVeG1wcGFk
-ZHIxLmV4YW1wbGUub3JnoCMGCCsGAQUFBwgFoBcMFXhtcHBhZGRyMi5leGFtcGxl
-Lm9yZzANBgkqhkiG9w0BAQUFAAOBgQBUFvQwcI9rLk7tKS7az1qAFPpDMoVEXVhG
-7m5R4MxD/7dVjsMK2QX2/xk0/k6ZKHpIrCZ1TqBJPN5Pcq6aoQZLDOjK52ZxgSSb
-lrd1p5GqT6v1TFsgwROpM1pPmZEOaID4wI59Z0ctcIdlhoUtNSEZrkvFJ6R4QNsf
-wqCb0a/etg==
+9w0BAQEFAAOBjQAwgYkCgYEAvbU0EPrI1SokCZiP39VdtknriXtXzEN0N5lH+ERG
+BFjKzae0ZE16UV7ixcnvqmfoB5+IXjHU3rgmr1TABq80y5CPbppU39HV6cyaVtaC
+17xRCcpsQEYCs3vB11liaf2H/zs81CtcDn+o1HWfoB3o47N9l2199H1B2D3zAJAQ
+tZUCAwEAAaCCASUwggEhBgkqhkiG9w0BCQ4xggESMIIBDjAJBgNVHRMEAjAAMAsG
+A1UdDwQEAwIF4DCB8wYDVR0RBIHrMIHoghBkbnMxLmV4YW1wbGUub3JnghBkbnMy
+LmV4YW1wbGUub3JnghIqLndpbGQuZXhhbXBsZS5vcmegMQYIKwYBBQUHCAegJRYj
+X3htcHAtY2xpZW50LmNsaWVudC1zcnYuZXhhbXBsZS5vcmegMQYIKwYBBQUHCAeg
+JRYjX3htcHAtc2VydmVyLnNlcnZlci1zcnYuZXhhbXBsZS5vcmegIwYIKwYBBQUH
+CAWgFwwVeG1wcGFkZHIxLmV4YW1wbGUub3JnoCMGCCsGAQUFBwgFoBcMFXhtcHBh
+ZGRyMi5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUFAAOBgQB8sdKSOHtqYE84RBwl
+djlBHMQsZ3bCVIKlLuBEOA2nCsbe6OHCfUhiDxQsCMOwWQqxNL4GSVv4Kxkmwwul
+YCVdRWssUvSKCqSfDAvBFfbfTjrYW4C+3/zbfTEGt2jhShRz1RM6vo8CnZT+ADFG
+X+Tpiie2aSVBZ9y37Ho3ozQTtw==
-----END CERTIFICATE REQUEST-----
@@ -1,18 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIC+TCCAmKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAzMQ8wDQYDVQQKDAZQeVhN
-UFAxEzARBgNVBAsMClVuaXQgVGVzdHMxCzAJBgNVBAMMAkNBMB4XDTExMDkwNTE4
-MjU1OFoXDTIxMDkwMjE4MjU1OFowSDEPMA0GA1UECgwGUHlYTVBQMRMwEQYDVQQL
+MIIDBTCCAm6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADAzMQ8wDQYDVQQKDAZQeVhN
+UFAxEzARBgNVBAsMClVuaXQgVGVzdHMxCzAJBgNVBAMMAkNBMB4XDTExMDkwNjE2
+MjAwNFoXDTIxMDkwMzE2MjAwNFowSDEPMA0GA1UECgwGUHlYTVBQMRMwEQYDVQQL
DApVbml0IFRlc3RzMSAwHgYDVQQDDBdjb21tb24tbmFtZS5leGFtcGxlLm9yZzCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA+H55d58bbXdsTiJ4Vlskh3AI//xZ
-tJfuhUIp9nX5wuLBU2WyfSLEt1fFXHbkLeDRx9lOGwZ9Tpj4axPnZ4jQ5iHY/0Z+
-cvBBwW5BL47Z8pSB+MUAYuX2uw24mg5XZgK9dGKeIIpkO1dtTrnwpuY6S+PH+wyL
-iVUC9kBWoEef2p8CAwEAAaOCAQYwggECMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXg
-MIHnBgNVHREEgd8wgdyCEGRuczEuZXhhbXBsZS5vcmeCEGRuczIuZXhhbXBsZS5v
-cmeCEioud2lsZC5leGFtcGxlLm9yZ6ArBggrBgEFBQcIB6AfFh1feG1wcC1zZXJ2
-ZXIuc3J2MS5leGFtcGxlLm9yZ6ArBggrBgEFBQcIB6AfFh1feG1wcC1zZXJ2ZXIu
-c3J2Mi5leGFtcGxlLm9yZ6AjBggrBgEFBQcIBaAXDBV4bXBwYWRkcjEuZXhhbXBs
-ZS5vcmegIwYIKwYBBQUHCAWgFwwVeG1wcGFkZHIyLmV4YW1wbGUub3JnMA0GCSqG
-SIb3DQEBBQUAA4GBAEYCT986NszS4XTflhkeTc9ivntt+TWgCf/LyfUOLEvrSTfz
-YD8CtysNNGz2tC0e3Vc6Ut2f/1YCn893JE7idtbouSoxb4twTpSjs2FXG+unEpa+
-RkuIHQyqsc69D8pfXt7KDFJyE12UsZXaSE4ARqpFCTVIXvVUZQfLgfbEd/E8
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvbU0EPrI1SokCZiP39VdtknriXtX
+zEN0N5lH+ERGBFjKzae0ZE16UV7ixcnvqmfoB5+IXjHU3rgmr1TABq80y5CPbppU
+39HV6cyaVtaC17xRCcpsQEYCs3vB11liaf2H/zs81CtcDn+o1HWfoB3o47N9l219
+9H1B2D3zAJAQtZUCAwEAAaOCARIwggEOMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXg
+MIHzBgNVHREEgeswgeiCEGRuczEuZXhhbXBsZS5vcmeCEGRuczIuZXhhbXBsZS5v
+cmeCEioud2lsZC5leGFtcGxlLm9yZ6AxBggrBgEFBQcIB6AlFiNfeG1wcC1jbGll
+bnQuY2xpZW50LXNydi5leGFtcGxlLm9yZ6AxBggrBgEFBQcIB6AlFiNfeG1wcC1z
+ZXJ2ZXIuc2VydmVyLXNydi5leGFtcGxlLm9yZ6AjBggrBgEFBQcIBaAXDBV4bXBw
+YWRkcjEuZXhhbXBsZS5vcmegIwYIKwYBBQUHCAWgFwwVeG1wcGFkZHIyLmV4YW1w
+bGUub3JnMA0GCSqGSIb3DQEBBQUAA4GBAKuMK8ZDD36qUq35I+mPIzgm74Z+xKz9
+haifGOK1EIX69AhfwFaArQkPu5VBCcJ9QzA4sTqp7sbx1ucBONAXfEeTeSOYO+BB
+j5OwHzxtngtzRk+DZ7KdCZ9Saka7Vf7XRRJ+5M3z/ReJ/9aYmvaXWxkcGtx066ZJ
+uHyVMqblMdho
-----END CERTIFICATE-----

0 comments on commit 72b77fc

Please sign in to comment.