aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-12-31 09:15:56 +1300
committerAldo Cortesi <aldo@nullcube.com>2012-12-31 09:15:56 +1300
commit018c229ae40d93f0f0987a37a33256db57cdc62c (patch)
tree6a098c71f3af7c8a52b58c342522723ef89ad3c1
parentcfab27232127437cca8ac3699065db653da97dba (diff)
downloadmitmproxy-018c229ae40d93f0f0987a37a33256db57cdc62c.tar.gz
mitmproxy-018c229ae40d93f0f0987a37a33256db57cdc62c.tar.bz2
mitmproxy-018c229ae40d93f0f0987a37a33256db57cdc62c.zip
Start solidifying proxy authentication
- Add a unit test file - Remove some extraneous methods - Change the auth API to make the authenticate method take a header object.
-rw-r--r--libmproxy/authentication.py39
-rw-r--r--libmproxy/proxy.py8
-rw-r--r--test/test_authentication.py18
3 files changed, 46 insertions, 19 deletions
diff --git a/libmproxy/authentication.py b/libmproxy/authentication.py
index e5383f5a..c928ebbd 100644
--- a/libmproxy/authentication.py
+++ b/libmproxy/authentication.py
@@ -2,32 +2,35 @@ import binascii
import contrib.md5crypt as md5crypt
class NullProxyAuth():
- """ No proxy auth at all (returns empty challange headers) """
- def __init__(self, password_manager=None):
+ """
+ No proxy auth at all (returns empty challange headers)
+ """
+ def __init__(self, password_manager):
self.password_manager = password_manager
self.username = ""
- def authenticate(self, auth_value):
- """ Tests that the specified user is allowed to use the proxy (stub) """
+ def authenticate(self, headers):
+ """
+ Tests that the specified user is allowed to use the proxy (stub)
+ """
return True
def auth_challenge_headers(self):
- """ Returns a dictionary containing the headers require to challenge the user """
+ """
+ Returns a dictionary containing the headers require to challenge the user
+ """
return {}
- def get_username(self):
- return self.username
-
class BasicProxyAuth(NullProxyAuth):
-
def __init__(self, password_manager, realm="mitmproxy"):
NullProxyAuth.__init__(self, password_manager)
self.realm = "mitmproxy"
- def authenticate(self, auth_value):
- if (not auth_value) or (not auth_value[0]):
- return False;
+ def authenticate(self, headers):
+ auth_value = headers.get('Proxy-Authorization', [])
+ if not auth_value:
+ return False
try:
scheme, username, password = self.parse_authorization_header(auth_value[0])
except:
@@ -49,6 +52,7 @@ class BasicProxyAuth(NullProxyAuth):
username, password = user.split(':')
return scheme, username, password
+
class PasswordManager():
def __init__(self):
pass
@@ -56,8 +60,8 @@ class PasswordManager():
def test(self, username, password_token):
return False
-class PermissivePasswordManager(PasswordManager):
+class PermissivePasswordManager(PasswordManager):
def __init__(self):
PasswordManager.__init__(self)
@@ -66,16 +70,17 @@ class PermissivePasswordManager(PasswordManager):
return True
return False
-class HtpasswdPasswordManager(PasswordManager):
- """ Read usernames and passwords from a file created by Apache htpasswd"""
+class HtpasswdPasswordManager(PasswordManager):
+ """
+ Read usernames and passwords from a file created by Apache htpasswd
+ """
def __init__(self, filehandle):
PasswordManager.__init__(self)
entries = (line.strip().split(':') for line in filehandle)
valid_entries = (entry for entry in entries if len(entry)==2)
self.usernames = {username:token for username,token in valid_entries}
-
def test(self, username, password_token):
if username not in self.usernames:
return False
@@ -84,8 +89,8 @@ class HtpasswdPasswordManager(PasswordManager):
expected = md5crypt.md5crypt(password_token, salt, '$'+magic+'$')
return expected==full_token
-class SingleUserPasswordManager(PasswordManager):
+class SingleUserPasswordManager(PasswordManager):
def __init__(self, username, password):
PasswordManager.__init__(self)
self.username = username
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index b1ce310c..2c62a880 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -356,8 +356,12 @@ class ProxyHandler(tcp.BaseHandler):
headers = http.read_headers(self.rfile)
if headers is None:
raise ProxyError(400, "Invalid headers")
- if authenticate and self.config.authenticator and not self.config.authenticator.authenticate(headers.get('Proxy-Authorization', [])):
- raise ProxyError(407, "Proxy Authentication Required", self.config.authenticator.auth_challenge_headers())
+ if authenticate and self.config.authenticator and not self.config.authenticator.authenticate(headers):
+ raise ProxyError(
+ 407,
+ "Proxy Authentication Required",
+ self.config.authenticator.auth_challenge_headers()
+ )
return headers
def send_response(self, response):
diff --git a/test/test_authentication.py b/test/test_authentication.py
new file mode 100644
index 00000000..25714263
--- /dev/null
+++ b/test/test_authentication.py
@@ -0,0 +1,18 @@
+from libmproxy import authentication
+from netlib import odict
+
+
+class TestNullProxyAuth:
+ def test_simple(self):
+ na = authentication.NullProxyAuth(authentication.PermissivePasswordManager())
+ assert not na.auth_challenge_headers()
+ assert na.authenticate("foo")
+
+
+class TestBasicProxyAuth:
+ def test_simple(self):
+ ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager())
+ h = odict.ODictCaseless()
+ assert ba.auth_challenge_headers()
+ assert not ba.authenticate(h)
+