summaryrefslogtreecommitdiff
path: root/sievelib/digest_md5.py
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-11-18 17:28:43 (GMT)
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-11-18 17:28:43 (GMT)
commit092eed219ad6863e6ce911265223ce7c1b50c01d (patch)
tree5a4ae9a1e1e29069db9e335dae5d5a01b1ef136c /sievelib/digest_md5.py
downloadpython-sievelib-092eed219ad6863e6ce911265223ce7c1b50c01d.tar.gz
Add original sievelib-0.5 releaseupstream-0.5
Diffstat (limited to 'sievelib/digest_md5.py')
-rw-r--r--sievelib/digest_md5.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/sievelib/digest_md5.py b/sievelib/digest_md5.py
new file mode 100644
index 0000000..9011177
--- /dev/null
+++ b/sievelib/digest_md5.py
@@ -0,0 +1,69 @@
+# coding: utf-8
+
+"""
+Simple Digest-MD5 implementation (client side)
+
+Implementation based on RFC 2831 (http://www.ietf.org/rfc/rfc2831.txt)
+"""
+
+import base64
+import hashlib
+import binascii
+import re
+import random
+
+class DigestMD5(object):
+ def __init__(self, challenge, digesturi):
+ self.__digesturi = digesturi
+ self.__challenge = challenge
+
+ self.__params = {}
+ pexpr = re.compile('(\w+)="(.+)"')
+ for elt in base64.b64decode(challenge).split(","):
+ m = pexpr.match(elt)
+ if m is None:
+ continue
+ self.__params[m.group(1)] = m.group(2)
+
+ def __make_cnonce(self):
+ ret = ""
+ for i in xrange(12):
+ ret += chr(random.randint(0, 0xff))
+ return base64.b64encode(ret)
+
+ def __digest(self, value):
+ return hashlib.md5(value).digest()
+
+ def __hexdigest(self, value):
+ return binascii.hexlify(hashlib.md5(value).digest())
+
+ def __make_response(self, username, password, check=False):
+ a1 = "%s:%s:%s" % (self.__digest("%s:%s:%s" % (username, self.realm, password)),
+ self.__params["nonce"], self.cnonce)
+ if check:
+ a2 = ":%s" % self.__digesturi
+ else:
+ a2 = "AUTHENTICATE:%s" % self.__digesturi
+ resp = "%s:%s:00000001:%s:auth:%s" \
+ % (self.__hexdigest(a1), self.__params["nonce"],
+ self.cnonce, self.__hexdigest(a2))
+
+ return self.__hexdigest(resp)
+
+ def response(self, username, password):
+ self.realm = self.__params["realm"] if self.__params.has_key("realm") else ""
+ self.cnonce = self.__make_cnonce()
+ respvalue = self.__make_response(username, password)
+
+ dgres = 'username="%s",%snonce="%s",cnonce="%s",nc=00000001,qop=auth,' \
+ 'digest-uri="%s",response=%s' \
+ % (username, ('realm="%s",' % self.realm) if len(self.realm) else "",
+ self.__params["nonce"], self.cnonce, self.__digesturi, respvalue)
+
+ return base64.b64encode(dgres)
+
+ def check_last_challenge(self, username, password, value):
+ challenge = base64.b64decode(value.strip('"'))
+ return challenge == \
+ ("rspauth=%s" % self.__make_response(username, password, True))
+