From dbade4ad8c245734443b32c994da9df6b6c62d7b Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 17 Mar 2004 09:54:49 +0000 Subject: [PATCH] Fix account lock check --- servers/slapd/overlays/ppolicy.c | 114 ++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index 1ad83ce79a..b8bce27efa 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -698,16 +698,22 @@ free_pwd_history_list( pw_hist **l ) *l = NULL; } +typedef struct ppbind { + slap_overinst *on; + int send_ctrl; + Modifications *mod; + LDAPPasswordPolicyError pErr; + PassPolicy pp; +} ppbind; + static int ppolicy_bind_resp( Operation *op, SlapReply *rs ) { - slap_overinst *on = op->o_callback->sc_private; - PassPolicy pp; - int send_ctrl; - Modifications *mod = NULL, *m; + ppbind *ppb = op->o_callback->sc_private; + slap_overinst *on = ppb->on; + Modifications *mod = ppb->mod, *m; int pwExpired = 0; int ngut = -1, warn = -1, age, rc, i; - LDAPPasswordPolicyError pErr = PP_noError; Attribute *a; struct tm *tm; 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; 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; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); op->o_bd->bd_info = bi; @@ -724,24 +735,6 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs ) 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 */ ldap_pvt_thread_mutex_lock( &gmtime_mutex ); tm = gmtime(&now); @@ -774,11 +767,11 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs ) * stay on the record until explicitly * reset by successful authentication. */ - if (pp.pwdFailureCountInterval == 0) { + if (ppb->pp.pwdFailureCountInterval == 0) { fc++; } else if (now <= parse_time(a->a_nvals[i].bv_val) + - pp.pwdFailureCountInterval) { + ppb->pp.pwdFailureCountInterval) { fc++; } @@ -789,8 +782,8 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs ) } } - if ((pp.pwdMaxFailure > 0) && - (fc >= pp.pwdMaxFailure - 1)) { + if ((ppb->pp.pwdMaxFailure > 0) && + (fc >= ppb->pp.pwdMaxFailure - 1)) { /* * 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 */ - if ( pp.pwdMustChange && + if ( ppb->pp.pwdMustChange && (a = attr_find( e->e_attrs, ad_pwdReset )) && !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; - pErr = PP_changeAfterReset; + ppb->pErr = PP_changeAfterReset; } else { /* @@ -844,7 +837,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs ) * We can skip this bit if passwords don't age in * the policy. */ - if (pp.pwdMaxAge == 0) goto grace; + if (ppb->pp.pwdMaxAge == 0) goto grace; if (pwtime == (time_t)-1) { /* @@ -873,7 +866,7 @@ ppolicy_bind_resp( Operation *op, SlapReply *rs ) * the password older than the maximum age * 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 ((a = attr_find( e->e_attrs, ad_pwdGraceUseTime )) == NULL) - ngut = pp.pwdGraceLoginLimit; + ngut = ppb->pp.pwdGraceLoginLimit; else { 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 if (ngut < 1) { - pErr = PP_passwordExpired; + ppb->pErr = PP_passwordExpired; rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } @@ -928,7 +921,7 @@ check_expiring_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. */ - if ((pp.pwdMaxAge < 1) || (pwExpired) || (pp.pwdExpireWarning < 1)) + if ((ppb->pp.pwdMaxAge < 1) || (pwExpired) || (ppb->pp.pwdExpireWarning < 1)) goto done; age = (int)(now - pwtime); @@ -940,7 +933,7 @@ check_expiring_password: * then this section isn't called anyway - you can't have an * 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. */ @@ -955,7 +948,7 @@ check_expiring_password: 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? */ #ifdef NEW_LOGGING @@ -974,6 +967,7 @@ done: op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, e ); +locked: if ( mod ) { Operation op2 = *op; SlapReply r2 = { REP_RESULT }; @@ -992,11 +986,11 @@ done: slap_mods_free( mod ); } - if ( send_ctrl ) { + if ( ppb->send_ctrl ) { LDAPControl **ctrls = NULL; ctrls = ch_calloc( sizeof( LDAPControl *) , 2 ); - ctrls[0] = create_passcontrol( warn, ngut, pErr ); + ctrls[0] = create_passcontrol( warn, ngut, ppb->pErr ); ctrls[1] = NULL; rs->sr_ctrls = ctrls; } @@ -1011,16 +1005,54 @@ ppolicy_bind( Operation *op, SlapReply *rs ) /* Root bypasses policy */ if ( !be_isroot( op->o_bd, &op->o_req_ndn )) { + Entry *e; + int i, rc; + ppbind *ppb; 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 */ cb->sc_response = ppolicy_bind_resp; cb->sc_next = op->o_callback->sc_next; - cb->sc_private = on; + cb->sc_private = ppb; 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; -- 2.39.5