]> git.sur5r.net Git - openldap/blobdiff - contrib/slapd-modules/autogroup/autogroup.c
Merge remote-tracking branch 'origin/mdb.RE/0.9'
[openldap] / contrib / slapd-modules / autogroup / autogroup.c
index 06e140789f1ac65558c2c91282122fea3153cec3..eb755bea5bd3bbd22acfac76d2441975081c517b 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2007-2013 The OpenLDAP Foundation.
+ * Copyright 2007-2014 The OpenLDAP Foundation.
  * Portions Copyright 2007 Michał Szulczyński.
  * Portions Copyright 2009 Howard Chu.
  * All rights reserved.
@@ -136,6 +136,8 @@ autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autog
        o.o_tag = LDAP_REQ_MODIFY;
        o.o_callback = &cb;
        o.orm_modlist = modlist;
+       o.o_dn = op->o_bd->be_rootdn;
+       o.o_ndn = op->o_bd->be_rootndn;
        o.o_req_dn = age->age_dn;
        o.o_req_ndn = age->age_ndn;
        o.o_permissive_modify = 1;
@@ -156,24 +158,16 @@ autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autog
 **     age     - the group to which the values will be added
 */
 static int
-autogroup_add_member_values_to_group( Operation *op, Entry *e, autogroup_entry_t *age, AttributeDescription *attrdesc )
+autogroup_add_member_values_to_group( Operation *op, struct berval *dn, autogroup_entry_t *age, Attribute *attr )
 {
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
        Modifications   modlist;
        SlapReply       sreply = {REP_RESULT};
-       Attribute       *attr;
        slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
        Operation       o = *op;
 
-       assert( e != NULL );
        Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_values_to_group adding <%s> to <%s>\n",
-               e->e_name.bv_val, age->age_dn.bv_val, 0);
-
-       attr = attrs_find( e->e_attrs, attrdesc );
-       if (!attr) {
-               // Nothing to add
-               return LDAP_SUCCESS;
-       }
+               dn->bv_val, age->age_dn.bv_val, 0);
 
        modlist.sml_op = LDAP_MOD_ADD;
        modlist.sml_desc = age->age_def->agd_member_ad;
@@ -187,6 +181,8 @@ autogroup_add_member_values_to_group( Operation *op, Entry *e, autogroup_entry_t
        o.o_tag = LDAP_REQ_MODIFY;
        o.o_callback = &cb;
        o.orm_modlist = &modlist;
+       o.o_dn = op->o_bd->be_rootdn;
+       o.o_ndn = op->o_bd->be_rootndn;
        o.o_req_dn = age->age_dn;
        o.o_req_ndn = age->age_ndn;
        o.o_permissive_modify = 1;
@@ -248,6 +244,8 @@ autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn,
        o.o_callback = &cb;
        o.o_tag = LDAP_REQ_MODIFY;
        o.orm_modlist = modlist;
+       o.o_dn = op->o_bd->be_rootdn;
+       o.o_ndn = op->o_bd->be_rootndn;
        o.o_req_dn = age->age_dn;
        o.o_req_ndn = age->age_ndn;
        o.o_relax = SLAP_CONTROL_CRITICAL;
@@ -268,24 +266,16 @@ autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn,
 **      age     - the group from which the values will be deleted
 */
 static int
-autogroup_delete_member_values_from_group( Operation *op, Entry *e, autogroup_entry_t *age, AttributeDescription *attrdesc )
+autogroup_delete_member_values_from_group( Operation *op, struct berval *dn, autogroup_entry_t *age, Attribute *attr )
 {
         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
         Modifications   modlist;
         SlapReply       sreply = {REP_RESULT};
-        Attribute       *attr;
         slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
         Operation       o = *op;
 
-        assert( e != NULL );
         Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_values_from_group removing <%s> from <%s>\n",
-                e->e_name.bv_val, age->age_dn.bv_val, 0);
-
-        attr = attrs_find( e->e_attrs, attrdesc );
-        if (!attr) {
-                // Nothing to add
-                return LDAP_SUCCESS;
-        }
+                       dn->bv_val, age->age_dn.bv_val, 0);
 
         modlist.sml_op = LDAP_MOD_DELETE;
         modlist.sml_desc = age->age_def->agd_member_ad;
@@ -299,6 +289,8 @@ autogroup_delete_member_values_from_group( Operation *op, Entry *e, autogroup_en
         o.o_tag = LDAP_REQ_MODIFY;
         o.o_callback = &cb;
         o.orm_modlist = &modlist;
+               o.o_dn = op->o_bd->be_rootdn;
+               o.o_ndn = op->o_bd->be_rootndn;
         o.o_req_dn = age->age_dn;
         o.o_req_ndn = age->age_ndn;
         o.o_permissive_modify = 1;
@@ -331,6 +323,7 @@ autogroup_member_search_cb( Operation *op, SlapReply *rs )
                const char              *text = NULL;
                char                    textbuf[1024];
                struct berval           *vals, *nvals;
+               struct berval           lvals[ 2 ], lnvals[ 2 ];
                int                     numvals;
 
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
@@ -347,7 +340,6 @@ autogroup_member_search_cb( Operation *op, SlapReply *rs )
                                return 0;
                        }
                } else {
-                       struct berval           lvals[ 2 ], lnvals[ 2 ];
                        lvals[ 0 ] = rs->sr_entry->e_name;
                        BER_BVZERO( &lvals[ 1 ] );
                        lnvals[ 0 ] = rs->sr_entry->e_nname;
@@ -387,6 +379,7 @@ autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
                autogroup_filter_t      *agf = agg->agg_filter;
                Modifications           *modlist;
                struct berval           *vals, *nvals;
+               struct berval           lvals[ 2 ], lnvals[ 2 ];
                int                     numvals;
 
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
@@ -403,7 +396,6 @@ autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
                                return 0;
                        }
                } else {
-                       struct berval           lvals[ 2 ], lnvals[ 2 ];
                        lvals[ 0 ] = rs->sr_entry->e_name;
                        BER_BVZERO( &lvals[ 1 ] );
                        lnvals[ 0 ] = rs->sr_entry->e_nname;
@@ -467,6 +459,8 @@ autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *a
        o.ors_attrsonly = 0;
        o.o_tag = LDAP_REQ_SEARCH;
 
+       o.o_dn = op->o_bd->be_rootdn;
+       o.o_ndn = op->o_bd->be_rootndn;
        o.o_req_dn = agf->agf_dn;
        o.o_req_ndn = agf->agf_ndn;
 
@@ -509,6 +503,8 @@ autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *a
                o.o_callback = &null_cb;
                o.o_tag = LDAP_REQ_MODIFY;
                o.orm_modlist = agg.agg_mod;
+               o.o_dn = op->o_bd->be_rootdn;
+               o.o_ndn = op->o_bd->be_rootndn;
                o.o_req_dn = age->age_dn;
                o.o_req_ndn = age->age_ndn;
                o.o_relax = SLAP_CONTROL_CRITICAL;
@@ -620,7 +616,11 @@ autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd,
                        if ( lud->lud_filter != NULL ) {
                                ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr);
                                agf->agf_filter = str2filter( lud->lud_filter );
-                       }                       
+                       } else {
+                               Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: URL filter is missing <%s>\n", bv->bv_val,0,0);
+                               /* FIXME: error? */
+                               goto cleanup;
+                       }
 
                        if ( lud->lud_attrs != NULL ) {
                                int i;
@@ -633,26 +633,33 @@ autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd,
                                        Debug( LDAP_DEBUG_ANY, "autogroup_add_group: too many attributes specified in url <%s>\n",
                                                bv->bv_val, 0, 0);
                                        /* FIXME: error? */
+                                       filter_free( agf->agf_filter );
+                                       ch_free( agf->agf_filterstr.bv_val );
+                                       ch_free( agf->agf_dn.bv_val );
+                                       ch_free( agf->agf_ndn.bv_val );
                                        ldap_free_urldesc( lud );
-                                       ch_free( agf ); 
+                                       ch_free( agf );
                                        continue;
                                }
-                                       
+
                                agf->agf_anlist = str2anlist( NULL, lud->lud_attrs[0], "," );
 
                                if ( agf->agf_anlist == NULL ) {
                                        Debug( LDAP_DEBUG_ANY, "autogroup_add_group: unable to find AttributeDescription \"%s\".\n",
-                                               lud->lud_attrs[0], 0, 0 );              
+                                               lud->lud_attrs[0], 0, 0 );
                                        /* FIXME: error? */
+                                       filter_free( agf->agf_filter );
+                                       ch_free( agf->agf_filterstr.bv_val );
+                                       ch_free( agf->agf_dn.bv_val );
+                                       ch_free( agf->agf_ndn.bv_val );
                                        ldap_free_urldesc( lud );
-                                       ch_free( agf ); 
+                                       ch_free( agf );
                                        continue;
                                }
                        }
 
                        agf->agf_next = NULL;
 
-
                        if( (*agep)->age_filter == NULL ) {
                                (*agep)->age_filter = agf;
                        }
@@ -677,6 +684,8 @@ autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd,
 
 cleanup:;
 
+                       ch_free( agf->agf_ndn.bv_val );
+                       ch_free( agf->agf_dn.bv_val );
                        ldap_free_urldesc( lud );                               
                        ch_free( agf ); 
                }
@@ -709,6 +718,66 @@ autogroup_group_add_cb( Operation *op, SlapReply *rs )
        return 0;
 }
 
+typedef struct ag_addinfo {
+       slap_overinst *on;
+       Entry *e;
+       autogroup_def_t         *agd;
+} ag_addinfo;
+
+static int
+autogroup_add_entry_cb( Operation *op, SlapReply *rs )
+{
+       slap_callback *sc = op->o_callback;
+       ag_addinfo *aa = sc->sc_private;
+       slap_overinst *on = aa->on;
+       autogroup_info_t        *agi = (autogroup_info_t *)on->on_bi.bi_private;
+       BackendInfo *bi = op->o_bd->bd_info;
+
+       if ( rs->sr_err != LDAP_SUCCESS )
+               goto done;
+
+       op->o_bd->bd_info = (BackendInfo *)on;
+       ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
+       if ( aa->agd ) {
+               autogroup_add_group( op, agi, aa->agd, aa->e, NULL, 1 , 0);
+       } else {
+               autogroup_entry_t       *age;
+               autogroup_filter_t      *agf;
+               int rc;
+               for ( age = agi->agi_entry; age ; age = age->age_next ) {
+                       ldap_pvt_thread_mutex_lock( &age->age_mutex );
+
+                       /* Check if any of the filters are the suffix to the entry DN.
+                          If yes, we can test that filter against the entry. */
+
+                       for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
+                               if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
+                                       rc = test_filter( op, aa->e, agf->agf_filter );
+                                       if ( rc == LDAP_COMPARE_TRUE ) {
+                                               if ( agf->agf_anlist ) {
+                                                       Attribute *a = attr_find( aa->e->e_attrs, agf->agf_anlist[0].an_desc );
+                                                       if ( a )
+                                                               autogroup_add_member_values_to_group( op, &op->o_req_dn, age, a );
+                                               } else {
+                                                       autogroup_add_member_to_group( op, &aa->e->e_name, &aa->e->e_nname, age );
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
+                       ldap_pvt_thread_mutex_unlock( &age->age_mutex );
+               }
+       }
+       ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
+
+       op->o_bd->bd_info = bi;
+
+done:
+       op->o_callback = sc->sc_next;
+       op->o_tmpfree( sc, op->o_tmpmemctx );
+
+       return SLAP_CB_CONTINUE;
+}
 
 /*
 ** When adding a group, we first strip any existing members,
@@ -720,14 +789,21 @@ autogroup_add_entry( Operation *op, SlapReply *rs)
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
        autogroup_info_t        *agi = (autogroup_info_t *)on->on_bi.bi_private;
        autogroup_def_t         *agd = agi->agi_def;
-       autogroup_entry_t       *age;
-       autogroup_filter_t      *agf;
+       slap_callback   *sc = NULL;
+       ag_addinfo      *aa = NULL;
        int                     rc = 0;
 
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n", 
                op->ora_e->e_name.bv_val, 0, 0);
 
-       ldap_pvt_thread_mutex_lock( &agi->agi_mutex );          
+       sc = op->o_tmpcalloc( sizeof(slap_callback) + sizeof(ag_addinfo), 1, op->o_tmpmemctx );
+       sc->sc_private = (sc+1);
+       sc->sc_response = autogroup_add_entry_cb;
+       aa = sc->sc_private;
+       aa->on = on;
+       aa->e = op->ora_e;
+       sc->sc_next = op->o_callback;
+       op->o_callback = sc;
 
        /* Check if it's a group. */
        for ( ; agd ; agd = agd->agd_next ) {
@@ -745,37 +821,12 @@ autogroup_add_entry( Operation *op, SlapReply *rs)
                        /* We don't want any member attributes added by the user. */
                        modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
 
-                       autogroup_add_group( op, agi, agd, op->ora_e, NULL, 1 , 0);
-                       ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
-                       return SLAP_CB_CONTINUE;
-               }
-       }
-
-       
-       for ( age = agi->agi_entry; age ; age = age->age_next ) {
-               ldap_pvt_thread_mutex_lock( &age->age_mutex );          
-
-               /* Check if any of the filters are the suffix to the entry DN. 
-                  If yes, we can test that filter against the entry. */
+                       aa->agd = agd;
 
-               for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
-                       if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
-                               rc = test_filter( op, op->ora_e, agf->agf_filter );
-                               if ( rc == LDAP_COMPARE_TRUE ) {
-                                       if ( agf->agf_anlist ) {
-                                               autogroup_add_member_values_to_group( op, op->ora_e, age, agf->agf_anlist[0].an_desc );
-                                       } else {
-                                               autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
-                                       }
-                                       break;
-                               }
-                       }
+                       break;
                }
-               ldap_pvt_thread_mutex_unlock( &age->age_mutex );                
        }
 
-       ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
-
        return SLAP_CB_CONTINUE;
 }
 
@@ -929,7 +980,7 @@ autogroup_response( Operation *op, SlapReply *rs )
        autogroup_filter_t      *agf;
        BerValue                new_dn, new_ndn, pdn;
        Entry                   *e, *group;
-       Attribute               *a, *ea;
+       Attribute               *a, *ea, *attrs;
        int                     is_olddn, is_newdn, is_value_refresh, dn_equal;
 
        /* Handle all cases where a refresh of the group is needed */
@@ -1038,16 +1089,17 @@ autogroup_response( Operation *op, SlapReply *rs )
                                and add it's DN to the group.
                           If 1 is true, and 2 is false, we delete the entry's DN from the group.
                        */
+                       attrs = attrs_dup( e->e_attrs );
+                       overlay_entry_release_ov( op, e, 0, on );
                        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
                                is_olddn = 0;
                                is_newdn = 0;
                                is_value_refresh = 0;
 
-
                                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
                                if ( age->age_filter && age->age_filter->agf_anlist ) {
-                                       ea = attrs_find( e->e_attrs, age->age_filter->agf_anlist[0].an_desc );
+                                       ea = attrs_find( attrs, age->age_filter->agf_anlist[0].an_desc );
                                }
                                else {
                                        ea = NULL;
@@ -1067,7 +1119,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                                                op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
                                                op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
 
-                                               overlay_entry_release_ov( op, e, 0, on );
+                                               attrs_free( attrs );
                                                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
                                                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
                                                return SLAP_CB_CONTINUE;
@@ -1113,16 +1165,16 @@ autogroup_response( Operation *op, SlapReply *rs )
                                }
                                if ( is_olddn == 1 && is_newdn == 0 ) {
                                        if ( ea )
-                                               autogroup_delete_member_values_from_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
+                                               autogroup_delete_member_values_from_group( op, &new_dn, age, ea );
                                        else
                                                autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
                                } else
                                if ( is_olddn == 0 && is_newdn == 1 ) {
                                        for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
                                                if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
-                                                       if ( ea )
-                                                               autogroup_add_member_values_to_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
-                                                       else
+                                                       if ( ea ) {
+                                                               autogroup_add_member_values_to_group( op, &new_dn, age, ea );
+                                                       else
                                                                autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
                                                        break;
                                                }
@@ -1149,7 +1201,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                        op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
                        op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
 
-                       overlay_entry_release_ov( op, e, 0, on );
+                       attrs_free( attrs );
 
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                        
                }
@@ -1212,7 +1264,6 @@ autogroup_response( Operation *op, SlapReply *rs )
 
                                                                        autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
 
-                                                                       overlay_entry_release_ov( op, e, 0, on );
                                                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
                                                                        return SLAP_CB_CONTINUE;
                                                                }
@@ -1231,7 +1282,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                                }
                        }
 
-                       /* When modifing any of the attributes of an entry, we must
+                       /* When modifying any of the attributes of an entry, we must
                           check if the entry is in any of our groups, and if
                           the modified entry maches any of the filters of that group.
 
@@ -1240,6 +1291,8 @@ autogroup_response( Operation *op, SlapReply *rs )
                           If the entry doesn't exist in a group, but matches a filter, 
                                we add it to that group.
                        */
+                       attrs = attrs_dup( e->e_attrs );
+                       overlay_entry_release_ov( op, e, 0, on );
                        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
                                is_olddn = 0;
                                is_newdn = 0;
@@ -1248,7 +1301,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
                                if ( age->age_filter && age->age_filter->agf_anlist ) {
-                                       ea = attrs_find( e->e_attrs, age->age_filter->agf_anlist[0].an_desc );
+                                       ea = attrs_find( attrs, age->age_filter->agf_anlist[0].an_desc );
                                }
                                else {
                                        ea = NULL;
@@ -1259,7 +1312,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", 
                                                age->age_dn.bv_val, 0, 0);
 
-                                       overlay_entry_release_ov( op, e, 0, on );
+                                       attrs_free( attrs );
                                        ldap_pvt_thread_mutex_unlock( &age->age_mutex );
                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
                                        return SLAP_CB_CONTINUE;
@@ -1291,13 +1344,13 @@ autogroup_response( Operation *op, SlapReply *rs )
 
                                if ( is_olddn == 1 && is_newdn == 0 ) {
                                        if(ea)
-                                               autogroup_delete_member_values_from_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
+                                               autogroup_delete_member_values_from_group( op, &op->o_req_dn, age, ea );
                                        else
                                                autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
                                } else
                                if ( is_olddn == 0 && is_newdn == 1 ) {
                                        if(ea)
-                                               autogroup_add_member_values_to_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
+                                               autogroup_add_member_values_to_group( op, &op->o_req_dn, age, ea );
                                        else
                                                autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
                                } 
@@ -1305,7 +1358,7 @@ autogroup_response( Operation *op, SlapReply *rs )
                                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
                        }
 
-                       overlay_entry_release_ov( op, e, 0, on );
+                       attrs_free( attrs );
 
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
                }
@@ -1528,7 +1581,7 @@ static ConfigDriver       ag_cfgen;
 
 static ConfigTable agcfg[] = {
        { "autogroup-attrset", "group-oc> <URL-ad> <member-ad",
-               3, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
+               4, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
                "( OLcfgCtAt:2.1 NAME 'olcAGattrSet' "
                        "DESC 'Automatic groups: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
                        "EQUALITY caseIgnoreMatch "