Beispiel #1
0
    def from_file(cls, f):
        ver, msg, rsv, atyp = struct.unpack("!BBBB", f.safe_read(4))
        if rsv != 0x00:
            raise SocksError(REP.GENERAL_SOCKS_SERVER_FAILURE,
                             "Socks Request: Invalid reserved byte: %s" % rsv)
        if atyp == ATYP.IPV4_ADDRESS:
            # We use tnoa here as ntop is not commonly available on Windows.
            host = ipaddress.IPv4Address(f.safe_read(4)).compressed
            use_ipv6 = False
        elif atyp == ATYP.IPV6_ADDRESS:
            host = ipaddress.IPv6Address(f.safe_read(16)).compressed
            use_ipv6 = True
        elif atyp == ATYP.DOMAINNAME:
            length, = struct.unpack("!B", f.safe_read(1))
            host = f.safe_read(length)
            if not utils.is_valid_host(host):
                raise SocksError(REP.GENERAL_SOCKS_SERVER_FAILURE,
                                 "Invalid hostname: %s" % host)
            host = host.decode("idna")
            use_ipv6 = False
        else:
            raise SocksError(REP.ADDRESS_TYPE_NOT_SUPPORTED,
                             "Socks Request: Unknown ATYP: %s" % atyp)

        port, = struct.unpack("!H", f.safe_read(2))
        addr = tcp.Address((host, port), use_ipv6=use_ipv6)
        return cls(ver, msg, atyp, addr)
    def _parse_init_connect(self, line):
        """
            Returns (host, port, httpversion) if line is a valid CONNECT line.
            http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 section 3.1
        """
        v = self._parse_init(line)
        if not v:
            return None
        method, url, httpversion = v

        if method.upper() != 'CONNECT':
            return None
        try:
            host, port = url.split(":")
        except ValueError:
            return None
        try:
            port = int(port)
        except ValueError:
            return None
        if not utils.is_valid_port(port):
            return None
        if not utils.is_valid_host(host):
            return None
        return host, port, httpversion
Beispiel #3
0
    def from_file(cls, f):
        ver, msg, rsv, atyp = struct.unpack("!BBBB", f.safe_read(4))
        if rsv != 0x00:
            raise SocksError(
                REP.GENERAL_SOCKS_SERVER_FAILURE,
                "Socks Request: Invalid reserved byte: %s" % rsv
            )
        if atyp == ATYP.IPV4_ADDRESS:
            # We use tnoa here as ntop is not commonly available on Windows.
            host = ipaddress.IPv4Address(f.safe_read(4)).compressed
            use_ipv6 = False
        elif atyp == ATYP.IPV6_ADDRESS:
            host = ipaddress.IPv6Address(f.safe_read(16)).compressed
            use_ipv6 = True
        elif atyp == ATYP.DOMAINNAME:
            length, = struct.unpack("!B", f.safe_read(1))
            host = f.safe_read(length)
            if not utils.is_valid_host(host):
                raise SocksError(REP.GENERAL_SOCKS_SERVER_FAILURE, "Invalid hostname: %s" % host)
            host = host.decode("idna")
            use_ipv6 = False
        else:
            raise SocksError(REP.ADDRESS_TYPE_NOT_SUPPORTED,
                             "Socks Request: Unknown ATYP: %s" % atyp)

        port, = struct.unpack("!H", f.safe_read(2))
        addr = tcp.Address((host, port), use_ipv6=use_ipv6)
        return cls(ver, msg, atyp, addr)
Beispiel #4
0
    def _parse_init_connect(self, line):
        """
            Returns (host, port, httpversion) if line is a valid CONNECT line.
            http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 section 3.1
        """
        v = self._parse_init(line)
        if not v:
            return None
        method, url, httpversion = v

        if method.upper() != 'CONNECT':
            return None
        try:
            host, port = url.split(":")
        except ValueError:
            return None
        try:
            port = int(port)
        except ValueError:
            return None
        if not utils.is_valid_port(port):
            return None
        if not utils.is_valid_host(host):
            return None
        return host, port, httpversion
Beispiel #5
0
 def sni(self):
     for extension in self._client_hello.extensions:
         is_valid_sni_extension = (extension.type == 0x00
                                   and len(extension.server_names) == 1
                                   and extension.server_names[0].type == 0
                                   and utils.is_valid_host(
                                       extension.server_names[0].name))
         if is_valid_sni_extension:
             return extension.server_names[0].name.decode("idna")
Beispiel #6
0
 def sni(self):
     for extension in self._client_hello.extensions:
         is_valid_sni_extension = (
             extension.type == 0x00 and
             len(extension.server_names) == 1 and
             extension.server_names[0].type == 0 and
             utils.is_valid_host(extension.server_names[0].name)
         )
         if is_valid_sni_extension:
             return extension.server_names[0].name.decode("idna")
Beispiel #7
0
def parse(url):
    """
        URL-parsing function that checks that
            - port is an integer 0-65535
            - host is a valid IDNA-encoded hostname with no null-bytes
            - path is valid ASCII

        Args:
            A URL (as bytes or as unicode)

        Returns:
            A (scheme, host, port, path) tuple

        Raises:
            ValueError, if the URL is not properly formatted.
    """
    parsed = urllib.parse.urlparse(url)

    if not parsed.hostname:
        raise ValueError("No hostname given")

    if isinstance(url, six.binary_type):
        host = parsed.hostname

        # this should not raise a ValueError,
        # but we try to be very forgiving here and accept just everything.
        # decode_parse_result(parsed, "ascii")
    else:
        host = parsed.hostname.encode("idna")
        parsed = encode_parse_result(parsed, "ascii")

    port = parsed.port
    if not port:
        port = 443 if parsed.scheme == b"https" else 80

    full_path = urllib.parse.urlunparse(
        (b"", b"", parsed.path, parsed.params, parsed.query, parsed.fragment)
    )
    if not full_path.startswith(b"/"):
        full_path = b"/" + full_path

    if not utils.is_valid_host(host):
        raise ValueError("Invalid Host")
    if not utils.is_valid_port(port):
        raise ValueError("Invalid Port")

    return parsed.scheme, host, port, full_path
Beispiel #8
0
def parse(url):
    """
        URL-parsing function that checks that
            - port is an integer 0-65535
            - host is a valid IDNA-encoded hostname with no null-bytes
            - path is valid ASCII

        Args:
            A URL (as bytes or as unicode)

        Returns:
            A (scheme, host, port, path) tuple

        Raises:
            ValueError, if the URL is not properly formatted.
    """
    parsed = urllib.parse.urlparse(url)

    if not parsed.hostname:
        raise ValueError("No hostname given")

    if isinstance(url, six.binary_type):
        host = parsed.hostname

        # this should not raise a ValueError,
        # but we try to be very forgiving here and accept just everything.
        # decode_parse_result(parsed, "ascii")
    else:
        host = parsed.hostname.encode("idna")
        parsed = encode_parse_result(parsed, "ascii")

    port = parsed.port
    if not port:
        port = 443 if parsed.scheme == b"https" else 80

    full_path = urllib.parse.urlunparse(
        (b"", b"", parsed.path, parsed.params, parsed.query, parsed.fragment)
    )
    if not full_path.startswith(b"/"):
        full_path = b"/" + full_path

    if not utils.is_valid_host(host):
        raise ValueError("Invalid Host")
    if not utils.is_valid_port(port):
        raise ValueError("Invalid Port")

    return parsed.scheme, host, port, full_path
Beispiel #9
0
def _parse_authority_form(hostport):
    """
        Returns (host, port) if hostport is a valid authority-form host specification.
        http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 section 3.1

        Raises:
            ValueError, if the input is malformed
    """
    try:
        host, port = hostport.split(b":")
        port = int(port)
        if not utils.is_valid_host(host) or not utils.is_valid_port(port):
            raise ValueError()
    except ValueError:
        raise exceptions.HttpSyntaxException("Invalid host specification: {}".format(hostport))

    return host, port
Beispiel #10
0
def test_is_valid_host():
    assert not utils.is_valid_host(b"")
    assert utils.is_valid_host(b"one.two")
    assert not utils.is_valid_host(b"one" * 255)
    assert utils.is_valid_host(b"one.two.")