Beispiel #1
0
    def __init__(self, client_conn, server_conn, handshake_flow, live=None):
        super().__init__("websocket", client_conn, server_conn, live)

        self.messages: List[WebSocketMessage] = []
        """A list containing all WebSocketMessage's."""
        self.close_sender = 'client'
        """'client' if the client initiated connection closing."""
        self.close_code = CloseReason.NORMAL_CLOSURE
        """WebSocket close code."""
        self.close_message = '(message missing)'
        """WebSocket close message."""
        self.close_reason = 'unknown status code'
        """WebSocket close reason."""
        self.stream = False
        """True of this connection is streaming directly to the other endpoint."""
        self.handshake_flow = handshake_flow
        """The HTTP flow containing the initial WebSocket handshake."""
        self.ended = False
        """True when the WebSocket connection has been closed."""

        self._inject_messages_client = queue.Queue(maxsize=1)
        self._inject_messages_server = queue.Queue(maxsize=1)

        if handshake_flow:
            self.client_key = websocket.get_client_key(
                handshake_flow.request.headers)
            self.client_protocol = websocket.get_protocol(
                handshake_flow.request.headers)
            self.client_extensions = websocket.get_extensions(
                handshake_flow.request.headers)
            self.server_accept = websocket.get_server_accept(
                handshake_flow.response.headers)
            self.server_protocol = websocket.get_protocol(
                handshake_flow.response.headers)
            self.server_extensions = websocket.get_extensions(
                handshake_flow.response.headers)
        else:
            self.client_key = ''
            self.client_protocol = ''
            self.client_extensions = ''
            self.server_accept = ''
            self.server_protocol = ''
            self.server_extensions = ''
Beispiel #2
0
def test_get_client_key():
    assert websocket.get_client_key({}) is None
    assert websocket.get_client_key({"sec-websocket-key": "foo"}) == "foo"
Beispiel #3
0
    def handle_http_request(self, logger):
        """
            Returns a (handler, log) tuple.

            handler: Handler for the next request, or None to disconnect
            log: A dictionary, or None
        """
        with logger.ctx() as lg:
            try:
                req = self.protocol.read_request(self.rfile)
            except exceptions.HttpReadDisconnect:
                return None, None
            except exceptions.HttpException as s:
                s = str(s)
                lg(s)
                return None, dict(type="error", msg=s)

            if req.method == 'CONNECT':
                return self.protocol.handle_http_connect(
                    [req.host, req.port, req.http_version], lg)

            method = req.method
            path = req.path
            http_version = req.http_version
            headers = req.headers
            first_line_format = req.first_line_format

            clientcert = None
            if self.clientcert:
                clientcert = dict(
                    cn=self.clientcert.cn,
                    subject=self.clientcert.subject,
                    serial=self.clientcert.serial,
                    notbefore=self.clientcert.notbefore.isoformat(),
                    notafter=self.clientcert.notafter.isoformat(),
                    keyinfo=self.clientcert.keyinfo,
                )

            retlog = dict(
                type="crafted",
                protocol="http",
                request=dict(path=path,
                             method=method,
                             headers=headers.fields,
                             http_version=http_version,
                             sni=self.sni,
                             remote_address=self.address,
                             clientcert=clientcert,
                             first_line_format=first_line_format),
                cipher=None,
            )
            if self.tls_established:
                retlog["cipher"] = self.get_current_cipher()

            m = utils.MemBool()

            valid_websocket_handshake = websocket.check_handshake(headers)
            self.settings.websocket_key = websocket.get_client_key(headers)

            # If this is a websocket initiation, we respond with a proper
            # server response, unless over-ridden.
            if valid_websocket_handshake:
                anchor_gen = language.parse_pathod("ws")
            else:
                anchor_gen = None

            for regex, spec in self.server.anchors:
                if regex.match(path):
                    anchor_gen = language.parse_pathod(spec, self.use_http2)
                    break
            else:
                if m(path.startswith(self.server.craftanchor)):
                    spec = urllib.parse.unquote(
                        path)[len(self.server.craftanchor):]
                    if spec:
                        try:
                            anchor_gen = language.parse_pathod(
                                spec, self.use_http2)
                        except language.ParseException as v:
                            lg("Parse error: %s" % v.msg)
                            anchor_gen = iter([
                                self.make_http_error_response(
                                    "Parse Error",
                                    "Error parsing response spec: %s\n" %
                                    (v.msg + v.marked()))
                            ])
                else:
                    if self.use_http2:
                        anchor_gen = iter([
                            self.make_http_error_response(
                                "Spec Error",
                                "HTTP/2 only supports request/response with the craft anchor point: %s"
                                % self.server.craftanchor)
                        ])

            if not anchor_gen:
                anchor_gen = iter([
                    self.make_http_error_response(
                        "Not found", "No valid craft request found")
                ])

            spec = next(anchor_gen)

            if self.use_http2 and isinstance(spec, language.http2.Response):
                spec.stream_id = req.stream_id

            lg("crafting spec: %s" % spec)
            nexthandler, retlog["response"] = self.http_serve_crafted(spec, lg)
            if nexthandler and valid_websocket_handshake:
                self.protocol = protocols.websockets.WebsocketsProtocol(self)
                return self.protocol.handle_websocket, retlog
            else:
                return nexthandler, retlog