Example #1
0
 def assert_decode(self, data, cls):
     # manual decode
     request, realm, _ = codec.asn1mod.decode_proxymessage(data)
     self.assertEqual(realm, self.realm)
     inst = cls.parse_request(realm, request)
     self.assertIsInstance(inst, cls)
     self.assertEqual(inst.realm, self.realm)
     self.assertEqual(inst.request, request)
     if cls is codec.KPASSWDProxyRequest:
         self.assertEqual(inst.version, 1)
     # codec decode
     outer = codec.decode(data)
     self.assertEqual(outer.realm, self.realm)
     self.assertIsInstance(outer, cls)
     # re-decode
     der = codec.encode(outer.request)
     self.assertIsInstance(der, bytes)
     decoded = codec.decode(der)
     self.assertIsInstance(decoded, cls)
     return outer
Example #2
0
 def assert_decode(self, data, cls):
     outer = codec.decode(data)
     self.assertEqual(outer.realm, self.realm)
     self.assertIsInstance(outer, cls)
     if cls is not codec.KPASSWDProxyRequest:
         inner, err = decoder.decode(outer.request[outer.OFFSET :], asn1Spec=outer.TYPE())
         if err:  # pragma: no cover
             self.fail(err)
         self.assertIsInstance(inner, outer.TYPE)
         der = encoder.encode(inner)
         encoded = codec.encode(der)
         self.assertIsInstance(encoded, bytes)
     return outer
Example #3
0
 def assert_decode(self, data, cls):
     outer = codec.decode(data)
     self.assertEqual(outer.realm, self.realm)
     self.assertIsInstance(outer, cls)
     if cls is not codec.KPASSWDProxyRequest:
         inner, err = decoder.decode(outer.request[outer.OFFSET:],
                                     asn1Spec=outer.TYPE())
         if err:  # pragma: no cover
             self.fail(err)
         self.assertIsInstance(inner, outer.TYPE)
         der = encoder.encode(inner)
         encoded = codec.encode(der)
         self.assertIsInstance(encoded, bytes)
     return outer
Example #4
0
    def __call__(self, env, start_response):
        try:
            # Validate the method
            method = env["REQUEST_METHOD"].upper()
            if method != "POST":
                raise HTTPException(405, "Method not allowed (%s)." % method)

            # Parse the request
            length = -1
            try:
                length = int(env["CONTENT_LENGTH"])
            except KeyError:
                pass
            except ValueError:
                pass
            if length < 0:
                raise HTTPException(411, "Length required.")
            if length > self.MAX_LENGTH:
                raise HTTPException(413, "Request entity too large.")
            try:
                pr = codec.decode(env["wsgi.input"].read(length))
            except codec.ParsingError as e:
                raise HTTPException(400, e.message)

            # Find the remote proxy
            servers = self.__resolver.lookup(pr.realm,
                                             kpasswd=isinstance(
                                                 pr,
                                                 codec.KPASSWDProxyRequest))
            if not servers:
                raise HTTPException(503, "Can't find remote (%s)." % pr)

            # Contact the remote server
            reply = None
            wsocks = []
            rsocks = []
            for server in map(urlparse.urlparse, servers):
                # Enforce valid, supported URIs
                scheme = server.scheme.lower().split("+", 1)
                if scheme[0] not in ("kerberos", "kpasswd"):
                    continue
                if len(scheme) > 1 and scheme[1] not in ("tcp", "udp"):
                    continue

                # Do the DNS lookup
                try:
                    port = server.port
                    if port is None:
                        port = scheme[0]
                    addrs = socket.getaddrinfo(server.hostname, port)
                except socket.gaierror:
                    continue

                # Sort addresses so that we get TCP first.
                #
                # Stick a None address on the end so we can get one
                # more attempt after all servers have been contacted.
                addrs = tuple(
                    sorted(filter(self.__filter_addr, addrs),
                           key=lambda a: a[2]))
                for addr in addrs + (None, ):
                    if addr is not None:
                        # Bypass unspecified socktypes
                        if len(scheme) > 1 and \
                           addr[1] != self.SOCKTYPES[scheme[1]]:
                            continue

                        # Create the socket
                        sock = socket.socket(*addr[:3])
                        sock.setblocking(0)

                        # Connect
                        try:
                            # In Python 2.x, non-blocking connect() throws
                            # socket.error() with errno == EINPROGRESS. In
                            # Python 3.x, it throws io.BlockingIOError().
                            sock.connect(addr[4])
                        except socket.error as e:
                            if e.errno != 115:  # errno != EINPROGRESS
                                sock.close()
                                continue
                        except io.BlockingIOError:
                            pass
                        wsocks.append(sock)

                    # Resend packets to UDP servers
                    for sock in tuple(rsocks):
                        if self.sock_type(sock) == socket.SOCK_DGRAM:
                            wsocks.append(sock)
                            rsocks.remove(sock)

                    # Call select()
                    timeout = time.time() + (15 if addr is None else 2)
                    reply = self.__await_reply(pr, rsocks, wsocks, timeout)
                    if reply is not None:
                        break

                if reply is not None:
                    break

            for sock in rsocks + wsocks:
                sock.close()

            if reply is None:
                raise HTTPException(503, "Remote unavailable (%s)." % pr)

            # Return the result to the client
            raise HTTPException(200, codec.encode(reply),
                                [("Content-Type", "application/kerberos")])
        except HTTPException as e:
            start_response(str(e), e.headers)
            return [e.message]
Example #5
0
    def __call__(self, env, start_response):
        try:
            # Validate the method
            method = env["REQUEST_METHOD"].upper()
            if method != "POST":
                raise HTTPException(405, "Method not allowed (%s)." % method)

            # Parse the request
            length = -1
            try:
                length = int(env["CONTENT_LENGTH"])
            except KeyError:
                pass
            except ValueError:
                pass
            if length < 0:
                raise HTTPException(411, "Length required.")
            if length > self.MAX_LENGTH:
                raise HTTPException(413, "Request entity too large.")
            try:
                pr = codec.decode(env["wsgi.input"].read(length))
            except codec.ParsingError as e:
                raise HTTPException(400, e.message)

            # Find the remote proxy
            servers = self.__resolver.lookup(
                pr.realm,
                kpasswd=isinstance(pr, codec.KPASSWDProxyRequest)
            )
            if not servers:
                raise HTTPException(503, "Can't find remote (%s)." % pr)

            # Contact the remote server
            reply = None
            wsocks = []
            rsocks = []
            for server in map(urlparse.urlparse, servers):
                # Enforce valid, supported URIs
                scheme = server.scheme.lower().split("+", 1)
                if scheme[0] not in ("kerberos", "kpasswd"):
                    continue
                if len(scheme) > 1 and scheme[1] not in ("tcp", "udp"):
                    continue

                # Do the DNS lookup
                try:
                    port = server.port
                    if port is None:
                        port = scheme[0]
                    addrs = socket.getaddrinfo(server.hostname, port)
                except socket.gaierror:
                    continue

                # Sort addresses so that we get TCP first.
                #
                # Stick a None address on the end so we can get one
                # more attempt after all servers have been contacted.
                addrs = tuple(sorted(filter(self.__filter_addr, addrs)))
                for addr in addrs + (None,):
                    if addr is not None:
                        # Bypass unspecified socktypes
                        if (len(scheme) > 1
                                and addr[1] != self.SOCKTYPES[scheme[1]]):
                            continue

                        # Create the socket
                        sock = socket.socket(*addr[:3])
                        sock.setblocking(0)

                        # Connect
                        try:
                            # In Python 2.x, non-blocking connect() throws
                            # socket.error() with errno == EINPROGRESS. In
                            # Python 3.x, it throws io.BlockingIOError().
                            sock.connect(addr[4])
                        except socket.error as e:
                            if e.errno != 115:  # errno != EINPROGRESS
                                sock.close()
                                continue
                        except io.BlockingIOError:
                            pass
                        wsocks.append(sock)

                    # Resend packets to UDP servers
                    for sock in tuple(rsocks):
                        if self.sock_type(sock) == socket.SOCK_DGRAM:
                            wsocks.append(sock)
                            rsocks.remove(sock)

                    # Call select()
                    timeout = time.time() + (15 if addr is None else 2)
                    reply = self.__await_reply(pr, rsocks, wsocks, timeout)
                    if reply is not None:
                        break

                if reply is not None:
                    break

            for sock in rsocks + wsocks:
                sock.close()

            if reply is None:
                raise HTTPException(503, "Remote unavailable (%s)." % pr)

            # Return the result to the client
            raise HTTPException(200, codec.encode(reply),
                                [("Content-Type", "application/kerberos")])
        except HTTPException as e:
            start_response(str(e), e.headers)
            return [e.message]