def test_uri(self):
     """
     Returns the correct URIPattern from a certificate.
     """
     rv = extract_ids(CERT_OTHER_NAME)
     assert [URIPattern(b"http://example.com/")
             ] == [id for id in rv if isinstance(id, URIPattern)]
예제 #2
0
 def test_catches_wildcards(self):
     """
     Raise CertificateError if URI contains a *.
     """
     with pytest.raises(CertificateError):
         URIPattern(b"sip:*.foo.com")
예제 #3
0
 def test_catches_missing_colon(self):
     """
     Raise CertificateError if URI doesn't contain a `:`.
     """
     with pytest.raises(CertificateError):
         URIPattern(b"sip;foo.com")
예제 #4
0
 def test_enforces_bytes(self):
     """
     Raise TypeError if unicode is passed.
     """
     with pytest.raises(TypeError):
         URIPattern(u"sip:foo.com")
예제 #5
0
 def test_match(self):
     """
     Accept legal matches.
     """
     assert URI_ID(u"sip:foo.com").verify(URIPattern(b"sip:foo.com"))
예제 #6
0
 def test_dns_mismatch(self):
     """
     If the hostname doesn't match, verify returns False.
     """
     assert not URI_ID(u"sip:bar.com").verify(URIPattern(b"sip:foo.com"))
예제 #7
0
 def test_protocol_mismatch(self):
     """
     If protocol doesn't match, verify returns False.
     """
     assert not URI_ID(u"sip:foo.com").verify(URIPattern(b"xmpp:foo.com"))
예제 #8
0
def verifyHostname(connection, hostname):
    if _is_ip_address(hostname):
        hostname_id = IPADDRESS_ID(hostname)
    else:
        hostname_id = DNS_ID(hostname)

    cert = connection.get_peer_certificate()
    ids = []

    # Basically the same as service_identity.pyopenssl.extract_ids, but with
    # subjectAltName support for iPAddress IDs and IP Addresses stuck in dNSName ids
    for i in range(cert.get_extension_count()):
        ext = cert.get_extension(i)
        if ext.get_short_name() == b"subjectAltName":
            names, _ = decode(ext.get_data(), asn1Spec=GeneralNames())
            for n in names:
                name_string = n.getName()

                if name_string == "iPAddress":
                    ids.append(IPADDRESSPattern(n.getComponent().asOctets()))

                elif name_string == "dNSName" and _is_ip_address(
                        n.getComponent().asOctets().strip()):
                    # If an IP Address is passed as a dNSName, it will
                    # cause service_identity to throw an exception, as
                    # it doesn't consider this valid.   From reading the
                    # RFCs, i think it's a gray area, so i'm going to
                    # allow it, since we've seen it happen with a customer.
                    try:
                        ip_string = n.getComponent().asOctets().strip()
                        if ":" in ip_string:
                            value = inet_pton(AF_INET6, ip_string)
                        else:
                            value = inet_pton(AF_INET, ip_string)

                        ids.append(IPADDRESSPattern(value))
                    except CertificateError as e:
                        log.warning(
                            "Ignoring invalid dNSName record in subjectAltName: %s",
                            e)

                # Normal behavior below:
                elif name_string == "dNSName":
                    ids.append(DNSPattern(n.getComponent().asOctets()))
                elif name_string == "uniformResourceIdentifier":
                    ids.append(URIPattern(n.getComponent().asOctets()))
                elif name_string == "otherName":
                    comp = n.getComponent()
                    oid = comp.getComponentByPosition(0)
                    if oid == ID_ON_DNS_SRV:
                        srv, _ = decode(comp.getComponentByPosition(1))
                        if isinstance(srv, IA5String):
                            ids.append(SRVPattern(srv.asOctets()))
                        else:  # pragma: nocover
                            raise CertificateError(
                                "Unexpected certificate content.")

    if not ids:
        # http://tools.ietf.org/search/rfc6125#section-6.4.4
        # A client MUST NOT seek a match for a reference identifier of CN-ID if
        # the presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
        # application-specific identifier types supported by the client.
        warnings.warn(
            "Certificate has no `subjectAltName`, falling back to check for a "
            "`commonName` for now.  This feature is being removed by major "
            "browsers and deprecated by RFC 2818.", SubjectAltNameWarning)
        ids = [
            DNSPattern(c[1]) for c in cert.get_subject().get_components()
            if c[0] == b"CN"
        ]

    verify_service_identity(
        cert_patterns=ids,
        obligatory_ids=[hostname_id],
        optional_ids=[],
    )