From a428afe1b556837045c0824fea2a2ee9664bf094 Mon Sep 17 00:00:00 2001 From: David Coutadeur Date: Tue, 24 Aug 2021 13:29:11 +0200 Subject: [PATCH] ITS#9644 - Add man page for ppm --- contrib/slapd-modules/ppm/CHANGELOG.md | 38 +++ contrib/slapd-modules/ppm/CONTRIBUTIONS.md | 5 + contrib/slapd-modules/ppm/INSTALL.md | 3 + contrib/slapd-modules/ppm/Makefile | 7 + contrib/slapd-modules/ppm/README.md | 361 +-------------------- contrib/slapd-modules/ppm/ppm.5 | 360 ++++++++++++++++++++ contrib/slapd-modules/ppm/ppm.md | 343 ++++++++++++++++++++ 7 files changed, 757 insertions(+), 360 deletions(-) create mode 100644 contrib/slapd-modules/ppm/CHANGELOG.md create mode 100644 contrib/slapd-modules/ppm/CONTRIBUTIONS.md create mode 100644 contrib/slapd-modules/ppm/ppm.5 create mode 100644 contrib/slapd-modules/ppm/ppm.md diff --git a/contrib/slapd-modules/ppm/CHANGELOG.md b/contrib/slapd-modules/ppm/CHANGELOG.md new file mode 100644 index 0000000000..d0e4ed732b --- /dev/null +++ b/contrib/slapd-modules/ppm/CHANGELOG.md @@ -0,0 +1,38 @@ +# CHANGELOG + +* 2021-02-23 David Coutadeur + remove maxLength attribute (#21) + adapt the readme and documentation of ppm (#22) + prepare ppolicy10 in OpenLDAP 2.5 (#20, #23 and #24) + add pwdCheckModuleArg feature + Version 2.0 +* 2019-08-20 David Coutadeur + adding debug symbols for ppm_test, + improve tests with the possibility to add username, + fix openldap crash when checkRDN=1 and username contains too short parts + Version 1.8 +* 2018-03-30 David Coutadeur + various minor improvements provided by Tim Bishop (tdb) (compilation, test program, + imprvts in Makefile: new OLDAP_SOURCES variable pointing to OLDAP install. directory + Version 1.7 +* 2017-05-19 David Coutadeur + Adds cracklib support + Readme adaptations and cleaning + Version 1.6 +* 2017-02-07 David Coutadeur + Adds maxConsecutivePerClass (idea from Trevor Vaughan / tvaughan@onyxpoint.com) + Version 1.5 +* 2016-08-22 David Coutadeur + Get config file from environment variable + Version 1.4 +* 2014-12-20 Daly Chikhaoui + Adding checkRDN parameter + Version 1.3 +* 2014-10-28 David Coutadeur + Adding maxLength parameter + Version 1.2 +* 2014-07-27 David Coutadeur + Changing the configuration file and the configuration data structure + Version 1.1 +* 2014-04-04 David Coutadeur + Version 1.0 diff --git a/contrib/slapd-modules/ppm/CONTRIBUTIONS.md b/contrib/slapd-modules/ppm/CONTRIBUTIONS.md new file mode 100644 index 0000000000..0d563d8ef0 --- /dev/null +++ b/contrib/slapd-modules/ppm/CONTRIBUTIONS.md @@ -0,0 +1,5 @@ +# CONTRIBUTIONS + +* 2014 - 2021 - David Coutadeur - maintainer +* 2015 - Daly Chikhaoui - Janua - contribution on RDN checks +* 2017 - tdb - Tim Bishop - contribution on some compilation improvements diff --git a/contrib/slapd-modules/ppm/INSTALL.md b/contrib/slapd-modules/ppm/INSTALL.md index 0ae238176a..6052dc6091 100644 --- a/contrib/slapd-modules/ppm/INSTALL.md +++ b/contrib/slapd-modules/ppm/INSTALL.md @@ -6,6 +6,7 @@ Dependencies ppm is provided along with OpenLDAP sources. By default, it is available into contrib/slapd-modules. - make sure both OpenLDAP sources and ppm are available for building. - install cracklib development files if you want to test passwords against cracklib + - install pandoc if you want to build the man page Build @@ -34,6 +35,7 @@ To build ppm, simply run these commands: make clean make make test +make doc make install ``` @@ -43,6 +45,7 @@ Here is an illustrative example showing how to overload some options: make clean make LDAP_SRC=../../.. prefix=/usr/local libdir=/usr/local/lib make test LDAP_SRC=../../.. +make doc prefix=/usr/local make install prefix=/usr/local libdir=/usr/local/lib ``` diff --git a/contrib/slapd-modules/ppm/Makefile b/contrib/slapd-modules/ppm/Makefile index 41192052d7..fd21596ed4 100644 --- a/contrib/slapd-modules/ppm/Makefile +++ b/contrib/slapd-modules/ppm/Makefile @@ -59,6 +59,9 @@ TEST=ppm_test EXAMPLE=ppm.example TESTS=./unit_tests.sh +MANDOC=ppm.5 +MDDOC=ppm.md + all: ppm $(TEST) $(TEST): ppm @@ -76,6 +79,7 @@ install: ppm $(LIBTOOL) --mode=install cp $$p $(DESTDIR)/$(moduledir) ; \ done $(INSTALL) -m 644 $(EXAMPLE) $(DESTDIR)$(sysconfdir)/ + $(INSTALL) -m 644 $(MANDOC) $(man5dir)/ # $(INSTALL) -m 755 $(TEST) $(libdir) .PHONY: clean @@ -87,4 +91,7 @@ clean: test: ppm $(TEST) LDAP_SRC=$(LDAP_SRC) $(TESTS) +doc: + pandoc $(MDDOC) -s -t man -o $(MANDOC) + sed -i -e 's#ETCDIR#$(DESTDIR)$(sysconfdir)#g' $(MANDOC) diff --git a/contrib/slapd-modules/ppm/README.md b/contrib/slapd-modules/ppm/README.md index 2762e4d7ee..129f788278 100644 --- a/contrib/slapd-modules/ppm/README.md +++ b/contrib/slapd-modules/ppm/README.md @@ -1,360 +1 @@ - -ppm.c - OpenLDAP password policy module - -version 2.0 - -ppm.c is an OpenLDAP module for checking password quality when they are modified. -Passwords are checked against the presence or absence of certain character classes. - -This module is used as an extension of the OpenLDAP password policy controls, -see slapo-ppolicy(5) section pwdCheckModule. - -contributions -------------- - -* 2014 - 2021 - David Coutadeur - maintainer -* 2015 - Daly Chikhaoui - Janua - contribution on RDN checks -* 2017 - tdb - Tim Bishop - contribution on some compilation improvements - - -INSTALLATION ------------- - -See INSTALL file - - -USAGE ------ - -Create a password policy entry and indicate the path of the ppm.so library -and the content of the desired policy. -Use a base64 tool to code / decode the content of the policy stored into -pwdCheckModuleArg. Here is an example: - -``` -dn: cn=default,ou=policies,dc=my-domain,dc=com -objectClass: pwdPolicy -objectClass: top -objectClass: pwdPolicyChecker -objectClass: person -pwdCheckQuality: 2 -pwdAttribute: userPassword -sn: default -cn: default -pwdMinLength: 6 -pwdCheckModule: /usr/local/lib/ppm.so -pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKZm9yYmlkZGVuQ2hhcnMKbWF4Q29uc2VjdXRpdmVQZXJDbGFzcyAwCnVzZUNyYWNrbGliIDAKY3JhY2tsaWJEaWN0IC92YXIvY2FjaGUvY3JhY2tsaWIvY3JhY2tsaWJfZGljdApjbGFzcy11cHBlckNhc2UgQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMCAxCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEKY2xhc3MtZGlnaXQgMDEyMzQ1Njc4OSAwIDEKY2xhc3Mtc3BlY2lhbCA8Piw/Oy46LyHCp8O5JSrCtV7CqCTCo8KyJsOpfiIjJ3soWy18w6hgX1zDp17DoEApXcKwPX0rIDAgMQ== -``` - - -See slapo-ppolicy for more information, but to sum up: -- enable ppolicy overlay in your database. -This example show the activation for a slapd.conf file -(see slapd-config and slapo-ppolicy for more information for - cn=config configuration) - -``` -overlay ppolicy -ppolicy_default "cn=default,ou=policies,dc=my-domain,dc=com" -#ppolicy_use_lockout # for having more infos about the lockout -``` - -- define a default password policy in OpenLDAP configuration or -use pwdPolicySubentry attribute to point to the given policy. - - - - -Password checks ---------------- - -- 4 character classes are defined by default: -upper case, lower case, digits and special characters. - -- more character classes can be defined, just write your own. - -- passwords must match the amount of quality points. -A point is validated when at least m characters of the corresponding -character class are present in the password. - -- passwords must have at least n of the corresponding character class -present, else they are rejected. - -- the two previous criteria are checked against any specific character class -defined. - -- if a password contains any of the forbidden characters, then it is -rejected. - -- if a password contains tokens from the RDN, then it is rejected. - -- if a password is too long, it can be rejected. - -- if a password does not pass cracklib check, it can be rejected. - - -Configuration -------------- - -Since OpenLDAP 2.5 version, ppm configuration is held in a binary -attribute of the password policy: pwdCheckModuleArg -The example file (/etc/openldap/ppm.example by default) is to be -considered as an example configuration, to import in the pwdCheckModuleArg -attribute. It is also used for testing passwords with the test program -provided. -If for some reasons, any parameter is not found, it will be given its -default value. - -Note: you can still compile ppm to use the configuration file, by enabling -PPM_READ_FILE in ppm.h (but this is deprecated now). If you decide to do so, -you can use the PPM_CONFIG_FILE environment variable for overloading the -configuration file path. - -The syntax of a configuration line is: -parameter value [min] [minForPoint] - -with spaces being delimiters and Line Feed (LF) ending the line. -Parameter names ARE case sensitive. - -The default configuration is the following: - -``` -# minQuality parameter -# Format: -# minQuality [NUMBER] -# Description: -# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. -# defines the minimum point numbers for the password to be accepted. -minQuality 3 - -# checkRDN parameter -# Format: -# checkRDN [0 | 1] -# Description: -# If set to 1, password must not contain a token from the RDN. -# Tokens are separated by the following delimiters : space tabulation _ - , ; £ -checkRDN 0 - -# forbiddenChars parameter -# Format: -# forbiddenChars [CHARACTERS_FORBIDDEN] -# Description: -# Defines the forbidden characters list (no separator). -# If one of them is found in the password, then it is rejected. -forbiddenChars - -# maxConsecutivePerClass parameter -# Format: -# maxConsecutivePerClass [NUMBER] -# Description: -# Defines the maximum number of consecutive character allowed for any class -maxConsecutivePerClass 0 - -# useCracklib parameter -# Format: -# useCracklib [0 | 1] -# Description: -# If set to 1, the password must pass the cracklib check -useCracklib 0 - -# cracklibDict parameter -# Format: -# cracklibDict [path_to_cracklib_dictionary] -# Description: -# directory+filename-prefix that your version of CrackLib will go hunting for -# For example, /var/pw_dict resolves as /var/pw_dict.pwd, -# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files -cracklibDict /var/cache/cracklib/cracklib_dict - -# classes parameter -# Format: -# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] -# Description: -# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) -# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected -# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class -class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 -class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 -class-digit 0123456789 0 1 -class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 -``` - -Example -------- - -With this policy: -``` -minQuality 4 -forbiddenChars .?, -checkRDN 1 -class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 5 -class-lowerCase abcdefghijklmnopqrstuvwxyz 0 12 -class-digit 0123456789 0 1 -class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 -class-myClass :) 1 1`` -``` - -the password - -ThereIsNoCowLevel) - -is working, because, -- it has 4 character classes validated : upper, lower, special, and myClass -- it has no character among .?, -- it has at least one character among : or ) - -but it won't work for the user uid=John Cowlevel,ou=people,cn=example,cn=com, -because the token "Cowlevel" from his RDN exists in the password (case insensitive). - - -Logs ----- -If a user password is rejected by ppm, the user will get this type of message: - -Typical user message from ldappasswd(5): - Result: Constraint violation (19) - Additional info: Password for dn=\"%s\" does not pass required number of strength checks (2 of 3) - -A more detailed message is written to the server log. - -Server log: - -``` -Feb 26 14:46:10 debian-10-64 slapd[1981]: conn=1000 op=16 MOD dn="uid=user,ou=persons,dc=my-domain,dc=com" -Feb 26 14:46:10 debian-10-64 slapd[1981]: conn=1000 op=16 MOD attr=userPassword -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: entry uid=user,ou=persons,dc=my-domain,dc=com -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Reading pwdCheckModuleArg attribute -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: RAW configuration: # minQuality parameter#012# Format:#012# minQuality [NUMBER]#012# Description:#012# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled.#012# defines the minimum point numbers for the password to be accepted.#012minQuality 3#012#012# checkRDN parameter#012# Format:#012# checkRDN [0 | 1]#012# Description:#012# If set to 1, password must not contain a token from the RDN.#012# Tokens are separated by the following delimiters : space tabulation _ - , ; £#012checkRDN 0#012#012# forbiddenChars parameter#012# Format:#012# forbiddenChars [CHARACTERS_FORBIDDEN]#012# Description:#012# Defines the forbidden characters list (no separator).#012# If one of them is found in the password, then it is rejected.#012forbiddenChars#012#012# maxConsecutivePerClass parameter#012# Format:#012# maxConsecutivePerClass [NUMBER]#012# Description:#012# Defines the maximum number of consecutive character allowed for any class#012maxConsecutivePerClass 0#012#012# useCracklib parameter#012# Format:#012# useCracklib [0 | 1]#012# Description:#012# If set to 1, the password must pass the cracklib check#012useCracklib 0#012#012# cracklibDict parameter#012# Format:#012# cracklibDict [path_to_cracklib_dictionary]#012# Description:#012# directory+filename-prefix that your version of CrackLib will go hunting for#012# For example, /var/pw_dict resolves as /var/pw_dict.pwd,#012# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files#012cracklibDict /var/cache/cracklib/cracklib_dict#012#012# classes parameter#012# Format:#012# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT]#012# Description:#012# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator)#012# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected#012# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class#012class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1#012class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1#012class-digit 0123456789 0 1#012class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Parsing pwdCheckModuleArg attribute -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # minQuality parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # minQuality [NUMBER] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # defines the minimum point numbers for the password to be accepted. -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: minQuality 3 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = minQuality, value = 3, min = (null), minForPoint= (null) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: 3 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # checkRDN parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # checkRDN [0 | 1] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # If set to 1, password must not contain a token from the RDN. -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Tokens are separated by the following delimiters : space tabulation _ - , ; £ -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: checkRDN 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = checkRDN, value = 0, min = (null), minForPoint= (null) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # forbiddenChars parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # forbiddenChars [CHARACTERS_FORBIDDEN] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Defines the forbidden characters list (no separator). -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # If one of them is found in the password, then it is rejected. -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: forbiddenChars -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: No value, goto next parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass [NUMBER] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Defines the maximum number of consecutive character allowed for any class -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: maxConsecutivePerClass 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = maxConsecutivePerClass, value = 0, min = (null), minForPoint= (null) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # useCracklib parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # useCracklib [0 | 1] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # If set to 1, the password must pass the cracklib check -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: useCracklib 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = useCracklib, value = 0, min = (null), minForPoint= (null) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: 0 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # cracklibDict parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # cracklibDict [path_to_cracklib_dictionary] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # directory+filename-prefix that your version of CrackLib will go hunting for -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # For example, /var/pw_dict resolves as /var/pw_dict.pwd, -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: cracklibDict /var/cache/cracklib/cracklib_dict -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = cracklibDict, value = /var/cache/cracklib/cracklib_dict, min = (null), minForPoint= (null) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: /var/cache/cracklib/cracklib_dict -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # classes parameter -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Format: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # Description: -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: # [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = class-upperCase, value = ABCDEFGHIJKLMNOPQRSTUVWXYZ, min = 0, minForPoint= 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: ABCDEFGHIJKLMNOPQRSTUVWXYZ -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = class-lowerCase, value = abcdefghijklmnopqrstuvwxyz, min = 0, minForPoint= 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: abcdefghijklmnopqrstuvwxyz -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: class-digit 0123456789 0 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = class-digit, value = 0123456789, min = 0, minForPoint= 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: 0123456789 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: get line: class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Param = class-special, value = <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+, min = 0, minForPoint= 1 -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Accepted replaced value: <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: 1 point granted for class class-lowerCase -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: 1 point granted for class class-digit -Feb 26 14:46:10 debian-10-64 slapd[1981]: ppm: Reallocating szErrStr from 64 to 173 -Feb 26 14:46:10 debian-10-64 slapd[1981]: check_password_quality: module error: (/usr/local/lib/ppm.so) Password for dn="uid=user,ou=persons,dc=my-domain,dc=com" does not pass required number of strength checks (2 of 3).[1] -Feb 26 14:46:10 debian-10-64 slapd[1981]: conn=1000 op=16 RESULT tag=103 err=19 qtime=0.000020 etime=0.001496 text=Password for dn="uid=user,ou=persons,dc=my-domain,dc=com" does not pass required number of strength checks (2 of 3) -``` - - -Tests ------ - -There is a unit test script: "unit_tests.sh" that illustrates checking some passwords. -It is possible to test one particular password using directly the test program: - -``` -cd /usr/local/lib -LD_LIBRARY_PATH=. ./ppm_test "uid=test,ou=users,dc=my-domain,dc=com" "my_password" "/usr/local/etc/openldap/ppm.example" && echo OK -``` - - - -HISTORY -------- - -* 2021-02-23 David Coutadeur - remove maxLength attribute (#21) - adapt the readme and documentation of ppm (#22) - prepare ppolicy10 in OpenLDAP 2.5 (#20, #23 and #24) - add pwdCheckModuleArg feature - Version 2.0 -* 2019-08-20 David Coutadeur - adding debug symbols for ppm_test, - improve tests with the possibility to add username, - fix openldap crash when checkRDN=1 and username contains too short parts - Version 1.8 -* 2018-03-30 David Coutadeur - various minor improvements provided by Tim Bishop (tdb) (compilation, test program, - imprvts in Makefile: new OLDAP_SOURCES variable pointing to OLDAP install. directory - Version 1.7 -* 2017-05-19 David Coutadeur - Adds cracklib support - Readme adaptations and cleaning - Version 1.6 -* 2017-02-07 David Coutadeur - Adds maxConsecutivePerClass (idea from Trevor Vaughan / tvaughan@onyxpoint.com) - Version 1.5 -* 2016-08-22 David Coutadeur - Get config file from environment variable - Version 1.4 -* 2014-12-20 Daly Chikhaoui - Adding checkRDN parameter - Version 1.3 -* 2014-10-28 David Coutadeur - Adding maxLength parameter - Version 1.2 -* 2014-07-27 David Coutadeur - Changing the configuration file and the configuration data structure - Version 1.1 -* 2014-04-04 David Coutadeur - Version 1.0 - +See ppm.md manual and INSTALL.md diff --git a/contrib/slapd-modules/ppm/ppm.5 b/contrib/slapd-modules/ppm/ppm.5 new file mode 100644 index 0000000000..10e9c8d447 --- /dev/null +++ b/contrib/slapd-modules/ppm/ppm.5 @@ -0,0 +1,360 @@ +.\" Automatically generated by Pandoc 2.9.2.1 +.\" +.TH "ppm" "5" "August 24, 2021" "ppm" "File Formats Manual" +.hy +.SH NAME +.PP +ppm (Password Policy Module) - extension of the password policy overlay +.SH SYNOPSIS +.PP +ETCDIR/ppm.example +.SH DESCRIPTION +.PP +\f[B]ppm\f[R] is an OpenLDAP module for checking password quality when +they are modified. +Passwords are checked against the presence or absence of certain +character classes. +.PP +This module is used as an extension of the OpenLDAP password policy +controls, see slapo-ppolicy(5) section \f[B]pwdCheckModule\f[R]. +.SH USAGE +.PP +Create a password policy entry and indicate the path of the ppm.so +library and the content of the desired policy. +Use a base64 tool to code / decode the content of the policy stored into +\f[B]pwdCheckModuleArg\f[R]. +Here is an example: +.IP +.nf +\f[C] +dn: cn=default,ou=policies,dc=my-domain,dc=com +objectClass: pwdPolicy +objectClass: top +objectClass: pwdPolicyChecker +objectClass: person +pwdCheckQuality: 2 +pwdAttribute: userPassword +sn: default +cn: default +pwdMinLength: 6 +pwdCheckModule: /usr/local/lib/ppm.so +pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKZm9yYmlkZGVuQ2hhcnMKbWF4Q29uc2VjdXRpdmVQZXJDbGFzcyAwCnVzZUNyYWNrbGliIDAKY3JhY2tsaWJEaWN0IC92YXIvY2FjaGUvY3JhY2tsaWIvY3JhY2tsaWJfZGljdApjbGFzcy11cHBlckNhc2UgQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMCAxCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEKY2xhc3MtZGlnaXQgMDEyMzQ1Njc4OSAwIDEKY2xhc3Mtc3BlY2lhbCA8Piw/Oy46LyHCp8O5JSrCtV7CqCTCo8KyJsOpfiIjJ3soWy18w6hgX1zDp17DoEApXcKwPX0rIDAgMQ== +\f[R] +.fi +.PP +See \f[B]slapo-ppolicy\f[R] for more information, but to sum up: +.IP \[bu] 2 +enable ppolicy overlay in your database. +.IP \[bu] 2 +define a default password policy in OpenLDAP configuration or use +pwdPolicySubentry attribute to point to the given policy. +.PP +This example show the activation for a \f[B]slapd.conf\f[R] file (see +\f[B]slapd-config\f[R] and \f[B]slapo-ppolicy\f[R] for more information +for \f[B]cn=config\f[R] configuration) +.IP +.nf +\f[C] +overlay ppolicy +ppolicy_default \[dq]cn=default,ou=policies,dc=my-domain,dc=com\[dq] +#ppolicy_use_lockout # for having more infos about the lockout +\f[R] +.fi +.SH FEATURES +.PP +Here are the main features: +.IP \[bu] 2 +4 character classes are defined by default: upper case, lower case, +digits and special characters. +.IP \[bu] 2 +more character classes can be defined, just write your own. +.IP \[bu] 2 +passwords must match the amount of quality points. +A point is validated when at least m characters of the corresponding +character class are present in the password. +.IP \[bu] 2 +passwords must have at least n of the corresponding character class +present, else they are rejected. +.IP \[bu] 2 +the two previous criteria are checked against any specific character +class defined. +.IP \[bu] 2 +if a password contains any of the forbidden characters, then it is +rejected. +.IP \[bu] 2 +if a password contains tokens from the RDN, then it is rejected. +.IP \[bu] 2 +if a password does not pass cracklib check, then it is rejected. +.SH CONFIGURATION +.PP +Since OpenLDAP 2.5 version, ppm configuration is held in a binary +attribute of the password policy: \f[B]pwdCheckModuleArg\f[R] +.PP +The example file (\f[B]ETCDIR/ppm.example\f[R] by default) is to be +considered as an example configuration, to import in the +\f[B]pwdCheckModuleArg\f[R] attribute. +It is also used for testing passwords with the test program provided. +.PP +If for some reasons, any parameter is not found, it will be given its +default value. +.PP +Note: you can still compile ppm to use the configuration file, by +enabling \f[B]PPM_READ_FILE\f[R] in \f[B]ppm.h\f[R] (but this is +deprecated now). +If you decide to do so, you can use the \f[B]PPM_CONFIG_FILE\f[R] +environment variable for overloading the configuration file path. +.PP +The syntax of a configuration line is: +.IP +.nf +\f[C] +parameter value [min] [minForPoint] +\f[R] +.fi +.PP +with spaces being delimiters and Line Feed (LF) ending the line. +.PP +Parameter names \f[B]are\f[R] case sensitive. +.PP +Lines beginning by a \f[B]#\f[R] are considered as comments. +.PP +The default configuration is the following: +.IP +.nf +\f[C] +# minQuality parameter +# Format: +# minQuality [NUMBER] +# Description: +# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. +# defines the minimum point numbers for the password to be accepted. +minQuality 3 + +# checkRDN parameter +# Format: +# checkRDN [0 | 1] +# Description: +# If set to 1, password must not contain a token from the RDN. +# Tokens are separated by the following delimiters : space tabulation _ - , ; \[Po] +checkRDN 0 + +# forbiddenChars parameter +# Format: +# forbiddenChars [CHARACTERS_FORBIDDEN] +# Description: +# Defines the forbidden characters list (no separator). +# If one of them is found in the password, then it is rejected. +forbiddenChars + +# maxConsecutivePerClass parameter +# Format: +# maxConsecutivePerClass [NUMBER] +# Description: +# Defines the maximum number of consecutive character allowed for any class +maxConsecutivePerClass 0 + +# useCracklib parameter +# Format: +# useCracklib [0 | 1] +# Description: +# If set to 1, the password must pass the cracklib check +useCracklib 0 + +# cracklibDict parameter +# Format: +# cracklibDict [path_to_cracklib_dictionary] +# Description: +# directory+filename-prefix that your version of CrackLib will go hunting for +# For example, /var/pw_dict resolves as /var/pw_dict.pwd, +# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files +cracklibDict /var/cache/cracklib/cracklib_dict + +# classes parameter +# Format: +# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] +# Description: +# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) +# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected +# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +class-digit 0123456789 0 1 +class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 +\f[R] +.fi +.SH EXAMPLE +.PP +With this policy: +.IP +.nf +\f[C] +minQuality 4 +forbiddenChars .?, +checkRDN 1 +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 5 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 12 +class-digit 0123456789 0 1 +class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 +class-myClass :) 1 1\[ga]\[ga] +\f[R] +.fi +.PP +the password \f[B]ThereIsNoCowLevel)\f[R] is working, because: +.IP \[bu] 2 +it has 4 character classes validated : upper, lower, special, and +myClass +.IP \[bu] 2 +it has no character among .?, +.IP \[bu] 2 +it has at least one character among : or ) +.PP +but it won\[cq]t work for the user uid=John +Cowlevel,ou=people,cn=example,cn=com, because the token +\[lq]Cowlevel\[rq] from his RDN exists in the password (case +insensitive). +.SH LOGS +.PP +If a user password is rejected by \f[B]ppm\f[R], the user will get this +type of message: +.PP +Typical user message from ldappasswd(5): +.IP +.nf +\f[C] + Result: Constraint violation (19) + Additional info: Password for dn=\[rs]\[dq]%s\[rs]\[dq] does not pass required number of strength checks (2 of 3) +\f[R] +.fi +.PP +A more detailed message is written to the server log. +.PP +Server log: +.IP +.nf +\f[C] +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 MOD dn=\[dq]uid=user,ou=persons,dc=my-domain,dc=com\[dq] +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 MOD attr=userPassword +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: entry uid=user,ou=persons,dc=my-domain,dc=com +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Reading pwdCheckModuleArg attribute +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: RAW configuration: # minQuality parameter#012# Format:#012# minQuality [NUMBER]#012# Description:#012# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled.#012# defines the minimum point numbers for the password to be accepted.#012minQuality 3#012#012# checkRDN parameter#012# Format:#012# checkRDN [0 | 1]#012# Description:#012# If set to 1, password must not contain a token from the RDN.#012# Tokens are separated by the following delimiters : space tabulation _ - , ; \[Po]#012checkRDN 0#012#012# forbiddenChars parameter#012# Format:#012# forbiddenChars [CHARACTERS_FORBIDDEN]#012# Description:#012# Defines the forbidden characters list (no separator).#012# If one of them is found in the password, then it is rejected.#012forbiddenChars#012#012# maxConsecutivePerClass parameter#012# Format:#012# maxConsecutivePerClass [NUMBER]#012# Description:#012# Defines the maximum number of consecutive character allowed for any class#012maxConsecutivePerClass 0#012#012# useCracklib parameter#012# Format:#012# useCracklib [0 | 1]#012# Description:#012# If set to 1, the password must pass the cracklib check#012useCracklib 0#012#012# cracklibDict parameter#012# Format:#012# cracklibDict [path_to_cracklib_dictionary]#012# Description:#012# directory+filename-prefix that your version of CrackLib will go hunting for#012# For example, /var/pw_dict resolves as /var/pw_dict.pwd,#012# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files#012cracklibDict /var/cache/cracklib/cracklib_dict#012#012# classes parameter#012# Format:#012# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT]#012# Description:#012# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator)#012# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected#012# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class#012class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1#012class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1#012class-digit 0123456789 0 1#012class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Parsing pwdCheckModuleArg attribute +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # minQuality parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # minQuality [NUMBER] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # defines the minimum point numbers for the password to be accepted. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: minQuality 3 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = minQuality, value = 3, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 3 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # checkRDN parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # checkRDN [0 | 1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If set to 1, password must not contain a token from the RDN. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Tokens are separated by the following delimiters : space tabulation _ - , ; \[Po] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: checkRDN 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = checkRDN, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # forbiddenChars parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # forbiddenChars [CHARACTERS_FORBIDDEN] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Defines the forbidden characters list (no separator). +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If one of them is found in the password, then it is rejected. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: forbiddenChars +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: No value, goto next parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass [NUMBER] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Defines the maximum number of consecutive character allowed for any class +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: maxConsecutivePerClass 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = maxConsecutivePerClass, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # useCracklib parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # useCracklib [0 | 1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If set to 1, the password must pass the cracklib check +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: useCracklib 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = useCracklib, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # cracklibDict parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # cracklibDict [path_to_cracklib_dictionary] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # directory+filename-prefix that your version of CrackLib will go hunting for +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # For example, /var/pw_dict resolves as /var/pw_dict.pwd, +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: cracklibDict /var/cache/cracklib/cracklib_dict +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = cracklibDict, value = /var/cache/cracklib/cracklib_dict, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: /var/cache/cracklib/cracklib_dict +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # classes parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-upperCase, value = ABCDEFGHIJKLMNOPQRSTUVWXYZ, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: ABCDEFGHIJKLMNOPQRSTUVWXYZ +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-lowerCase, value = abcdefghijklmnopqrstuvwxyz, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: abcdefghijklmnopqrstuvwxyz +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-digit 0123456789 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-digit, value = 0123456789, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0123456789 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-special, value = <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: 1 point granted for class class-lowerCase +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: 1 point granted for class class-digit +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Reallocating szErrStr from 64 to 173 +Feb 26 14:46:10 debian-11-64 slapd[1981]: check_password_quality: module error: (/usr/local/lib/ppm.so) Password for dn=\[dq]uid=user,ou=persons,dc=my-domain,dc=com\[dq] does not pass required number of strength checks (2 of 3).[1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 RESULT tag=103 err=19 qtime=0.000020 etime=0.001496 text=Password for dn=\[dq]uid=user,ou=persons,dc=my-domain,dc=com\[dq] does not pass required number of strength checks (2 of 3) +\f[R] +.fi +.SH TESTS +.PP +There is a unit test script: \f[B]unit_tests.sh\f[R] that illustrates +checking some passwords. +.PP +It is possible to test one particular password using directly the test +program: +.IP +.nf +\f[C] +cd /usr/local/lib +LD_LIBRARY_PATH=. ./ppm_test \[dq]uid=test,ou=users,dc=my-domain,dc=com\[dq] \[dq]my_password\[dq] \[dq]/usr/local/etc/openldap/ppm.example\[dq] && echo OK +\f[R] +.fi +.SH FILES +.PP +\f[B]ETCDIR/ppm.example\f[R] +.RS +.PP +example of ppm configuration to be inserted in +\f[B]pwdCheckModuleArg\f[R] attribute of given password policy +.RE +.PP +\f[B]ppm.so\f[R] +.RS +.PP +ppm library, loaded by the \f[B]pwdCheckModule\f[R] attribute of given +password policy +.RE +.PP +\f[B]ppm_test\f[R] +.RS +.PP +small test program for checking password in a command-line +.RE +.SH SEE ALSO +.PP +\f[B]slapo-ppolicy\f[R](5), \f[B]slapd-config\f[R](5), +\f[B]slapd.conf\f[R](5) +.SH ACKNOWLEDGEMENTS +.PP +This module was developed in 2014-2021 by David Coutadeur. diff --git a/contrib/slapd-modules/ppm/ppm.md b/contrib/slapd-modules/ppm/ppm.md new file mode 100644 index 0000000000..5b1accb31f --- /dev/null +++ b/contrib/slapd-modules/ppm/ppm.md @@ -0,0 +1,343 @@ +--- +title: ppm +section: 5 +header: File Formats Manual +footer: ppm +date: August 24, 2021 +--- + +# NAME + +ppm (Password Policy Module) - extension of the password policy overlay + +# SYNOPSIS + +ETCDIR/ppm.example + +# DESCRIPTION + +**ppm** is an OpenLDAP module for checking password quality when they are modified. +Passwords are checked against the presence or absence of certain character classes. + +This module is used as an extension of the OpenLDAP password policy controls, +see slapo-ppolicy(5) section **pwdCheckModule**. + + +# USAGE + +Create a password policy entry and indicate the path of the ppm.so library +and the content of the desired policy. +Use a base64 tool to code / decode the content of the policy stored into +**pwdCheckModuleArg**. Here is an example: + +``` +dn: cn=default,ou=policies,dc=my-domain,dc=com +objectClass: pwdPolicy +objectClass: top +objectClass: pwdPolicyChecker +objectClass: person +pwdCheckQuality: 2 +pwdAttribute: userPassword +sn: default +cn: default +pwdMinLength: 6 +pwdCheckModule: /usr/local/lib/ppm.so +pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKZm9yYmlkZGVuQ2hhcnMKbWF4Q29uc2VjdXRpdmVQZXJDbGFzcyAwCnVzZUNyYWNrbGliIDAKY3JhY2tsaWJEaWN0IC92YXIvY2FjaGUvY3JhY2tsaWIvY3JhY2tsaWJfZGljdApjbGFzcy11cHBlckNhc2UgQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMCAxCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEKY2xhc3MtZGlnaXQgMDEyMzQ1Njc4OSAwIDEKY2xhc3Mtc3BlY2lhbCA8Piw/Oy46LyHCp8O5JSrCtV7CqCTCo8KyJsOpfiIjJ3soWy18w6hgX1zDp17DoEApXcKwPX0rIDAgMQ== +``` + + +See **slapo-ppolicy** for more information, but to sum up: + +- enable ppolicy overlay in your database. +- define a default password policy in OpenLDAP configuration or use pwdPolicySubentry attribute to point to the given policy. + +This example show the activation for a **slapd.conf** file +(see **slapd-config** and **slapo-ppolicy** for more information for + **cn=config** configuration) + +``` +overlay ppolicy +ppolicy_default "cn=default,ou=policies,dc=my-domain,dc=com" +#ppolicy_use_lockout # for having more infos about the lockout +``` + + +# FEATURES + +Here are the main features: + +- 4 character classes are defined by default: +upper case, lower case, digits and special characters. + +- more character classes can be defined, just write your own. + +- passwords must match the amount of quality points. +A point is validated when at least m characters of the corresponding +character class are present in the password. + +- passwords must have at least n of the corresponding character class +present, else they are rejected. + +- the two previous criteria are checked against any specific character class +defined. + +- if a password contains any of the forbidden characters, then it is +rejected. + +- if a password contains tokens from the RDN, then it is rejected. + +- if a password does not pass cracklib check, then it is rejected. + + +# CONFIGURATION + +Since OpenLDAP 2.5 version, ppm configuration is held in a binary +attribute of the password policy: **pwdCheckModuleArg** + +The example file (**ETCDIR/ppm.example** by default) is to be +considered as an example configuration, to import in the **pwdCheckModuleArg** +attribute. It is also used for testing passwords with the test program +provided. + +If for some reasons, any parameter is not found, it will be given its +default value. + +Note: you can still compile ppm to use the configuration file, by enabling +**PPM_READ_FILE** in **ppm.h** (but this is deprecated now). If you decide to do so, +you can use the **PPM_CONFIG_FILE** environment variable for overloading the +configuration file path. + +The syntax of a configuration line is: + +``` +parameter value [min] [minForPoint] +``` + +with spaces being delimiters and Line Feed (LF) ending the line. + +Parameter names **are** case sensitive. + +Lines beginning by a **#** are considered as comments. + +The default configuration is the following: + +``` +# minQuality parameter +# Format: +# minQuality [NUMBER] +# Description: +# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. +# defines the minimum point numbers for the password to be accepted. +minQuality 3 + +# checkRDN parameter +# Format: +# checkRDN [0 | 1] +# Description: +# If set to 1, password must not contain a token from the RDN. +# Tokens are separated by the following delimiters : space tabulation _ - , ; £ +checkRDN 0 + +# forbiddenChars parameter +# Format: +# forbiddenChars [CHARACTERS_FORBIDDEN] +# Description: +# Defines the forbidden characters list (no separator). +# If one of them is found in the password, then it is rejected. +forbiddenChars + +# maxConsecutivePerClass parameter +# Format: +# maxConsecutivePerClass [NUMBER] +# Description: +# Defines the maximum number of consecutive character allowed for any class +maxConsecutivePerClass 0 + +# useCracklib parameter +# Format: +# useCracklib [0 | 1] +# Description: +# If set to 1, the password must pass the cracklib check +useCracklib 0 + +# cracklibDict parameter +# Format: +# cracklibDict [path_to_cracklib_dictionary] +# Description: +# directory+filename-prefix that your version of CrackLib will go hunting for +# For example, /var/pw_dict resolves as /var/pw_dict.pwd, +# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files +cracklibDict /var/cache/cracklib/cracklib_dict + +# classes parameter +# Format: +# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] +# Description: +# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) +# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected +# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +class-digit 0123456789 0 1 +class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 +``` + +# EXAMPLE + +With this policy: +``` +minQuality 4 +forbiddenChars .?, +checkRDN 1 +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 5 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 12 +class-digit 0123456789 0 1 +class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 +class-myClass :) 1 1`` +``` + +the password **ThereIsNoCowLevel)** is working, because: + +- it has 4 character classes validated : upper, lower, special, and myClass +- it has no character among .?, +- it has at least one character among : or ) + +but it won't work for the user uid=John Cowlevel,ou=people,cn=example,cn=com, +because the token "Cowlevel" from his RDN exists in the password (case insensitive). + + +# LOGS + +If a user password is rejected by **ppm**, the user will get this type of message: + +Typical user message from ldappasswd(5): + +``` + Result: Constraint violation (19) + Additional info: Password for dn=\"%s\" does not pass required number of strength checks (2 of 3) +``` + +A more detailed message is written to the server log. + +Server log: + +``` +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 MOD dn="uid=user,ou=persons,dc=my-domain,dc=com" +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 MOD attr=userPassword +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: entry uid=user,ou=persons,dc=my-domain,dc=com +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Reading pwdCheckModuleArg attribute +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: RAW configuration: # minQuality parameter#012# Format:#012# minQuality [NUMBER]#012# Description:#012# One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled.#012# defines the minimum point numbers for the password to be accepted.#012minQuality 3#012#012# checkRDN parameter#012# Format:#012# checkRDN [0 | 1]#012# Description:#012# If set to 1, password must not contain a token from the RDN.#012# Tokens are separated by the following delimiters : space tabulation _ - , ; £#012checkRDN 0#012#012# forbiddenChars parameter#012# Format:#012# forbiddenChars [CHARACTERS_FORBIDDEN]#012# Description:#012# Defines the forbidden characters list (no separator).#012# If one of them is found in the password, then it is rejected.#012forbiddenChars#012#012# maxConsecutivePerClass parameter#012# Format:#012# maxConsecutivePerClass [NUMBER]#012# Description:#012# Defines the maximum number of consecutive character allowed for any class#012maxConsecutivePerClass 0#012#012# useCracklib parameter#012# Format:#012# useCracklib [0 | 1]#012# Description:#012# If set to 1, the password must pass the cracklib check#012useCracklib 0#012#012# cracklibDict parameter#012# Format:#012# cracklibDict [path_to_cracklib_dictionary]#012# Description:#012# directory+filename-prefix that your version of CrackLib will go hunting for#012# For example, /var/pw_dict resolves as /var/pw_dict.pwd,#012# /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files#012cracklibDict /var/cache/cracklib/cracklib_dict#012#012# classes parameter#012# Format:#012# class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT]#012# Description:#012# [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator)#012# [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected#012# [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class#012class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1#012class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1#012class-digit 0123456789 0 1#012class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Parsing pwdCheckModuleArg attribute +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # minQuality parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # minQuality [NUMBER] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # One point is granted for each class for which MIN_FOR_POINT criteria is fulfilled. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # defines the minimum point numbers for the password to be accepted. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: minQuality 3 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = minQuality, value = 3, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 3 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # checkRDN parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # checkRDN [0 | 1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If set to 1, password must not contain a token from the RDN. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Tokens are separated by the following delimiters : space tabulation _ - , ; £ +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: checkRDN 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = checkRDN, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # forbiddenChars parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # forbiddenChars [CHARACTERS_FORBIDDEN] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Defines the forbidden characters list (no separator). +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If one of them is found in the password, then it is rejected. +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: forbiddenChars +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: No value, goto next parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # maxConsecutivePerClass [NUMBER] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Defines the maximum number of consecutive character allowed for any class +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: maxConsecutivePerClass 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = maxConsecutivePerClass, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # useCracklib parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # useCracklib [0 | 1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # If set to 1, the password must pass the cracklib check +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: useCracklib 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = useCracklib, value = 0, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # cracklibDict parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # cracklibDict [path_to_cracklib_dictionary] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # directory+filename-prefix that your version of CrackLib will go hunting for +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # For example, /var/pw_dict resolves as /var/pw_dict.pwd, +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # /var/pw_dict.pwi and /var/pw_dict.hwm dictionary files +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: cracklibDict /var/cache/cracklib/cracklib_dict +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = cracklibDict, value = /var/cache/cracklib/cracklib_dict, min = (null), minForPoint= (null) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: /var/cache/cracklib/cracklib_dict +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # classes parameter +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Format: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # class-[CLASS_NAME] [CHARACTERS_DEFINING_CLASS] [MIN] [MIN_FOR_POINT] +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # Description: +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [CHARACTERS_DEFINING_CLASS]: characters defining the class (no separator) +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [MIN]: If at least [MIN] characters of this class is not found in the password, then it is rejected +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: # [MIN_FOR_POINT]: one point is granted if password contains at least [MIN_FOR_POINT] character numbers of this class +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-upperCase, value = ABCDEFGHIJKLMNOPQRSTUVWXYZ, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: ABCDEFGHIJKLMNOPQRSTUVWXYZ +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-lowerCase, value = abcdefghijklmnopqrstuvwxyz, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: abcdefghijklmnopqrstuvwxyz +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-digit 0123456789 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-digit, value = 0123456789, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: 0123456789 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: get line: class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Param = class-special, value = <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+, min = 0, minForPoint= 1 +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Accepted replaced value: <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: 1 point granted for class class-lowerCase +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: 1 point granted for class class-digit +Feb 26 14:46:10 debian-11-64 slapd[1981]: ppm: Reallocating szErrStr from 64 to 173 +Feb 26 14:46:10 debian-11-64 slapd[1981]: check_password_quality: module error: (/usr/local/lib/ppm.so) Password for dn="uid=user,ou=persons,dc=my-domain,dc=com" does not pass required number of strength checks (2 of 3).[1] +Feb 26 14:46:10 debian-11-64 slapd[1981]: conn=1000 op=16 RESULT tag=103 err=19 qtime=0.000020 etime=0.001496 text=Password for dn="uid=user,ou=persons,dc=my-domain,dc=com" does not pass required number of strength checks (2 of 3) +``` + + +# TESTS + +There is a unit test script: **unit_tests.sh** that illustrates checking some passwords. + +It is possible to test one particular password using directly the test program: + +``` +cd /usr/local/lib +LD_LIBRARY_PATH=. ./ppm_test "uid=test,ou=users,dc=my-domain,dc=com" "my_password" "/usr/local/etc/openldap/ppm.example" && echo OK +``` + + +# FILES + +**ETCDIR/ppm.example** + +> example of ppm configuration to be inserted in **pwdCheckModuleArg** attribute of given password policy + +**ppm.so** + +> ppm library, loaded by the **pwdCheckModule** attribute of given password policy + +**ppm_test** + +> small test program for checking password in a command-line + + +# SEE ALSO + +**slapo-ppolicy**(5), **slapd-config**(5), **slapd.conf**(5) + +# ACKNOWLEDGEMENTS + +This module was developed in 2014-2021 by David Coutadeur. -- 2.47.3