Bowe Strickland
2018-10-26 29e4dce0a2ba187091b4644e2003297300162673
repoze/who/plugins/htpasswd.py
@@ -1,18 +1,19 @@
import itertools
from zope.interface import implements
from zope.interface import implementer
from repoze.who.interfaces import IAuthenticator
from repoze.who.utils import resolveDotted
from repoze.who._compat import izip_longest
def _padding_for_file_lines():
    yield 'aaaaaa:bbbbbb'
@implementer(IAuthenticator)
class HTPasswdPlugin(object):
    implements(IAuthenticator)
    def __init__(self, filename, check):
        self.filename = filename
@@ -37,9 +38,11 @@
            # assumed to have a readline
            self.filename.seek(0)
            f = self.filename
            must_close = False
        else:
            try:
                f = open(self.filename, 'r')
                must_close = True
            except IOError:
                environ['repoze.who.logger'].warn('could not open htpasswd '
                                                  'file %s' % self.filename)
@@ -62,6 +65,9 @@
                maybe_user = username
                to_check = hashed
        if must_close:
            f.close()
        # Check *something* here, to mitigate a timing attack.
        password_ok = self.check(password, to_check)
@@ -79,16 +85,26 @@
def _same_string(x, y):
    # Attempt at isochronous string comparison.
    match = True
    for a, b, ignored in itertools.izip_longest(x, y, PADDING):
        match = a == b and match
    return match
    mismatches = filter(None, [a != b for a, b, ignored
                                    in izip_longest(x, y, PADDING)])
    if type(mismatches) != list: #pragma NO COVER Python >= 3.0
        mismatches = list(mismatches)
    return len(mismatches) == 0
def crypt_check(password, hashed):
    from crypt import crypt
    salt = hashed[:2]
    return _same_string(hashed, crypt(password, salt))
def sha1_check(password, hashed):
    from hashlib import sha1
    from base64 import standard_b64encode
    from repoze.who._compat import must_encode
    encrypted_string = standard_b64encode(sha1(must_encode(password)).digest())
    if hasattr(encrypted_string, "decode"):
        encrypted_string = encrypted_string.decode()
    return _same_string(hashed, "%s%s" % ("{SHA}", encrypted_string))
def plain_check(password, hashed):
    return _same_string(password, hashed)