mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 01:12:08 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			82 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | 
						|
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
						|
 | 
						|
import hashlib
 | 
						|
from collections import OrderedDict
 | 
						|
 | 
						|
from django.conf import settings
 | 
						|
from django.contrib.auth.hashers import PBKDF2PasswordHasher, mask_hash
 | 
						|
from django.utils.crypto import constant_time_compare
 | 
						|
from django.utils.translation import gettext_lazy as _
 | 
						|
from note_kfet.middlewares import get_current_request
 | 
						|
 | 
						|
 | 
						|
class CustomNK15Hasher(PBKDF2PasswordHasher):
 | 
						|
    """
 | 
						|
    Permet d'importer les mots de passe depuis la Note KFet 2015.
 | 
						|
    Si un hash de mot de passe est de la forme :
 | 
						|
    `custom_nk15$<NB>$<ENCODED>`
 | 
						|
    où <NB> est un entier quelconque (symbolisant normalement un nombre d'itérations)
 | 
						|
    et <ENCODED> le hash du mot de passe dans la Note Kfet 2015,
 | 
						|
    alors ce hasher va vérifier le mot de passe.
 | 
						|
    N'ayant pas la priorité (cf note_kfet/settings/base.py), le mot de passe sera
 | 
						|
    converti automatiquement avec l'algorithme PBKDF2.
 | 
						|
    """
 | 
						|
    algorithm = "custom_nk15"
 | 
						|
 | 
						|
    def must_update(self, encoded):
 | 
						|
        if settings.DEBUG:
 | 
						|
            # Small hack to let superusers to impersonate people.
 | 
						|
            # Don't change their password.
 | 
						|
            request = get_current_request()
 | 
						|
            current_user = request.user
 | 
						|
            if current_user is not None and current_user.is_superuser:
 | 
						|
                return False
 | 
						|
        return True
 | 
						|
 | 
						|
    def verify(self, password, encoded):
 | 
						|
        if settings.DEBUG:
 | 
						|
            # Small hack to let superusers to impersonate people.
 | 
						|
            # If a superuser is already connected, let him/her log in as another person.
 | 
						|
            request = get_current_request()
 | 
						|
            current_user = request.user
 | 
						|
            if current_user is not None and current_user.is_superuser\
 | 
						|
                    and request.session.get("permission_mask", -1) >= 42:
 | 
						|
                return True
 | 
						|
 | 
						|
        if '|' in encoded:
 | 
						|
            salt, db_hashed_pass = encoded.split('$')[2].split('|')
 | 
						|
            return constant_time_compare(hashlib.sha256((salt + password).encode("utf-8")).hexdigest(), db_hashed_pass)
 | 
						|
        return super().verify(password, encoded)
 | 
						|
 | 
						|
    def safe_summary(self, encoded):
 | 
						|
        # Displayed information in Django Admin.
 | 
						|
        if '|' in encoded:
 | 
						|
            salt, db_hashed_pass = encoded.split('$')[2].split('|')
 | 
						|
            return OrderedDict([
 | 
						|
                (_('algorithm'), 'custom_nk15'),
 | 
						|
                (_('iterations'), '1'),
 | 
						|
                (_('salt'), mask_hash(salt)),
 | 
						|
                (_('hash'), mask_hash(db_hashed_pass)),
 | 
						|
            ])
 | 
						|
        return super().safe_summary(encoded)
 | 
						|
 | 
						|
 | 
						|
class DebugSuperuserBackdoor(PBKDF2PasswordHasher):
 | 
						|
    """
 | 
						|
    In debug mode and during the beta, superusers can login into other accounts for tests.
 | 
						|
    """
 | 
						|
    def must_update(self, encoded):
 | 
						|
        return False
 | 
						|
 | 
						|
    def verify(self, password, encoded):
 | 
						|
        if settings.DEBUG:
 | 
						|
            # Small hack to let superusers to impersonate people.
 | 
						|
            # If a superuser is already connected, let him/her log in as another person.
 | 
						|
            request = get_current_request()
 | 
						|
            current_user = request.user
 | 
						|
            if current_user is not None and current_user.is_superuser\
 | 
						|
                    and request.session.get("permission_mask", -1) >= 42:
 | 
						|
                return True
 | 
						|
        return super().verify(password, encoded)
 |