Commit 30a0d07a authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#5903

parent 5199cdb5
......@@ -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)
......
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment