Exemplo n.º 1
0
 def new_setHost(self, host, port, ssl=0):
     try:
         ip = IPAddress(host.decode("idna"))
     except AddrFormatError:
         ip = None  # `host` is a host or domain name.
     self._forceSSL = ssl  # set first so isSecure will work
     if self.isSecure():
         default = 443
     else:
         default = 80
     if ip is None:
         hostHeader = host
     elif ip.version == 4:
         hostHeader = host
     else:
         hostHeader = b"[" + host + b"]"
     if port != default:
         hostHeader += b":" + intToBytes(port)
     self.requestHeaders.setRawHeaders(b"host", [hostHeader])
     if ip is None:
         # Pretend that a host or domain name is an IPv4 address.
         self.host = address.IPv4Address("TCP", host, port)
     elif ip.version == 4:
         self.host = address.IPv4Address("TCP", host, port)
     else:
         self.host = address.IPv6Address("TCP", host, port)
Exemplo n.º 2
0
    def getHost(self):
        """
        Returns an IPv6Address.

        This indicates the address from which I am connecting.
        """
        return address.IPv6Address('TCP', *(self.socket.getsockname()))
Exemplo n.º 3
0
def fix_twisted_web_server_addressToTuple():
    """Add ipv6 support to t.w.server._addressToTuple()

       Return address.IPv6Address where appropriate.

       See https://bugs.launchpad.net/ubuntu/+source/twisted/+bug/1604608
    """
    import twisted.web.server
    from twisted.internet import address

    def new_addressToTuple(addr):
        if isinstance(addr, address.IPv4Address):
            return ("INET", addr.host, addr.port)
        elif isinstance(addr, address.IPv6Address):
            return ("INET6", addr.host, addr.port)
        elif isinstance(addr, address.UNIXAddress):
            return ("UNIX", addr.name)
        else:
            return tuple(addr)

    test = address.IPv6Address("TCP", "fe80::1", "80")
    try:
        twisted.web.server._addressToTuple(test)
    except TypeError:
        twisted.web.server._addressToTuple = new_addressToTuple
Exemplo n.º 4
0
 def test_validIPv6HeaderResolves_getPeerHost(self):
     """
     Test if IPv6 headers result in the correct host and peer data.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address('TCP', b'::1',
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(b'PROXY TCP6 ::1 ::2 8080 8888\r\n')
     self.assertEqual(proto.getPeer().host, b'::1')
     self.assertEqual(proto.getPeer().port, 8080)
     self.assertEqual(
         proto.wrappedProtocol.transport.getPeer().host,
         b'::1',
     )
     self.assertEqual(
         proto.wrappedProtocol.transport.getPeer().port,
         8080,
     )
     self.assertEqual(proto.getHost().host, b'::2')
     self.assertEqual(proto.getHost().port, 8888)
     self.assertEqual(
         proto.wrappedProtocol.transport.getHost().host,
         b'::2',
     )
     self.assertEqual(
         proto.wrappedProtocol.transport.getHost().port,
         8888,
     )
Exemplo n.º 5
0
 def getPeer(self):
     if self.parent._options["proxy_header"] and self.request.requestHeaders.hasHeader(self.parent._options["proxy_header"]):
         ip = self.request.requestHeaders.getRawHeaders(self.parent._options["proxy_header"])[0].decode().split(",")[-1].strip()
         if re.match("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", ip):
             return address.IPv4Address("TCP", ip, None)
         else:
             return address.IPv6Address("TCP", ip, None)
     return ProtocolWrapper.getPeer(self)
Exemplo n.º 6
0
 def test_describe(self):
     f = transit.InboundConnectionFactory(None)
     addrH = address.HostnameAddress("example.com", 1234)
     self.assertEqual(f._describePeer(addrH), "<-example.com:1234")
     addr4 = address.IPv4Address("TCP", "1.2.3.4", 1234)
     self.assertEqual(f._describePeer(addr4), "<-1.2.3.4:1234")
     addr6 = address.IPv6Address("TCP", "::1", 1234)
     self.assertEqual(f._describePeer(addr6), "<-::1:1234")
     addrU = address.UNIXAddress("/dev/unlikely")
     self.assertEqual(f._describePeer(addrU),
                      "<-UNIXAddress('/dev/unlikely')")
 def test_overflowBytesSentToWrappedProtocol(self):
     """
     Test if non-header bytes are passed to the wrapped protocol.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address("TCP", b"::1",
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(b"PROXY TCP6 ::1 ::2 8080 8888\r\nHTTP/1.1 / GET")
     self.assertEqual(proto.wrappedProtocol.data, b"HTTP/1.1 / GET")
Exemplo n.º 8
0
 def test_overflowBytesSentToWrappedProtocol(self):
     """
     Test if non-header bytes are passed to the wrapped protocol.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address('TCP', b'::1',
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(self.IPV6HEADER + b'HTTP/1.1 / GET')
     self.assertEqual(proto.wrappedProtocol.data, b'HTTP/1.1 / GET')
 def test_overflowBytesSentToWrappedProtocolChunks(self):
     """
     Test if header streaming passes extra data appropriately.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address("TCP", b"::1",
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(b"PROXY TCP6 ::1 ::2 ")
     proto.dataReceived(b"8080 8888\r\nHTTP/1.1 / GET")
     self.assertEqual(proto.wrappedProtocol.data, b"HTTP/1.1 / GET")
Exemplo n.º 10
0
    def getHost(self):
        """
        Return the local address of the UDP connection

        @returns: the local address of the UDP connection
        @rtype: L{IPv4Address} or L{IPv6Address}
        """
        addr = self.socket.getsockname()
        if self.addressFamily == socket.AF_INET:
            return address.IPv4Address('UDP', *addr)
        elif self.addressFamily == socket.AF_INET6:
            return address.IPv6Address('UDP', *(addr[:2]))
Exemplo n.º 11
0
 def test_overflowBytesSentToWrappedProtocolChunks(self):
     """
     Test if header streaming passes extra data appropriately.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address('TCP', b'::1',
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(self.IPV6HEADER[:18])
     proto.dataReceived(self.IPV6HEADER[18:] + b'HTTP/1.1 / GET')
     self.assertEqual(proto.wrappedProtocol.data, b'HTTP/1.1 / GET')
Exemplo n.º 12
0
 def test_invalidHeaderDisconnects(self):
     """
     Test if invalid headers result in connectionLost events.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address('TCP', b'::1',
                                                       8080), )
     transport = StringTransportWithDisconnection()
     transport.protocol = proto
     proto.makeConnection(transport)
     proto.dataReceived(b'\x00' + self.IPV4HEADER[1:])
     self.assertFalse(transport.connected)
Exemplo n.º 13
0
 def test_overflowBytesSentToWrappedProtocolAfter(self):
     """
     Test if wrapper writes all data to wrapped protocol after parsing.
     """
     factory = HAProxyWrappingFactory(Factory.forProtocol(StaticProtocol))
     proto = factory.buildProtocol(address.IPv6Address('TCP', b'::1',
                                                       8080), )
     transport = StringTransportWithDisconnection()
     proto.makeConnection(transport)
     proto.dataReceived(b'PROXY TCP6 ::1 ::2 ')
     proto.dataReceived(b'8080 8888\r\nHTTP/1.1 / GET')
     proto.dataReceived(b'\r\n\r\n')
     self.assertEqual(proto.wrappedProtocol.data, b'HTTP/1.1 / GET\r\n\r\n')
Exemplo n.º 14
0
    def __call__(self, arglist, line):
        # RFC 2821 4.5.3.1
        if len(line) > 256:
            raise AddressTooLong()

        match = self.address.match(line)
        if match is None:
            raise InvalidAddress()

        d = match.groupdict()

        if d['adl']:
            route = d['adl'][1:].split(',@')
        else:
            route = None

        localpart = d['localPart']

        if d['domain']:
            domain = d['domain']
        elif d['ipv4Literal']:
            domain = address.IPv4Address(d['ipv4Literal'])
        elif d['ipv6Literal']:
            # Chop off the leading 'IPv6:'
            domain = address.IPv6Address(d['ipv6Literal'][5:])
        else:
            domain = d['generalLiteral']

        at = d['at']

        if at:
            localpart = localpart or ''
            domain = domain or ''

        arglist.append(Address(route, localpart, domain))

        return match.end()
Exemplo n.º 15
0
    def parse(cls, line):
        """
        Parse a bytestring as a full PROXY protocol header line.

        @param line: A bytestring that represents a valid HAProxy PROXY
            protocol header line.
        @type line: bytes

        @return: A L{_interfaces.IProxyInfo} containing the parsed data.

        @raises InvalidProxyHeader: If the bytestring does not represent a
            valid PROXY header.

        @raises InvalidNetworkProtocol: When no protocol can be parsed or is
            not one of the allowed values.

        @raises MissingAddressData: When the protocol is TCP* but the header
            does not contain a complete set of addresses and ports.
        """
        originalLine = line
        proxyStr = None
        networkProtocol = None
        sourceAddr = None
        sourcePort = None
        destAddr = None
        destPort = None

        with convertError(ValueError, InvalidProxyHeader):
            proxyStr, line = line.split(b" ", 1)

        if proxyStr != cls.PROXYSTR:
            raise InvalidProxyHeader()

        with convertError(ValueError, InvalidNetworkProtocol):
            networkProtocol, line = line.split(b" ", 1)

        if networkProtocol not in cls.ALLOWED_NET_PROTOS:
            raise InvalidNetworkProtocol()

        if networkProtocol == cls.UNKNOWN_PROTO:

            return _info.ProxyInfo(originalLine, None, None)

        with convertError(ValueError, MissingAddressData):
            sourceAddr, line = line.split(b" ", 1)

        with convertError(ValueError, MissingAddressData):
            destAddr, line = line.split(b" ", 1)

        with convertError(ValueError, MissingAddressData):
            sourcePort, line = line.split(b" ", 1)

        with convertError(ValueError, MissingAddressData):
            destPort = line.split(b" ")[0]

        if networkProtocol == cls.TCP4_PROTO:

            return _info.ProxyInfo(
                originalLine,
                address.IPv4Address("TCP", sourceAddr, int(sourcePort)),
                address.IPv4Address("TCP", destAddr, int(destPort)),
            )

        return _info.ProxyInfo(
            originalLine,
            address.IPv6Address("TCP", sourceAddr, int(sourcePort)),
            address.IPv6Address("TCP", destAddr, int(destPort)),
        )
Exemplo n.º 16
0
 def getDestination(self):
     """
     @see twisted.internet.interfaces.IConnector.getDestination
     """
     return address.IPv6Address('TCP', self.host, self.port, self.flowinfo,
                                self.scopeid)
Exemplo n.º 17
0
def fix_twisted_web_http_Request():
    """Fix broken IPv6 handling in twisted.web.http.request.Request."""
    from netaddr import IPAddress
    from netaddr.core import AddrFormatError
    from twisted.internet import address
    from twisted.python.compat import intToBytes, networkString
    import twisted.web.http
    from twisted.web.server import Request
    from twisted.web.test.requesthelper import DummyChannel

    def new_getRequestHostname(self):
        # Unlike upstream, support/require IPv6 addresses to be
        # [ip:v6:add:ress]:port, with :port being optional.
        # IPv6 IP addresses are wrapped in [], to disambigate port numbers.
        host = self.getHeader(b"host")
        if host:
            if host.startswith(b"[") and b"]" in host:
                if host.find(b"]") < host.rfind(b":"):
                    # The format is: [ip:add:ress]:port.
                    return host[:host.rfind(b":")]
                else:
                    # no :port after [...]
                    return host
            # No brackets, so it must be host:port or IPv4:port.
            return host.split(b":", 1)[0]
        host = self.getHost().host
        try:
            if isinstance(host, str):
                ip = IPAddress(host)
            else:
                ip = IPAddress(host.decode("idna"))
        except AddrFormatError:
            # If we could not convert the hostname to an IPAddress, assume that
            # it is a hostname.
            return networkString(host)
        if ip.version == 4:
            return networkString(host)
        else:
            return networkString("[" + host + "]")

    def new_setHost(self, host, port, ssl=0):
        try:
            ip = IPAddress(host.decode("idna"))
        except AddrFormatError:
            ip = None  # `host` is a host or domain name.
        self._forceSSL = ssl  # set first so isSecure will work
        if self.isSecure():
            default = 443
        else:
            default = 80
        if ip is None:
            hostHeader = host
        elif ip.version == 4:
            hostHeader = host
        else:
            hostHeader = b"[" + host + b"]"
        if port != default:
            hostHeader += b":" + intToBytes(port)
        self.requestHeaders.setRawHeaders(b"host", [hostHeader])
        if ip is None:
            # Pretend that a host or domain name is an IPv4 address.
            self.host = address.IPv4Address("TCP", host, port)
        elif ip.version == 4:
            self.host = address.IPv4Address("TCP", host, port)
        else:
            self.host = address.IPv6Address("TCP", host, port)

    request = Request(DummyChannel(), False)
    request.client = address.IPv6Address("TCP", "fe80::1", "80")
    request.setHost(b"fe80::1", 1234)
    if isinstance(request.host, address.IPv4Address):
        # Buggy code calls fe80::1 an IPv4Address.
        twisted.web.http.Request.setHost = new_setHost
    if request.getRequestHostname() == b"fe80":
        # The fe80::1 test address above was incorrectly interpreted as
        # address='fe80', port = ':1', because it does host.split(':', 1)[0].
        twisted.web.http.Request.getRequestHostname = new_getRequestHostname
Exemplo n.º 18
0
def fix_twisted_web_http_Request():
    """Add ipv6 support to Request.getClientIP()

       Specifically, IPv6 IP addresses need to be wrapped in [], and return
       address.IPv6Address when needed.

       See https://bugs.launchpad.net/ubuntu/+source/twisted/+bug/1604608
    """
    from netaddr import IPAddress
    from netaddr.core import AddrFormatError
    from twisted.internet import address
    from twisted.python.compat import (
        intToBytes,
        networkString,
    )
    import twisted.web.http
    from twisted.web.server import Request
    from twisted.web.test.requesthelper import DummyChannel

    def new_getClientIP(self):
        from twisted.internet import address
        # upstream doesn't check for address.IPv6Address
        if isinstance(self.client, address.IPv4Address):
            return self.client.host
        elif isinstance(self.client, address.IPv6Address):
            return self.client.host
        else:
            return None

    def new_getRequestHostname(self):
        # Unlike upstream, support/require IPv6 addresses to be
        # [ip:v6:add:ress]:port, with :port being optional.
        # IPv6 IP addresses are wrapped in [], to disambigate port numbers.
        host = self.getHeader(b'host')
        if host:
            if host.startswith(b'[') and b']' in host:
                if host.find(b']') < host.rfind(b':'):
                    # The format is: [ip:add:ress]:port.
                    return host[:host.rfind(b':')]
                else:
                    # no :port after [...]
                    return host
            # No brackets, so it must be host:port or IPv4:port.
            return host.split(b':', 1)[0]
        host = self.getHost().host
        try:
            if isinstance(host, str):
                ip = IPAddress(host)
            else:
                ip = IPAddress(host.decode("idna"))
        except AddrFormatError:
            # If we could not convert the hostname to an IPAddress, assume that
            # it is a hostname.
            return networkString(host)
        if ip.version == 4:
            return networkString(host)
        else:
            return networkString('[' + host + ']')

    def new_setHost(self, host, port, ssl=0):
        try:
            ip = IPAddress(host.decode("idna"))
        except AddrFormatError:
            ip = None  # `host` is a host or domain name.
        self._forceSSL = ssl  # set first so isSecure will work
        if self.isSecure():
            default = 443
        else:
            default = 80
        if ip is None:
            hostHeader = host
        elif ip.version == 4:
            hostHeader = host
        else:
            hostHeader = b"[" + host + b"]"
        if port != default:
            hostHeader += b":" + intToBytes(port)
        self.requestHeaders.setRawHeaders(b"host", [hostHeader])
        if ip is None:
            # Pretend that a host or domain name is an IPv4 address.
            self.host = address.IPv4Address("TCP", host, port)
        elif ip.version == 4:
            self.host = address.IPv4Address("TCP", host, port)
        else:
            self.host = address.IPv6Address("TCP", host, port)

    request = Request(DummyChannel(), False)
    request.client = address.IPv6Address('TCP', 'fe80::1', '80')
    request.setHost(b"fe80::1", 1234)
    if request.getClientIP() is None:
        # Buggy code returns None for IPv6 addresses.
        twisted.web.http.Request.getClientIP = new_getClientIP
    if isinstance(request.host, address.IPv4Address):
        # Buggy code calls fe80::1 an IPv4Address.
        twisted.web.http.Request.setHost = new_setHost
    if request.getRequestHostname() == b'fe80':
        # The fe80::1 test address above was incorrectly interpreted as
        # address='fe80', port = ':1', because it does host.split(':', 1)[0].
        twisted.web.http.Request.getRequestHostname = new_getRequestHostname