Coverage for plugins/attributes/ldapPasswordHash/ldapPasswordHash.py: 39%

28 statements  

« prev     ^ index     » next       coverage.py v7.10.1, created at 2025-07-28 07:24 +0000

1#!/usr/bin/env python3 

2# -*- coding: utf-8 -*- 

3 

4# Hermes : Change Data Capture (CDC) tool from any source(s) to any target 

5# Copyright (C) 2023, 2024 INSA Strasbourg 

6# 

7# This file is part of Hermes. 

8# 

9# Hermes is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# Hermes is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with Hermes. If not, see <https://www.gnu.org/licenses/>. 

21 

22 

23from jinja2 import Undefined 

24 

25 

26from helpers.ldaphash import LDAPHash 

27from lib.plugins import AbstractAttributePlugin 

28 

29HERMES_PLUGIN_CLASSNAME: str | None = "LdapPasswordHashPlugin" 

30"""The plugin class name defined in this module file""" 

31 

32 

33class InvalidLdapPasswordHashType(Exception): 

34 """Raised when an unknown hash type has been requested""" 

35 

36 

37class LdapPasswordHashPlugin(AbstractAttributePlugin): 

38 """Plugin to generate LDAP password hashes""" 

39 

40 def __init__(self, settings: dict[str, any]) -> None: 

41 """Instantiate new plugin and store a copy of its settings dict in 

42 self._settings""" 

43 super().__init__(settings) 

44 self._defaulthashtypes: list[str] = self._settings["default_hash_types"] 

45 

46 def filter( 

47 self, password: str | None | Undefined, hashtypes: None | str | list[str] = None 

48 ) -> list[str] | None: 

49 """Call the plugin with specified value, and returns the result.""" 

50 

51 if password is None: 

52 return Undefined(hint="No password specified") 

53 

54 if isinstance(password, Undefined): 

55 return password 

56 

57 if type(password) is not str: 

58 raise TypeError( 

59 f"Invalid type for password: {type(password)=}." 

60 " Password must be a string" 

61 ) 

62 

63 if hashtypes is None: 

64 # No type(s) explicitly specified, use default values specified in config 

65 _hashtypes: list[str] = self._defaulthashtypes 

66 else: 

67 # Use specified type(s), and ensure to store values in a set to filter 

68 # duplicates 

69 if type(hashtypes) is str: 

70 _hashtypes = [hashtypes] 

71 elif type(hashtypes) is list: 

72 _hashtypes = hashtypes 

73 else: 

74 raise TypeError( 

75 f"Invalid type for hashtypes: {type(hashtypes)=}." 

76 " Hashtype must be a string or a list of string" 

77 ) 

78 

79 unknownHashTypes = set(_hashtypes) - set(LDAPHash.getAvailableHashtypes()) 

80 if unknownHashTypes: 

81 raise InvalidLdapPasswordHashType( 

82 f"Invalid LDAP password hash type specified: {unknownHashTypes}" 

83 ) 

84 

85 return [LDAPHash.hash(password, hashtype) for hashtype in _hashtypes]