X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fppolicy.c;h=e13c33a86629945f9d6e7f571356bfbbbcbf12f7;hb=10566c8be384c6435476ec54e842382841cb84b6;hp=ad229c5f1ecd03d2b2710f3646558bfbebcc913d;hpb=99ea907e745f7fa5da29fab12c330ad509d039e3;p=openldap diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index ad229c5f1e..e13c33a866 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2015 The OpenLDAP Foundation. + * Copyright 2004-2017 The OpenLDAP Foundation. * Portions Copyright 2004-2005 Howard Chu, Symas Corporation. * Portions Copyright 2004 Hewlett-Packard Company. * All rights reserved. @@ -45,6 +45,10 @@ #define MODULE_NAME_SZ 256 #endif +#ifndef PPOLICY_DEFAULT_MAXRECORDED_FAILURE +#define PPOLICY_DEFAULT_MAXRECORDED_FAILURE 5 +#endif + /* Per-instance configuration information */ typedef struct pp_info { struct berval def_policy; /* DN of default policy subentry */ @@ -79,6 +83,7 @@ typedef struct pass_policy { int pwdLockout; /* 0 = do not lockout passwords, 1 = lock them out */ int pwdLockoutDuration; /* time in seconds a password is locked out for */ int pwdMaxFailure; /* number of failed binds allowed before lockout */ + int pwdMaxRecordedFailure; /* number of failed binds to store */ int pwdFailureCountInterval; /* number of seconds before failure counts are zeroed */ int pwdMustChange; /* 0 = users can use admin set password @@ -179,7 +184,7 @@ static AttributeDescription *ad_pwdMinAge, *ad_pwdMaxAge, *ad_pwdInHistory, *ad_pwdGraceAuthNLimit, *ad_pwdExpireWarning, *ad_pwdLockoutDuration, *ad_pwdFailureCountInterval, *ad_pwdCheckModule, *ad_pwdLockout, *ad_pwdMustChange, *ad_pwdAllowUserChange, *ad_pwdSafeModify, - *ad_pwdAttribute; + *ad_pwdAttribute, *ad_pwdMaxRecordedFailure; #define TAB(name) { #name, &ad_##name } @@ -191,6 +196,7 @@ static struct schema_info pwd_UsSchema[] = { TAB(pwdCheckQuality), TAB(pwdMinLength), TAB(pwdMaxFailure), + TAB(pwdMaxRecordedFailure), TAB(pwdGraceAuthNLimit), TAB(pwdExpireWarning), TAB(pwdLockout), @@ -283,7 +289,7 @@ ppolicy_cf_default( ConfigArgs *c ) rc = 0; break; case SLAP_CONFIG_ADD: - /* fallthrough to LDAP_MOD_ADD */ + /* fallthru to LDAP_MOD_ADD */ case LDAP_MOD_ADD: Debug(LDAP_DEBUG_TRACE, "==> ppolicy_cf_default add\n", 0, 0, 0); if ( pi->def_policy.bv_val ) { @@ -462,6 +468,20 @@ add_passcontrol( Operation *op, SlapReply *rs, LDAPControl *ctrl ) return oldctrls; } +static void +ppolicy_get_default( PassPolicy *pp ) +{ + memset( pp, 0, sizeof(PassPolicy) ); + + pp->ad = slap_schema.si_ad_userPassword; + + /* Users can change their own password by default */ + pp->pwdAllowUserChange = 1; + if ( !pp->pwdMaxRecordedFailure ) + pp->pwdMaxRecordedFailure = PPOLICY_DEFAULT_MAXRECORDED_FAILURE; +} + + static void ppolicy_get( Operation *op, Entry *e, PassPolicy *pp ) { @@ -475,12 +495,7 @@ ppolicy_get( Operation *op, Entry *e, PassPolicy *pp ) const char *text; #endif - memset( pp, 0, sizeof(PassPolicy) ); - - pp->ad = slap_schema.si_ad_userPassword; - - /* Users can change their own password by default */ - pp->pwdAllowUserChange = 1; + ppolicy_get_default( pp ); if ((a = attr_find( e->e_attrs, ad_pwdPolicySubentry )) == NULL) { /* @@ -527,6 +542,9 @@ ppolicy_get( Operation *op, Entry *e, PassPolicy *pp ) if ( ( a = attr_find( pe->e_attrs, ad_pwdMaxFailure ) ) && lutil_atoi( &pp->pwdMaxFailure, a->a_vals[0].bv_val ) != 0 ) goto defaultpol; + if ( ( a = attr_find( pe->e_attrs, ad_pwdMaxRecordedFailure ) ) + && lutil_atoi( &pp->pwdMaxRecordedFailure, a->a_vals[0].bv_val ) != 0 ) + goto defaultpol; if ( ( a = attr_find( pe->e_attrs, ad_pwdGraceAuthNLimit ) ) && lutil_atoi( &pp->pwdGraceAuthNLimit, a->a_vals[0].bv_val ) != 0 ) goto defaultpol; @@ -555,6 +573,11 @@ ppolicy_get( Operation *op, Entry *e, PassPolicy *pp ) if ((a = attr_find( pe->e_attrs, ad_pwdSafeModify ))) pp->pwdSafeModify = bvmatch( &a->a_nvals[0], &slap_true_bv ); + if ( pp->pwdMaxRecordedFailure < pp->pwdMaxFailure ) + pp->pwdMaxRecordedFailure = pp->pwdMaxFailure; + if ( !pp->pwdMaxRecordedFailure ) + pp->pwdMaxRecordedFailure = PPOLICY_DEFAULT_MAXRECORDED_FAILURE; + op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, pe ); op->o_bd->bd_info = (BackendInfo *)on; @@ -562,8 +585,17 @@ ppolicy_get( Operation *op, Entry *e, PassPolicy *pp ) return; defaultpol: + if ( pe ) { + op->o_bd->bd_info = (BackendInfo *)on->on_info; + be_entry_release_r( op, pe ); + op->o_bd->bd_info = (BackendInfo *)on; + } + Debug( LDAP_DEBUG_TRACE, "ppolicy_get: using default policy\n", 0, 0, 0 ); + + ppolicy_get_default( pp ); + return; } @@ -999,6 +1031,50 @@ ppolicy_bind_response( Operation *op, SlapReply *rs ) * which are not due to expire. */ } + /* Do we have too many timestamps? If so, delete some values. + * We don't bother to sort the values here. OpenLDAP keeps the + * values in order by default. Fundamentally, relying on the + * information here is wrong anyway; monitoring systems should + * be tracking Bind failures in syslog, not here. + */ + if (a->a_numvals >= ppb->pp.pwdMaxRecordedFailure) { + int j = ppb->pp.pwdMaxRecordedFailure-1; + /* If more than 2x, cheaper to perform a Replace */ + if (a->a_numvals >= 2 * ppb->pp.pwdMaxRecordedFailure) { + struct berval v, nv; + + /* Change the mod we constructed above */ + m->sml_op = LDAP_MOD_REPLACE; + m->sml_numvals = ppb->pp.pwdMaxRecordedFailure; + v = m->sml_values[0]; + nv = m->sml_nvalues[0]; + ch_free(m->sml_values); + ch_free(m->sml_nvalues); + m->sml_values = ch_calloc( sizeof(struct berval), ppb->pp.pwdMaxRecordedFailure+1 ); + m->sml_nvalues = ch_calloc( sizeof(struct berval), ppb->pp.pwdMaxRecordedFailure+1 ); + for (i=0; isml_values[i], &a->a_vals[a->a_numvals-j+i]); + ber_dupbv(&m->sml_nvalues[i], &a->a_nvals[a->a_numvals-j+i]); + } + m->sml_values[i] = v; + m->sml_nvalues[i] = nv; + } else { + /* else just delete some */ + m = ch_calloc( sizeof(Modifications), 1 ); + m->sml_op = LDAP_MOD_DELETE; + m->sml_type = ad_pwdFailureTime->ad_cname; + m->sml_desc = ad_pwdFailureTime; + m->sml_numvals = a->a_numvals - j; + m->sml_values = ch_calloc( sizeof(struct berval), m->sml_numvals+1 ); + m->sml_nvalues = ch_calloc( sizeof(struct berval), m->sml_numvals+1 ); + for (i=0; isml_numvals; i++) { + ber_dupbv(&m->sml_values[i], &a->a_vals[i]); + ber_dupbv(&m->sml_nvalues[i], &a->a_nvals[i]); + } + m->sml_next = mod; + mod = m; + } + } } if ((ppb->pp.pwdMaxFailure > 0) &&