コード例 #1
0
    def from_stream(cls, rfile, include_content=True, body_size_limit=None):
        """
        Parse an HTTP request from a file stream
        """
        httpversion, host, port, scheme, method, path, headers, content, timestamp_start, timestamp_end \
            = None, None, None, None, None, None, None, None, None, None

        if hasattr(rfile, "reset_timestamps"):
            rfile.reset_timestamps()

        request_line = get_line(rfile)

        if hasattr(rfile, "first_byte_timestamp"):
            timestamp_start = rfile.first_byte_timestamp
        else:
            timestamp_start = utils.timestamp()

        request_line_parts = http.parse_init(request_line)
        if not request_line_parts:
            raise http.HttpError(
                400, "Bad HTTP request line: %s" % repr(request_line))
        method, path, httpversion = request_line_parts

        if path == '*':
            form_in = "asterisk"
        elif path.startswith("/"):
            form_in = "origin"
            if not netlib.utils.isascii(path):
                raise http.HttpError(
                    400, "Bad HTTP request line: %s" % repr(request_line))
        elif method.upper() == 'CONNECT':
            form_in = "authority"
            r = http.parse_init_connect(request_line)
            if not r:
                raise http.HttpError(
                    400, "Bad HTTP request line: %s" % repr(request_line))
            host, port, _ = r
            path = None
        else:
            form_in = "absolute"
            r = http.parse_init_proxy(request_line)
            if not r:
                raise http.HttpError(
                    400, "Bad HTTP request line: %s" % repr(request_line))
            _, scheme, host, port, path, _ = r

        headers = http.read_headers(rfile)
        if headers is None:
            raise http.HttpError(400, "Invalid headers")

        if include_content:
            content = http.read_http_body(rfile, headers, body_size_limit,
                                          True)
            timestamp_end = utils.timestamp()

        return HTTPRequest(form_in, method, scheme, host, port, path,
                           httpversion, headers, content, timestamp_start,
                           timestamp_end)
コード例 #2
0
    def assemble_response(self, response):
        assert isinstance(response, semantics.Response)

        if response.body == semantics.CONTENT_MISSING:
            raise http.HttpError(502,
                                 "Cannot assemble flow with CONTENT_MISSING")
        first_line = self._assemble_response_first_line(response)
        headers = self._assemble_response_headers(response)
        return "%s\r\n%s\r\n%s" % (first_line, headers, response.body)
コード例 #3
0
ファイル: http.py プロジェクト: yuljasc/mitmproxy
    def process_request(self, flow, request):

        if not self.skip_authentication:
            self.authenticate(request)

        if request.form_in == "authority":
            if self.c.client_conn.ssl_established:
                raise http.HttpError(
                    400, "Must not CONNECT on already encrypted connection")

            if self.expected_form_in == "absolute":
                if not self.c.config.get_upstream_server:
                    self.c.set_server_address(
                        (request.host, request.port),
                        proxy.AddressPriority.FROM_PROTOCOL)
                    self.c.establish_server_connection()
                    flow.server_conn = self.c.server_conn  # Update server_conn attribute on the flow
                    self.c.client_conn.send(
                        'HTTP/1.1 200 Connection established\r\n' +
                        'Content-Length: 0\r\n' +
                        ('Proxy-agent: %s\r\n' % self.c.server_version) +
                        '\r\n')

                    self.ssl_upgrade()
                    self.skip_authentication = True
                    return False
                else:
                    return True
        elif request.form_in == self.expected_form_in:
            if request.form_in == "absolute":
                if request.scheme != "http":
                    raise http.HttpError(
                        400, "Invalid request scheme: %s" % request.scheme)

                self.c.set_server_address((request.host, request.port),
                                          proxy.AddressPriority.FROM_PROTOCOL)
                flow.server_conn = self.c.server_conn  # Update server_conn attribute on the flow

            request.form_out = self.expected_form_out
            return True

        raise http.HttpError(
            400, "Invalid HTTP request form (expected: %s, got: %s)" %
            (self.expected_form_in, request.form_in))
コード例 #4
0
    def process_request(self, flow, request):
        if self.c.mode == "regular":
            self.authenticate(request)
        if request.form_in == "authority" and self.c.client_conn.ssl_established:
            raise http.HttpError(
                502, "Must not CONNECT on already encrypted connection")

        # If we have a CONNECT request, we might need to intercept
        if request.form_in == "authority":
            directly_addressed_at_mitmproxy = (self.c.mode == "regular" and
                                               not self.c.config.forward_proxy)
            if directly_addressed_at_mitmproxy:
                self.c.set_server_address((request.host, request.port),
                                          AddressPriority.FROM_PROTOCOL)
                flow.server_conn = self.c.server_conn  # Update server_conn attribute on the flow
                self.c.client_conn.wfile.write(
                    'HTTP/1.1 200 Connection established\r\n' +
                    ('Proxy-agent: %s\r\n' % self.c.server_version) + '\r\n')
                self.c.client_conn.wfile.flush()
                self.ssl_upgrade()  # raises ConnectionTypeChange exception

        if self.c.mode == "regular":
            if request.form_in == "authority":  # forward mode
                self.hook_reconnect(request)
            elif request.form_in == "absolute":
                if request.scheme != "http":
                    raise http.HttpError(400, "Invalid Request")
                if not self.c.config.forward_proxy:
                    request.form_out = "origin"
                    self.c.set_server_address((request.host, request.port),
                                              AddressPriority.FROM_PROTOCOL)
                    flow.server_conn = self.c.server_conn  # Update server_conn attribute on the flow
            else:
                raise http.HttpError(
                    400,
                    "Invalid request form (absolute-form or authority-form required)"
                )
コード例 #5
0
ファイル: http.py プロジェクト: aykutakar/mitmproxy
    def _assemble_first_line(self, form=None):
        form = form or self.form_out

        if form == "relative":
            path = self.path if self.method != "OPTIONS" else "*"
            request_line = '%s %s HTTP/%s.%s' % \
                           (self.method, path, self.httpversion[0], self.httpversion[1])
        elif form == "authority":
            request_line = '%s %s:%s HTTP/%s.%s' % (
                self.method, self.host, self.port, self.httpversion[0],
                self.httpversion[1])
        elif form == "absolute":
            request_line = '%s %s://%s:%s%s HTTP/%s.%s' % \
                           (self.method, self.scheme, self.host, self.port, self.path,
                            self.httpversion[0], self.httpversion[1])
        else:
            raise http.HttpError(400, "Invalid request form")
        return request_line
コード例 #6
0
    def _assemble_first_line(self, form=None):
        form = form or self.form_out

        if form == "asterisk" or \
           form == "origin":
            request_line = '%s %s HTTP/%s.%s' % (self.method, self.path,
                                                 self.httpversion[0],
                                                 self.httpversion[1])
        elif form == "authority":
            request_line = '%s %s:%s HTTP/%s.%s' % (
                self.method, self.host, self.port, self.httpversion[0],
                self.httpversion[1])
        elif form == "absolute":
            request_line = '%s %s://%s:%s%s HTTP/%s.%s' % \
                           (self.method, self.scheme, self.host, self.port, self.path,
                            self.httpversion[0], self.httpversion[1])
        else:
            raise http.HttpError(400, "Invalid request form")
        return request_line
コード例 #7
0
def test_httperror():
    e = http.HttpError(404, "Not found")
    assert str(e)
コード例 #8
0
ファイル: http.py プロジェクト: aykutakar/mitmproxy
    def process_request(self, flow, request):
        """
        @returns:
        True, if the request should not be sent upstream
        False, if the connection should be aborted
        None, if the request should be sent upstream
        (a status code != None should be returned directly by handle_flow)
        """

        if not self.skip_authentication:
            self.authenticate(request)

        # Determine .scheme, .host and .port attributes
        # For absolute-form requests, they are directly given in the request.
        # For authority-form requests, we only need to determine the request scheme.
        # For relative-form requests, we need to determine host and port as well.
        if not request.scheme:
            request.scheme = "https" if flow.server_conn and flow.server_conn.ssl_established else "http"
        if not request.host:
            # Host/Port Complication: In upstream mode, use the server we CONNECTed to,
            # not the upstream proxy.
            if flow.server_conn:
                for s in flow.server_conn.state:
                    if s[0] == "http" and s[1]["state"] == "connect":
                        request.host, request.port = s[1]["host"], s[1]["port"]
            if not request.host and flow.server_conn:
                request.host, request.port = flow.server_conn.address.host, flow.server_conn.address.port

        # Now we can process the request.
        if request.form_in == "authority":
            if self.c.client_conn.ssl_established:
                raise http.HttpError(
                    400, "Must not CONNECT on already encrypted connection")

            if self.c.config.mode == "regular":
                self.c.set_server_address((request.host, request.port))
                flow.server_conn = self.c.server_conn  # Update server_conn attribute on the flow
                self.c.establish_server_connection()
                self.c.client_conn.send(
                    'HTTP/1.1 200 Connection established\r\n' +
                    'Content-Length: 0\r\n' +
                    ('Proxy-agent: %s\r\n' % self.c.config.server_version) +
                    '\r\n')
                return self.process_connect_request(self.c.server_conn.address)
            elif self.c.config.mode == "upstream":
                return None
            else:
                pass  # CONNECT should never occur if we don't expect absolute-form requests

        elif request.form_in == self.expected_form_in:

            request.form_out = self.expected_form_out

            if request.form_in == "absolute":
                if request.scheme != "http":
                    raise http.HttpError(
                        400, "Invalid request scheme: %s" % request.scheme)
                if self.c.config.mode == "regular":
                    # Update info so that an inline script sees the correct value at flow.server_conn
                    self.c.set_server_address((request.host, request.port))
                    flow.server_conn = self.c.server_conn

            return None

        raise http.HttpError(
            400, "Invalid HTTP request form (expected: %s, got: %s)" %
            (self.expected_form_in, request.form_in))
コード例 #9
0
    def process_request(self, flow, request):
        """
        @returns:
        True, if the request should not be sent upstream
        False, if the connection should be aborted
        None, if the request should be sent upstream
        (a status code != None should be returned directly by handle_flow)
        """

        if not self.skip_authentication:
            self.authenticate(request)

        # Determine .scheme, .host and .port attributes
        # For absolute-form requests, they are directly given in the request.
        # For authority-form requests, we only need to determine the request scheme.
        # For relative-form requests, we need to determine host and port as
        # well.
        if not request.scheme:
            request.scheme = "https" if flow.server_conn and flow.server_conn.ssl_established else "http"
        if not request.host:
            # Host/Port Complication: In upstream mode, use the server we CONNECTed to,
            # not the upstream proxy.
            if flow.server_conn:
                for s in flow.server_conn.state:
                    if s[0] == "http" and s[1]["state"] == "connect":
                        request.host, request.port = s[1]["host"], s[1]["port"]
            if not request.host and flow.server_conn:
                request.host, request.port = flow.server_conn.address.host, flow.server_conn.address.port


        # Now we can process the request.
        if request.form_in == "authority":
            if self.c.client_conn.ssl_established:
                raise http.HttpError(
                    400,
                    "Must not CONNECT on already encrypted connection"
                )

            if self.c.config.mode == "regular":
                self.c.set_server_address((request.host, request.port))
                # Update server_conn attribute on the flow
                flow.server_conn = self.c.server_conn

                # since we currently only support HTTP/1 CONNECT requests
                # the response must be HTTP/1 as well
                self.c.client_conn.send(
                    ('HTTP/%s.%s 200 ' % (request.httpversion[0], request.httpversion[1])) +
                    'Connection established\r\n' +
                    'Content-Length: 0\r\n' +
                    ('Proxy-agent: %s\r\n' % self.c.config.server_version) +
                    '\r\n'
                )
                return self.process_connect_request(self.c.server_conn.address)
            elif self.c.config.mode == "upstream":
                return None
            else:
                # CONNECT should never occur if we don't expect absolute-form
                # requests
                pass

        elif request.form_in == self.expected_form_in:
            request.form_out = self.expected_form_out
            if request.form_in == "absolute":
                if request.scheme != "http":
                    raise http.HttpError(
                        400,
                        "Invalid request scheme: %s" % request.scheme
                    )
                if self.c.config.mode == "regular":
                    # Update info so that an inline script sees the correct
                    # value at flow.server_conn
                    self.c.set_server_address((request.host, request.port))
                    flow.server_conn = self.c.server_conn

            elif request.form_in == "relative":
                if self.c.config.mode == "spoof":
                    # Host header
                    h = request.pretty_host(hostheader=True)
                    if h is None:
                        raise http.HttpError(
                            400,
                            "Invalid request: No host information"
                        )
                    p = netlib.utils.parse_url("http://" + h)
                    request.scheme = p[0]
                    request.host = p[1]
                    request.port = p[2]
                    self.c.set_server_address((request.host, request.port))
                    flow.server_conn = self.c.server_conn

                if self.c.config.mode == "sslspoof":
                    # SNI is processed in server.py
                    if not (flow.server_conn and flow.server_conn.ssl_established):
                        raise http.HttpError(
                            400,
                            "Invalid request: No host information"
                        )

            return None

        raise http.HttpError(
            400, "Invalid HTTP request form (expected: %s, got: %s)" % (
                self.expected_form_in, request.form_in
            )
        )