From 30a0d07ab757f31e0b8851c38ec60808e6410ff6 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount Date: Fri, 30 Jan 2009 19:46:30 +0000 Subject: [PATCH] ITS#5903 --- CHANGES | 1 + servers/slapd/overlays/memberof.c | 302 +++++++++++++++--------------- 2 files changed, 153 insertions(+), 150 deletions(-) diff --git a/CHANGES b/CHANGES index 01eadf5ff2..7d1a801c34 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ OpenLDAP 2.4.14 Engineering Fixed slapd-ldif numerous bugs (ITS#5408) Fixed slapd-ldif rename on same DN (ITS#5319) Fixed slapd-ldif deadlock (ITS#5329) + Fixed slapo-memberof multiple instantiation (ITS#5903) Fixed slapd-meta double response sending (ITS#5854) Fixed slapd-meta alias deref for retry (ITS#5889) Fixed slapo-accesslog on glued dbs (ITS#5907) diff --git a/servers/slapd/overlays/memberof.c b/servers/slapd/overlays/memberof.c index 72b29ed8df..8c72ad1e6a 100644 --- a/servers/slapd/overlays/memberof.c +++ b/servers/slapd/overlays/memberof.c @@ -178,74 +178,18 @@ typedef enum memberof_is_t { MEMBEROF_IS_BOTH = (MEMBEROF_IS_GROUP|MEMBEROF_IS_MEMBER) } memberof_is_t; -/* - * failover storage for member attribute values of groups being deleted - * handles [no]thread cases. - */ -static BerVarray saved_member_vals; -static BerVarray saved_memberof_vals; - -static void -memberof_saved_member_free( void *key, void *data ) -{ - ber_bvarray_free( (BerVarray)data ); -} - -static BerVarray -memberof_saved_member_get( Operation *op, void *keyp ) -{ - void *vals; - BerVarray *key = (BerVarray *)keyp; - - assert( op != NULL ); - - if ( op->o_threadctx == NULL ) { - vals = *key; - *key = NULL; - - } else { - ldap_pvt_thread_pool_setkey( op->o_threadctx, - key, NULL, 0, &vals, NULL ); - } - - return vals; -} - -static void -memberof_saved_member_set( Operation *op, void *keyp, BerVarray vals ) -{ - BerVarray saved_vals = NULL; - BerVarray *key = (BerVarray*)keyp; - - assert( op != NULL ); - - if ( vals ) { - ber_bvarray_dup_x( &saved_vals, vals, NULL ); - } - - if ( op->o_threadctx == NULL ) { - if ( *key ) { - ber_bvarray_free( *key ); - } - *key = saved_vals; - - } else { - void *old_vals = NULL; - - ldap_pvt_thread_pool_setkey( op->o_threadctx, key, - saved_vals, memberof_saved_member_free, &old_vals, NULL ); - if ( old_vals != NULL ) { - ber_bvarray_free( old_vals ); - } - } -} - typedef struct memberof_cookie_t { AttributeDescription *ad; - void *key; + BerVarray vals; int foundit; } memberof_cookie_t; +typedef struct memberof_cbinfo_t { + slap_overinst *on; + BerVarray member; + BerVarray memberof; +} memberof_cbinfo_t; + static int memberof_isGroupOrMember_cb( Operation *op, SlapReply *rs ) { @@ -269,7 +213,6 @@ memberof_saveMember_cb( Operation *op, SlapReply *rs ) if ( rs->sr_type == REP_SEARCH ) { memberof_cookie_t *mc; Attribute *a; - BerVarray vals = NULL; mc = (memberof_cookie_t *)op->o_callback->sc_private; mc->foundit = 1; @@ -279,11 +222,9 @@ memberof_saveMember_cb( Operation *op, SlapReply *rs ) a = attr_find( rs->sr_entry->e_attrs, mc->ad ); if ( a != NULL ) { - vals = a->a_nvals; + ber_bvarray_dup_x( &mc->vals, a->a_nvals, op->o_tmpmemctx ); } - memberof_saved_member_set( op, mc->key, vals ); - if ( a && attr_find( a->a_next, mc->ad ) != NULL ) { Debug( LDAP_DEBUG_ANY, "%s: memberof_saveMember_cb(\"%s\"): " @@ -303,18 +244,19 @@ memberof_saveMember_cb( Operation *op, SlapReply *rs ) * attribute values of groups being deleted. */ static int -memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp ) +memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp, memberof_cbinfo_t *mci ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; Operation op2 = *op; SlapReply rs2 = { REP_RESULT }; slap_callback cb = { 0 }; - memberof_cookie_t mc; + BackendInfo *bi = op->o_bd->bd_info; AttributeName an[ 2 ]; memberof_is_t iswhat = MEMBEROF_IS_NONE; + memberof_cookie_t mc; assert( iswhatp != NULL ); assert( *iswhatp != MEMBEROF_IS_NONE ); @@ -343,8 +285,8 @@ memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp ) if ( *iswhatp & MEMBEROF_IS_GROUP ) { mc.ad = mo->mo_ad_member; - mc.key = &saved_member_vals; mc.foundit = 0; + mc.vals = NULL; an[ 0 ].an_desc = mo->mo_ad_member; an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname; op2.ors_filterstr = mo->mo_groupFilterstr; @@ -352,20 +294,19 @@ memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp ) op2.o_bd->bd_info = (BackendInfo *)on->on_info; (void)op->o_bd->be_search( &op2, &rs2 ); - op2.o_bd->bd_info = (BackendInfo *)on; + op2.o_bd->bd_info = bi; if ( mc.foundit ) { iswhat |= MEMBEROF_IS_GROUP; + mci->member = mc.vals; - } else { - memberof_saved_member_set( op, mc.key, NULL ); } } if ( *iswhatp & MEMBEROF_IS_MEMBER ) { mc.ad = mo->mo_ad_memberof; - mc.key = &saved_memberof_vals; mc.foundit = 0; + mc.vals = NULL; an[ 0 ].an_desc = mo->mo_ad_memberof; an[ 0 ].an_name = an[ 0 ].an_desc->ad_cname; op2.ors_filterstr = mo->mo_memberFilterstr; @@ -373,13 +314,12 @@ memberof_isGroupOrMember( Operation *op, memberof_is_t *iswhatp ) op2.o_bd->bd_info = (BackendInfo *)on->on_info; (void)op->o_bd->be_search( &op2, &rs2 ); - op2.o_bd->bd_info = (BackendInfo *)on; + op2.o_bd->bd_info = bi; if ( mc.foundit ) { iswhat |= MEMBEROF_IS_MEMBER; + mci->memberof = mc.vals; - } else { - memberof_saved_member_set( op, mc.key, NULL ); } } @@ -402,7 +342,8 @@ memberof_value_modify( struct berval *new_dn, struct berval *new_ndn ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + memberof_cbinfo_t *mci = op->o_callback->sc_private; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; Operation op2 = *op; @@ -417,8 +358,6 @@ memberof_value_modify( op2.o_req_dn = *ndn; op2.o_req_ndn = *ndn; - op2.o_bd->bd_info = (BackendInfo *)on->on_info; - op2.o_callback = &cb; op2.o_dn = op->o_bd->be_rootdn; op2.o_ndn = op->o_bd->be_rootndn; @@ -527,11 +466,29 @@ memberof_value_modify( * not optimal in terms of performance. At least it would * move towards self-repairing capabilities. */ - op2.o_bd->bd_info = (BackendInfo *)on; - return rs2.sr_err; } +static int +memberof_cleanup( Operation *op, SlapReply *rs ) +{ + slap_callback *sc = op->o_callback; + memberof_cbinfo_t *mci = sc->sc_private; + + op->o_callback = sc->sc_next; + if ( mci->memberof ) + ber_bvarray_free_x( mci->memberof, op->o_tmpmemctx ); + if ( mci->member ) + ber_bvarray_free_x( mci->member, op->o_tmpmemctx ); + op->o_tmpfree( sc, op->o_tmpmemctx ); + return 0; +} + +static int memberof_res_add( Operation *op, SlapReply *rs ); +static int memberof_res_delete( Operation *op, SlapReply *rs ); +static int memberof_res_modify( Operation *op, SlapReply *rs ); +static int memberof_res_modrdn( Operation *op, SlapReply *rs ); + static int memberof_op_add( Operation *op, SlapReply *rs ) { @@ -542,6 +499,8 @@ memberof_op_add( Operation *op, SlapReply *rs ) int rc = SLAP_CB_CONTINUE; int i; struct berval save_dn, save_ndn; + slap_callback *sc; + memberof_cbinfo_t *mci; if ( op->ora_e->e_attrs == NULL ) { /* FIXME: global overlay; need to deal with */ @@ -733,7 +692,18 @@ memberof_op_add( Operation *op, SlapReply *rs ) } rc = SLAP_CB_CONTINUE; - + + sc = op->o_tmpalloc( sizeof(slap_callback)+sizeof(*mci), op->o_tmpmemctx ); + sc->sc_private = sc+1; + sc->sc_response = memberof_res_add; + sc->sc_cleanup = memberof_cleanup; + mci = sc->sc_private; + mci->on = on; + mci->member = NULL; + mci->memberof = NULL; + sc->sc_next = op->o_callback; + op->o_callback = sc; + done:; op->o_dn = save_dn; op->o_ndn = save_ndn; @@ -749,12 +719,26 @@ memberof_op_delete( Operation *op, SlapReply *rs ) memberof_t *mo = (memberof_t *)on->on_bi.bi_private; memberof_is_t iswhat = MEMBEROF_IS_GROUP; + slap_callback *sc; + memberof_cbinfo_t *mci; if ( MEMBEROF_REFINT( mo ) ) { iswhat = MEMBEROF_IS_BOTH; } - memberof_isGroupOrMember( op, &iswhat ); + sc = op->o_tmpalloc( sizeof(slap_callback)+sizeof(*mci), op->o_tmpmemctx ); + sc->sc_private = sc+1; + sc->sc_response = memberof_res_delete; + sc->sc_cleanup = memberof_cleanup; + mci = sc->sc_private; + mci->on = on; + mci->member = NULL; + mci->memberof = NULL; + + memberof_isGroupOrMember( op, &iswhat, mci ); + + sc->sc_next = op->o_callback; + op->o_callback = sc; return SLAP_CB_CONTINUE; } @@ -766,9 +750,11 @@ memberof_op_modify( Operation *op, SlapReply *rs ) memberof_t *mo = (memberof_t *)on->on_bi.bi_private; Modifications **mlp, **mmlp = NULL; - int rc = SLAP_CB_CONTINUE; + int rc = SLAP_CB_CONTINUE, save_member = 0; struct berval save_dn, save_ndn; memberof_is_t iswhat = MEMBEROF_IS_GROUP; + slap_callback *sc; + memberof_cbinfo_t *mci, mcis; if ( MEMBEROF_REVERSE( mo ) ) { for ( mlp = &op->orm_modlist; *mlp; mlp = &(*mlp)->sml_next ) { @@ -783,12 +769,12 @@ memberof_op_modify( Operation *op, SlapReply *rs ) save_dn = op->o_dn; save_ndn = op->o_ndn; + mcis.on = on; - if ( memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS + if ( memberof_isGroupOrMember( op, &iswhat, &mcis ) == LDAP_SUCCESS && ( iswhat & MEMBEROF_IS_GROUP ) ) { Modifications *ml; - int save_member = 0; for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { if ( ml->sml_desc == mo->mo_ad_member ) { @@ -801,20 +787,6 @@ memberof_op_modify( Operation *op, SlapReply *rs ) } } - if ( save_member ) { - BerVarray vals = NULL; - - op->o_dn = op->o_bd->be_rootdn; - op->o_ndn = op->o_bd->be_rootndn; - op->o_bd->bd_info = (BackendInfo *)on->on_info; - rc = backend_attribute( op, NULL, &op->o_req_ndn, - mo->mo_ad_member, &vals, ACL_READ ); - op->o_bd->bd_info = (BackendInfo *)on; - if ( rc == LDAP_SUCCESS && vals != NULL ) { - memberof_saved_member_set( op, &saved_member_vals, vals ); - ber_bvarray_free_x( vals, op->o_tmpmemctx ); - } - } if ( MEMBEROF_DANGLING_CHECK( mo ) && !get_relax( op ) ) @@ -1147,6 +1119,27 @@ done2:; op->o_bd->bd_info = (BackendInfo *)on; } + sc = op->o_tmpalloc( sizeof(slap_callback)+sizeof(*mci), op->o_tmpmemctx ); + sc->sc_private = sc+1; + sc->sc_response = memberof_res_modify; + sc->sc_cleanup = memberof_cleanup; + mci = sc->sc_private; + mci->on = on; + mci->member = NULL; + mci->memberof = NULL; + + if ( save_member ) { + op->o_dn = op->o_bd->be_rootdn; + op->o_ndn = op->o_bd->be_rootndn; + op->o_bd->bd_info = (BackendInfo *)on->on_info; + rc = backend_attribute( op, NULL, &op->o_req_ndn, + mo->mo_ad_member, &mci->member, ACL_READ ); + op->o_bd->bd_info = (BackendInfo *)on; + } + + sc->sc_next = op->o_callback; + op->o_callback = sc; + rc = SLAP_CB_CONTINUE; done:; @@ -1157,34 +1150,60 @@ done:; return rc; } +static int +memberof_op_modrdn( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + slap_callback *sc; + memberof_cbinfo_t *mci; + + sc = op->o_tmpalloc( sizeof(slap_callback)+sizeof(*mci), op->o_tmpmemctx ); + sc->sc_private = sc+1; + sc->sc_response = memberof_res_modrdn; + sc->sc_cleanup = memberof_cleanup; + mci = sc->sc_private; + mci->on = on; + mci->member = NULL; + mci->memberof = NULL; + + sc->sc_next = op->o_callback; + op->o_callback = sc; + + return SLAP_CB_CONTINUE; +} + /* * response callback that adds memberof values when a group is added. */ static int memberof_res_add( Operation *op, SlapReply *rs ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + memberof_cbinfo_t *mci = op->o_callback->sc_private; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; int i; + if ( rs->sr_err != LDAP_SUCCESS ) { + return SLAP_CB_CONTINUE; + } + if ( MEMBEROF_REVERSE( mo ) ) { Attribute *ma; ma = attr_find( op->ora_e->e_attrs, mo->mo_ad_memberof ); if ( ma != NULL ) { - Operation op2 = *op; - SlapReply rs2 = { 0 }; + char relax = op->o_relax; /* relax is required to allow to add * a non-existing member */ - op2.o_relax = SLAP_CONTROL_CRITICAL; + op->o_relax = SLAP_CONTROL_CRITICAL; for ( i = 0; !BER_BVISNULL( &ma->a_nvals[ i ] ); i++ ) { /* the modification is attempted * with the original identity */ - (void)memberof_value_modify( &op2, &rs2, + (void)memberof_value_modify( op, rs, &ma->a_nvals[ i ], mo->mo_ad_member, NULL, NULL, &op->o_req_dn, &op->o_req_ndn ); } @@ -1218,13 +1237,18 @@ memberof_res_add( Operation *op, SlapReply *rs ) static int memberof_res_delete( Operation *op, SlapReply *rs ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + memberof_cbinfo_t *mci = op->o_callback->sc_private; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; BerVarray vals; int i; - vals = memberof_saved_member_get( op, &saved_member_vals ); + if ( rs->sr_err != LDAP_SUCCESS ) { + return SLAP_CB_CONTINUE; + } + + vals = mci->member; if ( vals != NULL ) { for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { (void)memberof_value_modify( op, rs, @@ -1232,13 +1256,10 @@ memberof_res_delete( Operation *op, SlapReply *rs ) &op->o_req_dn, &op->o_req_ndn, NULL, NULL ); } - - memberof_saved_member_set( op, &saved_memberof_vals, NULL ); - ber_bvarray_free( vals ); } if ( MEMBEROF_REFINT( mo ) ) { - vals = memberof_saved_member_get( op, &saved_memberof_vals ); + vals = mci->memberof; if ( vals != NULL ) { for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { (void)memberof_value_modify( op, rs, @@ -1246,9 +1267,6 @@ memberof_res_delete( Operation *op, SlapReply *rs ) &op->o_req_dn, &op->o_req_ndn, NULL, NULL ); } - - memberof_saved_member_set( op, &saved_member_vals, NULL ); - ber_bvarray_free( vals ); } } @@ -1262,7 +1280,8 @@ memberof_res_delete( Operation *op, SlapReply *rs ) static int memberof_res_modify( Operation *op, SlapReply *rs ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + memberof_cbinfo_t *mci = op->o_callback->sc_private; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; int i, rc; @@ -1270,6 +1289,10 @@ memberof_res_modify( Operation *op, SlapReply *rs ) BerVarray vals; memberof_is_t iswhat = MEMBEROF_IS_GROUP; + if ( rs->sr_err != LDAP_SUCCESS ) { + return SLAP_CB_CONTINUE; + } + if ( MEMBEROF_REVERSE( mo ) ) { for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { if ( ml->sml_desc == mo->mo_ad_memberof ) { @@ -1332,7 +1355,7 @@ memberof_res_modify( Operation *op, SlapReply *rs ) } } - if ( memberof_isGroupOrMember( op, &iswhat ) == LDAP_SUCCESS + if ( memberof_isGroupOrMember( op, &iswhat, mci ) == LDAP_SUCCESS && ( iswhat & MEMBEROF_IS_GROUP ) ) { for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { @@ -1355,7 +1378,7 @@ memberof_res_modify( Operation *op, SlapReply *rs ) /* fall thru */ case LDAP_MOD_REPLACE: - vals = memberof_saved_member_get( op, &saved_member_vals ); + vals = mci->member; /* delete all ... */ if ( vals != NULL ) { @@ -1365,7 +1388,6 @@ memberof_res_modify( Operation *op, SlapReply *rs ) &op->o_req_dn, &op->o_req_ndn, NULL, NULL ); } - ber_bvarray_free_x( vals, op->o_tmpmemctx ); } if ( ml->sml_op == LDAP_MOD_DELETE || !ml->sml_values ) { @@ -1395,12 +1417,13 @@ memberof_res_modify( Operation *op, SlapReply *rs ) /* * response callback that adds/deletes member values when a group member - * is modified. + * is renamed. */ static int -memberof_res_rename( Operation *op, SlapReply *rs ) +memberof_res_modrdn( Operation *op, SlapReply *rs ) { - slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + memberof_cbinfo_t *mci = op->o_callback->sc_private; + slap_overinst *on = mci->on; memberof_t *mo = (memberof_t *)on->on_bi.bi_private; struct berval newPDN, newDN = BER_BVNULL, newPNDN, newNDN; @@ -1410,6 +1433,10 @@ memberof_res_rename( Operation *op, SlapReply *rs ) struct berval save_dn, save_ndn; memberof_is_t iswhat = MEMBEROF_IS_GROUP; + if ( rs->sr_err != LDAP_SUCCESS ) { + return SLAP_CB_CONTINUE; + } + if ( MEMBEROF_REFINT( mo ) ) { iswhat |= MEMBEROF_IS_MEMBER; } @@ -1428,7 +1455,7 @@ memberof_res_rename( Operation *op, SlapReply *rs ) op->o_req_dn = newNDN; op->o_req_ndn = newNDN; - rc = memberof_isGroupOrMember( op, &iswhat ); + rc = memberof_isGroupOrMember( op, &iswhat, mci ); op->o_req_dn = save_dn; op->o_req_ndn = save_ndn; @@ -1488,30 +1515,6 @@ done:; return SLAP_CB_CONTINUE; } -static int -memberof_response( Operation *op, SlapReply *rs ) -{ - if ( rs->sr_err != LDAP_SUCCESS ) { - return SLAP_CB_CONTINUE; - } - - switch ( op->o_tag ) { - case LDAP_REQ_ADD: - return memberof_res_add( op, rs ); - - case LDAP_REQ_DELETE: - return memberof_res_delete( op, rs ); - - case LDAP_REQ_MODIFY: - return memberof_res_modify( op, rs ); - - case LDAP_REQ_MODDN: - return memberof_res_rename( op, rs ); - - default: - return SLAP_CB_CONTINUE; - } -} static int memberof_db_init( @@ -2057,8 +2060,7 @@ memberof_initialize( void ) memberof.on_bi.bi_op_add = memberof_op_add; memberof.on_bi.bi_op_delete = memberof_op_delete; memberof.on_bi.bi_op_modify = memberof_op_modify; - - memberof.on_response = memberof_response; + memberof.on_bi.bi_op_modrdn = memberof_op_modrdn; memberof.on_bi.bi_cf_ocs = mo_ocs; -- 2.39.5