diff options
Diffstat (limited to 'contrib/slapd-modules/ppm/slapm-ppm.5')
-rw-r--r-- | contrib/slapd-modules/ppm/slapm-ppm.5 | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/contrib/slapd-modules/ppm/slapm-ppm.5 b/contrib/slapd-modules/ppm/slapm-ppm.5 new file mode 100644 index 0000000..a852037 --- /dev/null +++ b/contrib/slapd-modules/ppm/slapm-ppm.5 @@ -0,0 +1,353 @@ +.\" 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]. +.PP +Here is an example for OpenLDAP 2.6: +.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 +pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKY2hlY2tBdHRyaWJ1dGVzCmZvcmJpZGRlbkNoYXJzCm1heENvbnNlY3V0aXZlUGVyQ2xhc3MgMAp1c2VDcmFja2xpYiAwCmNyYWNrbGliRGljdCAvdmFyL2NhY2hlL2NyYWNrbGliL2NyYWNrbGliX2RpY3QKY2xhc3MtdXBwZXJDYXNlIEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaIDAgMSAwCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEgMApjbGFzcy1kaWdpdCAwMTIzNDU2Nzg5IDAgMSAwCmNsYXNzLXNwZWNpYWwgPD4sPzsuOi8hwqfDuSUqwrVewqgkwqPCsibDqX4iIyd7KFstfMOoYF9cw6dew6BAKV3CsD19KyAwIDEgMAoK +pwdUseCheckModule: TRUE +\f[R] +.fi +.PP +For OpenLDAP 2.5, you must add a \f[B]pwdCheckModule\f[R] attribute +pointing to the ppm module (for example /usr/local/lib/ppm.so), and +remove the \f[B]pwdUseCheckModule\f[R] attribute. +.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 for +OpenLDAP 2.6 (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_check_module /usr/local/openldap/libexec/openldap/ppm.so +#ppolicy_use_lockout # for having more infos about the lockout +\f[R] +.fi +.PP +For OpenLDAP 2.5, you must remove \f[B]ppolicy_check_module\f[R] +parameter as it is managed in the password policy definition +.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 +passwords must have at the most x occurrences of characters from the +corresponding character class, else they are rejected. +.IP \[bu] 2 +the three 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 contains tokens from defined attributes, 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]/usr/local/etc/openldap/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] [max] +\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 + +# checkAttributes parameter +# Format: +# checkAttributes [ATTR1,ATTR2,...] +# Description: +# Password must not contain a token from the values in the given list of attributes +# Tokens are substrings of the values of the given attributes, +# delimited by: space tabulation _ - , ; \[at] +# For example, if uid=\[dq]the wonderful entry\[dq], +# password must not contain \[dq]the\[dq], nor \[dq]wonderful\[dq], nor \[dq]entry\[dq] +checkAttributes + +# 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] [MAX] +# 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 +# [MAX]: if > [MAX] occurrences of characters from this class are found, then the password is rejected (0 means no maximum) +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 0 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 0 +class-digit 0123456789 0 1 0 +class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 0 +\f[R] +.fi +.SH EXAMPLE +.PP +With this policy: +.IP +.nf +\f[C] +minQuality 4 +forbiddenChars .?, +checkRDN 1 +checkAttributes mail +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 5 0 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 12 0 +class-digit 0123456789 0 1 0 +class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 0 +class-myClass :) 1 1 0 +\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). +.PP +Also, it won\[cq]t work for a mail attribute containing: +\[lq]thereis\[at]domain.com\[rq] because the part \[lq]thereis\[rq] +matches the password. +.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 +While evaluating a password change, you should observe something looking +at this in the logs: +.IP +.nf +\f[C] +ppm: entry uid=jack.oneill,ou=people,dc=my-domain,dc=com +ppm: Reading pwdCheckModuleArg attribute +ppm: RAW configuration: minQuality 3#012checkRDN 0#012checkAttributes mail,uid#012forbiddenChars#012maxConsecutivePerClass 0#012useCracklib 0#012cracklibDict /var/cache/cracklib/cracklib_dict#012class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 0#012class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 0#012class-digit 0123456789 0 1 0#012class-special <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ 0 1 0 +ppm: Parsing pwdCheckModuleArg attribute +ppm: get line: minQuality 3 +ppm: Param = minQuality, value = 3, min = (null), minForPoint= (null) +ppm: Accepted replaced value: 3 +ppm: get line: checkRDN 0 +ppm: Param = checkRDN, value = 0, min = (null), minForPoint= (null) +ppm: Accepted replaced value: 0 +ppm: get line: checkAttributes mail,uid +ppm: Param = checkAttributes, value = mail,uid, min = (null), minForPoint= (null) +ppm: Accepted replaced value: mail,uid +ppm: get line: forbiddenChars +ppm: No value, goto next parameter +ppm: get line: maxConsecutivePerClass 0 +ppm: Param = maxConsecutivePerClass, value = 0, min = (null), minForPoint= (null) +ppm: Accepted replaced value: 0 +ppm: get line: useCracklib 0 +ppm: Param = useCracklib, value = 0, min = (null), minForPoint= (null) +ppm: Accepted replaced value: 0 +ppm: get line: cracklibDict /var/cache/cracklib/cracklib_dict +ppm: Param = cracklibDict, value = /var/cache/cracklib/cracklib_dict, min = (null), minForPoint= (null) +ppm: Accepted replaced value: /var/cache/cracklib/cracklib_dict +ppm: get line: class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 0 +ppm: Param = class-upperCase, value = ABCDEFGHIJKLMNOPQRSTUVWXYZ, min = 0, minForPoint = 1, max = 0 +ppm: Accepted replaced value: ABCDEFGHIJKLMNOPQRSTUVWXYZ +ppm: get line: class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 0 +ppm: Param = class-lowerCase, value = abcdefghijklmnopqrstuvwxyz, min = 0, minForPoint = 1, max = 0 +ppm: Accepted replaced value: abcdefghijklmnopqrstuvwxyz +ppm: get line: class-digit 0123456789 0 1 0 +ppm: Param = class-digit, value = 0123456789, min = 0, minForPoint = 1, max = 0 +ppm: Accepted replaced value: 0123456789 +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 0 +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, max = 0 +ppm: Accepted replaced value: <>,?;.:/!\[sc]\[`u]%*\[mc]\[ha]\[ad]$\[Po]\[S2]&\['e]\[ti]\[dq]#\[aq]{([-|\[`e]\[ga]_\[rs]\[,c]\[ha]\[`a]\[at])]\[de]=}+ +ppm: 1 point granted for class class-upperCase +ppm: 1 point granted for class class-lowerCase +ppm: Reallocating szErrStr from 64 to 179 +check_password_quality: module error: (/usr/local/openldap/libexec/openldap/ppm.so) Password for dn=\[dq]uid=jack.oneill,ou=people,dc=my-domain,dc=com\[dq] does not pass required number of strength checks (2 of 3).[1] +\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]/usr/local/etc/openldap/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 (OpenLDAP 2.5) or by the \f[B]ppolicy_check_module\f[R] +/ \f[B]olcPPolicyCheckModule\f[R] parameters of the ppolicy overlay +(OpenLDAP 2.6) +.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-2022 by David Coutadeur. |