Ejemplo n.º 1
0
def is_safe_hostname(hostname):
    """
    Tests a hostname to ensure it doesn't appear to be a blacklisted IP range.
    """
    # If we have no disallowed ips, we can skip any further validation
    # and there's no point in doing a DNS lookup to validate against
    # an empty list.
    if not DISALLOWED_IPS:
        return True

    if not hostname:
        return False

    hostname = ensure_fqdn(hostname)

    # Using the value from allowed_gai_family() in the context of getaddrinfo lets
    # us select whether to work with IPv4 DNS records, IPv6 records, or both.
    # The original create_connection function always returns all records.
    family = allowed_gai_family()

    try:
        for _, _, _, _, address in socket.getaddrinfo(hostname, 0, family,
                                                      socket.SOCK_STREAM):
            # Only one bad apple will spoil the entire lookup, so be nice.
            if not is_ipaddress_allowed(address[0]):
                return False
    except (socket.gaierror, UnicodeError):
        # If we fail to resolve, automatically bad
        return False

    return True
Ejemplo n.º 2
0
def safe_create_connection(address,
                           timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                           source_address=None,
                           socket_options=None):
    host, port = address
    if host.startswith("["):
        host = host.strip("[]")
    err = None

    host = ensure_fqdn(host)

    # Using the value from allowed_gai_family() in the context of getaddrinfo lets
    # us select whether to work with IPv4 DNS records, IPv6 records, or both.
    # The original create_connection function always returns all records.
    family = allowed_gai_family()

    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
        af, socktype, proto, canonname, sa = res

        # HACK(mattrobenolt): This is the only code that diverges
        ip = sa[0]
        if not is_ipaddress_allowed(ip):
            # I am explicitly choosing to be overly aggressive here. This means
            # the first IP that matches that hits our restricted set of IP networks,
            # we reject all records. In theory, there might be IP addresses that
            # are safe, but if one record is straddling safe and unsafe IPs, it's
            # suspicious.
            if host == ip:
                raise RestrictedIPAddress("(%s) matches the URL blacklist" %
                                          ip)
            raise RestrictedIPAddress("(%s/%s) matches the URL blacklist" %
                                      (host, ip))

        sock = None
        try:
            sock = socket.socket(af, socktype, proto)

            # If provided, set socket level options before connecting.
            _set_socket_options(sock, socket_options)

            if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                sock.settimeout(timeout)
            if source_address:
                sock.bind(source_address)
            sock.connect(sa)
            return sock

        except socket.error as e:
            err = e
            if sock is not None:
                sock.close()
                sock = None

    if err is not None:
        raise err

    raise socket.error("getaddrinfo returns an empty list")
Ejemplo n.º 3
0
 def test_ip_family_ipv6_disabled(self):
     with patch("urllib3.util.connection.HAS_IPV6", False):
         assert allowed_gai_family() == socket.AF_INET
Ejemplo n.º 4
0
 def test_ip_family_ipv6_enabled(self):
     with patch("urllib3.util.connection.HAS_IPV6", True):
         assert allowed_gai_family() == socket.AF_UNSPEC
Ejemplo n.º 5
0
 def test_ip_family_ipv6_disabled(self):
     with patch('urllib3.util.connection.HAS_IPV6', False):
         assert allowed_gai_family() == socket.AF_INET
Ejemplo n.º 6
0
 def test_ip_family_ipv6_enabled(self):
     with patch('urllib3.util.connection.HAS_IPV6', True):
         assert allowed_gai_family() == socket.AF_UNSPEC
Ejemplo n.º 7
0
 def test_ip_family_ipv6_disabled(self):
     with patch('urllib3.util.connection.HAS_IPV6', False):
         self.assertEqual(allowed_gai_family(), socket.AF_INET)
Ejemplo n.º 8
0
 def test_ip_family_ipv6_enabled(self):
     with patch('urllib3.util.connection.HAS_IPV6', True):
         self.assertEqual(allowed_gai_family(), socket.AF_UNSPEC)