Fix account lock check

This commit is contained in:
Howard Chu 2004-03-17 09:54:49 +00:00
parent 32573b3418
commit dbade4ad8c

View file

@ -698,16 +698,22 @@ free_pwd_history_list( pw_hist **l )
*l = NULL; *l = NULL;
} }
typedef struct ppbind {
slap_overinst *on;
int send_ctrl;
Modifications *mod;
LDAPPasswordPolicyError pErr;
PassPolicy pp;
} ppbind;
static int static int
ppolicy_bind_resp( Operation *op, SlapReply *rs ) ppolicy_bind_resp( Operation *op, SlapReply *rs )
{ {
slap_overinst *on = op->o_callback->sc_private; ppbind *ppb = op->o_callback->sc_private;
PassPolicy pp; slap_overinst *on = ppb->on;
int send_ctrl; Modifications *mod = ppb->mod, *m;
Modifications *mod = NULL, *m;
int pwExpired = 0; int pwExpired = 0;
int ngut = -1, warn = -1, age, rc, i; int ngut = -1, warn = -1, age, rc, i;
LDAPPasswordPolicyError pErr = PP_noError;
Attribute *a; Attribute *a;
struct tm *tm; struct tm *tm;
time_t now, then, pwtime = (time_t)-1; time_t now, then, pwtime = (time_t)-1;
@ -716,6 +722,11 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
BackendInfo *bi = op->o_bd->bd_info; BackendInfo *bi = op->o_bd->bd_info;
Entry *e; Entry *e;
/* If we already know it's locked, just get on with it */
if ( ppb->pErr != PP_noError ) {
goto locked;
}
op->o_bd->bd_info = (BackendInfo *)on->on_info; op->o_bd->bd_info = (BackendInfo *)on->on_info;
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
op->o_bd->bd_info = bi; op->o_bd->bd_info = bi;
@ -724,24 +735,6 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
return SLAP_CB_CONTINUE; return SLAP_CB_CONTINUE;
} }
/* Did we receive a password policy request control? */
for ( i=0; op->o_ctrls && op->o_ctrls[i]; i++ ) {
if ( !strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYREQUEST ) ) {
send_ctrl = 1;
break;
}
}
op->o_bd->bd_info = (BackendInfo *)on;
ppolicy_get( op, e, &pp );
if ( account_locked( op, e, &pp, &mod )) {
/* This will be the Draft 8 response, Unwilling is bogus */
rs->sr_err = LDAP_INVALID_CREDENTIALS;
pErr = PP_accountLocked;
goto done;
}
now = slap_get_time(); /* stored for later consideration */ now = slap_get_time(); /* stored for later consideration */
ldap_pvt_thread_mutex_lock( &gmtime_mutex ); ldap_pvt_thread_mutex_lock( &gmtime_mutex );
tm = gmtime(&now); tm = gmtime(&now);
@ -774,11 +767,11 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
* stay on the record until explicitly * stay on the record until explicitly
* reset by successful authentication. * reset by successful authentication.
*/ */
if (pp.pwdFailureCountInterval == 0) { if (ppb->pp.pwdFailureCountInterval == 0) {
fc++; fc++;
} else if (now <= } else if (now <=
parse_time(a->a_nvals[i].bv_val) + parse_time(a->a_nvals[i].bv_val) +
pp.pwdFailureCountInterval) { ppb->pp.pwdFailureCountInterval) {
fc++; fc++;
} }
@ -789,8 +782,8 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
} }
} }
if ((pp.pwdMaxFailure > 0) && if ((ppb->pp.pwdMaxFailure > 0) &&
(fc >= pp.pwdMaxFailure - 1)) { (fc >= ppb->pp.pwdMaxFailure - 1)) {
/* /*
* We subtract 1 from the failure max * We subtract 1 from the failure max
@ -823,7 +816,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
/* /*
* check to see if the password must be changed * check to see if the password must be changed
*/ */
if ( pp.pwdMustChange && if ( ppb->pp.pwdMustChange &&
(a = attr_find( e->e_attrs, ad_pwdReset )) && (a = attr_find( e->e_attrs, ad_pwdReset )) &&
!strcmp( a->a_nvals[0].bv_val, "TRUE" ) ) { !strcmp( a->a_nvals[0].bv_val, "TRUE" ) ) {
/* /*
@ -834,7 +827,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
*/ */
pwcons[op->o_conn->c_conn_idx].restrict = 1; pwcons[op->o_conn->c_conn_idx].restrict = 1;
pErr = PP_changeAfterReset; ppb->pErr = PP_changeAfterReset;
} else { } else {
/* /*
@ -844,7 +837,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
* We can skip this bit if passwords don't age in * We can skip this bit if passwords don't age in
* the policy. * the policy.
*/ */
if (pp.pwdMaxAge == 0) goto grace; if (ppb->pp.pwdMaxAge == 0) goto grace;
if (pwtime == (time_t)-1) { if (pwtime == (time_t)-1) {
/* /*
@ -873,7 +866,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs )
* the password older than the maximum age * the password older than the maximum age
* allowed. (Ignore case 2 from I-D, it's just silly.) * allowed. (Ignore case 2 from I-D, it's just silly.)
*/ */
if (now - pwtime > pp.pwdMaxAge ) pwExpired = 1; if (now - pwtime > ppb->pp.pwdMaxAge ) pwExpired = 1;
} }
} }
@ -881,10 +874,10 @@ grace:
if (!pwExpired) goto check_expiring_password; if (!pwExpired) goto check_expiring_password;
if ((a = attr_find( e->e_attrs, ad_pwdGraceUseTime )) == NULL) if ((a = attr_find( e->e_attrs, ad_pwdGraceUseTime )) == NULL)
ngut = pp.pwdGraceLoginLimit; ngut = ppb->pp.pwdGraceLoginLimit;
else { else {
for(ngut=0; a->a_nvals[ngut].bv_val; ngut++); for(ngut=0; a->a_nvals[ngut].bv_val; ngut++);
ngut = pp.pwdGraceLoginLimit - ngut; ngut = ppb->pp.pwdGraceLoginLimit - ngut;
} }
/* /*
@ -901,7 +894,7 @@ grace:
#endif #endif
if (ngut < 1) { if (ngut < 1) {
pErr = PP_passwordExpired; ppb->pErr = PP_passwordExpired;
rs->sr_err = LDAP_INVALID_CREDENTIALS; rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto done; goto done;
} }
@ -928,7 +921,7 @@ check_expiring_password:
* we don't need to do this bit. Similarly, if we don't have password * we don't need to do this bit. Similarly, if we don't have password
* aging, then there's no need to do this bit either. * aging, then there's no need to do this bit either.
*/ */
if ((pp.pwdMaxAge < 1) || (pwExpired) || (pp.pwdExpireWarning < 1)) if ((ppb->pp.pwdMaxAge < 1) || (pwExpired) || (ppb->pp.pwdExpireWarning < 1))
goto done; goto done;
age = (int)(now - pwtime); age = (int)(now - pwtime);
@ -940,7 +933,7 @@ check_expiring_password:
* then this section isn't called anyway - you can't have an * then this section isn't called anyway - you can't have an
* expiring password if there's no limit to expire. * expiring password if there's no limit to expire.
*/ */
if (pp.pwdMaxAge - age < pp.pwdExpireWarning ) { if (ppb->pp.pwdMaxAge - age < ppb->pp.pwdExpireWarning ) {
/* /*
* Set the warning value, add expiration warned timestamp to the entry. * Set the warning value, add expiration warned timestamp to the entry.
*/ */
@ -955,7 +948,7 @@ check_expiring_password:
mod = m; mod = m;
} }
warn = pp.pwdMaxAge - age; /* seconds left until expiry */ warn = ppb->pp.pwdMaxAge - age; /* seconds left until expiry */
if (warn < 0) warn = 0; /* something weird here - why is pwExpired not set? */ if (warn < 0) warn = 0; /* something weird here - why is pwExpired not set? */
#ifdef NEW_LOGGING #ifdef NEW_LOGGING
@ -974,6 +967,7 @@ done:
op->o_bd->bd_info = (BackendInfo *)on->on_info; op->o_bd->bd_info = (BackendInfo *)on->on_info;
be_entry_release_r( op, e ); be_entry_release_r( op, e );
locked:
if ( mod ) { if ( mod ) {
Operation op2 = *op; Operation op2 = *op;
SlapReply r2 = { REP_RESULT }; SlapReply r2 = { REP_RESULT };
@ -992,11 +986,11 @@ done:
slap_mods_free( mod ); slap_mods_free( mod );
} }
if ( send_ctrl ) { if ( ppb->send_ctrl ) {
LDAPControl **ctrls = NULL; LDAPControl **ctrls = NULL;
ctrls = ch_calloc( sizeof( LDAPControl *) , 2 ); ctrls = ch_calloc( sizeof( LDAPControl *) , 2 );
ctrls[0] = create_passcontrol( warn, ngut, pErr ); ctrls[0] = create_passcontrol( warn, ngut, ppb->pErr );
ctrls[1] = NULL; ctrls[1] = NULL;
rs->sr_ctrls = ctrls; rs->sr_ctrls = ctrls;
} }
@ -1011,16 +1005,54 @@ ppolicy_bind( Operation *op, SlapReply *rs )
/* Root bypasses policy */ /* Root bypasses policy */
if ( !be_isroot( op->o_bd, &op->o_req_ndn )) { if ( !be_isroot( op->o_bd, &op->o_req_ndn )) {
Entry *e;
int i, rc;
ppbind *ppb;
slap_callback *cb; slap_callback *cb;
cb = sl_calloc( sizeof(slap_callback), 1, op->o_tmpmemctx ); 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;
/* Setup a callback so we can munge the result */ /* Setup a callback so we can munge the result */
cb->sc_response = ppolicy_bind_resp; cb->sc_response = ppolicy_bind_resp;
cb->sc_next = op->o_callback->sc_next; cb->sc_next = op->o_callback->sc_next;
cb->sc_private = on; cb->sc_private = ppb;
op->o_callback->sc_next = cb; op->o_callback->sc_next = cb;
/* Did we receive a password policy request control? */
for ( i=0; op->o_ctrls && op->o_ctrls[i]; i++ ) {
if ( !strcmp( op->o_ctrls[i]->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYREQUEST ) ) {
ppb->send_ctrl = 1;
break;
}
}
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 ) {
/* 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; return SLAP_CB_CONTINUE;