1
0
mirror of https://github.com/Mailu/Mailu.git synced 2024-12-12 10:45:38 +02:00

Implement a simple credential cache

This commit is contained in:
Florent Daigniere 2021-02-10 13:51:07 +01:00
parent 9c57f2ac39
commit ae9206e968
2 changed files with 24 additions and 0 deletions

View File

@ -305,6 +305,7 @@ class User(Base, Email):
"""
__tablename__ = "user"
_ctx = None
_credential_cache = {}
domain = db.relationship(Domain,
backref=db.backref('users', cascade='all, delete-orphan'))
@ -382,6 +383,17 @@ class User(Base, Email):
return User._ctx
def check_password(self, password):
cache_result = self._credential_cache.get(self.get_id())
current_salt = self.password.split('$')[3] if len(self.password.split('$')) == 5 else None
if cache_result and current_salt:
cache_salt, cache_hash = cache_result
if cache_salt == current_salt:
return hash.pbkdf2_sha256.verify(password, cache_hash)
else:
# the cache is local per gunicorn; the password has changed
# so the local cache can be invalidated
del self._credential_cache[self.get_id()]
reference = self.password
# strip {scheme} if that's something mailu has added
# passlib will identify *crypt based hashes just fine
@ -396,6 +408,17 @@ class User(Base, Email):
self.password = new_hash
db.session.add(self)
db.session.commit()
if result:
"""The credential cache uses a low number of rounds to be fast.
While it's not meant to be persisted to cold-storage, no additional measures
are taken to ensure it isn't (mlock(), encrypted swap, ...) on the basis that
we have little control over GC and string interning anyways.
An attacker that can dump the process' memory is likely to find credentials
in clear-text regardless of the presence of the cache.
"""
self._credential_cache[self.get_id()] = (self.password.split('$')[3], hash.pbkdf2_sha256.using(rounds=1).hash(password))
return result
def set_password(self, password, hash_scheme=None, raw=False):

View File

@ -0,0 +1 @@
Add a credential cache to speedup authentication requests.