mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-24 13:24:56 +08:00
ITS#9615 move CheckModule from policy to overlay config
And fix errmsg FIXME
This commit is contained in:
parent
8311c71f3d
commit
e700dc03ee
@ -7,10 +7,10 @@
|
||||
|
||||
/*
|
||||
password policy module is called with:
|
||||
int check_password (char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
int check_password (char *pPasswd, struct berval *ppErrmsg, 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
|
||||
*/
|
||||
@ -360,13 +360,14 @@ typeParam(char* param)
|
||||
#endif
|
||||
|
||||
static int
|
||||
realloc_error_message(char **target, int curlen, int nextlen)
|
||||
realloc_error_message(const char *orig, 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);
|
||||
if (*target != orig)
|
||||
ber_memfree(*target);
|
||||
curlen = nextlen + MEMORY_MARGIN;
|
||||
*target = (char *) ber_memalloc(curlen);
|
||||
}
|
||||
@ -428,7 +429,7 @@ containsRDN(char* passwd, char* DN)
|
||||
|
||||
|
||||
int
|
||||
check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg)
|
||||
{
|
||||
|
||||
Entry *pEntry = e;
|
||||
@ -445,8 +446,9 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
(*(struct berval*)pwdCheckModuleArg).bv_val);
|
||||
#endif
|
||||
|
||||
char *szErrStr = (char *) ber_memalloc(MEM_INIT_SZ);
|
||||
int mem_len = MEM_INIT_SZ;
|
||||
char *origmsg = ppErrmsg->bv_val;
|
||||
char *szErrStr = origmsg;
|
||||
int mem_len = ppErrmsg->bv_len;
|
||||
int numParam = 0; // Number of params in current configuration
|
||||
|
||||
int useCracklib;
|
||||
@ -566,7 +568,7 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
}
|
||||
|
||||
if (nQuality < minQuality) {
|
||||
mem_len = realloc_error_message(&szErrStr, mem_len,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(PASSWORD_QUALITY_SZ) +
|
||||
strlen(pEntry->e_nname.bv_val) + 4);
|
||||
sprintf(szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_nname.bv_val,
|
||||
@ -579,7 +581,7 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
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,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(PASSWORD_CRITERIA) +
|
||||
strlen(pEntry->e_nname.bv_val) +
|
||||
2 + PARAM_MAX_LEN);
|
||||
@ -592,7 +594,7 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
|
||||
// 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,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(PASSWORD_FORBIDDENCHARS) +
|
||||
strlen(pEntry->e_nname.bv_val) + 2 +
|
||||
VALUE_MAX_LEN);
|
||||
@ -610,7 +612,7 @@ check_password(char *pPasswd, char **ppErrStr, 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);
|
||||
mem_len = realloc_error_message(&szErrStr, mem_len,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(PASSWORD_MAXCONSECUTIVEPERCLASS) +
|
||||
strlen(pEntry->e_nname.bv_val) + 2 +
|
||||
PARAM_MAX_LEN);
|
||||
@ -630,7 +632,7 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
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,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(GENERIC_ERROR));
|
||||
sprintf(szErrStr, GENERIC_ERROR);
|
||||
goto fail;
|
||||
@ -644,7 +646,7 @@ check_password(char *pPasswd, char **ppErrStr, 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);
|
||||
mem_len = realloc_error_message(&szErrStr, mem_len,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(PASSWORD_CRACKLIB) +
|
||||
strlen(pEntry->e_nname.bv_val));
|
||||
sprintf(szErrStr, PASSWORD_CRACKLIB, pEntry->e_nname.bv_val);
|
||||
@ -659,7 +661,7 @@ check_password(char *pPasswd, char **ppErrStr, 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
|
||||
{
|
||||
mem_len = realloc_error_message(&szErrStr, mem_len,
|
||||
mem_len = realloc_error_message(origmsg, &szErrStr, mem_len,
|
||||
strlen(RDN_TOKEN_FOUND) +
|
||||
strlen(pEntry->e_nname.bv_val));
|
||||
sprintf(szErrStr, RDN_TOKEN_FOUND, pEntry->e_nname.bv_val);
|
||||
@ -667,13 +669,12 @@ check_password(char *pPasswd, char **ppErrStr, Entry *e, void *pArg)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*ppErrStr = strdup("");
|
||||
ber_memfree(szErrStr);
|
||||
szErrStr[0] = '\0';
|
||||
return (LDAP_SUCCESS);
|
||||
|
||||
fail:
|
||||
*ppErrStr = strdup(szErrStr);
|
||||
ber_memfree(szErrStr);
|
||||
ppErrmsg->bv_val = szErrStr;
|
||||
ppErrmsg->bv_len = mem_len;
|
||||
return (EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#define DEFAULT_QUALITY 3
|
||||
#define MEMORY_MARGIN 50
|
||||
#define MEM_INIT_SZ 64
|
||||
#define DN_MAX_LEN 512
|
||||
|
||||
#define CONF_MAX_SIZE 50
|
||||
@ -111,7 +110,7 @@ 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, char **ppErrStr, Entry *e, void *pArg);
|
||||
int check_password(char *pPasswd, struct berval *ppErrmsg, Entry *e, void *pArg);
|
||||
int maxConsPerClass(char *password, char *charClass);
|
||||
void storeEntry(char *param, char *value, valueType valType,
|
||||
char *min, char *minForPoint, conf * fileConf, int *numParam);
|
||||
|
@ -19,7 +19,8 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
/* format user entry */
|
||||
char *errmsg = NULL;
|
||||
char errbuf[256];
|
||||
struct berval errmsg = { sizeof(errbuf)-1, errbuf };
|
||||
Entry pEntry;
|
||||
pEntry.e_nname.bv_val=argv[1];
|
||||
pEntry.e_name.bv_val=argv[1];
|
||||
@ -51,10 +52,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Password failed checks : %s\n", errmsg);
|
||||
printf("Password failed checks : %s\n", errmsg.bv_val);
|
||||
}
|
||||
|
||||
ber_memfree(errmsg);
|
||||
if (errmsg.bv_val != errbuf)
|
||||
ber_memfree(errmsg.bv_val);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -100,6 +100,24 @@ If set, ppolicy will send the password policy expired (2.16.840.1.113730.3.4.4)
|
||||
and password policy expiring (2.16.840.1.113730.3.4.5) controls when
|
||||
appropriate. The controls are not sent for bind requests where the Password
|
||||
policy control has already been requested. Default is not to send the controls.
|
||||
.TP
|
||||
.B ppolicy_check_module <path>
|
||||
Specify the path of a loadable module containing a
|
||||
.B check_password()
|
||||
function for additional password quality checks. The use of this module
|
||||
is described further below in the description of the
|
||||
.B pwdPolicyChecker
|
||||
objectclass.
|
||||
|
||||
Note: The user-defined loadable module must be in
|
||||
.B slapd's
|
||||
standard executable search PATH, or an absolute path must be provided.
|
||||
|
||||
Note: Use of a
|
||||
.B ppolicy_check_module
|
||||
is a non-standard extension to the LDAP password
|
||||
policy proposal.
|
||||
|
||||
|
||||
.SH OBJECT CLASS
|
||||
The
|
||||
@ -145,7 +163,7 @@ objectclass, used for password quality checking (see below).
|
||||
NAME 'pwdPolicyChecker'
|
||||
AUXILIARY
|
||||
SUP top
|
||||
MAY ( pwdCheckModule $ pwdCheckModuleArg ) )
|
||||
MAY ( pwdCheckModule $ pwdCheckModuleArg $ pwdUseCheckModule ) )
|
||||
.RE
|
||||
.P
|
||||
Every account that should be subject to password policy control should
|
||||
@ -279,8 +297,9 @@ without checking it (if
|
||||
is zero (0) or one (1)) or refuse it (if
|
||||
.B pwdCheckQuality
|
||||
is two (2)). If the number of characters should be enforced with regards
|
||||
to a particular encoding, the use of an appropriate pwdCheckModule is
|
||||
required.
|
||||
to a particular encoding, the use of an appropriate
|
||||
.B ppolicy_check_module
|
||||
is required.
|
||||
.LP
|
||||
.RS 4
|
||||
( 1.3.6.1.4.1.42.2.27.8.1.6
|
||||
@ -309,8 +328,9 @@ without checking it (if
|
||||
is zero (0) or one (1)) or refuse it (if
|
||||
.B pwdCheckQuality
|
||||
is two (2)). If the number of characters should be enforced with regards
|
||||
to a particular encoding, the use of an appropriate pwdCheckModule is
|
||||
required.
|
||||
to a particular encoding, the use of an appropriate
|
||||
.B ppolicy_check_module
|
||||
is required.
|
||||
.LP
|
||||
.RS 4
|
||||
( 1.3.6.1.4.1.42.2.27.8.1.31
|
||||
@ -622,9 +642,13 @@ is set to
|
||||
SINGLE\-VALUE )
|
||||
.RE
|
||||
|
||||
.BR pwdCheckModule / pwdCheckModuleArg
|
||||
.BR pwdUseCheckModule / pwdCheckModuleArg
|
||||
.P
|
||||
This attribute names a user-defined loadable module that must
|
||||
The
|
||||
.B pwdUseCheckModule
|
||||
attribute enables use of a loadable module previously configured with
|
||||
.B ppolicy_check_module
|
||||
for the current policy. The module must
|
||||
instantiate the check_password() function. This function
|
||||
will be called to further check a new password if
|
||||
.B pwdCheckQuality
|
||||
@ -635,14 +659,22 @@ function prototype:
|
||||
.RS 4
|
||||
int
|
||||
.I check_password
|
||||
(char *pPasswd, char **ppErrStr, Entry *pEntry, struct berval *pArg);
|
||||
(char *pPasswd, struct berval *pErrmsg, Entry *pEntry, struct berval *pArg);
|
||||
.RE
|
||||
The
|
||||
.B pPasswd
|
||||
parameter contains the clear-text user password, the
|
||||
.B ppErrStr
|
||||
parameter contains a double pointer that allows the function
|
||||
.B pErrmsg
|
||||
parameter points to a
|
||||
.B struct berval
|
||||
containing space
|
||||
to return human-readable details about any error it encounters.
|
||||
The
|
||||
.B bv_len
|
||||
field must contain the size of the space provided
|
||||
by the
|
||||
.B bv_val
|
||||
field.
|
||||
|
||||
The
|
||||
.B pEntry
|
||||
@ -658,24 +690,31 @@ containing the value of
|
||||
in the effective password policy, if set, otherwise NULL.
|
||||
|
||||
If
|
||||
.B ppErrStr
|
||||
.B pErrmsg
|
||||
is NULL, then
|
||||
.I funcName
|
||||
must NOT attempt to use it/them.
|
||||
must NOT attempt to use it.
|
||||
A return value of LDAP_SUCCESS from the called
|
||||
function indicates that the password is ok, any other value
|
||||
indicates that the password is unacceptable. If the password is
|
||||
unacceptable, the server will return an error to the client, and
|
||||
.B ppErrStr
|
||||
.B pErrmsg
|
||||
may be used to return a human-readable textual explanation of the
|
||||
error. The error string must be dynamically allocated as it will
|
||||
error. If the space passed in by the caller is too small, the function
|
||||
may replace it with a dynamically allocated buffer, which will
|
||||
be free()'d by slapd.
|
||||
|
||||
The
|
||||
.B pwdCheckModule
|
||||
attribute is now obsolete and is ignored.
|
||||
|
||||
.LP
|
||||
.RS 4
|
||||
( 1.3.6.1.4.1.4754.1.99.1
|
||||
NAME 'pwdCheckModule'
|
||||
EQUALITY caseExactIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||
OBSOLETE
|
||||
SINGLE\-VALUE )
|
||||
|
||||
( 1.3.6.1.4.1.4754.1.99.2
|
||||
@ -684,19 +723,13 @@ be free()'d by slapd.
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
|
||||
DESC 'Argument to pass to check_password() function'
|
||||
SINGLE\-VALUE )
|
||||
|
||||
( 1.3.6.1.4.1.4754.1.99.3
|
||||
NAME 'pwdUseCheckModule'
|
||||
EQUALITY booleanMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
|
||||
SINGLE\-VALUE )
|
||||
.RE
|
||||
.P
|
||||
Note:
|
||||
The user-defined loadable module named by
|
||||
.B pwdCheckModule
|
||||
must be in
|
||||
.B slapd's
|
||||
standard executable search PATH.
|
||||
.P
|
||||
Note:
|
||||
.B pwdCheckModule
|
||||
is a non-standard extension to the LDAP password
|
||||
policy proposal.
|
||||
|
||||
.SH OPERATIONAL ATTRIBUTES
|
||||
.P
|
||||
|
@ -41,14 +41,18 @@
|
||||
#include <ac/ctype.h>
|
||||
#include "slap-config.h"
|
||||
|
||||
#ifndef MODULE_NAME_SZ
|
||||
#define MODULE_NAME_SZ 256
|
||||
#endif
|
||||
|
||||
#ifndef PPOLICY_DEFAULT_MAXRECORDED_FAILURE
|
||||
#define PPOLICY_DEFAULT_MAXRECORDED_FAILURE 5
|
||||
#endif
|
||||
|
||||
/* External password quality checking function.
|
||||
* The error message must have a preallocated buffer and size
|
||||
* passed in. Module can still allocate a buffer for
|
||||
* it if the provided one is too small.
|
||||
*/
|
||||
typedef int (check_func)( char *passwd, struct berval *errmsg, Entry *ent, struct berval *arg );
|
||||
#define ERRBUFSIZ 256
|
||||
|
||||
/* Per-instance configuration information */
|
||||
typedef struct pp_info {
|
||||
struct berval def_policy; /* DN of default policy subentry */
|
||||
@ -57,6 +61,10 @@ typedef struct pp_info {
|
||||
int forward_updates; /* use frontend for policy state updates */
|
||||
int disable_write;
|
||||
int send_netscape_controls; /* send netscape password controls */
|
||||
char *pwdCheckModule; /* name of module to dynamically
|
||||
load to check password */
|
||||
lt_dlhandle pwdCheckHandle; /* handle from lt_dlopen */
|
||||
check_func *pwdCheckFunc;
|
||||
ldap_pvt_thread_mutex_t pwdFailureTime_mutex;
|
||||
} pp_info;
|
||||
|
||||
@ -104,8 +112,7 @@ typedef struct pass_policy {
|
||||
int pwdSafeModify; /* 0 = old password doesn't need to come
|
||||
with password change request
|
||||
1 = password change must supply existing pwd */
|
||||
char pwdCheckModule[MODULE_NAME_SZ]; /* name of module to dynamically
|
||||
load to check password */
|
||||
int pwdUseCheckModule; /* 0 = do not use password check module, 1 = use */
|
||||
struct berval pwdCheckModuleArg; /* Optional argument to the password check
|
||||
module */
|
||||
} PassPolicy;
|
||||
@ -129,7 +136,7 @@ static AttributeDescription *ad_pwdMinAge, *ad_pwdMaxAge, *ad_pwdMaxIdle,
|
||||
*ad_pwdMaxFailure, *ad_pwdGraceExpiry, *ad_pwdGraceAuthNLimit,
|
||||
*ad_pwdExpireWarning, *ad_pwdMinDelay, *ad_pwdMaxDelay,
|
||||
*ad_pwdLockoutDuration, *ad_pwdFailureCountInterval,
|
||||
*ad_pwdCheckModule, *ad_pwdCheckModuleArg, *ad_pwdLockout,
|
||||
*ad_pwdCheckModule, *ad_pwdCheckModuleArg, *ad_pwdUseCheckModule, *ad_pwdLockout,
|
||||
*ad_pwdMustChange, *ad_pwdAllowUserChange, *ad_pwdSafeModify,
|
||||
*ad_pwdAttribute, *ad_pwdMaxRecordedFailure;
|
||||
|
||||
@ -382,7 +389,8 @@ static struct schema_info {
|
||||
"NAME ( 'pwdCheckModule' ) "
|
||||
"EQUALITY caseExactIA5Match "
|
||||
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 "
|
||||
"DESC 'Loadable module that instantiates check_password() function' "
|
||||
"DESC 'Obsolete, no longer used' "
|
||||
"OBSOLETE "
|
||||
"SINGLE-VALUE )",
|
||||
&ad_pwdCheckModule },
|
||||
{ "( 1.3.6.1.4.1.4754.1.99.2 "
|
||||
@ -392,6 +400,13 @@ static struct schema_info {
|
||||
"DESC 'Argument to pass to check_password() function' "
|
||||
"SINGLE-VALUE )",
|
||||
&ad_pwdCheckModuleArg },
|
||||
{ "( 1.3.6.1.4.1.4754.1.99.3 "
|
||||
"NAME ( 'pwdUseCheckModule' ) "
|
||||
"EQUALITY booleanMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
|
||||
"DESC 'Toggle use of the loaded pwdCheckModule' "
|
||||
"SINGLE-VALUE )",
|
||||
&ad_pwdUseCheckModule },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -401,7 +416,7 @@ static char *pwd_ocs[] = {
|
||||
"NAME 'pwdPolicyChecker' "
|
||||
"SUP top "
|
||||
"AUXILIARY "
|
||||
"MAY ( pwdCheckModule $ pwdCheckModuleArg ) )" ,
|
||||
"MAY ( pwdCheckModule $ pwdCheckModuleArg $ pwdUseCheckModule ) )" ,
|
||||
"( 1.3.6.1.4.1.42.2.27.8.2.1 "
|
||||
"NAME 'pwdPolicy' "
|
||||
"SUP top "
|
||||
@ -424,9 +439,10 @@ enum {
|
||||
PPOLICY_HASH_CLEARTEXT,
|
||||
PPOLICY_USE_LOCKOUT,
|
||||
PPOLICY_DISABLE_WRITE,
|
||||
PPOLICY_CHECK_MODULE,
|
||||
};
|
||||
|
||||
static ConfigDriver ppolicy_cf_default;
|
||||
static ConfigDriver ppolicy_cf_default, ppolicy_cf_checkmod;
|
||||
|
||||
static ConfigTable ppolicycfg[] = {
|
||||
{ "ppolicy_default", "policyDN", 2, 2, 0,
|
||||
@ -470,6 +486,13 @@ static ConfigTable ppolicycfg[] = {
|
||||
"DESC 'Send Netscape policy controls' "
|
||||
"EQUALITY booleanMatch "
|
||||
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
|
||||
{ "ppolicy_check_module", "path", 2, 2, 0,
|
||||
ARG_STRING|ARG_MAGIC|PPOLICY_CHECK_MODULE, ppolicy_cf_checkmod,
|
||||
"( OLcfgOvAt:12.7 NAME 'olcPPolicyCheckModule' "
|
||||
"DESC 'Loadable module that instantiates check_password() function' "
|
||||
"EQUALITY caseExactIA5Match "
|
||||
"SYNTAX OMsIA5String "
|
||||
"SINGLE-VALUE )", NULL, NULL },
|
||||
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
|
||||
};
|
||||
|
||||
@ -480,7 +503,8 @@ static ConfigOCs ppolicyocs[] = {
|
||||
"SUP olcOverlayConfig "
|
||||
"MAY ( olcPPolicyDefault $ olcPPolicyHashCleartext $ "
|
||||
"olcPPolicyUseLockout $ olcPPolicyForwardUpdates $ "
|
||||
"olcPPolicyDisableWrite $ olcPPolicySendNetscapeControls ) )",
|
||||
"olcPPolicyDisableWrite $ olcPPolicySendNetscapeControls $ "
|
||||
"olcPPolicyCheckModule ) )",
|
||||
Cft_Overlay, ppolicycfg },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
@ -536,6 +560,61 @@ ppolicy_cf_default( ConfigArgs *c )
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
ppolicy_cf_checkmod( ConfigArgs *c )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)c->bi;
|
||||
pp_info *pi = (pp_info *)on->on_bi.bi_private;
|
||||
int rc = ARG_BAD_CONF;
|
||||
|
||||
assert ( c->type == PPOLICY_CHECK_MODULE );
|
||||
Debug(LDAP_DEBUG_TRACE, "==> ppolicy_cf_checkmod\n" );
|
||||
|
||||
switch ( c->op ) {
|
||||
case SLAP_CONFIG_EMIT:
|
||||
if ( pi->pwdCheckModule ) {
|
||||
c->value_string = ch_strdup( pi->pwdCheckModule );
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
case LDAP_MOD_DELETE:
|
||||
if ( pi->pwdCheckHandle ) {
|
||||
lt_dlclose( pi->pwdCheckHandle );
|
||||
pi->pwdCheckHandle = NULL;
|
||||
pi->pwdCheckFunc = NULL;
|
||||
}
|
||||
ch_free( pi->pwdCheckModule );
|
||||
pi->pwdCheckModule = NULL;
|
||||
rc = 0;
|
||||
break;
|
||||
case SLAP_CONFIG_ADD:
|
||||
/* fallthru to LDAP_MOD_ADD */
|
||||
case LDAP_MOD_ADD:
|
||||
pi->pwdCheckHandle = lt_dlopen( c->value_string );
|
||||
if ( pi->pwdCheckHandle == NULL ) {
|
||||
const char *dlerr = lt_dlerror();
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> lt_dlopen(%s) failed: %s",
|
||||
c->argv[0], c->value_string, dlerr );
|
||||
Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
|
||||
} else {
|
||||
if (( pi->pwdCheckFunc = lt_dlsym( pi->pwdCheckHandle, "check_password" )) == NULL) {
|
||||
const char *dlerr = lt_dlerror();
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> lt_dlsym(%s) failed: %s",
|
||||
c->argv[0], c->value_string, dlerr );
|
||||
Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
|
||||
} else {
|
||||
pi->pwdCheckModule = c->value_string;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static time_t
|
||||
parse_time( char *atm )
|
||||
{
|
||||
@ -1024,12 +1103,16 @@ ppolicy_get( Operation *op, Entry *e, PassPolicy *pp )
|
||||
}
|
||||
|
||||
ad = ad_pwdCheckModule;
|
||||
if ( (a = attr_find( pe->e_attrs, ad )) ) {
|
||||
strncpy( pp->pwdCheckModule, a->a_vals[0].bv_val,
|
||||
sizeof(pp->pwdCheckModule) );
|
||||
pp->pwdCheckModule[sizeof(pp->pwdCheckModule)-1] = '\0';
|
||||
if ( attr_find( pe->e_attrs, ad )) {
|
||||
Debug( LDAP_DEBUG_ANY, "ppolicy_get: "
|
||||
"WARNING: Ignoring OBSOLETE attribute %s in policy %s.\n",
|
||||
ad->ad_cname.bv_val, pe->e_name.bv_val );
|
||||
}
|
||||
|
||||
ad = ad_pwdUseCheckModule;
|
||||
if ( (a = attr_find( pe->e_attrs, ad )) )
|
||||
pp->pwdUseCheckModule = bvmatch( &a->a_nvals[0], &slap_true_bv );
|
||||
|
||||
ad = ad_pwdCheckModuleArg;
|
||||
if ( (a = attr_find( pe->e_attrs, ad )) ) {
|
||||
ber_dupbv_x( &pp->pwdCheckModuleArg, &a->a_vals[0], op->o_tmpmemctx );
|
||||
@ -1123,7 +1206,8 @@ password_scheme( struct berval *cred, struct berval *sch )
|
||||
}
|
||||
|
||||
static int
|
||||
check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyError *err, Entry *e, char **txt )
|
||||
check_password_quality( struct berval *cred, pp_info *pi, PassPolicy *pp, LDAPPasswordPolicyError *err,
|
||||
Entry *e, struct berval *errmsg )
|
||||
{
|
||||
int rc = LDAP_SUCCESS, ok = LDAP_SUCCESS;
|
||||
char *ptr;
|
||||
@ -1131,12 +1215,13 @@ check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyE
|
||||
|
||||
assert( cred != NULL );
|
||||
assert( pp != NULL );
|
||||
assert( txt != NULL );
|
||||
assert( errmsg != NULL );
|
||||
|
||||
ptr = errmsg->bv_val;
|
||||
*ptr = '\0';
|
||||
|
||||
ptr = cred->bv_val;
|
||||
|
||||
*txt = NULL;
|
||||
|
||||
if ((cred->bv_len == 0) || (pp->pwdMinLength > cred->bv_len)) {
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
if ( err ) *err = PP_passwordTooShort;
|
||||
@ -1180,63 +1265,40 @@ check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyE
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
if (pp->pwdCheckModule[0]) {
|
||||
if (pp->pwdUseCheckModule) {
|
||||
#ifdef SLAPD_MODULES
|
||||
lt_dlhandle mod;
|
||||
const char *err;
|
||||
|
||||
if ((mod = lt_dlopen( pp->pwdCheckModule )) == NULL) {
|
||||
err = lt_dlerror();
|
||||
check_func *prog;
|
||||
|
||||
if ( !pi->pwdCheckFunc ) {
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"check_password_quality: lt_dlopen failed: (%s) %s.\n",
|
||||
pp->pwdCheckModule, err );
|
||||
ok = LDAP_OTHER; /* internal error */
|
||||
"check_password_quality: no CheckModule loaded\n" );
|
||||
ok = LDAP_OTHER;
|
||||
} else {
|
||||
/* FIXME: the error message ought to be passed thru a
|
||||
* struct berval, with preallocated buffer and size
|
||||
* passed in. Module can still allocate a buffer for
|
||||
* it if the provided one is too small.
|
||||
*/
|
||||
int (*prog)( char *passwd, char **text, Entry *ent, struct berval *arg );
|
||||
|
||||
if ((prog = lt_dlsym( mod, "check_password" )) == NULL) {
|
||||
err = lt_dlerror();
|
||||
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"check_password_quality: lt_dlsym failed: (%s) %s.\n",
|
||||
pp->pwdCheckModule, err );
|
||||
ok = LDAP_OTHER;
|
||||
} else {
|
||||
struct berval *arg = NULL;
|
||||
if ( !BER_BVISNULL( &pp->pwdCheckModuleArg ) ) {
|
||||
arg = &pp->pwdCheckModuleArg;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &chk_syntax_mutex );
|
||||
ok = prog( ptr, txt, e, arg );
|
||||
ldap_pvt_thread_mutex_unlock( &chk_syntax_mutex );
|
||||
if (ok != LDAP_SUCCESS) {
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"check_password_quality: module error: (%s) %s.[%d]\n",
|
||||
pp->pwdCheckModule, *txt ? *txt : "", ok );
|
||||
}
|
||||
struct berval *arg = NULL;
|
||||
if ( !BER_BVISNULL( &pp->pwdCheckModuleArg ) ) {
|
||||
arg = &pp->pwdCheckModuleArg;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &chk_syntax_mutex );
|
||||
ok = pi->pwdCheckFunc( ptr, errmsg, e, arg );
|
||||
ldap_pvt_thread_mutex_unlock( &chk_syntax_mutex );
|
||||
if (ok != LDAP_SUCCESS) {
|
||||
Debug(LDAP_DEBUG_ANY,
|
||||
"check_password_quality: module error: (%s) %s.[%d]\n",
|
||||
pi->pwdCheckModule, errmsg->bv_val ? errmsg->bv_val : "", ok );
|
||||
}
|
||||
|
||||
lt_dlclose( mod );
|
||||
}
|
||||
#else
|
||||
Debug(LDAP_DEBUG_ANY, "check_password_quality: external modules not "
|
||||
"supported. pwdCheckModule ignored.\n" );
|
||||
Debug(LDAP_DEBUG_ANY, "check_password_quality: external modules not "
|
||||
"supported. pwdCheckModule ignored.\n" );
|
||||
#endif /* SLAPD_MODULES */
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ok != LDAP_SUCCESS) {
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
if (err) *err = PP_insufficientPasswordQuality;
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2240,14 +2302,16 @@ ppolicy_add(
|
||||
struct berval *bv = &(pa->a_vals[0]);
|
||||
int rc, send_ctrl = 0;
|
||||
LDAPPasswordPolicyError pErr = PP_noError;
|
||||
char *txt;
|
||||
char errbuf[ERRBUFSIZ];
|
||||
struct berval errmsg = BER_BVC( errbuf );
|
||||
|
||||
/* Did we receive a password policy request control? */
|
||||
if ( op->o_ctrlflag[ppolicy_cid] ) {
|
||||
send_ctrl = 1;
|
||||
}
|
||||
rc = check_password_quality( bv, &pp, &pErr, op->ora_e, &txt );
|
||||
rc = check_password_quality( bv, pi, &pp, &pErr, op->ora_e, &errmsg );
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
char *txt = errmsg.bv_val;
|
||||
LDAPControl **oldctrls = NULL;
|
||||
op->o_bd->bd_info = (BackendInfo *)on->on_info;
|
||||
if ( send_ctrl ) {
|
||||
@ -2255,8 +2319,8 @@ ppolicy_add(
|
||||
ctrl = create_passcontrol( op, -1, -1, pErr );
|
||||
oldctrls = add_passcontrol( op, rs, ctrl );
|
||||
}
|
||||
send_ldap_error( op, rs, rc, txt ? txt : "Password fails quality checking policy" );
|
||||
if ( txt ) {
|
||||
send_ldap_error( op, rs, rc, txt && txt[0] ? txt : "Password fails quality checking policy" );
|
||||
if ( txt != errbuf ) {
|
||||
free( txt );
|
||||
}
|
||||
if ( send_ctrl ) {
|
||||
@ -2353,6 +2417,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
|
||||
*ml, *delmod, *addmod;
|
||||
Attribute *pa, *ha, at;
|
||||
const char *txt;
|
||||
char errbuf[ERRBUFSIZ];
|
||||
pw_hist *tl = NULL, *p;
|
||||
int zapReset, send_ctrl = 0, free_txt = 0;
|
||||
Entry *e;
|
||||
@ -2767,13 +2832,16 @@ ppolicy_modify( Operation *op, SlapReply *rs )
|
||||
|
||||
bv = newpw.bv_val ? &newpw : &addmod->sml_values[0];
|
||||
if (pp.pwdCheckQuality > 0) {
|
||||
struct berval errmsg = BER_BVC( errbuf );
|
||||
|
||||
rc = check_password_quality( bv, &pp, &pErr, e, (char **)&txt );
|
||||
rc = check_password_quality( bv, pi, &pp, &pErr, e, &errmsg );
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
rs->sr_err = rc;
|
||||
if ( txt ) {
|
||||
txt = errmsg.bv_val;
|
||||
if ( txt && txt[0] ) {
|
||||
rs->sr_text = txt;
|
||||
free_txt = 1;
|
||||
if ( txt != errbuf )
|
||||
free_txt = 1;
|
||||
} else {
|
||||
rs->sr_text = "Password fails quality checking policy";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user