aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2017-03-07 20:18:30 +1300
committerAldo Cortesi <aldo@nullcube.com>2017-03-07 20:18:30 +1300
commitaed780bf48f6231e63a2b193318bc234152e2743 (patch)
treeb0eb10d80edc2205df5aa6b0a3fba09093382599
parentb0ba76559869053e49b9c11b826a542b4885b49d (diff)
downloadmitmproxy-aed780bf48f6231e63a2b193318bc234152e2743.tar.gz
mitmproxy-aed780bf48f6231e63a2b193318bc234152e2743.tar.bz2
mitmproxy-aed780bf48f6231e63a2b193318bc234152e2743.zip
Change the way proxy authetication is specified
We now have one option "proxyauth". If this is "any", we accept any credentials, if it starts with an @ it's treated as a path to an htpasswd file, if it is of the form username:password it's a single-user credential.
-rw-r--r--mitmproxy/addons/proxyauth.py46
-rw-r--r--mitmproxy/options.py17
-rw-r--r--mitmproxy/tools/cmdline.py4
-rw-r--r--test/mitmproxy/addons/test_proxyauth.py38
-rw-r--r--test/mitmproxy/proxy/test_server.py4
5 files changed, 51 insertions, 58 deletions
diff --git a/mitmproxy/addons/proxyauth.py b/mitmproxy/addons/proxyauth.py
index 18a85866..61477658 100644
--- a/mitmproxy/addons/proxyauth.py
+++ b/mitmproxy/addons/proxyauth.py
@@ -114,30 +114,28 @@ class ProxyAuth:
# Handlers
def configure(self, options, updated):
- if "auth_nonanonymous" in updated:
- self.nonanonymous = options.auth_nonanonymous
- if "auth_singleuser" in updated:
- if options.auth_singleuser:
- parts = options.auth_singleuser.split(':')
- if len(parts) != 2:
- raise exceptions.OptionsError(
- "Invalid single-user auth specification."
- )
- self.singleuser = parts
- else:
- self.singleuser = None
- if "auth_htpasswd" in updated:
- if options.auth_htpasswd:
- try:
- self.htpasswd = passlib.apache.HtpasswdFile(
- options.auth_htpasswd
- )
- except (ValueError, OSError) as v:
- raise exceptions.OptionsError(
- "Could not open htpasswd file: %s" % v
- )
- else:
- self.htpasswd = None
+ if "proxyauth" in updated:
+ self.nonanonymous = False
+ self.singleuser = None
+ self.htpasswd = None
+ if options.proxyauth:
+ if options.proxyauth == "any":
+ self.nonanonymous = True
+ elif options.proxyauth.startswith("@"):
+ p = options.proxyauth[1:]
+ try:
+ self.htpasswd = passlib.apache.HtpasswdFile(p)
+ except (ValueError, OSError) as v:
+ raise exceptions.OptionsError(
+ "Could not open htpasswd file: %s" % p
+ )
+ else:
+ parts = options.proxyauth.split(':')
+ if len(parts) != 2:
+ raise exceptions.OptionsError(
+ "Invalid single-user auth specification."
+ )
+ self.singleuser = parts
if "mode" in updated:
self.mode = options.mode
if self.enabled():
diff --git a/mitmproxy/options.py b/mitmproxy/options.py
index cee80158..a754325a 100644
--- a/mitmproxy/options.py
+++ b/mitmproxy/options.py
@@ -203,21 +203,16 @@ class Options(optmanager.OptManager):
# Proxy options
self.add_option(
- "auth_nonanonymous", False, bool,
- "Allow access to any user long as a credentials are specified."
- )
- self.add_option(
- "auth_singleuser", None, Optional[str],
+ "proxyauth", None, Optional[str],
"""
- Allows access to a a single user, specified in the form
- username:password.
+ Require authentication before proxying requests. If the value is
+ "any", we prompt for authentication, but permit any values. If it
+ starts with an "@", it is treated as a path to an Apache htpasswd
+ file. If its is of the form "username:password", it is treated as a
+ single-user credential.
"""
)
self.add_option(
- "auth_htpasswd", None, Optional[str],
- "Allow access to users specified in an Apache htpasswd file."
- )
- self.add_option(
"add_upstream_certs_to_client_chain", False, bool,
"""
Add all certificates of the upstream server to the certificate chain
diff --git a/mitmproxy/tools/cmdline.py b/mitmproxy/tools/cmdline.py
index bb33c1e4..fcf9ecaf 100644
--- a/mitmproxy/tools/cmdline.py
+++ b/mitmproxy/tools/cmdline.py
@@ -107,9 +107,7 @@ def common_options(parser, opts):
used for authenticating them.
"""
).add_mutually_exclusive_group()
- opts.make_parser(group, "auth_nonanonymous")
- opts.make_parser(group, "auth_singleuser", metavar="USER:PASS")
- opts.make_parser(group, "auth_htpasswd", metavar="PATH")
+ opts.make_parser(group, "proxyauth", metavar="SPEC")
def mitmproxy(opts):
diff --git a/test/mitmproxy/addons/test_proxyauth.py b/test/mitmproxy/addons/test_proxyauth.py
index dd5829ab..14782755 100644
--- a/test/mitmproxy/addons/test_proxyauth.py
+++ b/test/mitmproxy/addons/test_proxyauth.py
@@ -28,40 +28,43 @@ def test_configure():
up = proxyauth.ProxyAuth()
with taddons.context() as ctx:
with pytest.raises(exceptions.OptionsError):
- ctx.configure(up, auth_singleuser="foo")
+ ctx.configure(up, proxyauth="foo")
- ctx.configure(up, auth_singleuser="foo:bar")
+ ctx.configure(up, proxyauth="foo:bar")
assert up.singleuser == ["foo", "bar"]
- ctx.configure(up, auth_singleuser=None)
+ ctx.configure(up, proxyauth=None)
assert up.singleuser is None
- ctx.configure(up, auth_nonanonymous=True)
+ ctx.configure(up, proxyauth="any")
assert up.nonanonymous
- ctx.configure(up, auth_nonanonymous=False)
+ ctx.configure(up, proxyauth=None)
assert not up.nonanonymous
with pytest.raises(exceptions.OptionsError):
- ctx.configure(up, auth_htpasswd=tutils.test_data.path("mitmproxy/net/data/server.crt"))
+ ctx.configure(
+ up,
+ proxyauth= "@" + tutils.test_data.path("mitmproxy/net/data/server.crt")
+ )
with pytest.raises(exceptions.OptionsError):
- ctx.configure(up, auth_htpasswd="nonexistent")
+ ctx.configure(up, proxyauth="@nonexistent")
ctx.configure(
up,
- auth_htpasswd=tutils.test_data.path(
+ proxyauth= "@" + tutils.test_data.path(
"mitmproxy/net/data/htpasswd"
)
)
assert up.htpasswd
assert up.htpasswd.check_password("test", "test")
assert not up.htpasswd.check_password("test", "foo")
- ctx.configure(up, auth_htpasswd=None)
+ ctx.configure(up, proxyauth=None)
assert not up.htpasswd
with pytest.raises(exceptions.OptionsError):
- ctx.configure(up, auth_nonanonymous=True, mode="transparent")
+ ctx.configure(up, proxyauth="any", mode="transparent")
with pytest.raises(exceptions.OptionsError):
- ctx.configure(up, auth_nonanonymous=True, mode="socks5")
+ ctx.configure(up, proxyauth="any", mode="socks5")
ctx.configure(up, mode="regular")
assert up.mode == "regular"
@@ -70,7 +73,7 @@ def test_configure():
def test_check():
up = proxyauth.ProxyAuth()
with taddons.context() as ctx:
- ctx.configure(up, auth_nonanonymous=True, mode="regular")
+ ctx.configure(up, proxyauth="any", mode="regular")
f = tflow.tflow()
assert not up.check(f)
f.request.headers["Proxy-Authorization"] = proxyauth.mkauth(
@@ -86,18 +89,17 @@ def test_check():
)
assert not up.check(f)
- ctx.configure(up, auth_nonanonymous=False, auth_singleuser="test:test")
+ ctx.configure(up, proxyauth="test:test")
f.request.headers["Proxy-Authorization"] = proxyauth.mkauth(
"test", "test"
)
assert up.check(f)
- ctx.configure(up, auth_nonanonymous=False, auth_singleuser="test:foo")
+ ctx.configure(up, proxyauth="test:foo")
assert not up.check(f)
ctx.configure(
up,
- auth_singleuser=None,
- auth_htpasswd=tutils.test_data.path(
+ proxyauth="@" + tutils.test_data.path(
"mitmproxy/net/data/htpasswd"
)
)
@@ -114,7 +116,7 @@ def test_check():
def test_authenticate():
up = proxyauth.ProxyAuth()
with taddons.context() as ctx:
- ctx.configure(up, auth_nonanonymous=True, mode="regular")
+ ctx.configure(up, proxyauth="any", mode="regular")
f = tflow.tflow()
assert not f.response
@@ -147,7 +149,7 @@ def test_authenticate():
def test_handlers():
up = proxyauth.ProxyAuth()
with taddons.context() as ctx:
- ctx.configure(up, auth_nonanonymous=True, mode="regular")
+ ctx.configure(up, proxyauth="any", mode="regular")
f = tflow.tflow()
assert not f.response
diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py
index b90840ab..aa45761a 100644
--- a/test/mitmproxy/proxy/test_server.py
+++ b/test/mitmproxy/proxy/test_server.py
@@ -302,7 +302,7 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin):
class TestHTTPAuth(tservers.HTTPProxyTest):
def test_auth(self):
self.master.addons.add(proxyauth.ProxyAuth())
- self.master.options.auth_singleuser = "test:test"
+ self.master.options.proxyauth = "test:test"
assert self.pathod("202").status_code == 407
p = self.pathoc()
with p.connect():
@@ -321,7 +321,7 @@ class TestHTTPAuth(tservers.HTTPProxyTest):
class TestHTTPReverseAuth(tservers.ReverseProxyTest):
def test_auth(self):
self.master.addons.add(proxyauth.ProxyAuth())
- self.master.options.auth_singleuser = "test:test"
+ self.master.options.proxyauth = "test:test"
assert self.pathod("202").status_code == 401
p = self.pathoc()
with p.connect():