/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2004-2009 The OpenLDAP Foundation.
+ * Copyright 2004-2011 The OpenLDAP Foundation.
* Portions Copyright 2004-2005 Howard Chu, Symas Corporation.
* Portions Copyright 2004 Hewlett-Packard Company.
* All rights reserved.
check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyError *err, Entry *e, char **txt )
{
int rc = LDAP_SUCCESS, ok = LDAP_SUCCESS;
- char *ptr = cred->bv_val;
+ char *ptr;
struct berval sch;
assert( cred != NULL );
assert( pp != NULL );
assert( txt != NULL );
+ ptr = cred->bv_val;
+
*txt = NULL;
if ((cred->bv_len == 0) || (pp->pwdMinLength > cred->bv_len)) {
typedef struct ppbind {
slap_overinst *on;
int send_ctrl;
+ int set_restrict;
LDAPControl **oldctrls;
Modifications *mod;
LDAPPasswordPolicyError pErr;
* that we are disallowed from doing anything
* other than change password.
*/
- ber_dupbv( &pwcons[op->o_conn->c_conn_idx].dn,
- &op->o_conn->c_ndn );
+ if ( ppb->set_restrict ) {
+ ber_dupbv( &pwcons[op->o_conn->c_conn_idx].dn,
+ &op->o_conn->c_ndn );
+ }
ppb->pErr = PP_changeAfterReset;
op2.o_tag = LDAP_REQ_MODIFY;
op2.o_callback = &cb;
op2.orm_modlist = mod;
+ op2.orm_no_opattrs = 0;
op2.o_dn = op->o_bd->be_rootdn;
op2.o_ndn = op->o_bd->be_rootndn;
c.ldctl_iscritical = 1;
c.ldctl_oid = LDAP_CONTROL_RELAX;
} else {
+ /* If not forwarding, don't update opattrs and don't replicate */
+ if ( SLAP_SINGLE_SHADOW( op->o_bd )) {
+ op2.orm_no_opattrs = 1;
+ op2.o_dont_replicate = 1;
+ }
op2.o_bd->bd_info = (BackendInfo *)on->on_info;
}
rc = op2.o_bd->be_modify( &op2, &r2 );
ppb = (ppbind *)(cb+1);
ppb->on = on;
ppb->pErr = PP_noError;
+ ppb->set_restrict = 1;
/* Setup a callback so we can munge the result */
be_entry_release_r( op, e );
if ( rc ) {
- /* This will be the Draft 8 response, Unwilling is bogus */
ppb->pErr = PP_accountLocked;
send_ldap_error( op, rs, LDAP_INVALID_CREDENTIALS, NULL );
return rs->sr_err;
return SLAP_CB_CONTINUE;
}
+static int
+ppolicy_compare_response(
+ Operation *op,
+ SlapReply *rs )
+{
+ /* map compare responses to bind responses */
+ if ( rs->sr_err == LDAP_COMPARE_TRUE )
+ rs->sr_err = LDAP_SUCCESS;
+ else if ( rs->sr_err == LDAP_COMPARE_FALSE )
+ rs->sr_err = LDAP_INVALID_CREDENTIALS;
+
+ ppolicy_bind_response( op, rs );
+
+ /* map back to compare */
+ if ( rs->sr_err == LDAP_SUCCESS )
+ rs->sr_err = LDAP_COMPARE_TRUE;
+ else if ( rs->sr_err == LDAP_INVALID_CREDENTIALS )
+ rs->sr_err = LDAP_COMPARE_FALSE;
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+ppolicy_compare(
+ Operation *op,
+ SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+
+ if ( ppolicy_restrict( op, rs ) != SLAP_CB_CONTINUE )
+ return rs->sr_err;
+
+ /* Did we receive a password policy request control?
+ * Are we testing the userPassword?
+ */
+ if ( op->o_ctrlflag[ppolicy_cid] &&
+ op->orc_ava->aa_desc == slap_schema.si_ad_userPassword ) {
+ Entry *e;
+ int rc;
+ ppbind *ppb;
+ slap_callback *cb;
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return SLAP_CB_CONTINUE;
+ }
+
+ cb = op->o_tmpcalloc( sizeof(ppbind)+sizeof(slap_callback),
+ 1, op->o_tmpmemctx );
+ ppb = (ppbind *)(cb+1);
+ ppb->on = on;
+ ppb->pErr = PP_noError;
+ ppb->send_ctrl = 1;
+ /* failures here don't lockout the connection */
+ ppb->set_restrict = 0;
+
+ /* Setup a callback so we can munge the result */
+
+ cb->sc_response = ppolicy_compare_response;
+ cb->sc_next = op->o_callback->sc_next;
+ cb->sc_private = ppb;
+ op->o_callback->sc_next = cb;
+
+ op->o_bd->bd_info = (BackendInfo *)on;
+ ppolicy_get( op, e, &ppb->pp );
+
+ rc = account_locked( op, e, &ppb->pp, &ppb->mod );
+
+ op->o_bd->bd_info = (BackendInfo *)on->on_info;
+ be_entry_release_r( op, e );
+
+ if ( rc ) {
+ ppb->pErr = PP_accountLocked;
+ send_ldap_error( op, rs, LDAP_COMPARE_FALSE, NULL );
+ return rs->sr_err;
+ }
+ }
+ return SLAP_CB_CONTINUE;
+}
+
static int
ppolicy_add(
Operation *op,
if (be_isroot( op )) goto do_modify;
- if (!pp.pwdAllowUserChange) {
+ /* NOTE: according to draft-behera-ldap-password-policy
+ * pwdAllowUserChange == FALSE must only prevent pwd changes
+ * by the user the pwd belongs to (ITS#7021) */
+ if (!pp.pwdAllowUserChange && dn_match(&op->o_req_ndn, &op->o_ndn)) {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "User alteration of password is not allowed";
pErr = PP_passwordModNotAllowed;
timestamp.bv_len = sizeof(timebuf);
slap_timestamp( &now, ×tamp );
- mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 );
- mods->sml_desc = ad_pwdChangedTime;
+ mods = NULL;
if (pwmop != LDAP_MOD_DELETE) {
+ mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 );
mods->sml_op = LDAP_MOD_REPLACE;
mods->sml_numvals = 1;
mods->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
ber_dupbv( &mods->sml_values[0], ×tamp );
BER_BVZERO( &mods->sml_values[1] );
assert( !BER_BVISNULL( &mods->sml_values[0] ) );
-
- } else {
+ } else if (attr_find(e->e_attrs, ad_pwdChangedTime )) {
+ mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 );
mods->sml_op = LDAP_MOD_DELETE;
}
- mods->sml_flags = SLAP_MOD_INTERNAL;
- mods->sml_next = NULL;
- modtail->sml_next = mods;
- modtail = mods;
+ if (mods) {
+ mods->sml_desc = ad_pwdChangedTime;
+ mods->sml_flags = SLAP_MOD_INTERNAL;
+ mods->sml_next = NULL;
+ modtail->sml_next = mods;
+ modtail = mods;
+ }
if (attr_find(e->e_attrs, ad_pwdGraceUseTime )) {
mods = (Modifications *) ch_calloc( sizeof( Modifications ), 1 );
if ( cr ){
snprintf( cr->msg, sizeof(cr->msg),
"slapo-ppolicy cannot be global" );
- fprintf( stderr, "%s\n", cr->msg );
+ Debug( LDAP_DEBUG_ANY, "%s\n", cr->msg, 0, 0 );
}
return 1;
}
snprintf( cr->msg, sizeof(cr->msg),
"User Schema load failed for attribute \"%s\". Error code %d: %s",
pwd_UsSchema[i].def, code, err );
- fprintf( stderr, "%s\n", cr->msg );
+ Debug( LDAP_DEBUG_ANY, "%s\n", cr->msg, 0, 0 );
}
return code;
}
SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE, extops,
ppolicy_parseCtrl, &ppolicy_cid );
if ( code != LDAP_SUCCESS ) {
- fprintf( stderr, "Failed to register control %d\n", code );
+ Debug( LDAP_DEBUG_ANY, "Failed to register control %d\n", code, 0, 0 );
return code;
}
ppolicy.on_bi.bi_op_add = ppolicy_add;
ppolicy.on_bi.bi_op_bind = ppolicy_bind;
- ppolicy.on_bi.bi_op_compare = ppolicy_restrict;
+ ppolicy.on_bi.bi_op_compare = ppolicy_compare;
ppolicy.on_bi.bi_op_delete = ppolicy_restrict;
ppolicy.on_bi.bi_op_modify = ppolicy_modify;
ppolicy.on_bi.bi_op_search = ppolicy_restrict;