예제 #1
0
    def Control(self):
        """Handle POSTS."""
        # Get the api version
        try:
            api_version = int(
                urlparse.parse_qs(self.path.split("?")[1])["api"][0])
        except (ValueError, KeyError, IndexError):
            # The oldest api version we support if not specified.
            api_version = 3

        try:
            if compatibility.PY2:
                content_length = self.headers.getheader("content-length")
            else:
                content_length = self.headers.get("content-length")
            if not content_length:
                raise IOError("No content-length header provided.")

            length = int(content_length)

            request_comms = rdf_flows.ClientCommunication.FromSerializedBytes(
                self._GetPOSTData(length))

            # If the client did not supply the version in the protobuf we use the get
            # parameter.
            if not request_comms.api_version:
                request_comms.api_version = api_version

            # Reply using the same version we were requested with.
            responses_comms = rdf_flows.ClientCommunication(
                api_version=request_comms.api_version)

            # TODO: Python's documentation is just plain terrible and
            # does not explain what `client_address` exactly is or what type does it
            # have (because its Python, why would they bother) so just to be on the
            # safe side, we anticipate byte-string addresses in Python 2 and convert
            # that if needed. On Python 3 these should be always unicode strings, so
            # once support for Python 2 is dropped this branch can be removed.
            address = self.client_address[0]
            if compatibility.PY2 and isinstance(self.client_address[0], bytes):
                address = address.decode("ascii")
            source_ip = ipaddress.ip_address(address)

            if source_ip.version == 6:
                source_ip = source_ip.ipv4_mapped or source_ip

            request_comms.orig_request = rdf_flows.HttpRequest(
                timestamp=rdfvalue.RDFDatetime.Now(),
                raw_headers=str(self.headers),
                source_ip=str(source_ip))

            source, nr_messages = self.server.frontend.HandleMessageBundles(
                request_comms, responses_comms)

            server_logging.LOGGER.LogHttpFrontendAccess(
                request_comms.orig_request,
                source=source,
                message_count=nr_messages)

            self.Send(responses_comms.SerializeToBytes())

        except communicator.UnknownClientCertError:
            # "406 Not Acceptable: The server can only generate a response that is not
            # accepted by the client". This is because we can not encrypt for the
            # client appropriately.
            self.Send(b"Enrollment required", status=406)
예제 #2
0
    def Control(self):
        """Handle POSTS."""
        if not master.MASTER_WATCHER.IsMaster():
            # We shouldn't be getting requests from the client unless we
            # are the active instance.
            stats_collector_instance.Get().IncrementCounter(
                "frontend_inactive_request_count", fields=["http"])
            logging.info("Request sent to inactive frontend from %s",
                         self.client_address[0])

        # Get the api version
        try:
            api_version = int(cgi.parse_qs(self.path.split("?")[1])["api"][0])
        except (ValueError, KeyError, IndexError):
            # The oldest api version we support if not specified.
            api_version = 3

        try:
            content_length = self.headers.getheader("content-length")
            if not content_length:
                raise IOError("No content-length header provided.")

            length = int(content_length)

            request_comms = rdf_flows.ClientCommunication.FromSerializedString(
                self._GetPOSTData(length))

            # If the client did not supply the version in the protobuf we use the get
            # parameter.
            if not request_comms.api_version:
                request_comms.api_version = api_version

            # Reply using the same version we were requested with.
            responses_comms = rdf_flows.ClientCommunication(
                api_version=request_comms.api_version)

            source_ip = ipaddr.IPAddress(self.client_address[0])

            if source_ip.version == 6:
                source_ip = source_ip.ipv4_mapped or source_ip

            request_comms.orig_request = rdf_flows.HttpRequest(
                timestamp=rdfvalue.RDFDatetime.Now().AsMicrosecondsSinceEpoch(
                ),
                raw_headers=utils.SmartStr(self.headers),
                source_ip=utils.SmartStr(source_ip))

            source, nr_messages = self.server.frontend.HandleMessageBundles(
                request_comms, responses_comms)

            server_logging.LOGGER.LogHttpFrontendAccess(
                request_comms.orig_request,
                source=source,
                message_count=nr_messages)

            self.Send(responses_comms.SerializeToString())

        except communicator.UnknownClientCert:
            # "406 Not Acceptable: The server can only generate a response that is not
            # accepted by the client". This is because we can not encrypt for the
            # client appropriately.
            self.Send("Enrollment required", status=406)