def configure(self, updated):
     opts = ctx.options
     if opts.add_upstream_certs_to_client_chain and not opts.upstream_cert:
         raise exceptions.OptionsError(
             "The no-upstream-cert and add-upstream-certs-to-client-chain "
             "options are mutually exclusive. If no-upstream-cert is enabled "
             "then the upstream certificate is not retrieved before generating "
             "the client certificate chain."
         )
     if "body_size_limit" in updated and opts.body_size_limit:
         try:
             opts._processed["body_size_limit"] = human.parse_size(
                 opts.body_size_limit
             )
         except ValueError as e:
             raise exceptions.OptionsError(
                 "Invalid body size limit specification: %s" %
                 opts.body_size_limit
             )
     if "mode" in updated:
         mode = opts.mode
         if mode.startswith("reverse:") or mode.startswith("upstream:"):
             try:
                 server_spec.parse_with_mode(mode)
             except ValueError as e:
                 raise exceptions.OptionsError(str(e)) from e
         elif mode == "transparent":
             if not platform.original_addr:
                 raise exceptions.OptionsError(
                     "Transparent mode not supported on this platform."
                 )
         elif mode not in ["regular", "socks5"]:
             raise exceptions.OptionsError(
                 "Invalid mode specification: %s" % mode
             )
Exemplo n.º 2
0
 def configure(self, updated):
     opts = ctx.options
     if opts.add_upstream_certs_to_client_chain and not opts.upstream_cert:
         raise exceptions.OptionsError(
             "The no-upstream-cert and add-upstream-certs-to-client-chain "
             "options are mutually exclusive. If no-upstream-cert is enabled "
             "then the upstream certificate is not retrieved before generating "
             "the client certificate chain."
         )
     if opts.add_upstream_certs_to_client_chain and not opts.ssl_insecure:
         raise exceptions.OptionsError(
             "The verify-upstream-cert requires certificate verification to be disabled. "
             "If upstream certificates are verified then extra upstream certificates are "
             "not available for inclusion to the client chain."
         )
     if "body_size_limit" in updated:
         try:
             human.parse_size(opts.body_size_limit)
         except ValueError as e:
             raise exceptions.OptionsError(
                 "Invalid body size limit specification: %s" %
                 opts.body_size_limit
             )
     if "mode" in updated:
         mode = opts.mode
         if mode.startswith("reverse:") or mode.startswith("upstream:"):
             try:
                 server_spec.parse_with_mode(mode)
             except ValueError as e:
                 raise exceptions.OptionsError(str(e)) from e
         elif mode == "transparent":
             if not platform.original_addr:
                 raise exceptions.OptionsError(
                     "Transparent mode not supported on this platform."
                 )
         elif mode not in ["regular", "socks5"]:
             raise exceptions.OptionsError(
                 "Invalid mode specification: %s" % mode
             )
     if "client_certs" in updated:
         if opts.client_certs:
             client_certs = os.path.expanduser(opts.client_certs)
             if not os.path.exists(client_certs):
                 raise exceptions.OptionsError(
                     "Client certificate path does not exist: {}".format(opts.client_certs)
                 )
Exemplo n.º 3
0
 def _change_reverse_host(self, f):
     """
     When we load flows in reverse proxy mode, we adjust the target host to
     the reverse proxy destination for all flows we load. This makes it very
     easy to replay saved flows against a different host.
     """
     if self.options.mode.startswith("reverse:"):
         _, upstream_spec = server_spec.parse_with_mode(self.options.mode)
         f.request.host, f.request.port = upstream_spec.address
         f.request.scheme = upstream_spec.scheme
Exemplo n.º 4
0
 def _change_reverse_host(self, f):
     """
     When we load flows in reverse proxy mode, we adjust the target host to
     the reverse proxy destination for all flows we load. This makes it very
     easy to replay saved flows against a different host.
     """
     if self.options.mode.startswith("reverse:"):
         _, upstream_spec = server_spec.parse_with_mode(self.options.mode)
         f.request.host, f.request.port = upstream_spec.address
         f.request.scheme = upstream_spec.scheme
Exemplo n.º 5
0
    def configure(self, options: moptions.Options, updated: Any) -> None:
        if options.add_upstream_certs_to_client_chain and not options.ssl_insecure:
            raise exceptions.OptionsError(
                "The verify-upstream-cert requires certificate verification to be disabled. "
                "If upstream certificates are verified then extra upstream certificates are "
                "not available for inclusion to the client chain.")

        if options.ssl_insecure:
            self.openssl_verification_mode_server = SSL.VERIFY_NONE
        else:
            self.openssl_verification_mode_server = SSL.VERIFY_PEER

        self.check_ignore = HostMatcher(options.ignore_hosts)
        self.check_tcp = HostMatcher(options.tcp_hosts)

        self.openssl_method_client, self.openssl_options_client = \
            tcp.sslversion_choices[options.ssl_version_client]
        self.openssl_method_server, self.openssl_options_server = \
            tcp.sslversion_choices[options.ssl_version_server]

        certstore_path = os.path.expanduser(options.cadir)
        if not os.path.exists(os.path.dirname(certstore_path)):
            raise exceptions.OptionsError(
                "Certificate Authority parent directory does not exist: %s" %
                os.path.dirname(options.cadir))
        self.certstore = certs.CertStore.from_store(certstore_path,
                                                    CONF_BASENAME)

        if options.client_certs:
            client_certs = os.path.expanduser(options.client_certs)
            if not os.path.exists(client_certs):
                raise exceptions.OptionsError(
                    "Client certificate path does not exist: %s" %
                    options.client_certs)
            self.client_certs = client_certs

        for c in options.certs:
            parts = c.split("=", 1)
            if len(parts) == 1:
                parts = ["*", parts[0]]

            cert = os.path.expanduser(parts[1])
            if not os.path.exists(cert):
                raise exceptions.OptionsError(
                    "Certificate file does not exist: %s" % cert)
            try:
                self.certstore.add_cert_file(parts[0], cert)
            except crypto.Error:
                raise exceptions.OptionsError(
                    "Invalid certificate format: %s" % cert)
        m = options.mode
        if m.startswith("upstream:") or m.startswith("reverse:"):
            _, spec = server_spec.parse_with_mode(options.mode)
            self.upstream_server = spec
Exemplo n.º 6
0
 def configure(self, updated):
     opts = ctx.options
     if opts.add_upstream_certs_to_client_chain and not opts.upstream_cert:
         raise exceptions.OptionsError(
             "The no-upstream-cert and add-upstream-certs-to-client-chain "
             "options are mutually exclusive. If no-upstream-cert is enabled "
             "then the upstream certificate is not retrieved before generating "
             "the client certificate chain.")
     if opts.add_upstream_certs_to_client_chain and not opts.ssl_insecure:
         raise exceptions.OptionsError(
             "The verify-upstream-cert requires certificate verification to be disabled. "
             "If upstream certificates are verified then extra upstream certificates are "
             "not available for inclusion to the client chain.")
     if "body_size_limit" in updated:
         try:
             human.parse_size(opts.body_size_limit)
         except ValueError as e:
             raise exceptions.OptionsError(
                 "Invalid body size limit specification: %s" %
                 opts.body_size_limit)
     if "mode" in updated:
         mode = opts.mode
         if mode.startswith("reverse:") or mode.startswith("upstream:"):
             try:
                 server_spec.parse_with_mode(mode)
             except ValueError as e:
                 raise exceptions.OptionsError(str(e)) from e
         elif mode == "transparent":
             if not platform.original_addr:
                 raise exceptions.OptionsError(
                     "Transparent mode not supported on this platform.")
         elif mode not in ["regular", "socks5"]:
             raise exceptions.OptionsError(
                 "Invalid mode specification: %s" % mode)
     if "client_certs" in updated:
         if opts.client_certs:
             client_certs = os.path.expanduser(opts.client_certs)
             if not os.path.exists(client_certs):
                 raise exceptions.OptionsError(
                     "Client certificate path does not exist: {}".format(
                         opts.client_certs))
Exemplo n.º 7
0
 def load_flow(self, f):
     """
     Loads a flow
     """
     if isinstance(f, http.HTTPFlow):
         if self.options.mode.startswith("reverse:"):
             _, upstream_spec = server_spec.parse_with_mode(self.options.mode)
             f.request.host, f.request.port = upstream_spec.address
             f.request.scheme = upstream_spec.scheme
     f.reply = controller.DummyReply()
     for e, o in eventsequence.iterate(f):
         self.addons.handle_lifecycle(e, o)
Exemplo n.º 8
0
 def _handle_event(self, event: events.Event):
     if isinstance(event, events.Start):
         yield from self.event_to_child(
             self.connections[self.context.client], event)
         if self.mode is HTTPMode.upstream:
             self.context.server.via = server_spec.parse_with_mode(
                 self.context.options.mode)[1]
     elif isinstance(event, events.CommandCompleted):
         stream = self.command_sources.pop(event.command)
         yield from self.event_to_child(stream, event)
     elif isinstance(event, events.MessageInjected):
         # For injected messages we pass the HTTP stacks entirely and directly address the stream.
         try:
             conn = self.connections[event.flow.server_conn]
         except KeyError:
             # We have a miss for the server connection, which means we're looking at a connection object
             # that is tunneled over another connection (for example: over an upstream HTTP proxy).
             # We now take the stream associated with the client connection. That won't work for HTTP/2,
             # but it's good enough for HTTP/1.
             conn = self.connections[event.flow.client_conn]
         if isinstance(conn, HttpStream):
             stream_id = conn.stream_id
         else:
             # We reach to the end of the connection's child stack to get the HTTP/1 client layer,
             # which tells us which stream we are dealing with.
             conn = conn.context.layers[-1]
             assert isinstance(conn, Http1Connection)
             assert conn.stream_id
             stream_id = conn.stream_id
         yield from self.event_to_child(self.streams[stream_id], event)
     elif isinstance(event, events.ConnectionEvent):
         if event.connection == self.context.server and self.context.server not in self.connections:
             # We didn't do anything with this connection yet, now the peer is doing something.
             if isinstance(event, events.ConnectionClosed):
                 # The peer has closed it - let's close it too!
                 yield commands.CloseConnection(event.connection)
             elif isinstance(event, events.DataReceived):
                 # The peer has sent data. This can happen with HTTP/2 servers that already send a settings frame.
                 child_layer: HttpConnection
                 if self.context.server.alpn == b"h2":
                     child_layer = Http2Client(self.context.fork())
                 else:
                     child_layer = Http1Client(self.context.fork())
                 self.connections[self.context.server] = child_layer
                 yield from self.event_to_child(child_layer, events.Start())
                 yield from self.event_to_child(child_layer, event)
             else:
                 raise AssertionError(f"Unexpected event: {event}")
         else:
             handler = self.connections[event.connection]
             yield from self.event_to_child(handler, event)
     else:
         raise AssertionError(f"Unexpected event: {event}")
Exemplo n.º 9
0
 def load_flow(self, f):
     """
     Loads a flow
     """
     if isinstance(f, http.HTTPFlow):
         if self.options.mode.startswith("reverse:"):
             _, upstream_spec = server_spec.parse_with_mode(self.options.mode)
             f.request.host, f.request.port = upstream_spec.address
             f.request.scheme = upstream_spec.scheme
     f.reply = controller.DummyReply()
     for e, o in eventsequence.iterate(f):
         self.addons.handle_lifecycle(e, o)
Exemplo n.º 10
0
    def _handle_event(self,
                      event: events.Event) -> layer.CommandGenerator[None]:
        spec = server_spec.parse_with_mode(self.context.options.mode)[1]
        self.context.server.address = spec.address

        if spec.scheme not in ("http", "tcp"):
            if not self.context.options.keep_host_header:
                self.context.server.sni = spec.address[0]
            self.child_layer = tls.ServerTLSLayer(self.context)
        else:
            self.child_layer = layer.NextLayer(self.context)

        yield from self.finish_start()
Exemplo n.º 11
0
 def configure(self, updated):
     opts = ctx.options
     if opts.add_upstream_certs_to_client_chain and not opts.upstream_cert:
         raise exceptions.OptionsError(
             "add_upstream_certs_to_client_chain requires the upstream_cert option to be enabled."
         )
     if "body_size_limit" in updated:
         if opts.body_size_limit:  # pragma: no cover
             ctx.log.warn(
                 "body_size_limit is currently nonfunctioning, "
                 "see https://github.com/mitmproxy/mitmproxy/issues/4348")
         try:
             human.parse_size(opts.body_size_limit)
         except ValueError:
             raise exceptions.OptionsError(
                 "Invalid body size limit specification: %s" %
                 opts.body_size_limit)
     if "mode" in updated:
         mode = opts.mode
         if mode.startswith("reverse:") or mode.startswith("upstream:"):
             try:
                 server_spec.parse_with_mode(mode)
             except ValueError as e:
                 raise exceptions.OptionsError(str(e)) from e
         elif mode == "transparent":
             if not platform.original_addr:
                 raise exceptions.OptionsError(
                     "Transparent mode not supported on this platform.")
         elif mode not in ["regular", "socks5"]:
             raise exceptions.OptionsError(
                 "Invalid mode specification: %s" % mode)
     if "client_certs" in updated:
         if opts.client_certs:
             client_certs = os.path.expanduser(opts.client_certs)
             if not os.path.exists(client_certs):
                 raise exceptions.OptionsError(
                     f"Client certificate path does not exist: {opts.client_certs}"
                 )
Exemplo n.º 12
0
    def __init__(self, flow: http.HTTPFlow, options: Options) -> None:
        client = flow.client_conn.copy()
        client.state = ConnectionState.OPEN

        context = Context(client, options)
        context.server = Server((flow.request.host, flow.request.port))
        context.server.tls = flow.request.scheme == "https"
        if options.mode.startswith("upstream:"):
            context.server.via = server_spec.parse_with_mode(options.mode)[1]

        super().__init__(context)

        self.layer = layers.HttpLayer(context, HTTPMode.transparent)
        self.layer.connections[client] = MockServer(flow, context.fork())
        self.flow = flow
        self.done = asyncio.Event()
Exemplo n.º 13
0
    async def load_flow(self, f):
        """
        Loads a flow
        """

        if isinstance(f, http.HTTPFlow):
            if self.options.mode.startswith("reverse:"):
                # When we load flows in reverse proxy mode, we adjust the target host to
                # the reverse proxy destination for all flows we load. This makes it very
                # easy to replay saved flows against a different host.
                _, upstream_spec = server_spec.parse_with_mode(self.options.mode)
                f.request.host, f.request.port = upstream_spec.address
                f.request.scheme = upstream_spec.scheme

        for e in eventsequence.iterate(f):
            await self.addons.handle_lifecycle(e)
Exemplo n.º 14
0
    def configure(self, options: moptions.Options, updated: typing.Any) -> None:
        if options.allow_hosts and options.ignore_hosts:
            raise exceptions.OptionsError("--ignore-hosts and --allow-hosts are mutually "
                                          "exclusive; please choose one.")

        if options.ignore_hosts:
            self.check_filter = HostMatcher("ignore", options.ignore_hosts)
        elif options.allow_hosts:
            self.check_filter = HostMatcher("allow", options.allow_hosts)
        else:
            self.check_filter = HostMatcher(False)
        if "tcp_hosts" in updated:
            self.check_tcp = HostMatcher("tcp", options.tcp_hosts)

        certstore_path = os.path.expanduser(options.confdir)
        if not os.path.exists(os.path.dirname(certstore_path)):
            raise exceptions.OptionsError(
                "Certificate Authority parent directory does not exist: %s" %
                os.path.dirname(certstore_path)
            )
        key_size = options.key_size
        self.certstore = certs.CertStore.from_store(
            certstore_path,
            moptions.CONF_BASENAME,
            key_size
        )

        for c in options.certs:
            parts = c.split("=", 1)
            if len(parts) == 1:
                parts = ["*", parts[0]]

            cert = os.path.expanduser(parts[1])
            if not os.path.exists(cert):
                raise exceptions.OptionsError(
                    "Certificate file does not exist: %s" % cert
                )
            try:
                self.certstore.add_cert_file(parts[0], cert)
            except crypto.Error:
                raise exceptions.OptionsError(
                    "Invalid certificate format: %s" % cert
                )
        m = options.mode
        if m.startswith("upstream:") or m.startswith("reverse:"):
            _, spec = server_spec.parse_with_mode(options.mode)
            self.upstream_server = spec
Exemplo n.º 15
0
 def _handle_event(self, event: events.Event):
     if isinstance(event, events.Start):
         yield from self.event_to_child(self.connections[self.context.client], event)
         if self.mode is HTTPMode.upstream:
             self.context.server.via = server_spec.parse_with_mode(self.context.options.mode)[1]
     elif isinstance(event, events.CommandCompleted):
         stream = self.command_sources.pop(event.command)
         yield from self.event_to_child(stream, event)
     elif isinstance(event, events.ConnectionEvent):
         if event.connection == self.context.server and self.context.server not in self.connections:
             # We didn't do anything with this connection yet, now the peer has closed it - let's close it too!
             yield commands.CloseConnection(event.connection)
         else:
             handler = self.connections[event.connection]
             yield from self.event_to_child(handler, event)
     else:
         raise AssertionError(f"Unexpected event: {event}")
Exemplo n.º 16
0
    def configure(self, options: moptions.Options, updated: typing.Any) -> None:
        if "ignore_hosts" in updated:
            self.check_ignore = HostMatcher(options.ignore_hosts)
        if "tcp_hosts" in updated:
            self.check_tcp = HostMatcher(options.tcp_hosts)

        certstore_path = os.path.expanduser(options.cadir)
        if not os.path.exists(os.path.dirname(certstore_path)):
            raise exceptions.OptionsError(
                "Certificate Authority parent directory does not exist: %s" %
                os.path.dirname(certstore_path)
            )
        self.certstore = certs.CertStore.from_store(
            certstore_path,
            CONF_BASENAME
        )

        for c in options.certs:
            parts = c.split("=", 1)
            if len(parts) == 1:
                parts = ["*", parts[0]]

            cert = os.path.expanduser(parts[1])
            if not os.path.exists(cert):
                raise exceptions.OptionsError(
                    "Certificate file does not exist: %s" % cert
                )
            try:
                self.certstore.add_cert_file(parts[0], cert)
            except crypto.Error:
                raise exceptions.OptionsError(
                    "Invalid certificate format: %s" % cert
                )
        m = options.mode
        if m.startswith("upstream:") or m.startswith("reverse:"):
            _, spec = server_spec.parse_with_mode(options.mode)
            self.upstream_server = spec
Exemplo n.º 17
0
    def configure(self, options: moptions.Options, updated: typing.Any) -> None:
        if "ignore_hosts" in updated:
            self.check_ignore = HostMatcher(options.ignore_hosts)
        if "tcp_hosts" in updated:
            self.check_tcp = HostMatcher(options.tcp_hosts)

        certstore_path = os.path.expanduser(options.confdir)
        if not os.path.exists(os.path.dirname(certstore_path)):
            raise exceptions.OptionsError(
                "Certificate Authority parent directory does not exist: %s" %
                os.path.dirname(certstore_path)
            )
        self.certstore = certs.CertStore.from_store(
            certstore_path,
            CONF_BASENAME
        )

        for c in options.certs:
            parts = c.split("=", 1)
            if len(parts) == 1:
                parts = ["*", parts[0]]

            cert = os.path.expanduser(parts[1])
            if not os.path.exists(cert):
                raise exceptions.OptionsError(
                    "Certificate file does not exist: %s" % cert
                )
            try:
                self.certstore.add_cert_file(parts[0], cert)
            except crypto.Error:
                raise exceptions.OptionsError(
                    "Invalid certificate format: %s" % cert
                )
        m = options.mode
        if m.startswith("upstream:") or m.startswith("reverse:"):
            _, spec = server_spec.parse_with_mode(options.mode)
            self.upstream_server = spec
    def replay(self, f):  # pragma: no cover
        f.live = True
        r = f.request
        bsl = human.parse_size(self.options.body_size_limit)
        authority_backup = r.authority
        server = None
        try:
            f.response = None

            # If we have a channel, run script hooks.
            request_reply = self.channel.ask("request", f)
            if isinstance(request_reply, http.HTTPResponse):
                f.response = request_reply

            if not f.response:
                # In all modes, we directly connect to the server displayed
                if self.options.mode.startswith("upstream:"):
                    server_address = server_spec.parse_with_mode(
                        self.options.mode)[1].address
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        connect_request = http.make_connect_request(
                            (r.data.host, r.port))
                        server.wfile.write(
                            http1.assemble_request(connect_request))
                        server.wfile.flush()
                        resp = http1.read_response(server.rfile,
                                                   connect_request,
                                                   body_size_limit=bsl)
                        if resp.status_code != 200:
                            raise exceptions.ReplayException(
                                "Upstream server refuses CONNECT request")
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options))
                        r.authority = b""
                    else:
                        r.authority = hostport(r.scheme, r.host, r.port)
                else:
                    server_address = (r.host, r.port)
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options))
                    r.authority = ""

                server.wfile.write(http1.assemble_request(r))
                server.wfile.flush()
                r.timestamp_start = r.timestamp_end = time.time()

                if f.server_conn:
                    f.server_conn.close()
                f.server_conn = server

                f.response = http1.read_response(server.rfile,
                                                 r,
                                                 body_size_limit=bsl)
            response_reply = self.channel.ask("response", f)
            if response_reply == exceptions.Kill:
                raise exceptions.Kill()
        except (exceptions.ReplayException, exceptions.NetlibException) as e:
            f.error = flow.Error(str(e))
            self.channel.ask("error", f)
        except exceptions.Kill:
            self.channel.tell("log",
                              log.LogEntry(flow.Error.KILLED_MESSAGE, "info"))
        except Exception as e:
            self.channel.tell("log", log.LogEntry(repr(e), "error"))
        finally:
            r.authority = authority_backup
            f.live = False
            if server and server.connected():
                server.finish()
                server.close()
Exemplo n.º 19
0
    def configure(self, options: moptions.Options, updated: typing.Any) -> None:
        if options.add_upstream_certs_to_client_chain and not options.ssl_insecure:
            raise exceptions.OptionsError(
                "The verify-upstream-cert requires certificate verification to be disabled. "
                "If upstream certificates are verified then extra upstream certificates are "
                "not available for inclusion to the client chain."
            )

        if options.ssl_insecure:
            self.openssl_verification_mode_server = SSL.VERIFY_NONE
        else:
            self.openssl_verification_mode_server = SSL.VERIFY_PEER

        if "ignore_hosts" in updated:
            self.check_ignore = HostMatcher(options.ignore_hosts)
        if "tcp_hosts" in updated:
            self.check_tcp = HostMatcher(options.tcp_hosts)

        self.openssl_method_client, self.openssl_options_client = \
            tls.VERSION_CHOICES[options.ssl_version_client]
        self.openssl_method_server, self.openssl_options_server = \
            tls.VERSION_CHOICES[options.ssl_version_server]

        certstore_path = os.path.expanduser(options.cadir)
        if not os.path.exists(os.path.dirname(certstore_path)):
            raise exceptions.OptionsError(
                "Certificate Authority parent directory does not exist: %s" %
                os.path.dirname(options.cadir)
            )
        self.certstore = certs.CertStore.from_store(
            certstore_path,
            CONF_BASENAME
        )

        if options.client_certs:
            client_certs = os.path.expanduser(options.client_certs)
            if not os.path.exists(client_certs):
                raise exceptions.OptionsError(
                    "Client certificate path does not exist: %s" %
                    options.client_certs
                )
            self.client_certs = client_certs

        for c in options.certs:
            parts = c.split("=", 1)
            if len(parts) == 1:
                parts = ["*", parts[0]]

            cert = os.path.expanduser(parts[1])
            if not os.path.exists(cert):
                raise exceptions.OptionsError(
                    "Certificate file does not exist: %s" % cert
                )
            try:
                self.certstore.add_cert_file(parts[0], cert)
            except crypto.Error:
                raise exceptions.OptionsError(
                    "Invalid certificate format: %s" % cert
                )
        m = options.mode
        if m.startswith("upstream:") or m.startswith("reverse:"):
            _, spec = server_spec.parse_with_mode(options.mode)
            self.upstream_server = spec
Exemplo n.º 20
0
    def run(self):
        r = self.f.request
        bsl = self.options._processed.get("body_size_limit")
        first_line_format_backup = r.first_line_format
        server = None
        try:
            self.f.response = None

            # If we have a channel, run script hooks.
            if self.channel:
                request_reply = self.channel.ask("request", self.f)
                if isinstance(request_reply, http.HTTPResponse):
                    self.f.response = request_reply

            if not self.f.response:
                # In all modes, we directly connect to the server displayed
                if self.options.mode.startswith("upstream:"):
                    server_address = server_spec.parse_with_mode(
                        self.options.mode)[1].address
                    server = connections.ServerConnection(
                        server_address, (self.options.listen_host, 0))
                    server.connect()
                    if r.scheme == "https":
                        connect_request = http.make_connect_request(
                            (r.data.host, r.port))
                        server.wfile.write(
                            http1.assemble_request(connect_request))
                        server.wfile.flush()
                        resp = http1.read_response(server.rfile,
                                                   connect_request,
                                                   body_size_limit=bsl)
                        if resp.status_code != 200:
                            raise exceptions.ReplayException(
                                "Upstream server refuses CONNECT request")
                        server.establish_ssl(self.options.client_certs,
                                             sni=self.f.server_conn.sni)
                        r.first_line_format = "relative"
                    else:
                        r.first_line_format = "absolute"
                else:
                    server_address = (r.host, r.port)
                    server = connections.ServerConnection(
                        server_address, (self.options.listen_host, 0))
                    server.connect()
                    if r.scheme == "https":
                        server.establish_ssl(self.options.client_certs,
                                             sni=self.f.server_conn.sni)
                    r.first_line_format = "relative"

                server.wfile.write(http1.assemble_request(r))
                server.wfile.flush()

                if self.f.server_conn:
                    self.f.server_conn.close()
                self.f.server_conn = server

                self.f.response = http.HTTPResponse.wrap(
                    http1.read_response(server.rfile, r, body_size_limit=bsl))
            if self.channel:
                response_reply = self.channel.ask("response", self.f)
                if response_reply == exceptions.Kill:
                    raise exceptions.Kill()
        except (exceptions.ReplayException, exceptions.NetlibException) as e:
            self.f.error = flow.Error(str(e))
            if self.channel:
                self.channel.ask("error", self.f)
        except exceptions.Kill:
            # Kill should only be raised if there's a channel in the
            # first place.
            self.channel.tell("log", log.LogEntry("Connection killed", "info"))
        except Exception as e:
            self.channel.tell("log", log.LogEntry(repr(e), "error"))
        finally:
            r.first_line_format = first_line_format_backup
            self.f.live = False
            if server.connected():
                server.finish()
Exemplo n.º 21
0
    def replay(self, f):  # pragma: no cover
        f.live = True
        r = f.request
        bsl = human.parse_size(self.options.body_size_limit)
        first_line_format_backup = r.first_line_format
        server = None
        global new, cur_cycle, cur_group
        try:
            f.response = None
            # If we have a channel, run script hooks.
            request_reply = self.channel.ask("request", f)
            if isinstance(request_reply, http.HTTPResponse):
                f.response = request_reply
            if not f.response:
                # In all modes, we directly connect to the server displayed
                if self.options.mode.startswith("upstream:"):
                    server_address = server_spec.parse_with_mode(
                        self.options.mode)[1].address
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        connect_request = http.make_connect_request(
                            (r.data.host, r.port))
                        server.wfile.write(
                            http1.assemble_request(connect_request))
                        server.wfile.flush()
                        resp = http1.read_response(server.rfile,
                                                   connect_request,
                                                   body_size_limit=bsl)
                        if resp.status_code != 200:
                            raise exceptions.ReplayException(
                                "Upstream server refuses CONNECT request")
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options))
                        r.first_line_format = "relative"
                    else:
                        r.first_line_format = "absolute"
                else:
                    server_address = (r.host, r.port)
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options))
                    r.first_line_format = "relative"

                server.wfile.write(http1.assemble_request(r))
                server.wfile.flush()

                if f.server_conn:
                    f.server_conn.close()
                f.server_conn = server

                f.response = http.HTTPResponse.wrap(
                    http1.read_response(server.rfile, r, body_size_limit=bsl))
            response_reply = self.channel.ask("response", f)

            #new.append(f) #record the response
            cur_cycle[cur_group] = f
            if response_reply == exceptions.Kill:
                raise exceptions.Kill()
        except (exceptions.ReplayException, exceptions.NetlibException) as e:
            f.error = flow.Error(str(e))
            self.channel.ask("error", f)
        except exceptions.Kill:
            self.channel.tell("log", log.LogEntry("Connection killed", "info"))
        except Exception as e:
            self.channel.tell("log", log.LogEntry(repr(e), "error"))
        finally:
            r.first_line_format = first_line_format_backup
            f.live = False
            if server.connected():
                server.finish()
                server.close()
Exemplo n.º 22
0
    def run(self):
        r = self.f.request
        bsl = human.parse_size(self.options.body_size_limit)
        first_line_format_backup = r.first_line_format
        server = None
        try:
            self.f.response = None

            # If we have a channel, run script hooks.
            if self.channel:
                request_reply = self.channel.ask("request", self.f)
                if isinstance(request_reply, http.HTTPResponse):
                    self.f.response = request_reply

            if not self.f.response:
                # In all modes, we directly connect to the server displayed
                if self.options.mode.startswith("upstream:"):
                    server_address = server_spec.parse_with_mode(self.options.mode)[1].address
                    server = connections.ServerConnection(server_address, (self.options.listen_host, 0))
                    server.connect()
                    if r.scheme == "https":
                        connect_request = http.make_connect_request((r.data.host, r.port))
                        server.wfile.write(http1.assemble_request(connect_request))
                        server.wfile.flush()
                        resp = http1.read_response(
                            server.rfile,
                            connect_request,
                            body_size_limit=bsl
                        )
                        if resp.status_code != 200:
                            raise exceptions.ReplayException("Upstream server refuses CONNECT request")
                        server.establish_ssl(
                            self.options.client_certs,
                            sni=self.f.server_conn.sni
                        )
                        r.first_line_format = "relative"
                    else:
                        r.first_line_format = "absolute"
                else:
                    server_address = (r.host, r.port)
                    server = connections.ServerConnection(
                        server_address,
                        (self.options.listen_host, 0)
                    )
                    server.connect()
                    if r.scheme == "https":
                        server.establish_ssl(
                            self.options.client_certs,
                            sni=self.f.server_conn.sni
                        )
                    r.first_line_format = "relative"

                server.wfile.write(http1.assemble_request(r))
                server.wfile.flush()

                if self.f.server_conn:
                    self.f.server_conn.close()
                self.f.server_conn = server

                self.f.response = http.HTTPResponse.wrap(
                    http1.read_response(
                        server.rfile,
                        r,
                        body_size_limit=bsl
                    )
                )
            if self.channel:
                response_reply = self.channel.ask("response", self.f)
                if response_reply == exceptions.Kill:
                    raise exceptions.Kill()
        except (exceptions.ReplayException, exceptions.NetlibException) as e:
            self.f.error = flow.Error(str(e))
            if self.channel:
                self.channel.ask("error", self.f)
        except exceptions.Kill:
            # Kill should only be raised if there's a channel in the
            # first place.
            self.channel.tell(
                "log",
                log.LogEntry("Connection killed", "info")
            )
        except Exception as e:
            self.channel.tell(
                "log",
                log.LogEntry(repr(e), "error")
            )
        finally:
            r.first_line_format = first_line_format_backup
            self.f.live = False
            if server.connected():
                server.finish()
Exemplo n.º 23
0
    def replay(self, f):  # pragma: no cover
        f.live = True
        r = f.request
        bsl = human.parse_size(self.options.body_size_limit)
        first_line_format_backup = r.first_line_format
        server = None
        try:
            f.response = None

            # If we have a channel, run script hooks.
            request_reply = self.channel.ask("request", f)
            if isinstance(request_reply, http.HTTPResponse):
                f.response = request_reply

            if not f.response:
                # In all modes, we directly connect to the server displayed
                if self.options.mode.startswith("upstream:"):
                    server_address = server_spec.parse_with_mode(self.options.mode)[1].address
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        connect_request = http.make_connect_request((r.data.host, r.port))
                        server.wfile.write(http1.assemble_request(connect_request))
                        server.wfile.flush()
                        resp = http1.read_response(
                            server.rfile,
                            connect_request,
                            body_size_limit=bsl
                        )
                        if resp.status_code != 200:
                            raise exceptions.ReplayException(
                                "Upstream server refuses CONNECT request"
                            )
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options)
                        )
                        r.first_line_format = "relative"
                    else:
                        r.first_line_format = "absolute"
                else:
                    server_address = (r.host, r.port)
                    server = connections.ServerConnection(server_address)
                    server.connect()
                    if r.scheme == "https":
                        server.establish_tls(
                            sni=f.server_conn.sni,
                            **tls.client_arguments_from_options(self.options)
                        )
                    r.first_line_format = "relative"

                server.wfile.write(http1.assemble_request(r))
                server.wfile.flush()
                r.timestamp_start = r.timestamp_end = time.time()

                if f.server_conn:
                    f.server_conn.close()
                f.server_conn = server

                f.response = http.HTTPResponse.wrap(
                    http1.read_response(server.rfile, r, body_size_limit=bsl)
                )
            response_reply = self.channel.ask("response", f)
            if response_reply == exceptions.Kill:
                raise exceptions.Kill()
        except (exceptions.ReplayException, exceptions.NetlibException) as e:
            f.error = flow.Error(str(e))
            self.channel.ask("error", f)
        except exceptions.Kill:
            self.channel.tell("log", log.LogEntry("Connection killed", "info"))
        except Exception as e:
            self.channel.tell("log", log.LogEntry(repr(e), "error"))
        finally:
            r.first_line_format = first_line_format_backup
            f.live = False
            if server.connected():
                server.finish()
                server.close()
Exemplo n.º 24
0
def test_parse_with_mode():
    assert server_spec.parse_with_mode("m:example.com") == ("m", ("https", ("example.com", 443)))
    with pytest.raises(ValueError):
        server_spec.parse_with_mode("moo")