1 From 26002bd1d02d871e3c0526f3a0b7b99e25f3564c Mon Sep 17 00:00:00 2001
2 From: babak sarashki <babak.sarashki@windriver.com>
3 Date: Tue, 5 Nov 2019 18:02:38 -0800
4 Subject: [PATCH] ltb project openldap ppolicy check password 1.1
6 From stx 1901 openldap src RPM 2.4.44
7 Upstream at https://github.com/ltb-project/openldap-ppolicy-check-password.git
12 .../README | 146 ++++++
13 .../check_password.c | 447 ++++++++++++++++++
14 5 files changed, 722 insertions(+)
15 create mode 100644 ltb-project-openldap-ppolicy-check-password-1.1/INSTALL
16 create mode 100644 ltb-project-openldap-ppolicy-check-password-1.1/LICENSE
17 create mode 100644 ltb-project-openldap-ppolicy-check-password-1.1/Makefile
18 create mode 100644 ltb-project-openldap-ppolicy-check-password-1.1/README
19 create mode 100644 ltb-project-openldap-ppolicy-check-password-1.1/check_password.c
21 diff --git a/ltb-project-openldap-ppolicy-check-password-1.1/INSTALL b/ltb-project-openldap-ppolicy-check-password-1.1/INSTALL
23 index 0000000..eb2dab4
25 +++ b/ltb-project-openldap-ppolicy-check-password-1.1/INSTALL
32 +cracklib header files (link with -lcrack). The Makefile does not look for
33 +cracklib; you may need to provide the paths manually.
37 +Use the provided Makefile to build the module.
39 +Copy the resulting check_password.so into the OpenLDAP modulepath.
41 +Or, change the installation path to match with the OpenLDAP module path in the
42 +Makefile and use 'make install'.
47 +Add objectClass 'pwdPolicyChecker' with an attribute
49 + pwdCheckModule: check_password.so
51 +to a password policy entry.
53 +The module depends on a working cracklib installation including wordlist files.
54 +If the wordlist files are not readable, the cracklib check will be skipped
57 +But you can use this module without cracklib, just checks for syntatic checks.
58 diff --git a/ltb-project-openldap-ppolicy-check-password-1.1/LICENSE b/ltb-project-openldap-ppolicy-check-password-1.1/LICENSE
60 index 0000000..03f692b
62 +++ b/ltb-project-openldap-ppolicy-check-password-1.1/LICENSE
64 +OpenLDAP Public License
66 +The OpenLDAP Public License
67 + Version 2.8.1, 25 November 2003
69 +Redistribution and use of this software and associated documentation
70 +("Software"), with or without modification, are permitted provided
71 +that the following conditions are met:
73 +1. Redistributions in source form must retain copyright statements
76 +2. Redistributions in binary form must reproduce applicable copyright
77 + statements and notices, this list of conditions, and the following
78 + disclaimer in the documentation and/or other materials provided
79 + with the distribution, and
81 +3. Redistributions must contain a verbatim copy of this document.
83 +The OpenLDAP Foundation may revise this license from time to time.
84 +Each revision is distinguished by a version number. You may use
85 +this Software under terms of this license revision or under the
86 +terms of any subsequent revision of the license.
88 +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
89 +CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
90 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
91 +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
92 +SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
93 +OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
94 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
95 +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
96 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
97 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
98 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
99 +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
100 +POSSIBILITY OF SUCH DAMAGE.
102 +The names of the authors and copyright holders must not be used in
103 +advertising or otherwise to promote the sale, use or other dealing
104 +in this Software without specific, written prior permission. Title
105 +to copyright in this Software shall at all times remain with copyright
108 +OpenLDAP is a registered trademark of the OpenLDAP Foundation.
110 +Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
111 +California, USA. All rights reserved. Permission to copy and
112 +distribute verbatim copies of this document is granted.
114 diff --git a/ltb-project-openldap-ppolicy-check-password-1.1/Makefile b/ltb-project-openldap-ppolicy-check-password-1.1/Makefile
116 index 0000000..91de40b
118 +++ b/ltb-project-openldap-ppolicy-check-password-1.1/Makefile
120 +# contrib/slapd-modules/check_password/Makefile
121 +# Copyright 2007 Michael Steinmann, Calivia. All Rights Reserved.
122 +# Updated by Pierre-Yves Bonnetain, B&A Consultants, 2008
127 +# Where to look for the CrackLib dictionaries
129 +CRACKLIB=/usr/share/cracklib/pw_dict
131 +# Path to the configuration file
133 +CONFIG=/etc/openldap/check_password.conf
136 + -DHAVE_CRACKLIB -DCRACKLIB_DICTPATH="\"$(CRACKLIB)\"" \
137 + -DCONFIG_FILE="\"$(CONFIG)\"" \
140 +LDAP_LIB=-lldap_r -llber
142 +# Comment out this line if you do NOT want to use the cracklib.
143 +# You may have to add an -Ldirectory if the libcrak is not in a standard
146 +CRACKLIB_LIB=-lcrack
148 +LIBS=$(LDAP_LIB) $(CRACKLIB_LIB)
150 +LIBDIR=/usr/lib/openldap/
156 + $(CC) $(CFLAGS) -c $(LDAP_INC) check_password.c
158 +check_password: clean check_password.o
159 + $(CC) $(LDFLAGS) -shared -o check_password.so check_password.o $(CRACKLIB_LIB)
161 +install: check_password
162 + cp -f check_password.so ../../../usr/lib/openldap/modules/
165 + $(RM) check_password.o check_password.so check_password.lo
168 diff --git a/ltb-project-openldap-ppolicy-check-password-1.1/README b/ltb-project-openldap-ppolicy-check-password-1.1/README
170 index 0000000..10191c2
172 +++ b/ltb-project-openldap-ppolicy-check-password-1.1/README
175 +check_password.c - OpenLDAP pwdChecker library
177 +2007-06-06 Michael Steinmann <msl@calivia.com>
178 +2008-01-30 Pierre-Yves Bonnetain <py.bonnetain@ba-cst.com>
179 +2009 Clement Oudot <clem.oudot@gmail.com> - LTB-project
180 +2009 Jerome HUET - LTB-project
182 +check_password.c is an OpenLDAP pwdPolicyChecker module used to check the
183 +strength and quality of user-provided passwords.
185 +This module is used as an extension of the OpenLDAP password policy controls,
186 +see slapo-ppolicy(5) section pwdCheckModule.
188 +check_password.c will run a number of checks on the passwords to ensure minimum
189 +strength and quality requirements are met. Passwords that do not meet these
190 +requirements are rejected.
195 + - passwords shorter than 6 characters are rejected if cracklib is used (because
196 + cracklib WILL reject them).
198 + - syntactic checks controls how many different character classes are used
199 + (lower, upper, digit and punctuation characters). The minimum number of
200 + classes is defined in a configuration file. You can set the minimum for each
203 + - passwords are checked against cracklib if cracklib is enabled at compile
204 + time. It can be disabled in configuration file.
208 +Use the provided Makefile to build the module.
210 +Compilation constants :
212 +CONFIG_FILE : Path to the configuration file.
213 + Defaults to /etc/openldap/check_password.conf
215 +DEBUG : If defined, check_password will syslog() its actions.
218 +cracklib header files (link with -lcrack). The Makefile does not look for
219 +cracklib; you may need to provide the paths manually.
221 +Install into the slapd server module path. Change the installation
222 +path to match with the OpenLDAP module path in the Makefile.
224 +The module may be defined with slapd.conf parameter "modulepath".
228 +To use this module you need to add objectClass pwdPolicyChecker with an
229 +attribute 'pwdCheckModule: check_password.so' to a password policy entry.
231 +The module depends on a working cracklib installation including wordlist files.
232 +If the wordlist files are not readable, the cracklib check will be skipped
235 +Note: pwdPolicyChecker modules are loaded on *every* password change operation.
239 +The configuration file (/etc/openldap/check_password.conf by default) contains
240 +parameters for the module. If the file is not found, parameters are given their
243 +The syntax of the file is :
247 +with spaces being delimiters. Parameter names ARE case sensitive (this may
248 +change in the future).
250 +Current parameters :
252 +- useCracklib: integer. Default value: 1. Set it to 0 to disable cracklib verification.
253 + It has no effect if cracklib is not included at compile time.
255 +- minPoints: integer. Default value: 3. Minimum number of quality points a new
256 + password must have to be accepted. One quality point is awarded for each character
257 + class used in the password.
259 +- minUpper: integer. Defaut value: 0. Minimum upper characters expected.
261 +- minLower: integer. Defaut value: 0. Minimum lower characters expected.
263 +- minDigit: integer. Defaut value: 0. Minimum digit characters expected.
265 +- minPunct: integer. Defaut value: 0. Minimum punctuation characters expected.
269 +If a user password is rejected by an OpenLDAP pwdChecker module, the user will
270 +*not* get a detailed error message, this is by design.
272 +Typical user message from ldappasswd(5):
273 + Result: Constraint violation (19)
274 + Additional info: Password fails quality checking policy
276 +A more detailed message is written to the server log.
279 + check_password_quality: module error: (check_password.so)
280 + Password for dn=".." does not pass required number of strength checks (2 of 3)
285 +Runtime errors with this module (such as cracklib configuration problems) may
286 +bring down the slapd process.
288 +Use at your own risk.
293 +* use proper malloc function, see ITS#4998
298 +* 2009-10-30 Clement OUDOT - LTB-project
300 + - Apply patch from Jerome HUET for minUpper/minLower/minDigit/minPunct
302 +* 2009-02-05 Clement Oudot <clem.oudot@gmail.com> - LINAGORA Group
304 + - Add useCracklib parameter in config file (with help of Pascal Pejac)
305 + - Prefix log messages with "check_password: "
306 + - Log what character type is found for quality checking
308 +* 2008-01-31 Pierre-Yves Bonnetain <py.bonnetain@ba-cst.com>
310 + - Several bug fixes.
311 + - Add external config file
313 +* 2007-06-06 Michael Steinmann <msl@calivia.com>
315 + - add dn to error messages
317 +* 2007-06-02 Michael Steinmann <msl@calivia.com>
320 diff --git a/ltb-project-openldap-ppolicy-check-password-1.1/check_password.c b/ltb-project-openldap-ppolicy-check-password-1.1/check_password.c
322 index 0000000..f4dd1cb
324 +++ b/ltb-project-openldap-ppolicy-check-password-1.1/check_password.c
327 + * check_password.c for OpenLDAP
329 + * See LICENSE, README and INSTALL files
334 +#include <portable.h>
337 +#ifdef HAVE_CRACKLIB
345 +#ifndef CRACKLIB_DICTPATH
346 +#define CRACKLIB_DICTPATH "/usr/share/cracklib/pw_dict"
350 +#define CONFIG_FILE "/etc/openldap/check_password.conf"
353 +#define DEFAULT_QUALITY 3
354 +#define DEFAULT_CRACKLIB 1
355 +#define MEMORY_MARGIN 50
356 +#define MEM_INIT_SZ 64
357 +#define FILENAME_MAXLEN 512
359 +#define PASSWORD_TOO_SHORT_SZ \
360 + "Password for dn=\"%s\" is too short (%d/6)"
361 +#define PASSWORD_QUALITY_SZ \
362 + "Password for dn=\"%s\" does not pass required number of strength checks for the required character sets (%d of %d)"
363 +#define BAD_PASSWORD_SZ \
364 + "Bad password for dn=\"%s\" because %s"
365 +#define UNKNOWN_ERROR_SZ \
366 + "An unknown error occurred, please see your systems administrator"
368 +typedef int (*validator) (char*);
369 +static int read_config_file ();
370 +static validator valid_word (char *);
371 +static int set_quality (char *);
372 +static int set_cracklib (char *);
374 +int check_password (char *pPasswd, char **ppErrStr, Entry *pEntry);
376 +struct config_entry {
380 +} config_entries[] = { { "minPoints", NULL, "3"},
381 + { "useCracklib", NULL, "1"},
382 + { "minUpper", NULL, "0"},
383 + { "minLower", NULL, "0"},
384 + { "minDigit", NULL, "0"},
385 + { "minPunct", NULL, "0"},
386 + { NULL, NULL, NULL }};
388 +int get_config_entry_int(char* entry) {
389 + struct config_entry* centry = config_entries;
392 + char* key = centry[i].key;
393 + while (key != NULL) {
394 + if ( strncmp(key, entry, strlen(key)) == 0 ) {
395 + if ( centry[i].value == NULL ) {
396 + return atoi(centry[i].def_value);
399 + return atoi(centry[i].value);
403 + key = centry[i].key;
409 +void dealloc_config_entries() {
410 + struct config_entry* centry = config_entries;
413 + while (centry[i].key != NULL) {
414 + if ( centry[i].value != NULL ) {
415 + ber_memfree(centry[i].value);
421 +char* chomp(char *s)
423 + char* t = ber_memalloc(strlen(s)+1);
424 + strncpy (t,s,strlen(s)+1);
426 + if ( t[strlen(t)-1] == '\n' ) {
427 + t[strlen(t)-1] = '\0';
433 +static int set_quality (char *value)
436 + syslog(LOG_INFO, "check_password: Setting quality to [%s]", value);
439 + /* No need to require more quality than we can check for. */
440 + if (!isdigit(*value) || (int) (value[0] - '0') > 4) return DEFAULT_QUALITY;
441 + return (int) (value[0] - '0');
445 +static int set_cracklib (char *value)
448 + syslog(LOG_INFO, "check_password: Setting cracklib usage to [%s]", value);
452 + return (int) (value[0] - '0');
456 +static int set_digit (char *value)
459 + syslog(LOG_INFO, "check_password: Setting parameter to [%s]", value);
461 + if (!isdigit(*value) || (int) (value[0] - '0') > 9) return 0;
462 + return (int) (value[0] - '0');
465 +static validator valid_word (char *word)
470 + } list[] = { { "minPoints", set_quality },
471 + { "useCracklib", set_cracklib },
472 + { "minUpper", set_digit },
473 + { "minLower", set_digit },
474 + { "minDigit", set_digit },
475 + { "minPunct", set_digit },
480 + syslog(LOG_DEBUG, "check_password: Validating parameter [%s]", word);
483 + while (list[index].parameter != NULL) {
484 + if (strlen(word) == strlen(list[index].parameter) &&
485 + strcmp(list[index].parameter, word) == 0) {
487 + syslog(LOG_DEBUG, "check_password: Parameter accepted.");
489 + return list[index].dealer;
495 + syslog(LOG_DEBUG, "check_password: Parameter rejected.");
501 +static int read_config_file ()
505 + int returnValue = -1;
507 + line = ber_memcalloc(260, sizeof(char));
509 + if ( line == NULL ) {
510 + return returnValue;
513 + if ( (config = fopen(CONFIG_FILE, "r")) == NULL) {
515 + syslog(LOG_ERR, "check_password: Opening file %s failed", CONFIG_FILE);
519 + return returnValue;
524 + while (fgets(line, 256, config) != NULL) {
525 + char *start = line;
526 + char *word, *value;
530 + /* Debug traces to syslog. */
531 + syslog(LOG_DEBUG, "check_password: Got line |%s|", line);
534 + while (isspace(*start) && isascii(*start)) start++;
536 + /* If we've got punctuation, just skip the line. */
537 + if ( ispunct(*start)) {
539 + /* Debug traces to syslog. */
540 + syslog(LOG_DEBUG, "check_password: Skipped line |%s|", line);
545 + if( isascii(*start)) {
547 + struct config_entry* centry = config_entries;
549 + char* keyWord = centry[i].key;
550 + if ((word = strtok(start, " \t")) && (value = strtok(NULL, " \t"))) {
551 + while ( keyWord != NULL ) {
552 + if ((strncmp(keyWord,word,strlen(keyWord)) == 0) && (dealer = valid_word(word)) ) {
555 + syslog(LOG_DEBUG, "check_password: Word = %s, value = %s", word, value);
558 + centry[i].value = chomp(value);
562 + keyWord = centry[i].key;
570 + return returnValue;
573 +static int realloc_error_message (char ** target, int curlen, int nextlen)
575 + if (curlen < nextlen + MEMORY_MARGIN) {
577 + syslog(LOG_WARNING, "check_password: Reallocating szErrStr from %d to %d",
578 + curlen, nextlen + MEMORY_MARGIN);
580 + ber_memfree(*target);
581 + curlen = nextlen + MEMORY_MARGIN;
582 + *target = (char *) ber_memalloc(curlen);
589 +check_password (char *pPasswd, char **ppErrStr, Entry *pEntry)
592 + char *szErrStr = (char *) ber_memalloc(MEM_INIT_SZ);
593 + int mem_len = MEM_INIT_SZ;
607 + /* Set a sensible default to keep original behaviour. */
608 + int minQuality = DEFAULT_QUALITY;
609 + int useCracklib = DEFAULT_CRACKLIB;
611 + /** bail out early as cracklib will reject passwords shorter
612 + * than 6 characters
615 + nLen = strlen (pPasswd);
617 + mem_len = realloc_error_message(&szErrStr, mem_len,
618 + strlen(PASSWORD_TOO_SHORT_SZ) +
619 + strlen(pEntry->e_name.bv_val) + 1);
620 + sprintf (szErrStr, PASSWORD_TOO_SHORT_SZ, pEntry->e_name.bv_val, nLen);
624 + if (read_config_file() == -1) {
625 + syslog(LOG_ERR, "Warning: Could not read values from config file %s. Using defaults.", CONFIG_FILE);
628 + minQuality = get_config_entry_int("minPoints");
629 + useCracklib = get_config_entry_int("useCracklib");
630 + minUpper = get_config_entry_int("minUpper");
631 + minLower = get_config_entry_int("minLower");
632 + minDigit = get_config_entry_int("minDigit");
633 + minPunct = get_config_entry_int("minPunct");
635 + /** The password must have at least minQuality strength points with one
636 + * point for the first occurrance of a lower, upper, digit and
637 + * punctuation character
640 + for ( i = 0; i < nLen; i++ ) {
642 + if ( islower (pPasswd[i]) ) {
644 + if ( !nLower && (minLower < 1)) {
645 + nLower = 1; nQuality++;
647 + syslog(LOG_DEBUG, "check_password: Found lower character - quality raise %d", nQuality);
653 + if ( isupper (pPasswd[i]) ) {
655 + if ( !nUpper && (minUpper < 1)) {
656 + nUpper = 1; nQuality++;
658 + syslog(LOG_DEBUG, "check_password: Found upper character - quality raise %d", nQuality);
664 + if ( isdigit (pPasswd[i]) ) {
666 + if ( !nDigit && (minDigit < 1)) {
667 + nDigit = 1; nQuality++;
669 + syslog(LOG_DEBUG, "check_password: Found digit character - quality raise %d", nQuality);
675 + if ( ispunct (pPasswd[i]) ) {
677 + if ( !nPunct && (minPunct < 1)) {
678 + nPunct = 1; nQuality++;
680 + syslog(LOG_DEBUG, "check_password: Found punctuation character - quality raise %d", nQuality);
688 + * If you have a required field, then it should be required in the strength
697 + (nQuality < minQuality)
699 + mem_len = realloc_error_message(&szErrStr, mem_len,
700 + strlen(PASSWORD_QUALITY_SZ) +
701 + strlen(pEntry->e_name.bv_val) + 2);
702 + sprintf (szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_name.bv_val,
703 + nQuality, minQuality);
707 +#ifdef HAVE_CRACKLIB
709 + /** Check password with cracklib */
711 + if ( useCracklib > 0 ) {
714 + char filename[FILENAME_MAXLEN];
715 + char const* ext[] = { "hwm", "pwd", "pwi" };
719 + * Silently fail when cracklib wordlist is not found
722 + for ( j = 0; j < 3; j++ ) {
724 + snprintf (filename, FILENAME_MAXLEN - 1, "%s.%s", \
725 + CRACKLIB_DICTPATH, ext[j]);
727 + if (( fp = fopen ( filename, "r")) == NULL ) {
742 + r = (char *) FascistCheck (pPasswd, CRACKLIB_DICTPATH);
744 + mem_len = realloc_error_message(&szErrStr, mem_len,
745 + strlen(BAD_PASSWORD_SZ) +
746 + strlen(pEntry->e_name.bv_val) +
748 + sprintf (szErrStr, BAD_PASSWORD_SZ, pEntry->e_name.bv_val, r);
756 + syslog(LOG_NOTICE, "check_password: Cracklib verification disabled by configuration");
761 + dealloc_config_entries();
762 + *ppErrStr = strdup ("");
763 + ber_memfree(szErrStr);
764 + return (LDAP_SUCCESS);
767 + dealloc_config_entries();
768 + *ppErrStr = strdup (szErrStr);
769 + ber_memfree(szErrStr);
770 + return (EXIT_FAILURE);