예제 #1
0
 def test_mismatch_dns(self):
     """
     If the dns_id doesn't match, verify returns False.
     """
     assert not (
         SRV_ID(u"_mail.foo.com").verify(SRVPattern(b"_mail.bar.com"))
     )
예제 #2
0
 def test_mismatch_service_name(self):
     """
     If the service name doesn't match, verify returns False.
     """
     assert not (
         SRV_ID(u"_mail.foo.com").verify(SRVPattern(b"_xmpp.foo.com"))
     )
예제 #3
0
 def test_match_idna(self):
     """
     IDNAs are handled properly.
     """
     assert SRV_ID(u"_mail.f\xf8\xf8.com").verify(
         SRVPattern(b'_mail.xn--f-5gaa.com')
     )
예제 #4
0
 def test_obligatory_mismatch(self):
     """
     Raise if one of the obligatory IDs doesn't match.
     """
     i = DNS_ID(u"example.net")
     with pytest.raises(VerificationError) as e:
         verify_service_identity(
             [SRVPattern(b"_mail.example.net"), DNSPattern(b"example.com")],
             obligatory_ids=[SRV_ID(u"_mail.example.net"), i],
             optional_ids=[],
         )
     assert [DNSMismatch(mismatched_id=i)] == e.value.errors
예제 #5
0
 def test_optional_mismatch(self):
     """
     Raise VerificationError if an ID from optional_ids does not match
     a pattern of respective type even if obligatory IDs match.
     """
     i = SRV_ID(u"_xmpp.example.com")
     with pytest.raises(VerificationError) as e:
         verify_service_identity(
             [DNSPattern(b"example.net"), SRVPattern(b"_mail.example.com")],
             obligatory_ids=[DNS_ID(u"example.net")],
             optional_ids=[i],
         )
     assert [SRVMismatch(mismatched_id=i)] == e.value.errors
예제 #6
0
 def test_contains_optional_and_matches(self):
     """
     If an optional ID is found, return the match within the returned
     list and don't raise an error.
     """
     p = SRVPattern(b"_mail.example.net")
     i = SRV_ID(u"_mail.example.net")
     rv = verify_service_identity(
         [DNSPattern(b"example.net"), p],
         obligatory_ids=[DNS_ID(u"example.net")],
         optional_ids=[i],
     )
     assert ServiceMatch(cert_pattern=p, service_id=i) == rv[1]
예제 #7
0
 def test_catches_wildcards(self):
     """
     Raise CertificateError if SRV contains a *.
     """
     with pytest.raises(CertificateError):
         SRVPattern(b"sip:*.foo.com")
예제 #8
0
 def test_catches_missing_underscore(self):
     """
     Raise CertificateError if SRV doesn't start with a `_`.
     """
     with pytest.raises(CertificateError):
         SRVPattern(b"foo.com")
예제 #9
0
 def test_enforces_bytes(self):
     """
     Raise TypeError if unicode is passed.
     """
     with pytest.raises(TypeError):
         SRVPattern(u"_mail.example.com")
예제 #10
0
 def test_match(self):
     """
     Accept legal matches.
     """
     assert SRV_ID(u"_mail.foo.com").verify(SRVPattern(b"_mail.foo.com"))
예제 #11
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=[],
    )