def test_parse_size(): assert human.parse_size("0") == 0 assert human.parse_size("0b") == 0 assert human.parse_size("1") == 1 assert human.parse_size("1k") == 1024 assert human.parse_size("1m") == 1024**2 assert human.parse_size("1g") == 1024**3 tutils.raises(ValueError, human.parse_size, "1f") tutils.raises(ValueError, human.parse_size, "ak")
def get_common_options(options): stickycookie, stickyauth = None, None if options.stickycookie_filt: stickycookie = options.stickycookie_filt if options.stickyauth_filt: stickyauth = options.stickyauth_filt stream_large_bodies = options.stream_large_bodies if stream_large_bodies: stream_large_bodies = human.parse_size(stream_large_bodies) reps = [] for i in options.replace: try: p = parse_replace_hook(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) reps.append(p) for i in options.replace_file: try: patt, rex, path = parse_replace_hook(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) try: v = open(path, "rb").read() except IOError as e: raise configargparse.ArgumentTypeError( "Could not read replace file: %s" % path ) reps.append((patt, rex, v)) setheaders = [] for i in options.setheader: try: p = parse_setheader(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) setheaders.append(p) if options.outfile and options.outfile[0] == options.rfile: if options.outfile[1] == "wb": raise configargparse.ArgumentTypeError( "Cannot use '{}' for both reading and writing flows. " "Are you looking for --afile?".format(options.rfile) ) else: raise configargparse.ArgumentTypeError( "Cannot use '{}' for both reading and appending flows. " "That would trigger an infinite loop." ) return dict( app=options.app, app_host=options.app_host, app_port=options.app_port, anticache=options.anticache, anticomp=options.anticomp, client_replay=options.client_replay, kill=options.kill, no_server=options.no_server, refresh_server_playback=not options.norefresh, rheaders=options.rheaders, rfile=options.rfile, replacements=reps, setheaders=setheaders, server_replay=options.server_replay, scripts=options.scripts, stickycookie=stickycookie, stickyauth=stickyauth, stream_large_bodies=stream_large_bodies, showhost=options.showhost, outfile=options.outfile, verbosity=options.verbose, nopop=options.nopop, replay_ignore_content=options.replay_ignore_content, replay_ignore_params=options.replay_ignore_params, replay_ignore_payload_params=options.replay_ignore_payload_params, replay_ignore_host=options.replay_ignore_host )
def args_pathod(argv, stdout_=sys.stdout, stderr_=sys.stderr): parser = argparse.ArgumentParser( description='A pathological HTTP/S daemon.') parser.add_argument('--version', action='version', version="pathod " + version.VERSION) parser.add_argument( "-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port. (9999)') parser.add_argument("-l", dest='address', default="127.0.0.1", type=str, help='Listening address. (127.0.0.1)') parser.add_argument("-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", help=""" Add an anchor. Specified as a string with the form pattern=spec or pattern=filepath, where pattern is a regular expression. """) parser.add_argument("-c", dest='craftanchor', default=pathod.DEFAULT_CRAFT_ANCHOR, type=str, help=""" URL path specifying prefix for URL crafting commands. (%s) """ % pathod.DEFAULT_CRAFT_ANCHOR) parser.add_argument("--confdir", action="store", type=str, dest="confdir", default='~/.mitmproxy', help="Configuration directory. (~/.mitmproxy)") parser.add_argument("-d", dest='staticdir', default=None, type=str, help='Directory for static files.') parser.add_argument("-D", dest='daemonize', default=False, action="store_true", help='Daemonize.') parser.add_argument("-t", dest="timeout", type=int, default=None, help="Connection timeout") parser.add_argument( "--limit-size", dest='sizelimit', default=None, type=str, help= 'Size limit of served responses. Understands size suffixes, i.e. 100k.' ) parser.add_argument("--noapi", dest='noapi', default=False, action="store_true", help='Disable API.') parser.add_argument( "--nohang", dest='nohang', default=False, action="store_true", help='Disable pauses during crafted response generation.') parser.add_argument("--noweb", dest='noweb', default=False, action="store_true", help='Disable both web interface and API.') parser.add_argument( "--nocraft", dest='nocraft', default=False, action="store_true", help= 'Disable response crafting. If anchors are specified, they still work.' ) parser.add_argument("--webdebug", dest='webdebug', default=False, action="store_true", help='Debugging mode for the web app (dev only).') group = parser.add_argument_group('SSL', ) group.add_argument("-s", dest='ssl', default=False, action="store_true", help='Run in HTTPS mode.') group.add_argument("--cn", dest="cn", type=str, default=None, help="CN for generated SSL certs. Default: %s" % pathod.DEFAULT_CERT_DOMAIN) group.add_argument("-C", dest='ssl_not_after_connect', default=False, action="store_true", help="Don't expect SSL after a CONNECT request.") group.add_argument("--cert", dest='ssl_certs', default=[], type=str, metavar="SPEC", action="append", help=""" Add an SSL certificate. SPEC is of the form "[domain=]path". The domain may include a wildcard, and is equal to "*" if not specified. The file at path is a certificate in PEM format. If a private key is included in the PEM, it is used, else the default key in the conf dir is used. Can be passed multiple times. """) group.add_argument("--ciphers", dest="ciphers", type=str, default=False, help="SSL cipher specification") group.add_argument("--san", dest="sans", type=str, default=[], action="append", metavar="SAN", help=""" Subject Altnernate Name to add to the server certificate. May be passed multiple times. """) group.add_argument( "--ssl-version", dest="ssl_version", type=str, default="secure", choices=tcp.sslversion_choices.keys(), help="Set supported SSL/TLS versions. " "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." ) group = parser.add_argument_group( 'Controlling Logging', """ Some of these options expand generated values for logging - if you're generating large data, use them with caution. """) group.add_argument("-e", dest="explain", action="store_true", default=False, help="Explain responses") group.add_argument("-f", dest='logfile', default=None, type=str, help='Log to file.') group.add_argument("-q", dest="logreq", action="store_true", default=False, help="Log full request") group.add_argument("-r", dest="logresp", action="store_true", default=False, help="Log full response") group.add_argument("-x", dest="hexdump", action="store_true", default=False, help="Log request/response in hexdump format") group.add_argument("--http2-framedump", dest="http2_framedump", action="store_true", default=False, help="Output all received & sent HTTP/2 frames") args = parser.parse_args(argv[1:]) args.ssl_version, args.ssl_options = tcp.sslversion_choices[ args.ssl_version] certs = [] for i in args.ssl_certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] parts[1] = os.path.expanduser(parts[1]) if not os.path.isfile(parts[1]): return parser.error("Certificate file does not exist: %s" % parts[1]) certs.append(parts) args.ssl_certs = certs alst = [] for i in args.anchors: parts = utils.parse_anchor_spec(i) if not parts: return parser.error("Invalid anchor specification: %s" % i) alst.append(parts) args.anchors = alst sizelimit = None if args.sizelimit: try: sizelimit = human.parse_size(args.sizelimit) except ValueError as v: return parser.error(v) args.sizelimit = sizelimit anchors = [] for patt, spec in args.anchors: if os.path.isfile(spec): data = open(spec).read() spec = data try: arex = re.compile(patt) except re.error: return parser.error("Invalid regex in anchor: %s" % patt) anchors.append((arex, spec)) args.anchors = anchors return args
def process_proxy_options(parser, options): body_size_limit = options.body_size_limit if body_size_limit: body_size_limit = human.parse_size(body_size_limit) c = 0 mode, upstream_server, upstream_auth = "regular", None, None if options.transparent_proxy: c += 1 if not platform.resolver: return parser.error("Transparent mode not supported on this platform.") mode = "transparent" if options.socks_proxy: c += 1 mode = "socks5" if options.reverse_proxy: c += 1 mode = "reverse" upstream_server = options.reverse_proxy if options.upstream_proxy: c += 1 mode = "upstream" upstream_server = options.upstream_proxy upstream_auth = options.upstream_auth if c > 1: return parser.error( "Transparent, SOCKS5, reverse and upstream proxy mode " "are mutually exclusive. Read the docs on proxy modes to understand why." ) if options.add_upstream_certs_to_client_chain and options.no_upstream_cert: return parser.error( "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 options.add_upstream_certs_to_client_chain and options.ssl_verify_upstream_cert: return parser.error( "The verify-upstream-cert and add-upstream-certs-to-client-chain " "options are mutually exclusive. If upstream certificates are verified " "then extra upstream certificates are not available for inclusion " "to the client chain." ) if options.clientcerts: options.clientcerts = os.path.expanduser(options.clientcerts) if not os.path.exists(options.clientcerts): return parser.error( "Client certificate path does not exist: %s" % options.clientcerts ) if options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd: if options.transparent_proxy: return parser.error("Proxy Authentication not supported in transparent mode.") if options.socks_proxy: return parser.error( "Proxy Authentication not supported in SOCKS mode. " "https://github.com/mitmproxy/mitmproxy/issues/738" ) if options.auth_singleuser: if len(options.auth_singleuser.split(':')) != 2: return parser.error( "Invalid single-user specification. Please use the format username:password" ) username, password = options.auth_singleuser.split(':') password_manager = authentication.PassManSingleUser(username, password) elif options.auth_nonanonymous: password_manager = authentication.PassManNonAnon() elif options.auth_htpasswd: try: password_manager = authentication.PassManHtpasswd( options.auth_htpasswd) except ValueError as v: return parser.error(v) authenticator = authentication.BasicProxyAuth(password_manager, "mitmproxy") else: authenticator = authentication.NullProxyAuth(None) certs = [] for i in options.certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] parts[1] = os.path.expanduser(parts[1]) if not os.path.exists(parts[1]): parser.error("Certificate file does not exist: %s" % parts[1]) certs.append(parts) return ProxyConfig( host=options.addr, port=options.port, cadir=options.cadir, clientcerts=options.clientcerts, no_upstream_cert=options.no_upstream_cert, body_size_limit=body_size_limit, mode=mode, upstream_server=upstream_server, upstream_auth=upstream_auth, ignore_hosts=options.ignore_hosts, tcp_hosts=options.tcp_hosts, http2=options.http2, rawtcp=options.rawtcp, authenticator=authenticator, ciphers_client=options.ciphers_client, ciphers_server=options.ciphers_server, certs=tuple(certs), ssl_version_client=options.ssl_version_client, ssl_version_server=options.ssl_version_server, ssl_verify_upstream_cert=options.ssl_verify_upstream_cert, ssl_verify_upstream_trusted_cadir=options.ssl_verify_upstream_trusted_cadir, ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca, add_upstream_certs_to_client_chain=options.add_upstream_certs_to_client_chain, )
def get_common_options(args): stickycookie, stickyauth = None, None if args.stickycookie_filt: stickycookie = args.stickycookie_filt if args.stickyauth_filt: stickyauth = args.stickyauth_filt stream_large_bodies = args.stream_large_bodies if stream_large_bodies: stream_large_bodies = human.parse_size(stream_large_bodies) reps = [] for i in args.replace: try: p = parse_replace_hook(i) except ParseException as e: raise exceptions.OptionsError(e) reps.append(p) for i in args.replace_file: try: patt, rex, path = parse_replace_hook(i) except ParseException as e: raise exceptions.OptionsError(e) try: v = open(path, "rb").read() except IOError as e: raise exceptions.OptionsError( "Could not read replace file: %s" % path ) reps.append((patt, rex, v)) setheaders = [] for i in args.setheader: try: p = parse_setheader(i) except ParseException as e: raise exceptions.OptionsError(e) setheaders.append(p) if args.outfile and args.outfile[0] == args.rfile: if args.outfile[1] == "wb": raise exceptions.OptionsError( "Cannot use '{}' for both reading and writing flows. " "Are you looking for --afile?".format(args.rfile) ) else: raise exceptions.OptionsError( "Cannot use '{}' for both reading and appending flows. " "That would trigger an infinite loop." ) # Proxy config certs = [] for i in args.certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] certs.append(parts) body_size_limit = args.body_size_limit if body_size_limit: try: body_size_limit = human.parse_size(body_size_limit) except ValueError as e: raise exceptions.OptionsError( "Invalid body size limit specification: %s" % body_size_limit ) # Establish proxy mode c = 0 mode, upstream_server = "regular", None if args.transparent_proxy: c += 1 if not platform.resolver: raise exceptions.OptionsError( "Transparent mode not supported on this platform." ) mode = "transparent" if args.socks_proxy: c += 1 mode = "socks5" if args.reverse_proxy: c += 1 mode = "reverse" upstream_server = args.reverse_proxy if args.upstream_proxy: c += 1 mode = "upstream" upstream_server = args.upstream_proxy if c > 1: raise exceptions.OptionsError( "Transparent, SOCKS5, reverse and upstream proxy mode " "are mutually exclusive. Read the docs on proxy modes " "to understand why." ) if args.add_upstream_certs_to_client_chain and args.no_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 args.quiet: args.verbose = 0 return dict( app=args.app, app_host=args.app_host, app_port=args.app_port, anticache=args.anticache, anticomp=args.anticomp, client_replay=args.client_replay, kill=args.kill, no_server=args.no_server, refresh_server_playback=not args.norefresh, rheaders=args.rheaders, rfile=args.rfile, replacements=reps, setheaders=setheaders, server_replay=args.server_replay, scripts=args.scripts, stickycookie=stickycookie, stickyauth=stickyauth, stream_large_bodies=stream_large_bodies, showhost=args.showhost, outfile=args.outfile, verbosity=args.verbose, nopop=args.nopop, replay_ignore_content=args.replay_ignore_content, replay_ignore_params=args.replay_ignore_params, replay_ignore_payload_params=args.replay_ignore_payload_params, replay_ignore_host=args.replay_ignore_host, auth_nonanonymous = args.auth_nonanonymous, auth_singleuser = args.auth_singleuser, auth_htpasswd = args.auth_htpasswd, add_upstream_certs_to_client_chain = args.add_upstream_certs_to_client_chain, body_size_limit = body_size_limit, cadir = args.cadir, certs = certs, ciphers_client = args.ciphers_client, ciphers_server = args.ciphers_server, clientcerts = args.clientcerts, http2 = args.http2, ignore_hosts = args.ignore_hosts, listen_host = args.addr, listen_port = args.port, mode = mode, no_upstream_cert = args.no_upstream_cert, rawtcp = args.rawtcp, upstream_server = upstream_server, upstream_auth = args.upstream_auth, ssl_version_client = args.ssl_version_client, ssl_version_server = args.ssl_version_server, ssl_verify_upstream_cert = args.ssl_verify_upstream_cert, ssl_verify_upstream_trusted_cadir = args.ssl_verify_upstream_trusted_cadir, ssl_verify_upstream_trusted_ca = args.ssl_verify_upstream_trusted_ca, tcp_hosts = args.tcp_hosts, )
def args_pathod(argv, stdout_=sys.stdout, stderr_=sys.stderr): parser = argparse.ArgumentParser( description='A pathological HTTP/S daemon.' ) parser.add_argument( '--version', action='version', version="pathod " + version.VERSION ) parser.add_argument( "-p", dest='port', default=9999, type=int, help='Port. Specify 0 to pick an arbitrary empty port. (9999)' ) parser.add_argument( "-l", dest='address', default="127.0.0.1", type=str, help='Listening address. (127.0.0.1)' ) parser.add_argument( "-a", dest='anchors', default=[], type=str, action="append", metavar="ANCHOR", help=""" Add an anchor. Specified as a string with the form pattern=spec or pattern=filepath, where pattern is a regular expression. """ ) parser.add_argument( "-c", dest='craftanchor', default=pathod.DEFAULT_CRAFT_ANCHOR, type=str, help=""" URL path specifying prefix for URL crafting commands. (%s) """ % pathod.DEFAULT_CRAFT_ANCHOR ) parser.add_argument( "--confdir", action="store", type=str, dest="confdir", default='~/.mitmproxy', help="Configuration directory. (~/.mitmproxy)" ) parser.add_argument( "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' ) parser.add_argument( "-D", dest='daemonize', default=False, action="store_true", help='Daemonize.' ) parser.add_argument( "-t", dest="timeout", type=int, default=None, help="Connection timeout" ) parser.add_argument( "--limit-size", dest='sizelimit', default=None, type=str, help='Size limit of served responses. Understands size suffixes, i.e. 100k.') parser.add_argument( "--nohang", dest='nohang', default=False, action="store_true", help='Disable pauses during crafted response generation.' ) parser.add_argument( "--nocraft", dest='nocraft', default=False, action="store_true", help='Disable response crafting. If anchors are specified, they still work.') parser.add_argument( "--webdebug", dest='webdebug', default=False, action="store_true", help='Debugging mode for the web app (dev only).' ) group = parser.add_argument_group( 'SSL', ) group.add_argument( "-s", dest='ssl', default=False, action="store_true", help='Run in HTTPS mode.' ) group.add_argument( "--cn", dest="cn", type=str, default=None, help="CN for generated SSL certs. Default: %s" % pathod.DEFAULT_CERT_DOMAIN) group.add_argument( "-C", dest='ssl_not_after_connect', default=False, action="store_true", help="Don't expect SSL after a CONNECT request." ) group.add_argument( "--cert", dest='ssl_certs', default=[], type=str, metavar="SPEC", action="append", help=""" Add an SSL certificate. SPEC is of the form "[domain=]path". The domain may include a wildcard, and is equal to "*" if not specified. The file at path is a certificate in PEM format. If a private key is included in the PEM, it is used, else the default key in the conf dir is used. Can be passed multiple times. """ ) group.add_argument( "--ciphers", dest="ciphers", type=str, default=False, help="SSL cipher specification" ) group.add_argument( "--san", dest="sans", type=str, default=[], action="append", metavar="SAN", help=""" Subject Altnernate Name to add to the server certificate. May be passed multiple times. """ ) group.add_argument( "--ssl-version", dest="ssl_version", type=str, default="secure", choices=tcp.sslversion_choices.keys(), help="Set supported SSL/TLS versions. " "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." ) group = parser.add_argument_group( 'Controlling Logging', """ Some of these options expand generated values for logging - if you're generating large data, use them with caution. """ ) group.add_argument( "-e", dest="explain", action="store_true", default=False, help="Explain responses" ) group.add_argument( "-f", dest='logfile', default=None, type=str, help='Log to file.' ) group.add_argument( "-q", dest="logreq", action="store_true", default=False, help="Log full request" ) group.add_argument( "-r", dest="logresp", action="store_true", default=False, help="Log full response" ) group.add_argument( "-x", dest="hexdump", action="store_true", default=False, help="Log request/response in hexdump format" ) group.add_argument( "--http2-framedump", dest="http2_framedump", action="store_true", default=False, help="Output all received & sent HTTP/2 frames" ) args = parser.parse_args(argv[1:]) args.ssl_version, args.ssl_options = tcp.sslversion_choices[args.ssl_version] certs = [] for i in args.ssl_certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] parts[1] = os.path.expanduser(parts[1]) if not os.path.isfile(parts[1]): return parser.error( "Certificate file does not exist: %s" % parts[1]) certs.append(parts) args.ssl_certs = certs alst = [] for i in args.anchors: parts = parse_anchor_spec(i) if not parts: return parser.error("Invalid anchor specification: %s" % i) alst.append(parts) args.anchors = alst sizelimit = None if args.sizelimit: try: sizelimit = human.parse_size(args.sizelimit) except ValueError as v: return parser.error(v) args.sizelimit = sizelimit anchors = [] for patt, spec in args.anchors: if os.path.isfile(spec): data = open(spec).read() spec = data try: arex = re.compile(patt) except re.error: return parser.error("Invalid regex in anchor: %s" % patt) anchors.append((arex, spec)) args.anchors = anchors return args
def get_common_options(args): stickycookie, stickyauth = None, None if args.stickycookie_filt: stickycookie = args.stickycookie_filt if args.stickyauth_filt: stickyauth = args.stickyauth_filt stream_large_bodies = args.stream_large_bodies if stream_large_bodies: stream_large_bodies = human.parse_size(stream_large_bodies) reps = [] for i in args.replace: try: p = parse_replace_hook(i) except ParseException as e: raise exceptions.OptionsError(e) reps.append(p) for i in args.replace_file: try: patt, rex, path = parse_replace_hook(i) except ParseException as e: raise exceptions.OptionsError(e) try: v = open(path, "rb").read() except IOError as e: raise exceptions.OptionsError("Could not read replace file: %s" % path) reps.append((patt, rex, v)) setheaders = [] for i in args.setheader: try: p = parse_setheader(i) except ParseException as e: raise exceptions.OptionsError(e) setheaders.append(p) if args.outfile and args.outfile[0] == args.rfile: if args.outfile[1] == "wb": raise exceptions.OptionsError( "Cannot use '{}' for both reading and writing flows. " "Are you looking for --afile?".format(args.rfile)) else: raise exceptions.OptionsError( "Cannot use '{}' for both reading and appending flows. " "That would trigger an infinite loop.") # Proxy config certs = [] for i in args.certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] certs.append(parts) body_size_limit = args.body_size_limit if body_size_limit: try: body_size_limit = human.parse_size(body_size_limit) except ValueError as e: raise exceptions.OptionsError( "Invalid body size limit specification: %s" % body_size_limit) # Establish proxy mode c = 0 mode, upstream_server = "regular", None if args.transparent_proxy: c += 1 if not platform.resolver: raise exceptions.OptionsError( "Transparent mode not supported on this platform.") mode = "transparent" if args.socks_proxy: c += 1 mode = "socks5" if args.reverse_proxy: c += 1 mode = "reverse" upstream_server = args.reverse_proxy if args.upstream_proxy: c += 1 mode = "upstream" upstream_server = args.upstream_proxy if c > 1: raise exceptions.OptionsError( "Transparent, SOCKS5, reverse and upstream proxy mode " "are mutually exclusive. Read the docs on proxy modes " "to understand why.") if args.add_upstream_certs_to_client_chain and args.no_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 args.quiet: args.verbose = 0 return dict( app=args.app, app_host=args.app_host, app_port=args.app_port, anticache=args.anticache, anticomp=args.anticomp, client_replay=args.client_replay, kill=args.kill, no_server=args.no_server, refresh_server_playback=not args.norefresh, rheaders=args.rheaders, rfile=args.rfile, replacements=reps, setheaders=setheaders, server_replay=args.server_replay, scripts=args.scripts, stickycookie=stickycookie, stickyauth=stickyauth, stream_large_bodies=stream_large_bodies, showhost=args.showhost, outfile=args.outfile, verbosity=args.verbose, nopop=args.nopop, replay_ignore_content=args.replay_ignore_content, replay_ignore_params=args.replay_ignore_params, replay_ignore_payload_params=args.replay_ignore_payload_params, replay_ignore_host=args.replay_ignore_host, auth_nonanonymous=args.auth_nonanonymous, auth_singleuser=args.auth_singleuser, auth_htpasswd=args.auth_htpasswd, add_upstream_certs_to_client_chain=args. add_upstream_certs_to_client_chain, body_size_limit=body_size_limit, cadir=args.cadir, certs=certs, ciphers_client=args.ciphers_client, ciphers_server=args.ciphers_server, clientcerts=args.clientcerts, http2=args.http2, ignore_hosts=args.ignore_hosts, listen_host=args.addr, listen_port=args.port, mode=mode, no_upstream_cert=args.no_upstream_cert, rawtcp=args.rawtcp, upstream_server=upstream_server, upstream_auth=args.upstream_auth, ssl_version_client=args.ssl_version_client, ssl_version_server=args.ssl_version_server, ssl_verify_upstream_cert=args.ssl_verify_upstream_cert, ssl_verify_upstream_trusted_cadir=args. ssl_verify_upstream_trusted_cadir, ssl_verify_upstream_trusted_ca=args.ssl_verify_upstream_trusted_ca, tcp_hosts=args.tcp_hosts, )
def process_proxy_options(parser, options): body_size_limit = options.body_size_limit if body_size_limit: body_size_limit = human.parse_size(body_size_limit) c = 0 mode, upstream_server, upstream_auth = "regular", None, None if options.transparent_proxy: c += 1 if not platform.resolver: return parser.error( "Transparent mode not supported on this platform.") mode = "transparent" if options.socks_proxy: c += 1 mode = "socks5" if options.reverse_proxy: c += 1 mode = "reverse" upstream_server = options.reverse_proxy if options.upstream_proxy: c += 1 mode = "upstream" upstream_server = options.upstream_proxy upstream_auth = options.upstream_auth if c > 1: return parser.error( "Transparent, SOCKS5, reverse and upstream proxy mode " "are mutually exclusive. Read the docs on proxy modes to understand why." ) if options.add_upstream_certs_to_client_chain and options.no_upstream_cert: return parser.error( "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 options.add_upstream_certs_to_client_chain and options.ssl_verify_upstream_cert: return parser.error( "The verify-upstream-cert and add-upstream-certs-to-client-chain " "options are mutually exclusive. If upstream certificates are verified " "then extra upstream certificates are not available for inclusion " "to the client chain.") if options.clientcerts: options.clientcerts = os.path.expanduser(options.clientcerts) if not os.path.exists(options.clientcerts): return parser.error("Client certificate path does not exist: %s" % options.clientcerts) if options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd: if options.transparent_proxy: return parser.error( "Proxy Authentication not supported in transparent mode.") if options.socks_proxy: return parser.error( "Proxy Authentication not supported in SOCKS mode. " "https://github.com/mitmproxy/mitmproxy/issues/738") if options.auth_singleuser: if len(options.auth_singleuser.split(':')) != 2: return parser.error( "Invalid single-user specification. Please use the format username:password" ) username, password = options.auth_singleuser.split(':') password_manager = authentication.PassManSingleUser( username, password) elif options.auth_nonanonymous: password_manager = authentication.PassManNonAnon() elif options.auth_htpasswd: try: password_manager = authentication.PassManHtpasswd( options.auth_htpasswd) except ValueError as v: return parser.error(v.message) authenticator = authentication.BasicProxyAuth(password_manager, "mitmproxy") else: authenticator = authentication.NullProxyAuth(None) certs = [] for i in options.certs: parts = i.split("=", 1) if len(parts) == 1: parts = ["*", parts[0]] parts[1] = os.path.expanduser(parts[1]) if not os.path.exists(parts[1]): parser.error("Certificate file does not exist: %s" % parts[1]) certs.append(parts) return ProxyConfig( host=options.addr, port=options.port, cadir=options.cadir, clientcerts=options.clientcerts, no_upstream_cert=options.no_upstream_cert, body_size_limit=body_size_limit, mode=mode, upstream_server=upstream_server, upstream_auth=upstream_auth, ignore_hosts=options.ignore_hosts, tcp_hosts=options.tcp_hosts, http2=options.http2, rawtcp=options.rawtcp, authenticator=authenticator, ciphers_client=options.ciphers_client, ciphers_server=options.ciphers_server, certs=tuple(certs), ssl_version_client=options.ssl_version_client, ssl_version_server=options.ssl_version_server, ssl_verify_upstream_cert=options.ssl_verify_upstream_cert, ssl_verify_upstream_trusted_cadir=options. ssl_verify_upstream_trusted_cadir, ssl_verify_upstream_trusted_ca=options.ssl_verify_upstream_trusted_ca, add_upstream_certs_to_client_chain=options. add_upstream_certs_to_client_chain, )
def get_common_options(options): stickycookie, stickyauth = None, None if options.stickycookie_filt: stickycookie = options.stickycookie_filt if options.stickyauth_filt: stickyauth = options.stickyauth_filt stream_large_bodies = options.stream_large_bodies if stream_large_bodies: stream_large_bodies = human.parse_size(stream_large_bodies) reps = [] for i in options.replace: try: p = parse_replace_hook(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) reps.append(p) for i in options.replace_file: try: patt, rex, path = parse_replace_hook(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) try: v = open(path, "rb").read() except IOError as e: raise configargparse.ArgumentTypeError( "Could not read replace file: %s" % path) reps.append((patt, rex, v)) setheaders = [] for i in options.setheader: try: p = parse_setheader(i) except ParseException as e: raise configargparse.ArgumentTypeError(e.message) setheaders.append(p) if options.outfile and options.outfile[0] == options.rfile: if options.outfile[1] == "wb": raise configargparse.ArgumentTypeError( "Cannot use '{}' for both reading and writing flows. " "Are you looking for --afile?".format(options.rfile)) else: raise configargparse.ArgumentTypeError( "Cannot use '{}' for both reading and appending flows. " "That would trigger an infinite loop.") return dict( app=options.app, app_host=options.app_host, app_port=options.app_port, anticache=options.anticache, anticomp=options.anticomp, client_replay=options.client_replay, kill=options.kill, no_server=options.no_server, refresh_server_playback=not options.norefresh, rheaders=options.rheaders, rfile=options.rfile, replacements=reps, setheaders=setheaders, server_replay=options.server_replay, scripts=options.scripts, stickycookie=stickycookie, stickyauth=stickyauth, stream_large_bodies=stream_large_bodies, showhost=options.showhost, outfile=options.outfile, verbosity=options.verbose, nopop=options.nopop, replay_ignore_content=options.replay_ignore_content, replay_ignore_params=options.replay_ignore_params, replay_ignore_payload_params=options.replay_ignore_payload_params, replay_ignore_host=options.replay_ignore_host)