diff options
author | Aldo Cortesi <aldo@corte.si> | 2012-12-30 11:27:04 -0800 |
---|---|---|
committer | Aldo Cortesi <aldo@corte.si> | 2012-12-30 11:27:04 -0800 |
commit | cfab27232127437cca8ac3699065db653da97dba (patch) | |
tree | 60a92d02b45daf421a0329e4d404652b8f6b3baa /libmproxy/authentication.py | |
parent | 3c8dcf880860191ef3bd000f95cf7ea980c6bda9 (diff) | |
parent | 440a9f6bda8d645945e8c056a5e869c712dd2d69 (diff) | |
download | mitmproxy-cfab27232127437cca8ac3699065db653da97dba.tar.gz mitmproxy-cfab27232127437cca8ac3699065db653da97dba.tar.bz2 mitmproxy-cfab27232127437cca8ac3699065db653da97dba.zip |
Merge pull request #83 from rouli/master
Adding some basic proxy authentication code
Diffstat (limited to 'libmproxy/authentication.py')
-rw-r--r-- | libmproxy/authentication.py | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/libmproxy/authentication.py b/libmproxy/authentication.py new file mode 100644 index 00000000..e5383f5a --- /dev/null +++ b/libmproxy/authentication.py @@ -0,0 +1,95 @@ +import binascii +import contrib.md5crypt as md5crypt + +class NullProxyAuth(): + """ No proxy auth at all (returns empty challange headers) """ + def __init__(self, password_manager=None): + self.password_manager = password_manager + self.username = "" + + def authenticate(self, auth_value): + """ 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 """ + 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; + try: + scheme, username, password = self.parse_authorization_header(auth_value[0]) + except: + return False + if scheme.lower()!='basic': + return False + if not self.password_manager.test(username, password): + return False + self.username = username + return True + + def auth_challenge_headers(self): + return {'Proxy-Authenticate':'Basic realm="%s"'%self.realm} + + def parse_authorization_header(self, auth_value): + words = auth_value.split() + scheme = words[0] + user = binascii.a2b_base64(words[1]) + username, password = user.split(':') + return scheme, username, password + +class PasswordManager(): + def __init__(self): + pass + + def test(self, username, password_token): + return False + +class PermissivePasswordManager(PasswordManager): + + def __init__(self): + PasswordManager.__init__(self) + + def test(self, username, password_token): + if username: + return True + return False + +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 + full_token = self.usernames[username] + dummy, magic, salt, hashed_password = full_token.split('$') + expected = md5crypt.md5crypt(password_token, salt, '$'+magic+'$') + return expected==full_token + +class SingleUserPasswordManager(PasswordManager): + + def __init__(self, username, password): + PasswordManager.__init__(self) + self.username = username + self.password = password + + def test(self, username, password_token): + return self.username==username and self.password==password_token |