8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-28 01:43:46 +00:00

Support old hashes, md5/crypt

This commit is contained in:
Charlie Jacomme 2018-08-04 16:58:42 +02:00
parent cf3edceff5
commit fbb2c59722
2 changed files with 116 additions and 1 deletions

View file

@ -33,8 +33,10 @@ import binascii
import os
from base64 import encodestring
from base64 import decodestring
from base64 import b64encode
from base64 import b64decode
from collections import OrderedDict
import crypt
from django.contrib.auth import hashers
@ -72,6 +74,117 @@ def checkPassword(challenge_password, password):
return valid_password
def hash_password_salt(hashed_password):
""" Extract the salt from a given hashed password """
if hashed_password.upper().startswith('{CRYPT}'):
hashed_password = hashed_password[7:]
if hashed_password.startswith('$'):
return '$'.join(hashed_password.split('$')[:-1])
else:
return hashed_password[:2]
elif hashed_password.upper().startswith('{SSHA}'):
try:
digest = b64decode(hashed_password[6:])
except TypeError as error:
raise ValueError("b64 error for `hashed_password` : %s" % error)
if len(digest) < 20:
raise ValueError("`hashed_password` too short")
return digest[20:]
elif hashed_password.upper().startswith('{SMD5}'):
try:
digest = b64decode(hashed_password[7:])
except TypeError as error:
raise ValueError("b64 error for `hashed_password` : %s" % error)
if len(digest) < 16:
raise ValueError("`hashed_password` too short")
return digest[16:]
else:
raise ValueError("`hashed_password` should start with '{SSHA}' or '{CRYPT}' or '{SMD5}'")
class CryptPasswordHasher(hashers.BasePasswordHasher):
"""
Crypt password hashing to allow for LDAP auth compatibility
We do not encode, this should bot be used !
"""
algorithm = "{crypt}"
def encode(self, password, salt):
pass
def verify(self, password, encoded):
"""
Check password against encoded using SSHA algorithm
"""
assert encoded.startswith(self.algorithm)
salt = hash_password_salt(challenge_password)
return crypt.crypt(password.encode(), salt) == challenge.encode()
def safe_summary(self, encoded):
"""
Provides a safe summary of the password
"""
assert encoded.startswith(self.algorithm)
hash_str = encoded[7:]
hash_str = binascii.hexlify(decodestring(hash_str.encode())).decode()
return OrderedDict([
('algorithm', self.algorithm),
('iterations', 0),
('salt', hashers.mask_hash(hash_str[2*DIGEST_LEN:], show=2)),
('hash', hashers.mask_hash(hash_str[:2*DIGEST_LEN])),
])
def harden_runtime(self, password, encoded):
"""
Method implemented to shut up BasePasswordHasher warning
As we are not using multiple iterations the method is pretty useless
"""
pass
class MD5PasswordHasher(hashers.BasePasswordHasher):
"""
MD5 password hashing to allow for LDAP auth compatibility
We do not encode, this should bot be used !
"""
algorithm = "{SMD5}"
def encode(self, password, salt):
pass
def verify(self, password, encoded):
"""
Check password against encoded using SSHA algorithm
"""
assert encoded.startswith(self.algorithm)
salt = hash_password_salt(encoded)
return b64encode(hashlib.md5(password.encode() + salt).digest() + salt) == encoded.encode()
def safe_summary(self, encoded):
"""
Provides a safe summary of the password
"""
assert encoded.startswith(self.algorithm)
hash_str = encoded[7:]
hash_str = binascii.hexlify(decodestring(hash_str.encode())).decode()
return OrderedDict([
('algorithm', self.algorithm),
('iterations', 0),
('salt', hashers.mask_hash(hash_str[2*DIGEST_LEN:], show=2)),
('hash', hashers.mask_hash(hash_str[:2*DIGEST_LEN])),
])
def harden_runtime(self, password, encoded):
"""
Method implemented to shut up BasePasswordHasher warning
As we are not using multiple iterations the method is pretty useless
"""
pass
class SSHAPasswordHasher(hashers.BasePasswordHasher):
"""
SSHA password hashing to allow for LDAP auth compatibility

View file

@ -46,6 +46,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Auth definition
PASSWORD_HASHERS = (
're2o.login.SSHAPasswordHasher',
're2o.login.MD5PasswordHasher',
're2o.login.CryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
)
AUTH_USER_MODEL = 'users.User' # The class to use for authentication