/usr/lib/python3/dist-packages/sievelib/digest_md5.py is in python3-sievelib 1.1.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | # 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(r'(\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, authz_id=''):
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)
if authz_id:
if type(authz_id) is unicode:
authz_id = authz_id.encode("utf-8")
dgres += ',authzid="%s"' % authz_id
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))
|