Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
openldap
OpenLDAP
Commits
c34d419f
Commit
c34d419f
authored
May 11, 2022
by
David Coutadeur
Browse files
provide ppm v2.2 (
#9846
)
parent
cda12cd4
Pipeline
#4339
passed with stage
in 44 minutes and 51 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/ppm/CHANGELOG.md
View file @
c34d419f
# CHANGELOG
*
2022-05-17 David Coutadeur
<david.coutadeur@gmail.com>
implement a maximum number of characters for each class #18
upgrade documentation for new olcPPolicyCheckModule in OpenLDAP 2.6 #30
Make one unique code of development for 2.5 and 2.6 OpenLDAP versions #35
fix segmentation fault in ppm_test #36
various minor fixes and optimizations
Version 2.2
*
2022-03-22 David Coutadeur
<david.coutadeur@gmail.com>
Reject password if it contains tokens from an attribute of the LDAP entry #17
Version 2.1
...
...
contrib/slapd-modules/ppm/CONTRIBUTIONS.md
View file @
c34d419f
# CONTRIBUTIONS
*
2014 - 202
1
- David Coutadeur
<david.coutadeur@gmail.com>
- maintainer
*
2014 - 202
2
- David Coutadeur
<david.coutadeur@gmail.com>
- maintainer
*
2015 - Daly Chikhaoui - Janua
<dchikhaoui@janua.fr>
- contribution on RDN checks
*
2017 - tdb - Tim Bishop - contribution on some compilation improvements
contrib/slapd-modules/ppm/INSTALL.md
View file @
c34d419f
...
...
@@ -20,7 +20,7 @@ You can optionally customize some variables if you don't want the default ones:
-
etcdir: used to compose default sysconfdir location (defaults to $prefix/etc)
-
sysconfdir: where the ppm example policy is to be deployed (defaults to $prefix/$etcdir/$ldap_subdir)
-
LDAP_SRC: path to OpenLDAP source directory
-
Options in
OPT
S variable:
-
Options in
DEF
S variable:
CONFIG_FILE: (DEPRECATED) path to a ppm configuration file (see PPM_READ_FILE in ppm.h)
note: ppm configuration now lies into pwdCheckModuleArg password policy attribute
provided example file is only helpful as an example or for testing
...
...
@@ -43,7 +43,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 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
...
...
contrib/slapd-modules/ppm/Makefile
View file @
c34d419f
...
...
@@ -65,7 +65,7 @@ MDDOC=ppm.md
all
:
ppm $(TEST)
$(TEST)
:
ppm
$(CC)
$(CFLAGS)
$(OPT)
$(CPPFLAGS)
$(LDFLAGS)
$(INCS)
$(LDAP_LIBS)
-Wl
,-rpath
=
.
-o
$(TEST)
ppm_test.c
$(PROGRAMS)
$(LDAP_LIBS)
$(CRACKLIB)
$(CC)
$(CFLAGS)
$(OPT)
$(CPPFLAGS)
$(DEFS)
$(LDFLAGS)
$(INCS)
-Wl
,-rpath
=
.
-o
$(TEST)
ppm_test.c
$(PROGRAMS)
$(LDAP_LIBS)
$(CRACKLIB)
ppm.o
:
$(CC)
$(CFLAGS)
$(OPT)
$(CPPFLAGS)
$(DEFS)
-c
$(INCS)
ppm.c
...
...
contrib/slapd-modules/ppm/ppm.c
View file @
c34d419f
...
...
@@ -6,10 +6,14 @@
/*
password policy module is called with:
password policy module is called with
(openldap 2.6)
:
int check_password (char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
password policy module is called with (openldap 2.5):
int check_password (char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
*pPasswd: new password
**ppErrStr: pointer to the string containing the error message
*ppErrmsg: pointer to a struct berval containing space for an error message of length bv_len
*e: pointer to the current user entry
*pArg: pointer to a struct berval holding the value of pwdCheckModuleArg attr
...
...
@@ -120,11 +124,13 @@ int maxConsPerClass(char *password, char *charClass)
void
storeEntry
(
char
*
param
,
char
*
value
,
valueType
valType
,
char
*
min
,
char
*
minForPoint
,
conf
*
fileConf
,
int
*
numParam
)
char
*
min
,
char
*
minForPoint
,
char
*
max
,
conf
*
fileConf
,
int
*
numParam
)
{
int
i
=
0
;
int
iMin
;
int
iMinForPoint
;
int
iMax
;
if
(
min
==
NULL
||
strcmp
(
min
,
""
)
==
0
)
iMin
=
0
;
else
...
...
@@ -135,6 +141,11 @@ storeEntry(char *param, char *value, valueType valType,
else
iMinForPoint
=
atoi
(
minForPoint
);
if
(
max
==
NULL
||
strcmp
(
max
,
""
)
==
0
)
iMax
=
0
;
else
iMax
=
atoi
(
max
);
// First scan parameters
for
(
i
=
0
;
i
<
*
numParam
;
i
++
)
{
if
((
strlen
(
param
)
==
strlen
(
fileConf
[
i
].
param
))
...
...
@@ -147,6 +158,7 @@ storeEntry(char *param, char *value, valueType valType,
strcpy_safe
(
fileConf
[
i
].
value
.
sVal
,
value
,
VALUE_MAX_LEN
);
fileConf
[
i
].
min
=
iMin
;
fileConf
[
i
].
minForPoint
=
iMinForPoint
;
fileConf
[
i
].
max
=
iMax
;
if
(
valType
==
typeInt
)
ppm_log
(
LOG_NOTICE
,
"ppm: Accepted replaced value: %d"
,
fileConf
[
i
].
value
.
iVal
);
...
...
@@ -165,6 +177,7 @@ storeEntry(char *param, char *value, valueType valType,
strcpy_safe
(
fileConf
[
i
].
value
.
sVal
,
value
,
VALUE_MAX_LEN
);
fileConf
[
*
numParam
].
min
=
iMin
;
fileConf
[
*
numParam
].
minForPoint
=
iMinForPoint
;
fileConf
[
*
numParam
].
max
=
iMax
;
++
(
*
numParam
);
if
(
valType
==
typeInt
)
ppm_log
(
LOG_NOTICE
,
"ppm: Accepted new value: %d"
,
...
...
@@ -228,7 +241,7 @@ typeParam(char* param)
ppm_log
(
LOG_NOTICE
,
"ppm: get line: %s"
,
token
);
char
*
start
=
token
;
char
*
word
,
*
value
;
char
*
min
,
*
minForPoint
;
;
char
*
min
,
*
minForPoint
,
*
max
;
while
(
isspace
(
*
start
)
&&
isascii
(
*
start
))
start
++
;
...
...
@@ -262,17 +275,21 @@ typeParam(char* param)
if
(
minForPoint
!=
NULL
)
if
(
strchr
(
minForPoint
,
'\n'
)
!=
NULL
)
strchr
(
minForPoint
,
'\n'
)[
0
]
=
'\0'
;
max
=
strtok_r
(
NULL
,
"
\t
"
,
&
saveptr2
);
if
(
max
!=
NULL
)
if
(
strchr
(
max
,
'\n'
)
!=
NULL
)
strchr
(
max
,
'\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
);
"ppm: Param = %s, value = %s, min = %s, minForPoint
= %s, max
= %s"
,
word
,
value
,
min
,
minForPoint
,
max
);
storeEntry
(
word
,
value
,
allowedParameters
[
nParam
].
iType
,
min
,
minForPoint
,
fileConf
,
numParam
);
min
,
minForPoint
,
max
,
fileConf
,
numParam
);
}
else
{
...
...
@@ -310,7 +327,7 @@ typeParam(char* param)
while
(
fgets
(
line
,
256
,
config
)
!=
NULL
)
{
char
*
start
=
line
;
char
*
word
,
*
value
;
char
*
min
,
*
minForPoint
;
;
char
*
min
,
*
minForPoint
,
*
max
;
while
(
isspace
(
*
start
)
&&
isascii
(
*
start
))
start
++
;
...
...
@@ -333,17 +350,21 @@ typeParam(char* param)
if
(
minForPoint
!=
NULL
)
if
(
strchr
(
minForPoint
,
'\n'
)
!=
NULL
)
strchr
(
minForPoint
,
'\n'
)[
0
]
=
'\0'
;
max
=
strtok
(
NULL
,
"
\t
"
);
if
(
max
!=
NULL
)
if
(
strchr
(
max
,
'\n'
)
!=
NULL
)
strchr
(
max
,
'\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
);
"ppm: Param = %s, value = %s, min = %s, minForPoint
= %s, max
= %s"
,
word
,
value
,
min
,
minForPoint
,
max
);
storeEntry
(
word
,
value
,
allowedParameters
[
nParam
].
iType
,
min
,
minForPoint
,
fileConf
,
numParam
);
min
,
minForPoint
,
max
,
fileConf
,
numParam
);
}
else
{
...
...
@@ -360,14 +381,22 @@ typeParam(char* param)
#endif
static
int
#if OLDAP_VERSION == 0x0205
realloc_error_message
(
char
**
target
,
int
curlen
,
int
nextlen
)
#else
realloc_error_message
(
const
char
*
orig
,
char
**
target
,
int
curlen
,
int
nextlen
)
#endif
{
if
(
curlen
<
nextlen
+
MEMORY_MARGIN
)
{
ppm_log
(
LOG_WARNING
,
"ppm: Reallocating szErrStr from %d to %d"
,
curlen
,
nextlen
+
MEMORY_MARGIN
);
#if OLDAP_VERSION == 0x0205
ber_memfree
(
*
target
);
#else
if
(
*
target
!=
orig
)
ber_memfree
(
*
target
);
#endif
curlen
=
nextlen
+
MEMORY_MARGIN
;
*
target
=
(
char
*
)
ber_memalloc
(
curlen
);
}
...
...
@@ -511,14 +540,23 @@ containsAttributes(char* passwd, Entry* pEntry, char* checkAttributes)
int
#if OLDAP_VERSION == 0x0205
check_password
(
char
*
pPasswd
,
char
**
ppErrStr
,
Entry
*
e
,
void
*
pArg
)
#else
check_password
(
char
*
pPasswd
,
struct
berval
*
ppErrmsg
,
Entry
*
e
,
void
*
pArg
)
#endif
{
Entry
*
pEntry
=
e
;
struct
berval
*
pwdCheckModuleArg
=
pArg
;
#if OLDAP_VERSION == 0x0205
char
*
szErrStr
=
(
char
*
)
ber_memalloc
(
MEM_INIT_SZ
);
int
mem_len
=
MEM_INIT_SZ
;
#else
char
*
origmsg
=
ppErrmsg
->
bv_val
;
char
*
szErrStr
=
origmsg
;
int
mem_len
=
ppErrmsg
->
bv_len
;
#endif
int
numParam
=
0
;
// Number of params in current configuration
int
useCracklib
;
...
...
@@ -554,7 +592,11 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
#else
if
(
!
pwdCheckModuleArg
||
!
pwdCheckModuleArg
->
bv_val
)
{
ppm_log
(
LOG_ERR
,
"ppm: No config provided in pwdCheckModuleArg"
);
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
GENERIC_ERROR
));
sprintf
(
szErrStr
,
GENERIC_ERROR
);
goto
fail
;
...
...
@@ -564,43 +606,40 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
ppm_log
(
LOG_NOTICE
,
"ppm: RAW configuration: %s"
,
pwdCheckModuleArg
->
bv_val
);
#endif
for
(
i
=
0
;
i
<
CONF_MAX_SIZE
;
i
++
)
nbInClass
[
i
]
=
0
;
/* Set default values */
conf
fileConf
[
CONF_MAX_SIZE
]
=
{
{
"minQuality"
,
typeInt
,
{.
iVal
=
DEFAULT_QUALITY
},
0
,
0
{
"minQuality"
,
typeInt
,
{.
iVal
=
DEFAULT_QUALITY
},
0
,
0
,
0
}
,
{
"checkRDN"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
{
"checkRDN"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
,
0
}
,
{
"forbiddenChars"
,
typeStr
,
{.
sVal
=
""
},
0
,
0
{
"forbiddenChars"
,
typeStr
,
{.
sVal
=
""
},
0
,
0
,
0
}
,
{
"maxConsecutivePerClass"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
{
"maxConsecutivePerClass"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
,
0
}
,
{
"useCracklib"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
{
"useCracklib"
,
typeInt
,
{.
iVal
=
0
},
0
,
0
,
0
}
,
{
"cracklibDict"
,
typeStr
,
{.
sVal
=
"/var/cache/cracklib/cracklib_dict"
},
0
,
0
{
"cracklibDict"
,
typeStr
,
{.
sVal
=
"/var/cache/cracklib/cracklib_dict"
},
0
,
0
,
0
}
,
{
"class-upperCase"
,
typeStr
,
{.
sVal
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
},
0
,
1
{
"class-upperCase"
,
typeStr
,
{.
sVal
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
},
0
,
1
,
0
}
,
{
"class-lowerCase"
,
typeStr
,
{.
sVal
=
"abcdefghijklmnopqrstuvwxyz"
},
0
,
1
{
"class-lowerCase"
,
typeStr
,
{.
sVal
=
"abcdefghijklmnopqrstuvwxyz"
},
0
,
1
,
0
}
,
{
"class-digit"
,
typeStr
,
{.
sVal
=
"0123456789"
},
0
,
1
{
"class-digit"
,
typeStr
,
{.
sVal
=
"0123456789"
},
0
,
1
,
0
}
,
{
"class-special"
,
typeStr
,
{.
sVal
=
"<>,?;.:/!§ù%*µ^¨$£²&é~
\"
#'{([-|è`_
\\
ç^à@)]°=}+"
},
0
,
1
{.
sVal
=
"<>,?;.:/!§ù%*µ^¨$£²&é~
\"
#'{([-|è`_
\\
ç^à@)]°=}+"
},
0
,
1
,
0
}
,
{
"checkAttributes"
,
typeStr
,
{.
sVal
=
""
},
0
,
0
{
"checkAttributes"
,
typeStr
,
{.
sVal
=
""
},
0
,
0
,
0
}
};
numParam
=
11
;
...
...
@@ -627,10 +666,14 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
getValue
(
fileConf
,
numParam
,
"checkAttributes"
)
->
sVal
,
VALUE_MAX_LEN
);
for
(
i
=
0
;
i
<
numParam
;
i
++
)
nbInClass
[
i
]
=
0
;
/*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 contains at most max chars of each class
* It must not contain any char in forbiddenChar */
for
(
i
=
0
;
i
<
strlen
(
pPasswd
);
i
++
)
{
...
...
@@ -649,7 +692,7 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
}
// Password checking done, now loocking for minForPoint criteria
for
(
i
=
0
;
i
<
CONF_MAX_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
numParam
;
i
++
)
{
if
(
strstr
(
fileConf
[
i
].
param
,
"class-"
)
!=
NULL
)
{
if
((
nbInClass
[
i
]
>=
fileConf
[
i
].
minForPoint
)
&&
strlen
(
fileConf
[
i
].
value
.
sVal
)
!=
0
)
{
...
...
@@ -662,33 +705,68 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
}
if
(
nQuality
<
minQuality
)
{
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
PASSWORD_QUALITY_SZ
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
)
+
4
);
sprintf
(
szErrStr
,
PASSWORD_QUALITY_SZ
,
pEntry
->
e_nname
.
bv_val
,
nQuality
,
minQuality
);
goto
fail
;
}
// Password checking done, now loocking for constraintClass criteria
for
(
i
=
0
;
i
<
CONF_MAX_SIZE
;
i
++
)
{
// Password checking done, now loocking for minimum criteria
for
(
i
=
0
;
i
<
numParam
;
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
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
strlen
(
PASSWORD_CRITERIA
)
+
#endif
strlen
(
PASSWORD_MIN_CRITERIA
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
)
+
2
+
PARAM_MAX_LEN
);
sprintf
(
szErrStr
,
PASSWORD_CRITERIA
,
pEntry
->
e_nname
.
bv_val
,
sprintf
(
szErrStr
,
PASSWORD_
MIN_
CRITERIA
,
pEntry
->
e_nname
.
bv_val
,
fileConf
[
i
].
min
,
fileConf
[
i
].
param
);
goto
fail
;
}
}
}
// Password checking done, now loocking for maximum criteria
for
(
i
=
0
;
i
<
numParam
;
i
++
)
{
if
(
strstr
(
fileConf
[
i
].
param
,
"class-"
)
!=
NULL
)
{
if
(
(
fileConf
[
i
].
max
!=
0
)
&&
(
nbInClass
[
i
]
>
fileConf
[
i
].
max
)
&&
strlen
(
fileConf
[
i
].
value
.
sVal
)
!=
0
)
{
// constraint is not satisfied... goto fail
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
PASSWORD_MAX_CRITERIA
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
)
+
2
+
PARAM_MAX_LEN
);
sprintf
(
szErrStr
,
PASSWORD_MAX_CRITERIA
,
pEntry
->
e_nname
.
bv_val
,
fileConf
[
i
].
max
,
fileConf
[
i
].
param
);
goto
fail
;
}
}
}
// Password checking done, now loocking for forbiddenChars criteria
if
(
nForbiddenChars
>
0
)
{
// at least 1 forbidden char... goto fail
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
PASSWORD_FORBIDDENCHARS
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
)
+
2
+
VALUE_MAX_LEN
);
...
...
@@ -698,7 +776,7 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
}
// Password checking done, now loocking for maxConsecutivePerClass criteria
for
(
i
=
0
;
i
<
CONF_MAX_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
numParam
;
i
++
)
{
if
(
strstr
(
fileConf
[
i
].
param
,
"class-"
)
!=
NULL
)
{
if
(
maxConsecutivePerClass
!=
0
&&
(
maxConsPerClass
(
pPasswd
,
fileConf
[
i
].
value
.
sVal
)
...
...
@@ -706,7 +784,11 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
// Too much consecutive characters of the same class
ppm_log
(
LOG_NOTICE
,
"ppm: Too much consecutive chars for class %s"
,
fileConf
[
i
].
param
);
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
PASSWORD_MAXCONSECUTIVEPERCLASS
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
)
+
2
+
PARAM_MAX_LEN
);
...
...
@@ -726,7 +808,11 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
if
((
fd
=
fopen
(
cracklibDictFiles
[
j
],
"r"
))
==
NULL
)
{
ppm_log
(
LOG_NOTICE
,
"ppm: Error while reading %s file"
,
cracklibDictFiles
[
j
]);
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
GENERIC_ERROR
));
sprintf
(
szErrStr
,
GENERIC_ERROR
);
goto
fail
;
...
...
@@ -740,7 +826,11 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
if
(
res
!=
NULL
)
{
ppm_log
(
LOG_NOTICE
,
"ppm: cracklib does not validate password for entry %s"
,
pEntry
->
e_nname
.
bv_val
);
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
PASSWORD_CRACKLIB
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
));
sprintf
(
szErrStr
,
PASSWORD_CRACKLIB
,
pEntry
->
e_nname
.
bv_val
);
...
...
@@ -755,7 +845,11 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
if
(
checkRDN
==
1
&&
containsRDN
(
pPasswd
,
pEntry
->
e_nname
.
bv_val
))
// RDN check enabled and a token from RDN is found in password: goto fail
{
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
RDN_TOKEN_FOUND
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
));
sprintf
(
szErrStr
,
RDN_TOKEN_FOUND
,
pEntry
->
e_nname
.
bv_val
);
...
...
@@ -764,10 +858,15 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
}
// Password checking done, now looking for checkAttributes criteria
if
(
containsAttributes
(
pPasswd
,
pEntry
,
checkAttributes
))
if
(
strcmp
(
checkAttributes
,
""
)
!=
0
&&
containsAttributes
(
pPasswd
,
pEntry
,
checkAttributes
))
// A token from an attribute is found in password: goto fail
{
#if OLDAP_VERSION == 0x0205
mem_len
=
realloc_error_message
(
&
szErrStr
,
mem_len
,
#else
mem_len
=
realloc_error_message
(
origmsg
,
&
szErrStr
,
mem_len
,
#endif
strlen
(
ATTR_TOKEN_FOUND
)
+
strlen
(
pEntry
->
e_nname
.
bv_val
));
sprintf
(
szErrStr
,
ATTR_TOKEN_FOUND
,
pEntry
->
e_nname
.
bv_val
);
...
...
@@ -775,12 +874,22 @@ check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
goto
fail
;
}
#if OLDAP_VERSION == 0x0205
*
ppErrStr
=
strdup
(
""
);
ber_memfree
(
szErrStr
);
#else
szErrStr
[
0
]
=
'\0'
;
#endif
return
(
LDAP_SUCCESS
);
fail:
#if OLDAP_VERSION == 0x0205
*
ppErrStr
=
strdup
(
szErrStr
);
ber_memfree
(
szErrStr
);
#else
ppErrmsg
->
bv_val
=
szErrStr
;
ppErrmsg
->
bv_len
=
mem_len
;
#endif
return
(
EXIT_FAILURE
);
}
contrib/slapd-modules/ppm/ppm.example
View file @
c34d419f
...
...
@@ -15,7 +15,7 @@
# cn: default
# pwdMinLength: 6
# pwdCheckModule: /usr/local/lib/ppm.so
# pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKY2hlY2tBdHRyaWJ1dGVzCmZvcmJpZGRlbkNoYXJzCm1heENvbnNlY3V0aXZlUGVyQ2xhc3MgMAp1c2VDcmFja2xpYiAwCmNyYWNrbGliRGljdCAvdmFyL2NhY2hlL2NyYWNrbGliL2NyYWNrbGliX2RpY3QKY2xhc3MtdXBwZXJDYXNlIEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaIDAgM
QpjbGFzcy1sb3dlckNhc2UgYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogMCAxCmNsYXNzLWRpZ2l0IDAxMjM0NTY3ODkgMCAx
CmNsYXNzLXNwZWNpYWwgPD4sPzsuOi8hwqfDuSUqwrVewqgkwqPCsibDqX4iIyd7KFstfMOoYF9cw6dew6BAKV3CsD19KyAwIDE
K
# pwdCheckModuleArg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKY2hlY2tBdHRyaWJ1dGVzCmZvcmJpZGRlbkNoYXJzCm1heENvbnNlY3V0aXZlUGVyQ2xhc3MgMAp1c2VDcmFja2xpYiAwCmNyYWNrbGliRGljdCAvdmFyL2NhY2hlL2NyYWNrbGliL2NyYWNrbGliX2RpY3QKY2xhc3MtdXBwZXJDYXNlIEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaIDAgM
SAwCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEgMApjbGFzcy1kaWdpdCAwMTIzNDU2Nzg5IDAgMSAw
CmNsYXNzLXNwZWNpYWwgPD4sPzsuOi8hwqfDuSUqwrVewqgkwqPCsibDqX4iIyd7KFstfMOoYF9cw6dew6BAKV3CsD19KyAwIDE
gMAo=
#
# Different parameters are separated by a linefeed (\n)
# Parameters starting with a # are ignored
...
...
@@ -90,7 +90,8 @@ cracklibDict /var/cache/cracklib/cracklib_dict
# [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
# [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 <>,?;.:/!§ù%*µ^¨$£²&é~"#'{([-|è`_\ç^à@)]°=}+ 0 1 0
contrib/slapd-modules/ppm/ppm.h
View file @
c34d419f
...
...
@@ -18,6 +18,11 @@
#include
<syslog.h>
#endif
// Get OpenLDAP version
#define OLDAP_VERSION ((LDAP_VENDOR_VERSION_MAJOR << 8) | LDAP_VENDOR_VERSION_MINOR)
// OLDAP_VERSION = 0x0205 // (v2.5)
// OLDAP_VERSION = 0x0206 // (v2.6)
//#define PPM_READ_FILE 1 // old deprecated configuration mode
// 1: (deprecated) don't read pwdCheckModuleArg
// attribute, instead read config file
...
...
@@ -31,6 +36,9 @@
#define DEFAULT_QUALITY 3
#define MEMORY_MARGIN 50
#if OLDAP_VERSION == 0x0205
#define MEM_INIT_SZ 64
#endif
#define DN_MAX_LEN 512
#define CONF_MAX_SIZE 50
...
...
@@ -47,8 +55,10 @@
#define PASSWORD_QUALITY_SZ \
"Password for dn=\"%s\" does not pass required number of strength checks (%d of %d)"
#define PASSWORD_CRITERIA \
#define PASSWORD_
MIN_
CRITERIA \
"Password for dn=\"%s\" has not reached the minimum number of characters (%d) for class %s"
#define PASSWORD_MAX_CRITERIA \
"Password for dn=\"%s\" has reached the maximum 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 \
...
...
@@ -104,6 +114,7 @@ typedef struct conf {
genValue
value
;
int
min
;
int
minForPoint
;
int
max
;
}
conf
;
void
ppm_log
(
int
priority
,
const
char
*
format
,
...);
...
...
@@ -114,10 +125,16 @@ int min(char *str1, char *str2);
#ifdef PPM_READ_FILE
static
void
read_config_file
(
conf
*
fileConf
,
int
*
numParam
,
char
*
ppm_config_file
);
#endif
int
check_password
(
char
*
pPasswd
,
struct
berval
*
ppErrmsg
,
Entry
*
e
,
void
*
pArg
);
#if OLDAP_VERSION == 0x0205
int
check_password
(
char
*
pPasswd
,
char
**
ppErrStr
,
Entry
*
e
,
void
*
pArg
);
#else
int
check_password
(
char
*
pPasswd
,
struct
berval
*
ppErrmsg
,
Entry
*
e
,
void
*
pArg
);
#endif
int
maxConsPerClass
(
char
*
password
,
char
*
charClass
);
void
storeEntry
(
char
*
param
,
char
*
value
,
valueType
valType
,
char
*
min
,
char
*
minForPoint
,
conf
*
fileConf
,
int
*
numParam
);
char
*
min
,
char
*
minForPoint
,
char
*
max
,
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
);
...
...
contrib/slapd-modules/ppm/ppm.md
View file @
c34d419f
...
...
@@ -28,7 +28,9 @@ see slapo-ppolicy(5) section **pwdCheckModule**.
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:
**pwdCheckModuleArg**
.
Here is an example for OpenLDAP 2.6:
```
dn: cn=default,ou=policies,dc=my-domain,dc=com
...
...
@@ -41,26 +43,35 @@ pwdAttribute: userPassword
sn: default
cn: default
pwdMinLength: 6
pwdCheckModule
: /usr/local/lib/ppm.so
pwdCheckModule
Arg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKY2hlY2tBdHRyaWJ1dGVzCmZvcmJpZGRlbkNoYXJzCm1heENvbnNlY3V0aXZlUGVyQ2xhc3MgMAp1c2VDcmFja2xpYiAwCmNyYWNrbGliRGljdCAvdmFyL2NhY2hlL2NyYWNrbGliL2NyYWNrbGliX2RpY3QKY2xhc3MtdXBwZXJDYXNlIEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaIDAgMQpjbGFzcy1sb3dlckNhc2UgYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogMCAxCmNsYXNzLWRpZ2l0IDAxMjM0NTY3ODkgMCAxCmNsYXNzLXNwZWNpYWwgPD4sPzsuOi8hwqfDuSUqwrVewqgkwqPCsibDqX4iIyd7KFstfMOoYF9cw6dew6BAKV3CsD19KyAwIDEK
pwdCheckModule
Arg:: bWluUXVhbGl0eSAzCmNoZWNrUkROIDAKY2hlY2tBdHRyaWJ1dGVzCmZvcmJpZGRlbkNoYXJzCm1heENvbnNlY3V0aXZlUGVyQ2xhc3MgMAp1c2VDcmFja2xpYiAwCmNyYWNrbGliRGljdCAvdmFyL2NhY2hlL2NyYWNrbGliL2NyYWNrbGliX2RpY3QKY2xhc3MtdXBwZXJDYXNlIEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaIDAgMSAwCmNsYXNzLWxvd2VyQ2FzZSBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiAwIDEgMApjbGFzcy1kaWdpdCAwMTIzNDU2Nzg5IDAgMSAwCmNsYXNzLXNwZWNpYWwgPD4sPzsuOi8hwqfDuSUqwrVewqgkwqPCsibDqX4iIyd7KFstfMOoYF9cw6dew6BAKV3CsD19KyAwIDEgMAoK
pwd
Use
CheckModule
: TRUE
```
For OpenLDAP 2.5, you must add a
**pwdCheckModule**
attribute pointing
to the ppm module (for example /usr/local/lib/ppm.so),
and remove the
**pwdUseCheckModule**
attribute.
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
This example show the activation for a
**slapd.conf**
file
for OpenLDAP 2.6
(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_check_module /usr/local/openldap/libexec/openldap/ppm.so
#ppolicy_use_lockout # for having more infos about the lockout
```
For OpenLDAP 2.5, you must remove
**ppolicy_check_module**
parameter as
it is managed in the password policy definition
# FEATURES
...
...
@@ -78,7 +89,10 @@ 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
-
passwords must have at the most x occurrences of characters from the
corresponding character class, else they are rejected.