From a0e3e68a025ea69f6ec08d7213a926371dd5ded3 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 27 Sep 2008 10:06:43 +0000 Subject: [PATCH] allow controls deletion to be deferred; pass response controls back to frontend in extops (ITS#5711) --- servers/slapd/overlays/ppolicy.c | 51 +++++++++++++++++++------------- servers/slapd/result.c | 8 +++++ servers/slapd/slap.h | 3 ++ tests/scripts/test022-ppolicy | 25 +++++++++++----- 4 files changed, 59 insertions(+), 28 deletions(-) diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index 160358a964..36836c5127 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -362,20 +362,14 @@ account_locked( Operation *op, Entry *e, static const char ppolicy_ctrl_oid[] = LDAP_CONTROL_PASSWORDPOLICYRESPONSE; static LDAPControl * -create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err ) +create_passcontrol( Operation *op, int exptime, int grace, LDAPPasswordPolicyError err ) { char berbuf[LBER_ELEMENT_SIZEOF], bb2[LBER_ELEMENT_SIZEOF]; BerElement *ber = (BerElement *)berbuf, *b2 = (BerElement *)bb2; - LDAPControl *c; + LDAPControl c = { 0 }, *cp; struct berval bv; - c = ch_calloc( sizeof( LDAPControl ), 1 ); - if ( c == NULL ) { - return NULL; - } - c->ldctl_oid = (char *)ppolicy_ctrl_oid; - c->ldctl_iscritical = 0; - BER_BVZERO( &c->ldctl_value ); + BER_BVZERO( &c.ldctl_value ); ber_init2( ber, NULL, LBER_USE_DER ); ber_printf( ber, "{" /*}*/ ); @@ -401,12 +395,19 @@ create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err ) } ber_printf( ber, /*{*/ "N}" ); - if (ber_flatten2( ber, &(c->ldctl_value), 1 ) == LBER_DEFAULT) { - ch_free(c); - c = NULL; + if (ber_flatten2( ber, &(c.ldctl_value), 1 ) == LBER_DEFAULT) { + return NULL; } (void)ber_free_buf(ber); - return c; + cp = op->o_tmpalloc( sizeof( LDAPControl ) + c.ldctl_value.bv_len, op->o_tmpmemctx ); + cp->ldctl_oid = (char *)ppolicy_ctrl_oid; + cp->ldctl_iscritical = 0; + cp->ldctl_value.bv_val = (char *)&cp[1]; + cp->ldctl_value.bv_len = c.ldctl_value.bv_len; + AC_MEMCPY( cp->ldctl_value.bv_val, c.ldctl_value.bv_val, c.ldctl_value.bv_len ); + ber_memfree( c.ldctl_value.bv_val ); + + return cp; } static LDAPControl ** @@ -1138,7 +1139,7 @@ locked: if ( ppb->pErr == PP_accountLocked && !pi->use_lockout ) { ppb->pErr = PP_noError; } - ctrl = create_passcontrol( warn, ngut, ppb->pErr ); + ctrl = create_passcontrol( op, warn, ngut, ppb->pErr ); ppb->oldctrls = add_passcontrol( op, rs, ctrl ); op->o_callback->sc_cleanup = ppolicy_ctrls_cleanup; } @@ -1251,7 +1252,7 @@ ppolicy_restrict( "connection restricted to password changing only\n", 0, 0, 0); if ( send_ctrl ) { LDAPControl *ctrl = NULL; - ctrl = create_passcontrol( -1, -1, PP_changeAfterReset ); + ctrl = create_passcontrol( op, -1, -1, PP_changeAfterReset ); oldctrls = add_passcontrol( op, rs, ctrl ); } op->o_bd->bd_info = (BackendInfo *)on->on_info; @@ -1317,7 +1318,7 @@ ppolicy_add( op->o_bd->bd_info = (BackendInfo *)on->on_info; if ( send_ctrl ) { LDAPControl *ctrl = NULL; - ctrl = create_passcontrol( -1, -1, pErr ); + ctrl = create_passcontrol( op, -1, -1, pErr ); oldctrls = add_passcontrol( op, rs, ctrl ); } send_ldap_error( op, rs, rc, "Password fails quality checking policy" ); @@ -1406,7 +1407,9 @@ ppolicy_modify( Operation *op, SlapReply *rs ) struct berval newpw = BER_BVNULL, oldpw = BER_BVNULL, *bv, cr[2]; LDAPPasswordPolicyError pErr = PP_noError; + LDAPControl *ctrl = NULL; LDAPControl **oldctrls = NULL; + int is_pwdexop = 0; op->o_bd->bd_info = (BackendInfo *)on->on_info; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); @@ -1526,6 +1529,7 @@ ppolicy_modify( Operation *op, SlapReply *rs ) req_pwdexop_s *qpw = sc->sc_private; newpw = qpw->rs_new; oldpw = qpw->rs_old; + is_pwdexop = 1; break; } } @@ -2010,14 +2014,21 @@ return_results: op->o_bd->bd_info = (BackendInfo *)on->on_info; be_entry_release_r( op, e ); if ( send_ctrl ) { - LDAPControl *ctrl = NULL; - - ctrl = create_passcontrol( -1, -1, pErr ); + ctrl = create_passcontrol( op, -1, -1, pErr ); oldctrls = add_passcontrol( op, rs, ctrl ); } send_ldap_result( op, rs ); if ( send_ctrl ) { - ctrls_cleanup( op, rs, oldctrls ); + if ( is_pwdexop ) { + if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { + slap_free_ctrls( op, oldctrls ); + } + oldctrls = NULL; + rs->sr_flags |= REP_CTRLS_MUSTBEFREED; + + } else { + ctrls_cleanup( op, rs, oldctrls ); + } } return rs->sr_err; } diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 8b623bbaba..f89b87304c 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -538,6 +538,14 @@ clean2:; } } + if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { + rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ + if ( rs->sr_ctrls ) { + slap_free_ctrls( op, rs->sr_ctrls ); + rs->sr_ctrls = NULL; + } + } + return rc; } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 4b5e84dfd7..24fc1c1719 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -2059,6 +2059,9 @@ struct SlapReply { #define REP_REF_MUSTBEFREED 0x0020U #define REP_REF_MASK (REP_REF_MUSTBEFREED) +#define REP_CTRLS_MUSTBEFREED 0x0040U +#define REP_CTRLS_MASK (REP_CTRLS_MUSTBEFREED) + #define REP_NO_ENTRYDN 0x1000U #define REP_NO_SUBSCHEMA 0x2000U #define REP_NO_OPERATIONALS (REP_NO_ENTRYDN|REP_NO_SUBSCHEMA) diff --git a/tests/scripts/test022-ppolicy b/tests/scripts/test022-ppolicy index 3a8d9d09e0..51f5f48f2c 100755 --- a/tests/scripts/test022-ppolicy +++ b/tests/scripts/test022-ppolicy @@ -142,7 +142,7 @@ $LDAPMODIFY -v -D "$USER" -h $LOCALHOST -p $PORT1 -w $PASS >> \ dn: uid=nd, ou=People, dc=example, dc=com changetype: modify delete: userpassword -userpassword: testpassword +userpassword: $PASS - replace: userpassword userpassword: 20urgle12-1 @@ -220,7 +220,7 @@ $LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD >> \ dn: uid=nd, ou=People, dc=example, dc=com changetype: modify replace: userPassword -userPassword: testpassword +userPassword: $PASS - replace: pwdReset pwdReset: TRUE @@ -288,8 +288,11 @@ fi sleep 2 +OLDPASS=$PASS +PASS=successexpect + $LDAPPASSWD -h $LOCALHOST -p $PORT1 \ - -w $PASS -s failexpect -a $PASS \ + -w $OLDPASS -s $PASS -a $OLDPASS \ -D "$USER" >> $TESTOUT 2>&1 RC=$? if test $RC != 0 ; then @@ -299,10 +302,10 @@ if test $RC != 0 ; then fi echo "Testing length requirement..." - +# check control in response (ITS#5711) $LDAPPASSWD -h $LOCALHOST -p $PORT1 \ - -w failexpect -a failexpect -s spw \ - -D "$USER" > ${TESTOUT}.2 2>&1 + -w $PASS -a $PASS -s 2shr \ + -D "$USER" -e ppolicy > ${TESTOUT}.2 2>&1 RC=$? cat ${TESTOUT}.2 >> $TESTOUT if test $RC = 0 ; then @@ -316,15 +319,21 @@ if test $COUNT != 1 ; then test $KILLSERVERS != no && kill -HUP $KILLPIDS exit 1 fi +COUNT=`grep "Password is too short for policy" ${TESTOUT}.2 | wc -l` +if test $COUNT != 1 ; then + echo "Control not returned in response" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi echo "Testing hashed length requirement..." -$LDAPMODIFY -h $LOCALHOST -p $PORT1 -D "$USER" -w failexpect > \ +$LDAPMODIFY -h $LOCALHOST -p $PORT1 -D "$USER" -w $PASS > \ ${TESTOUT}.2 2>&1 << EOMODS dn: $USER changetype: modify delete: userPassword -userPassword: failexpect +userPassword: $PASS - add: userPassword userPassword: {MD5}xxxxxx -- 2.39.5