From c55b12f8a403d0ace2e6ed1de9b49cf3ec405f5a Mon Sep 17 00:00:00 2001 From: epictete Date: Tue, 20 Aug 2019 16:07:07 +0200 Subject: [PATCH] include ppm release 1.8 --- .../debian/openldap-ltb.vars | 2 +- .../ltb-project-openldap-ppm-1.8/INSTALL | 55 ++ .../ltb-project-openldap-ppm-1.8/LICENSE | 50 ++ .../ltb-project-openldap-ppm-1.8/Makefile | 67 ++ .../ltb-project-openldap-ppm-1.8/README.md | 250 ++++++++ .../ltb-project-openldap-ppm-1.8/ppm.c | 577 ++++++++++++++++++ .../ltb-project-openldap-ppm-1.8/ppm.conf | 66 ++ .../ltb-project-openldap-ppm-1.8/ppm.h | 117 ++++ .../ltb-project-openldap-ppm-1.8/ppm_test.c | 40 ++ .../unit_tests.sh | 119 ++++ 10 files changed, 1342 insertions(+), 1 deletion(-) create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/INSTALL create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/LICENSE create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/Makefile create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/README.md create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.c create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.conf create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.h create mode 100644 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm_test.c create mode 100755 debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/unit_tests.sh diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/debian/openldap-ltb.vars b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/debian/openldap-ltb.vars index 8ec76be..a0fd832 100755 --- a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/debian/openldap-ltb.vars +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/debian/openldap-ltb.vars @@ -41,7 +41,7 @@ CHECK_PASSWORD_MINDIGIT="0" CHECK_PASSWORD_MINPUNCT="0" PPM_NAME="ltb-project-openldap-ppm" -PPM_VERSION="1.7" +PPM_VERSION="1.8" PPM_CONF="${LDAPSERVERDIR}/etc/openldap/ppm.conf" EXPL_NAME="ltb-project-openldap-explockout" diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/INSTALL b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/INSTALL new file mode 100644 index 0000000..c434cf6 --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/INSTALL @@ -0,0 +1,55 @@ +INSTALLATION +============ + +Build dependencies +------------------ +OpenLDAP sources must be available. For an easier build, copy all ppm module +into contrib/slapd-modules OpenLDAP source directory. + +Build +----- +Be sure to have copied ppm module into contrib/slapd-modules OpenLDAP source +directory. + +Adapt the Makefile command to indicate: +OLDAP_SOURCES : should point to OpenLDAP source directory +CONFIG: where the ppm.conf configuration file will finally stand +LIBDIR: where the library will be installed +DEBUG: If defined, ppm logs its actions with syslog + +If necessary, you can also adapt some OpenLDAP source directories (if changed): +LDAP_INC : OpenLDAP headers directory +LDAP_LIBS : OpenLDAP built libraries directory + +then type: + +make clean +make CONFIG=/etc/openldap/ppm.conf OLDAP_SOURCES=../../.. +make install CONFIG=/etc/openldap/ppm.conf LIBDIR=/usr/lib/openldap + + +USAGE +===== + +Create a password policy entry and indicate the fresh compiled +library ppm.so: + +dn: cn=default,ou=policies,dc=my-domain,dc=com +objectClass: pwdPolicy +objectClass: pwdPolicyChecker +objectClass: person +objectClass: top +cn: default +sn: default +pwdAttribute: userPassword +pwdCheckQuality: 2 +... +pwdCheckModule: /path/to/new/ppm.so + + +See slapo-ppolicy for more information, but to sum up: +- add ppolicy schema to your directory +- enable ppolicy overlay +- define a default ppolicy in OpenLDAP configuration or use pwdPolicySubentry +attribute to point to the previous policy. + diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/LICENSE b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/LICENSE new file mode 100644 index 0000000..03f692b --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/LICENSE @@ -0,0 +1,50 @@ +OpenLDAP Public License + +The OpenLDAP Public License + Version 2.8.1, 25 November 2003 + +Redistribution and use of this software and associated documentation +("Software"), with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions in source form must retain copyright statements + and notices, + +2. Redistributions in binary form must reproduce applicable copyright + statements and notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution, and + +3. Redistributions must contain a verbatim copy of this document. + +The OpenLDAP Foundation may revise this license from time to time. +Each revision is distinguished by a version number. You may use +this Software under terms of this license revision or under the +terms of any subsequent revision of the license. + +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS +CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) +OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +The names of the authors and copyright holders must not be used in +advertising or otherwise to promote the sale, use or other dealing +in this Software without specific, written prior permission. Title +to copyright in this Software shall at all times remain with copyright +holders. + +OpenLDAP is a registered trademark of the OpenLDAP Foundation. + +Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, +California, USA. All rights reserved. Permission to copy and +distribute verbatim copies of this document is granted. + diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/Makefile b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/Makefile new file mode 100644 index 0000000..2bd198f --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/Makefile @@ -0,0 +1,67 @@ +# contrib/slapd-modules/ppm/Makefile +# Copyright 2014 David Coutadeur, Paris. All Rights Reserved. +# + +CC=gcc + +# Path of OpenLDAP sources +OLDAP_SOURCES=../../.. +# Where the ppm configuration file should be installed +CONFIG=/etc/openldap/ppm.conf +# Path of OpenLDAP installed libs, where the ppm library should be installed +LIBDIR=/usr/lib/openldap + +OPT=-g -O2 -Wall -fpic \ + -DCONFIG_FILE="\"$(CONFIG)\"" \ + -DDEBUG + +# Where to find the OpenLDAP headers. + +LDAP_INC=-I$(OLDAP_SOURCES)/include \ + -I$(OLDAP_SOURCES)/servers/slapd + +# Where to find the OpenLDAP libraries. + +LDAP_LIBS=-L$(OLDAP_SOURCES)/libraries/liblber/.libs \ + -L$(OLDAP_SOURCES)/libraries/libldap_r/.libs + +CRACK_INC=-DCRACKLIB + +INCS=$(LDAP_INC) $(CRACK_INC) + +LDAP_LIB=-lldap_r -llber + +CRACK_LIB=-lcrack + +LIBS=$(LDAP_LIB) $(CRACK_LIB) + +TESTS=./unit_tests.sh + + + +all: ppm ppm_test + +ppm_test: + $(CC) -g $(LDAP_INC) $(LDAP_LIBS) -Wl,-rpath=. -o ppm_test ppm_test.c ppm.so $(LIBS) + +ppm.o: + $(CC) $(OPT) -c $(INCS) ppm.c + +ppm: ppm.o + $(CC) $(LDAP_INC) -shared -o ppm.so ppm.o $(CRACK_LIB) + +install: ppm + cp -f ppm.so $(LIBDIR) + cp -f ppm_test $(LIBDIR) + cp -f ppm.conf $(CONFIG) + +.PHONY: clean + +clean: + $(RM) -f ppm.o ppm.so ppm.lo ppm_test + $(RM) -rf .libs + +test: ppm ppm_test + $(TESTS) + + diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/README.md b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/README.md new file mode 100644 index 0000000..a029601 --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/README.md @@ -0,0 +1,250 @@ + +ppm.c - OpenLDAP password policy module + +version 1.7 + +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 - 2017 - 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 +----- + +See INSTALL file + + +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 criterias 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 file +------------------ + +The configuration file (/etc/openldap/ppm.conf by default) contains +parameters for the module. The PPM_CONFIG_FILE environment variable, +if defined, overloads the configuration file path. +If the file is not found, parameters are given their default value. + +The syntax of the file is : +parameter value [min] [minForPoint] + +with spaces being delimiters. Parameter names ARE case sensitive + +The default configuration file 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 + +# maxLength parameter +# Format: +# maxLength [NUMBER] +# Description: +# The password must not be more than [NUMBER] long. 0 means no limit is set. +maxLength 0 + +# 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_dictionnary] +# 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 dictionnary 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 .?, +maxLength 0 +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 ) +- there is no size constraint (maxLength of 0) + +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: + +``` +Jul 27 20:09:14 machine slapd[20270]: ppm: Opening file /etc/openldap/ppm.conf +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = minQuality, value = 3, min = (null), minForPoint= (null) +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: 3 +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = forbiddenChars, value = , min = (null), minForPoint= (null) +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = class-upperCase, value = ABCDEFGHIJKLMNOPQRSTUVWXYZ, min = 0, minForPoint= 5 +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: ABCDEFGHIJKLMNOPQRSTUVWXYZ +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = class-lowerCase, value = abcdefghijklmnopqrstuvwxyz, min = 0, minForPoint= 12 +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: abcdefghijklmnopqrstuvwxyz +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = class-digit, value = 0123456789, min = 0, minForPoint= 1 +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: 0123456789 +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = class-special, value = <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+, min = 0, minForPoint= 1 +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted replaced value: <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ +Jul 27 20:09:14 machine slapd[20270]: ppm: Param = class-myClass, value = :), min = 1, minForPoint= 1 +Jul 27 20:09:14 machine slapd[20270]: ppm: Accepted new value: +Jul 27 20:09:14 machine slapd[20270]: ppm: 1 point granted for class class-upperCase +Jul 27 20:09:14 machine slapd[20270]: ppm: 1 point granted for class class-lowerCase +Jul 27 20:09:14 machine slapd[20270]: ppm: 1 point granted for class class-digit +``` + + +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/openldap/lib64 +PPM_CONFIG_FILE=/usr/local/openldap/etc/openldap/ppm.conf LD_LIBRARY_PATH=. ./ppm_test "uid=test,ou=users,dc=my-domain,dc=com" "my_password" && echo OK +``` + + +TODO +---- +* integrate configuration file into cn=config + + +HISTORY +------- +* 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 instal. 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/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.c b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.c new file mode 100644 index 0000000..55acc62 --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.c @@ -0,0 +1,577 @@ +/* + * ppm.c for OpenLDAP + * + * See LICENSE, README and INSTALL files + */ + +#include // for type conversion, such as atoi... +#include // for matching allowedParameters / conf file +#include +#include +#include +#include +#include // for variable nb of arguments functions +#include "ppm.h" + +#ifdef CRACKLIB +#include "crack.h" // use cracklib to check password +#endif + + +void +ppm_log(int priority, const char *format, ...) +{ + // if DEBUG flag is set + // logs into syslog (for OpenLDAP) or to stdout (for tests) +#if defined(DEBUG) + if(ppm_test != 1) + { + va_list syslog_args; + va_start(syslog_args, format); + vsyslog(priority, format, syslog_args); + va_end(syslog_args); + } + else + { + va_list stdout_args; + va_start(stdout_args, format); + vprintf(format, stdout_args); + printf("\n"); + fflush(stdout); + va_end(stdout_args); + } +#endif +} + +void +strcpy_safe(char *dest, char *src, int length_dest) +{ + if(src == NULL) + { + dest[0] = '\0'; + } + else + { + int length_src = strlen(src); + int n = (length_dest < length_src) ? length_dest : length_src; + // Copy the string — don’t copy too many bytes. + strncpy(dest, src, n); + // Ensure null-termination. + dest[n] = '\0'; + } +} + +genValue* +getValue(conf *fileConf, int numParam, char* param) +{ + int i = 0; + + // First scan parameters + for (i = 0; i < numParam; i++) { + if ((strlen(param) == strlen(fileConf[i].param)) + && (strncmp(param, fileConf[i].param, strlen(fileConf[i].param)) + == 0)) { + return &(fileConf[i].value); + } + } + return NULL; +} + +int maxConsPerClass(char *password, char *charClass) +{ + // find maximum number of consecutive class characters in the password + + int bestMax = 0; + int max = 0; + int i; + + for(i=0 ; i bestMax) + { + // found a better maxConsecutivePerClass + bestMax = max; + } + } + else + { + // current character is not in class + // reinitialize max + max=0; + } + } + return bestMax; +} + +void +storeEntry(char *param, char *value, valueType valType, + char *min, char *minForPoint, conf * fileConf, int *numParam) +{ + int i = 0; + int iMin; + int iMinForPoint; + if (min == NULL || strcmp(min,"") == 0) + iMin = 0; + else + iMin = atoi(min); + + if (minForPoint == NULL || strcmp(minForPoint,"") == 0) + iMinForPoint = 0; + else + iMinForPoint = atoi(minForPoint); + + // First scan parameters + for (i = 0; i < *numParam; i++) { + if ((strlen(param) == strlen(fileConf[i].param)) + && (strncmp(param, fileConf[i].param, strlen(fileConf[i].param)) + == 0)) { + // entry found, replace values + if(valType == typeInt) + fileConf[i].value.iVal = atoi(value); + else + strcpy_safe(fileConf[i].value.sVal, value, VALUE_MAX_LEN); + fileConf[i].min = iMin; + fileConf[i].minForPoint = iMinForPoint; + if(valType == typeInt) + ppm_log(LOG_NOTICE, "ppm: Accepted replaced value: %d", + fileConf[i].value.iVal); + else + ppm_log(LOG_NOTICE, "ppm: Accepted replaced value: %s", + fileConf[i].value.sVal); + return; + } + } + // entry not found, add values + strcpy_safe(fileConf[*numParam].param, param, PARAM_MAX_LEN); + fileConf[*numParam].iType = valType; + if(valType == typeInt) + fileConf[i].value.iVal = atoi(value); + else + strcpy_safe(fileConf[i].value.sVal, value, VALUE_MAX_LEN); + fileConf[*numParam].min = iMin; + fileConf[*numParam].minForPoint = iMinForPoint; + ++(*numParam); + if(valType == typeInt) + ppm_log(LOG_NOTICE, "ppm: Accepted new value: %d", + fileConf[*numParam].value.iVal); + else + ppm_log(LOG_NOTICE, "ppm: Accepted new value: %s", + fileConf[*numParam].value.sVal); +} + +int +typeParam(char* param) +{ + int i; + int n = sizeof(allowedParameters)/sizeof(params); + + regex_t regex; + int reti; + + for(i = 0 ; i < n ; i++ ) + { + // Compile regular expression + reti = regcomp(®ex, allowedParameters[i].param, 0); + if (reti) { + ppm_log(LOG_ERR, "ppm: Cannot compile regex: %s", + allowedParameters[i].param); + exit(EXIT_FAILURE); + } + + // Execute regular expression + reti = regexec(®ex, param, 0, NULL, 0); + if (!reti) + { + regfree(®ex); + return i; + } + regfree(®ex); + } + return n; +} + +static void +read_config_file(conf * fileConf, int *numParam, char *ppm_config_file) +{ + FILE *config; + char line[260] = ""; + int nParam = 0; // position of found parameter in allowedParameters + int sAllowedParameters = sizeof(allowedParameters)/sizeof(params); + + ppm_log(LOG_NOTICE, "ppm: Opening file %s", ppm_config_file); + if ((config = fopen(ppm_config_file, "r")) == NULL) { + ppm_log(LOG_ERR, "ppm: Opening file %s failed", ppm_config_file); + exit(EXIT_FAILURE); + } + + while (fgets(line, 256, config) != NULL) { + char *start = line; + char *word, *value; + char *min, *minForPoint;; + + while (isspace(*start) && isascii(*start)) + start++; + + if (!isascii(*start)) + continue; + if (start[0] == '#') + continue; + + if ((word = strtok(start, " \t"))) { + if ((value = strtok(NULL, " \t")) == NULL) + continue; + if (strchr(value, '\n') != NULL) + strchr(value, '\n')[0] = '\0'; + min = strtok(NULL, " \t"); + if (min != NULL) + if (strchr(min, '\n') != NULL) + strchr(min, '\n')[0] = '\0'; + minForPoint = strtok(NULL, " \t"); + if (minForPoint != NULL) + if (strchr(minForPoint, '\n') != NULL) + strchr(minForPoint, '\n')[0] = '\0'; + + + nParam = typeParam(word); // search for param in allowedParameters + if (nParam != sAllowedParameters) // param has been found + { + ppm_log(LOG_NOTICE, + "ppm: Param = %s, value = %s, min = %s, minForPoint= %s", + word, value, min, minForPoint); + + storeEntry(word, value, allowedParameters[nParam].iType, + min, minForPoint, fileConf, numParam); + } + else + { + ppm_log(LOG_NOTICE, + "ppm: Parameter '%s' rejected", word); + } + + } + } + + fclose(config); +} + +static int +realloc_error_message(char **target, int curlen, int nextlen) +{ + if (curlen < nextlen + MEMORY_MARGIN) { + ppm_log(LOG_WARNING, + "ppm: Reallocating szErrStr from %d to %d", curlen, + nextlen + MEMORY_MARGIN); + ber_memfree(*target); + curlen = nextlen + MEMORY_MARGIN; + *target = (char *) ber_memalloc(curlen); + } + + return curlen; +} + +// Does the password contains a token from the RDN ? +int +containsRDN(char* passwd, char* DN) +{ + char lDN[DN_MAX_LEN]; + char * tmpToken; + char * token; + regex_t regex; + int reti; + + strcpy_safe(lDN, DN, DN_MAX_LEN); + + // Extract the RDN from the DN + tmpToken = strtok(lDN, ",+"); + tmpToken = strtok(tmpToken, "="); + tmpToken = strtok(NULL, "="); + + // Search for each token in the password */ + token = strtok(tmpToken, TOKENS_DELIMITERS); + + while (token != NULL) + { + if (strlen(token) > 2) + { + ppm_log(LOG_NOTICE, "ppm: Checking if %s part of RDN matches the password", token); + // Compile regular expression + reti = regcomp(®ex, token, REG_ICASE); + if (reti) { + ppm_log(LOG_ERR, "ppm: Cannot compile regex: %s", token); + exit(EXIT_FAILURE); + } + + // Execute regular expression + reti = regexec(®ex, passwd, 0, NULL, 0); + if (!reti) + { + regfree(®ex); + return 1; + } + + regfree(®ex); + } + else + { + ppm_log(LOG_NOTICE, "ppm: %s part of RDN is too short to be checked", token); + } + token = strtok(NULL, TOKENS_DELIMITERS); + } + + return 0; +} + + +int +check_password(char *pPasswd, char **ppErrStr, Entry * pEntry) +{ + + ppm_log(LOG_NOTICE, "ppm: entry %s", pEntry->e_nname.bv_val); + + char *szErrStr = (char *) ber_memalloc(MEM_INIT_SZ); + int mem_len = MEM_INIT_SZ; + int numParam = 0; // Number of params in current configuration + + int maxLength; + int useCracklib; + char cracklibDict[VALUE_MAX_LEN]; + char cracklibDictFiles[3][(VALUE_MAX_LEN+5)]; + char const* cracklibExt[] = { ".hwm", ".pwd", ".pwi" }; + FILE* fd; + char* res; + int minQuality; + int checkRDN; + char forbiddenChars[VALUE_MAX_LEN]; + int nForbiddenChars = 0; + int nQuality = 0; + int maxConsecutivePerClass; + int nbInClass[CONF_MAX_SIZE]; + int i,j; + char ppm_config_file[FILENAME_MAX_LEN]; + + /* Determine config file */ + strcpy_safe(ppm_config_file, getenv("PPM_CONFIG_FILE"), FILENAME_MAX_LEN); + if (ppm_config_file[0] == '\0') { + strcpy_safe(ppm_config_file, CONFIG_FILE, FILENAME_MAX_LEN); + } + ppm_log(LOG_NOTICE, "ppm: reading config file from %s", ppm_config_file); + + for (i = 0; i < CONF_MAX_SIZE; i++) + nbInClass[i] = 0; + + /* Set default values */ + conf fileConf[CONF_MAX_SIZE] = { + {"maxLength", typeInt, {.iVal = 0}, 0, 0 + } + , + {"minQuality", typeInt, {.iVal = DEFAULT_QUALITY}, 0, 0 + } + , + {"checkRDN", typeInt, {.iVal = 0}, 0, 0 + } + , + {"forbiddenChars", typeStr, {.sVal = ""}, 0, 0 + } + , + {"maxConsecutivePerClass", typeInt, {.iVal = 0}, 0, 0 + } + , + {"useCracklib", typeInt, {.iVal = 0}, 0, 0 + } + , + {"cracklibDict", typeStr, {.sVal = "/var/cache/cracklib/cracklib_dict"}, 0, 0 + } + , + {"class-upperCase", typeStr, {.sVal = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 0, 1 + } + , + {"class-lowerCase", typeStr, {.sVal = "abcdefghijklmnopqrstuvwxyz"}, 0, 1 + } + , + {"class-digit", typeStr, {.sVal = "0123456789"}, 0, 1 + } + , + {"class-special", typeStr, + {.sVal = "<>,?;.:/!§ù%*µ^¨$£²&é~\"#'{([-|è`_\\ç^à@)]°=}+"}, 0, 1 + } + }; + numParam = 11; + + /* Read config file */ + read_config_file(fileConf, &numParam, ppm_config_file); + + maxLength = getValue(fileConf, numParam, "maxLength")->iVal; + minQuality = getValue(fileConf, numParam, "minQuality")->iVal; + checkRDN = getValue(fileConf, numParam, "checkRDN")->iVal; + strcpy_safe(forbiddenChars, + getValue(fileConf, numParam, "forbiddenChars")->sVal, + VALUE_MAX_LEN); + maxConsecutivePerClass = getValue(fileConf, numParam, "maxConsecutivePerClass")->iVal; + useCracklib = getValue(fileConf, numParam, "useCracklib")->iVal; + strcpy_safe(cracklibDict, + getValue(fileConf, numParam, "cracklibDict")->sVal, + VALUE_MAX_LEN); + + + /*The password must have at least minQuality strength points with one + * point granted if the password contains at least minForPoint characters for each class + * It must contains at least min chars of each class + * It must not contain any char in forbiddenChar */ + + if(maxLength != 0 && strlen(pPasswd) > maxLength) { + // constraint is not satisfied... goto fail + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_TOO_LONG_SZ) + + strlen(pEntry->e_name.bv_val) + + 2 * sizeof(maxLength)); + sprintf(szErrStr, PASSWORD_TOO_LONG_SZ, pEntry->e_name.bv_val, + (int)strlen(pPasswd), maxLength); + goto fail; + + } + + for (i = 0; i < strlen(pPasswd); i++) { + + int n; + for (n = 0; n < numParam; n++) { + if (strstr(fileConf[n].param, "class-") != NULL) { + if (strchr(fileConf[n].value.sVal, pPasswd[i]) != NULL) { + ++(nbInClass[n]); + } + } + } + if (strchr(forbiddenChars, pPasswd[i]) != NULL) { + nForbiddenChars++; + } + } + + // Password checking done, now loocking for minForPoint criteria + for (i = 0; i < CONF_MAX_SIZE; i++) { + if (strstr(fileConf[i].param, "class-") != NULL) { + if ((nbInClass[i] >= fileConf[i].minForPoint) + && strlen(fileConf[i].value.sVal) != 0) { + // 1 point granted + ++nQuality; + ppm_log(LOG_NOTICE, "ppm: 1 point granted for class %s", + fileConf[i].param); + } + } + } + + if (nQuality < minQuality) { + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_QUALITY_SZ) + + strlen(pEntry->e_name.bv_val) + 4); + sprintf(szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_name.bv_val, + nQuality, minQuality); + goto fail; + } + // Password checking done, now loocking for constraintClass criteria + for (i = 0; i < CONF_MAX_SIZE; i++) { + if (strstr(fileConf[i].param, "class-") != NULL) { + if ((nbInClass[i] < fileConf[i].min) && + strlen(fileConf[i].value.sVal) != 0) { + // constraint is not satisfied... goto fail + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_CRITERIA) + + strlen(pEntry->e_name.bv_val) + + 2 + PARAM_MAX_LEN); + sprintf(szErrStr, PASSWORD_CRITERIA, pEntry->e_name.bv_val, + fileConf[i].min, fileConf[i].param); + goto fail; + } + } + } + + // Password checking done, now loocking for forbiddenChars criteria + if (nForbiddenChars > 0) { // at least 1 forbidden char... goto fail + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_FORBIDDENCHARS) + + strlen(pEntry->e_name.bv_val) + 2 + + VALUE_MAX_LEN); + sprintf(szErrStr, PASSWORD_FORBIDDENCHARS, pEntry->e_name.bv_val, + nForbiddenChars, forbiddenChars); + goto fail; + } + + // Password checking done, now loocking for maxConsecutivePerClass criteria + for (i = 0; i < CONF_MAX_SIZE; i++) { + if (strstr(fileConf[i].param, "class-") != NULL) { + if ( maxConsecutivePerClass != 0 && + (maxConsPerClass(pPasswd,fileConf[i].value.sVal) + > maxConsecutivePerClass)) { + // Too much consecutive characters of the same class + ppm_log(LOG_NOTICE, "ppm: Too much consecutive chars for class %s", + fileConf[i].param); + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_MAXCONSECUTIVEPERCLASS) + + strlen(pEntry->e_name.bv_val) + 2 + + PARAM_MAX_LEN); + sprintf(szErrStr, PASSWORD_MAXCONSECUTIVEPERCLASS, pEntry->e_name.bv_val, + maxConsecutivePerClass, fileConf[i].param); + goto fail; + } + } + } +#ifdef CRACKLIB + // Password checking done, now loocking for cracklib criteria + if ( useCracklib > 0 ) { + + for( j = 0 ; j < 3 ; j++) { + strcpy_safe(cracklibDictFiles[j], cracklibDict, VALUE_MAX_LEN); + strcat(cracklibDictFiles[j], cracklibExt[j]); + if (( fd = fopen ( cracklibDictFiles[j], "r")) == NULL ) { + ppm_log(LOG_NOTICE, "ppm: Error while reading %s file", + cracklibDictFiles[j]); + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(GENERIC_ERROR)); + sprintf(szErrStr, GENERIC_ERROR); + goto fail; + + } + else { + fclose (fd); + } + } + res = (char *) FascistCheck (pPasswd, cracklibDict); + if ( res != NULL ) { + ppm_log(LOG_NOTICE, "ppm: cracklib does not validate password for entry %s", + pEntry->e_name.bv_val); + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(PASSWORD_CRACKLIB) + + strlen(pEntry->e_name.bv_val)); + sprintf(szErrStr, PASSWORD_CRACKLIB, pEntry->e_name.bv_val); + goto fail; + + } + + } +#endif + + // Password checking done, now looking for checkRDN criteria + if (checkRDN == 1 && containsRDN(pPasswd, pEntry->e_name.bv_val)) + // RDN check enabled and a token from RDN is found in password: goto fail + { + mem_len = realloc_error_message(&szErrStr, mem_len, + strlen(RDN_TOKEN_FOUND) + + strlen(pEntry->e_name.bv_val)); + sprintf(szErrStr, RDN_TOKEN_FOUND, pEntry->e_name.bv_val); + + goto fail; + } + + *ppErrStr = strdup(""); + ber_memfree(szErrStr); + return (LDAP_SUCCESS); + + fail: + *ppErrStr = strdup(szErrStr); + ber_memfree(szErrStr); + return (EXIT_FAILURE); + +} diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.conf b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.conf new file mode 100644 index 0000000..23993bc --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.conf @@ -0,0 +1,66 @@ + +# 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 + +# maxLength parameter +# Format: +# maxLength [NUMBER] +# Description: +# The password must not be more than [NUMBER] long. 0 means no limit is set. +maxLength 0 + +# checkRDN parameter +# Format: +# checkRDN [0 | 1] +# Description: +# If set to 1, password must not contain a token from the RDN. +# Tokens are separated by these 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_dictionnary] +# 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 dictionnary 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 diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.h b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.h new file mode 100644 index 0000000..4739404 --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm.h @@ -0,0 +1,117 @@ +/* + * ppm.h for OpenLDAP + * + * See LICENSE, README and INSTALL files + */ + +#ifndef PPM_H_ +#define PPM_H_ + +#include // for type conversion, such as atoi... +#include // for matching allowedParameters / conf file +#include +#include +#include +#include + +#if defined(DEBUG) +#include +#endif + +#ifndef CONFIG_FILE +#define CONFIG_FILE "/etc/openldap/ppm.conf" +#endif + +#define DEFAULT_QUALITY 3 +#define MEMORY_MARGIN 50 +#define MEM_INIT_SZ 64 +#define FILENAME_MAX_LEN 512 +#define DN_MAX_LEN 512 + +#define CONF_MAX_SIZE 50 +#define PARAM_MAX_LEN 32 +#define VALUE_MAX_LEN 128 +#define ATTR_NAME_MAX_LEN 150 + +#define PARAM_PREFIX_CLASS "class-" +#define TOKENS_DELIMITERS " ,;-_£\t" + + +#define DEBUG_MSG_MAX_LEN 256 + +#define PASSWORD_TOO_LONG_SZ \ + "Password for dn=\"%s\" is too long (%d / %d)" +#define PASSWORD_QUALITY_SZ \ + "Password for dn=\"%s\" does not pass required number of strength checks (%d of %d)" +#define PASSWORD_CRITERIA \ + "Password for dn=\"%s\" has not reached the minimum number of characters (%d) for class %s" +#define PASSWORD_MAXCONSECUTIVEPERCLASS \ + "Password for dn=\"%s\" has reached the maximum number of characters (%d) for class %s" +#define PASSWORD_FORBIDDENCHARS \ + "Password for dn=\"%s\" contains %d forbidden characters in %s" +#define RDN_TOKEN_FOUND \ + "Password for dn=\"%s\" contains tokens from the RDN" +#define GENERIC_ERROR \ + "Error while checking password" +#define PASSWORD_CRACKLIB \ + "Password for dn=\"%s\" is too weak" +#define BAD_PASSWORD_SZ \ + "Bad password for dn=\"%s\" because %s" + + + +typedef union genValue { + int iVal; + char sVal[VALUE_MAX_LEN]; +} genValue; + +typedef enum { + typeInt, + typeStr +} valueType; + +typedef struct params { + char param[PARAM_MAX_LEN]; + valueType iType; +} params; + +// allowed parameters loaded into configuration structure +// it also contains the type of the corresponding value +params allowedParameters[8] = { + {"^maxLength", typeInt}, + {"^minQuality", typeInt}, + {"^checkRDN", typeInt}, + {"^forbiddenChars", typeStr}, + {"^maxConsecutivePerClass", typeInt}, + {"^useCracklib", typeInt}, + {"^cracklibDict", typeStr}, + {"^class-.*", typeStr} +}; + + +// configuration structure, containing a parameter, a value, +// a corresponding min and minForPoint indicators if necessary +// and a type for the value (typeInt or typeStr) +typedef struct conf { + char param[PARAM_MAX_LEN]; + valueType iType; + genValue value; + int min; + int minForPoint; +} conf; + +void ppm_log(int priority, const char *format, ...); +int min(char *str1, char *str2); +static void read_config_file(conf * fileConf, int *numParam, char *ppm_config_file); +int check_password(char *pPasswd, char **ppErrStr, Entry * pEntry); +int maxConsPerClass(char *password, char *charClass); +void storeEntry(char *param, char *value, valueType valType, + char *min, char *minForPoint, conf * fileConf, int *numParam); +int typeParam(char* param); +genValue* getValue(conf *fileConf, int numParam, char* param); +void strcpy_safe(char *dest, char *src, int length_dest); + + +int ppm_test = 0; + +#endif diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm_test.c b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm_test.c new file mode 100644 index 0000000..11ac53a --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/ppm_test.c @@ -0,0 +1,40 @@ +#include +#include +#include "ppm.h" + +int main(int argc, char *argv[]) +{ + int ret = 1; + + if(argc > 2) + { + printf("Testing password : '%s' for user %s\n", argv[2], argv[1]); + + char *errmsg = NULL; + Entry pEntry; + pEntry.e_nname.bv_val=argv[1]; + pEntry.e_name.bv_val=argv[1]; + + ppm_test=1; // enable ppm_test for informing ppm not to use syslog + + ret = check_password(argv[2], &errmsg, &pEntry); + + if(ret == 0) + { + printf("Password is OK!\n"); + } + else + { + printf("Password failed checks : %s\n", errmsg); + } + + ber_memfree(errmsg); + return ret; + + } + + return ret; +} + + + diff --git a/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/unit_tests.sh b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/unit_tests.sh new file mode 100755 index 0000000..a5c0e49 --- /dev/null +++ b/debian/paquet-openldap-debian/openldap-ltb-2.4.48/ltb-project-openldap-ppm-1.8/unit_tests.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +# Launch unitary tests +# + + +CONFIG_FILE="ppm.conf" +LIB_PATH="." + +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' + +RESULT=0 + +PPM_CONF_1='minQuality 3 +maxLength 0 +checkRDN 0 +forbiddenChars +maxConsecutivePerClass 0 +useCracklib 0 +cracklibDict /var/cache/cracklib/cracklib_dict +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +class-digit 0123456789 0 1 +class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'\''{([-|è`_\ç^à@)]°=}+ 0 1' + +PPM_CONF_2='minQuality 3 +maxLength 20 +checkRDN 0 +forbiddenChars à +maxConsecutivePerClass 5 +useCracklib 0 +cracklibDict /var/cache/cracklib/cracklib_dict +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 2 4 +class-lowerCase abcdefghijklmnopqrstuvwxyz 3 4 +class-digit 0123456789 2 4 +class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'\''{([-|è`_\ç^à@)]°=}+ 0 4' + +PPM_CONF_3='minQuality 3 +maxLength 0 +checkRDN 1 +forbiddenChars +maxConsecutivePerClass 0 +useCracklib 0 +cracklibDict /var/cache/cracklib/cracklib_dict +class-upperCase ABCDEFGHIJKLMNOPQRSTUVWXYZ 0 1 +class-lowerCase abcdefghijklmnopqrstuvwxyz 0 1 +class-digit 0123456789 0 1 +class-special <>,?;.:/!§ù%*µ^¨$£²&é~"#'\''{([-|è`_\ç^à@)]°=}+ 0 1' + + +echo "$PPM_CONF_1" > ppm1.conf +echo "$PPM_CONF_2" > ppm2.conf +echo "$PPM_CONF_3" > ppm3.conf + + +launch_test() +{ + # launch tests + # FORMAT: launch_test [conf_file] [password] [expected_result] + # [expected_result] = [PASS|FAIL] + + local CONF="$1" + local USER="$2" + local PASS="$3" + local EXPECT="$4" + + [[ $EXPECT == "PASS" ]] && EXP="0" || EXP="1" + + PPM_CONFIG_FILE="${CONF}" LD_LIBRARY_PATH="${LIB_PATH}" ./ppm_test "${USER}" "${PASS}" + RES="$?" + + if [ "$RES" -eq "$EXP" ] ; then + echo -e "conf=${CONF} user=${USER} pass=${PASS} expect=${EXPECT}... ${GREEN}PASS${NC}" + else + echo -e "conf=${CONF} user=${USER} pass=${PASS} expect=${EXPECT}... ${RED}FAIL${NC}" + ((RESULT+=1)) + fi + + echo +} + + + + +launch_test "ppm1.conf" "uid=test,ou=users,dc=my-domain,dc=com" "azerty" "FAIL" +launch_test "ppm1.conf" "uid=test,ou=users,dc=my-domain,dc=com" "azeRTY" "FAIL" +launch_test "ppm1.conf" "uid=test,ou=users,dc=my-domain,dc=com" "azeRTY123" "PASS" +launch_test "ppm1.conf" "uid=test,ou=users,dc=my-domain,dc=com" "azeRTY." "PASS" + + +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "AAaaa01AAaaa01AAaaa0" "PASS" +# too long +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "AAaaa01AAaaa01AAaaa01" "FAIL" +# forbidden char +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "AAaaa01AAaaa01AAaaaà" "FAIL" +# too much consecutive for upper +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "AAaaa01AAaaa01AAAAAA" "FAIL" +# not enough upper +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "Aaaaa01aaaaa01aa.;.;" "FAIL" +# not enough lower +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "aaAAA01BB0123AAA.;.;" "FAIL" +# not enough digit +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "1AAAA.;BBB.;.;AA.;.;" "FAIL" +# not enough points (no point for digit) +launch_test "ppm2.conf" "uid=test,ou=users,dc=my-domain,dc=com" "AAaaaBBBBaaa01AAaaaa" "FAIL" + +# password in RDN +launch_test "ppm3.conf" "uid=User_Password10-test,ou=users,dc=my-domain,dc=com" "Password10" "FAIL" +launch_test "ppm3.conf" "uid=User_Passw0rd-test,ou=users,dc=my-domain,dc=com" "Password10" "PASS" +launch_test "ppm3.conf" "uid=User-Pw-Test,ou=users,dc=my-domain,dc=com" "Password10" "PASS" + + +echo "${RESULT} error(s) encountered" + +rm ppm1.conf ppm2.conf ppm3.conf +exit ${RESULT} +