Example #1
0
    def __init__(self, ip_address):
        if not isinstance(ip_address, text_type):
            raise TypeError("IPADDRESS-ID must be a unicode string.")

        ip_address = ip_address.strip()
        if not _is_ip_address(ip_address):
            raise ValueError("Invalid IPADDRESS-ID.")

        self.ip_address = ip_address
Example #2
0
    def __init__(self, ip_address):
        if not isinstance(ip_address, text_type):
            raise TypeError("IPADDRESS-ID must be a unicode string.")

        ip_address = ip_address.strip()
        if not _is_ip_address(ip_address):
            raise ValueError("Invalid IPADDRESS-ID.")

        self.ip_address = ip_address
Example #3
0
 def test_no_ips(self):
     """
     Return False for patterns and hosts that aren't IP addresses.
     """
     for s in [
         b"*.twistedmatrix.com",
         b"twistedmatrix.com",
         b"mail.google.com",
         b"omega7.de",
         b"omega7",
     ]:
         assert not _is_ip_address(s), "False positive {0!r}".format(s)
Example #4
0
 def test_no_ips(self):
     """
     Return False for patterns and hosts that aren't IP addresses.
     """
     for s in [
         b"*.twistedmatrix.com",
         b"twistedmatrix.com",
         b"mail.google.com",
         b"omega7.de",
         b"omega7",
     ]:
         assert not _is_ip_address(s), "False positive {0!r}".format(s)
Example #5
0
 def test_ips(self):
     """
     Returns True for patterns and hosts that could match IP addresses.
     """
     for s in [
         b"127.0.0.1",
         u"127.0.0.1",
         b"172.16.254.12",
         b"*.0.0.1",
         b"::1",
         b"*::1",
         b"2001:0db8:0000:0000:0000:ff00:0042:8329",
         b"2001:0db8::ff00:0042:8329",
     ]:
         assert _is_ip_address(s), "Not detected {0!r}".format(s)
Example #6
0
 def test_ips(self):
     """
     Returns True for patterns and hosts that could match IP addresses.
     """
     for s in [
         b"127.0.0.1",
         u"127.0.0.1",
         b"172.16.254.12",
         b"*.0.0.1",
         b"::1",
         b"*::1",
         b"2001:0db8:0000:0000:0000:ff00:0042:8329",
         b"2001:0db8::ff00:0042:8329",
     ]:
         assert _is_ip_address(s), "Not detected {0!r}".format(s)
Example #7
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=[],
    )
Example #8
0
 def test_not_ips(self, not_ip):
     """
     Return False for patterns and hosts that aren't IP addresses.
     """
     assert _is_ip_address(not_ip) is False
Example #9
0
 def test_ips(self, ip):
     """
     Returns True for patterns and hosts that could match IP addresses.
     """
     assert _is_ip_address(ip) is True
Example #10
0
 def test_not_ips(self, not_ip):
     """
     Return False for patterns and hosts that aren't IP addresses.
     """
     assert _is_ip_address(not_ip) is False
Example #11
0
 def test_ips(self, ip):
     """
     Returns True for patterns and hosts that could match IP addresses.
     """
     assert _is_ip_address(ip) is True
Example #12
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=[],
    )