autogroup.c revision 1.2 1 1.2 christos /* $NetBSD: autogroup.c,v 1.2 2020/08/11 13:15:35 christos Exp $ */
2 1.2 christos
3 1.1 lukem /* autogroup.c - automatic group overlay */
4 1.2 christos /* $OpenLDAP$ */
5 1.2 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.2 christos *
7 1.2 christos * Copyright 2007-2020 The OpenLDAP Foundation.
8 1.2 christos * Portions Copyright 2007 Micha Szulczyski.
9 1.2 christos * Portions Copyright 2009 Howard Chu.
10 1.1 lukem * All rights reserved.
11 1.1 lukem *
12 1.1 lukem * Redistribution and use in source and binary forms, with or without
13 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
14 1.1 lukem * Public License.
15 1.1 lukem *
16 1.1 lukem * A copy of this license is available in the file LICENSE in the
17 1.1 lukem * top-level directory of the distribution or, alternatively, at
18 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
19 1.1 lukem */
20 1.2 christos /* ACKNOWLEDGEMENTS:
21 1.2 christos * This work was initially developed by Micha Szulczyski for inclusion in
22 1.2 christos * OpenLDAP Software. Additional significant contributors include:
23 1.2 christos * Howard Chu
24 1.2 christos * Raphael Ouazana
25 1.2 christos * Norbert Pueschel
26 1.2 christos * Christian Manal
27 1.2 christos */
28 1.2 christos
29 1.2 christos #include <sys/cdefs.h>
30 1.2 christos __RCSID("$NetBSD: autogroup.c,v 1.2 2020/08/11 13:15:35 christos Exp $");
31 1.1 lukem
32 1.1 lukem #include "portable.h"
33 1.1 lukem
34 1.1 lukem #include <stdio.h>
35 1.1 lukem
36 1.1 lukem #include <ac/string.h>
37 1.1 lukem
38 1.1 lukem #include "slap.h"
39 1.1 lukem #include "config.h"
40 1.1 lukem #include "lutil.h"
41 1.1 lukem
42 1.2 christos #ifndef SLAPD_MEMBEROF_ATTR
43 1.2 christos #define SLAPD_MEMBEROF_ATTR "memberOf"
44 1.2 christos #endif
45 1.2 christos
46 1.2 christos static slap_overinst autogroup;
47 1.2 christos
48 1.1 lukem /* Filter represents the memberURL of a group. */
49 1.1 lukem typedef struct autogroup_filter_t {
50 1.1 lukem struct berval agf_dn; /* The base DN in memberURL */
51 1.1 lukem struct berval agf_ndn;
52 1.1 lukem struct berval agf_filterstr;
53 1.1 lukem Filter *agf_filter;
54 1.1 lukem int agf_scope;
55 1.2 christos AttributeName *agf_anlist;
56 1.1 lukem struct autogroup_filter_t *agf_next;
57 1.1 lukem } autogroup_filter_t;
58 1.1 lukem
59 1.1 lukem /* Description of group attributes. */
60 1.1 lukem typedef struct autogroup_def_t {
61 1.1 lukem ObjectClass *agd_oc;
62 1.1 lukem AttributeDescription *agd_member_url_ad;
63 1.1 lukem AttributeDescription *agd_member_ad;
64 1.1 lukem struct autogroup_def_t *agd_next;
65 1.1 lukem } autogroup_def_t;
66 1.1 lukem
67 1.1 lukem /* Represents the group entry. */
68 1.1 lukem typedef struct autogroup_entry_t {
69 1.1 lukem BerValue age_dn;
70 1.1 lukem BerValue age_ndn;
71 1.1 lukem autogroup_filter_t *age_filter; /* List of filters made from memberURLs */
72 1.1 lukem autogroup_def_t *age_def; /* Attribute definition */
73 1.1 lukem ldap_pvt_thread_mutex_t age_mutex;
74 1.2 christos int age_mustrefresh; /* Defined in request to refresh in response */
75 1.2 christos int age_modrdn_olddnmodified; /* Defined in request to refresh in response */
76 1.1 lukem struct autogroup_entry_t *age_next;
77 1.1 lukem } autogroup_entry_t;
78 1.1 lukem
79 1.1 lukem /* Holds pointers to attribute definitions and groups. */
80 1.1 lukem typedef struct autogroup_info_t {
81 1.1 lukem autogroup_def_t *agi_def; /* Group attributes definitions. */
82 1.1 lukem autogroup_entry_t *agi_entry; /* Group entries. */
83 1.2 christos AttributeDescription *agi_memberof_ad; /* memberOf attribute description */
84 1.1 lukem ldap_pvt_thread_mutex_t agi_mutex;
85 1.1 lukem } autogroup_info_t;
86 1.1 lukem
87 1.1 lukem /* Search callback for adding groups initially. */
88 1.1 lukem typedef struct autogroup_sc_t {
89 1.1 lukem autogroup_info_t *ags_info; /* Group definitions and entries. */
90 1.1 lukem autogroup_def_t *ags_def; /* Attributes definition of the group being added. */
91 1.1 lukem } autogroup_sc_t;
92 1.1 lukem
93 1.1 lukem /* Used for adding members, found when searching, to a group. */
94 1.1 lukem typedef struct autogroup_ga_t {
95 1.1 lukem autogroup_entry_t *agg_group; /* The group to which the members will be added. */
96 1.2 christos autogroup_filter_t *agg_filter; /* Current filter */
97 1.1 lukem Entry *agg_entry; /* Used in autogroup_member_search_cb to modify
98 1.1 lukem this entry with the search results. */
99 1.1 lukem
100 1.1 lukem Modifications *agg_mod; /* Used in autogroup_member_search_modify_cb to hold the
101 1.1 lukem search results which will be added to the group. */
102 1.1 lukem
103 1.1 lukem Modifications *agg_mod_last; /* Used in autogroup_member_search_modify_cb so we don't
104 1.1 lukem have to search for the last mod added. */
105 1.1 lukem } autogroup_ga_t;
106 1.1 lukem
107 1.1 lukem
108 1.1 lukem /*
109 1.1 lukem ** dn, ndn - the DN of the member to add
110 1.1 lukem ** age - the group to which the member DN will be added
111 1.1 lukem */
112 1.1 lukem static int
113 1.1 lukem autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
114 1.1 lukem {
115 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
116 1.2 christos Modifications *modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
117 1.1 lukem SlapReply sreply = {REP_RESULT};
118 1.2 christos BerValue *vals, *nvals;
119 1.1 lukem slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
120 1.1 lukem Operation o = *op;
121 1.2 christos unsigned long opid = op->o_opid;
122 1.2 christos OpExtra oex;
123 1.1 lukem
124 1.2 christos assert( dn != NULL );
125 1.2 christos assert( ndn != NULL );
126 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_to_group adding <%s> to <%s>\n",
127 1.1 lukem dn->bv_val, age->age_dn.bv_val, 0);
128 1.1 lukem
129 1.2 christos vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
130 1.2 christos nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
131 1.2 christos ber_dupbv( vals, dn );
132 1.1 lukem BER_BVZERO( &vals[ 1 ] );
133 1.2 christos ber_dupbv( nvals, ndn );
134 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
135 1.1 lukem
136 1.2 christos modlist->sml_op = LDAP_MOD_ADD;
137 1.2 christos modlist->sml_desc = age->age_def->agd_member_ad;
138 1.2 christos modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
139 1.2 christos modlist->sml_values = vals;
140 1.2 christos modlist->sml_nvalues = nvals;
141 1.2 christos modlist->sml_numvals = 1;
142 1.2 christos modlist->sml_flags = SLAP_MOD_INTERNAL;
143 1.2 christos modlist->sml_next = NULL;
144 1.2 christos
145 1.2 christos o.o_opid = 0; /* shared with op, saved above */
146 1.2 christos o.o_tag = LDAP_REQ_MODIFY;
147 1.2 christos o.o_callback = &cb;
148 1.2 christos o.orm_modlist = modlist;
149 1.2 christos o.o_dn = op->o_bd->be_rootdn;
150 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
151 1.2 christos o.o_req_dn = age->age_dn;
152 1.2 christos o.o_req_ndn = age->age_ndn;
153 1.2 christos o.o_permissive_modify = 1;
154 1.2 christos o.o_dont_replicate = 1;
155 1.2 christos o.orm_no_opattrs = 1;
156 1.2 christos o.o_managedsait = SLAP_CONTROL_CRITICAL;
157 1.2 christos o.o_relax = SLAP_CONTROL_CRITICAL;
158 1.2 christos
159 1.2 christos oex.oe_key = (void *)&autogroup;
160 1.2 christos LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
161 1.2 christos
162 1.2 christos o.o_bd->bd_info = (BackendInfo *)on->on_info;
163 1.2 christos (void)op->o_bd->be_modify( &o, &sreply );
164 1.2 christos o.o_bd->bd_info = (BackendInfo *)on;
165 1.2 christos
166 1.2 christos LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
167 1.2 christos
168 1.2 christos slap_mods_free( modlist, 1 );
169 1.2 christos op->o_opid = opid;
170 1.2 christos
171 1.2 christos return sreply.sr_err;
172 1.2 christos }
173 1.2 christos
174 1.2 christos /*
175 1.2 christos ** e - the entry where to get the attribute values
176 1.2 christos ** age - the group to which the values will be added
177 1.2 christos */
178 1.2 christos static int
179 1.2 christos autogroup_add_member_values_to_group( Operation *op, struct berval *dn, autogroup_entry_t *age, Attribute *attr )
180 1.2 christos {
181 1.2 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
182 1.2 christos Modifications modlist;
183 1.2 christos SlapReply sreply = {REP_RESULT};
184 1.2 christos slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
185 1.2 christos Operation o = *op;
186 1.2 christos unsigned long opid = op->o_opid;
187 1.2 christos OpExtra oex;
188 1.2 christos
189 1.2 christos Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_values_to_group adding <%s> to <%s>\n",
190 1.2 christos dn->bv_val, age->age_dn.bv_val, 0);
191 1.2 christos
192 1.1 lukem modlist.sml_op = LDAP_MOD_ADD;
193 1.1 lukem modlist.sml_desc = age->age_def->agd_member_ad;
194 1.1 lukem modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
195 1.2 christos modlist.sml_values = attr->a_vals;
196 1.2 christos modlist.sml_nvalues = attr->a_nvals;
197 1.2 christos modlist.sml_numvals = attr->a_numvals;
198 1.1 lukem modlist.sml_flags = SLAP_MOD_INTERNAL;
199 1.1 lukem modlist.sml_next = NULL;
200 1.1 lukem
201 1.2 christos o.o_opid = 0;
202 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
203 1.1 lukem o.o_callback = &cb;
204 1.1 lukem o.orm_modlist = &modlist;
205 1.2 christos o.o_dn = op->o_bd->be_rootdn;
206 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
207 1.1 lukem o.o_req_dn = age->age_dn;
208 1.1 lukem o.o_req_ndn = age->age_ndn;
209 1.1 lukem o.o_permissive_modify = 1;
210 1.2 christos o.o_dont_replicate = 1;
211 1.2 christos o.orm_no_opattrs = 1;
212 1.1 lukem o.o_managedsait = SLAP_CONTROL_CRITICAL;
213 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
214 1.1 lukem
215 1.2 christos oex.oe_key = (void *)&autogroup;
216 1.2 christos LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
217 1.2 christos
218 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
219 1.1 lukem (void)op->o_bd->be_modify( &o, &sreply );
220 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
221 1.2 christos op->o_opid = opid;
222 1.2 christos LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
223 1.1 lukem
224 1.1 lukem return sreply.sr_err;
225 1.1 lukem }
226 1.1 lukem
227 1.1 lukem /*
228 1.1 lukem ** dn,ndn - the DN to be deleted
229 1.1 lukem ** age - the group from which the DN will be deleted
230 1.1 lukem ** If we pass a NULL dn and ndn, all members are deleted from the group.
231 1.1 lukem */
232 1.1 lukem static int
233 1.1 lukem autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
234 1.1 lukem {
235 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
236 1.2 christos Modifications *modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
237 1.1 lukem SlapReply sreply = {REP_RESULT};
238 1.2 christos BerValue *vals, *nvals;
239 1.1 lukem slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
240 1.1 lukem Operation o = *op;
241 1.2 christos unsigned long opid = op->o_opid;
242 1.2 christos OpExtra oex;
243 1.1 lukem
244 1.1 lukem if ( dn == NULL || ndn == NULL ) {
245 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
246 1.1 lukem age->age_dn.bv_val, 0 ,0);
247 1.1 lukem
248 1.2 christos modlist->sml_values = NULL;
249 1.2 christos modlist->sml_nvalues = NULL;
250 1.2 christos modlist->sml_numvals = 0;
251 1.1 lukem } else {
252 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing <%s> from <%s>\n",
253 1.1 lukem dn->bv_val, age->age_dn.bv_val, 0);
254 1.1 lukem
255 1.2 christos vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
256 1.2 christos nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
257 1.2 christos ber_dupbv( vals, dn );
258 1.1 lukem BER_BVZERO( &vals[ 1 ] );
259 1.2 christos ber_dupbv( nvals, ndn );
260 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
261 1.1 lukem
262 1.2 christos modlist->sml_values = vals;
263 1.2 christos modlist->sml_nvalues = nvals;
264 1.2 christos modlist->sml_numvals = 1;
265 1.1 lukem }
266 1.1 lukem
267 1.1 lukem
268 1.2 christos modlist->sml_op = LDAP_MOD_DELETE;
269 1.2 christos modlist->sml_desc = age->age_def->agd_member_ad;
270 1.2 christos modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
271 1.2 christos modlist->sml_flags = SLAP_MOD_INTERNAL;
272 1.2 christos modlist->sml_next = NULL;
273 1.1 lukem
274 1.2 christos o.o_opid = 0;
275 1.1 lukem o.o_callback = &cb;
276 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
277 1.2 christos o.orm_modlist = modlist;
278 1.2 christos o.o_dn = op->o_bd->be_rootdn;
279 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
280 1.1 lukem o.o_req_dn = age->age_dn;
281 1.1 lukem o.o_req_ndn = age->age_ndn;
282 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
283 1.1 lukem o.o_managedsait = SLAP_CONTROL_CRITICAL;
284 1.1 lukem o.o_permissive_modify = 1;
285 1.2 christos o.o_dont_replicate = 1;
286 1.2 christos o.orm_no_opattrs = 1;
287 1.2 christos
288 1.2 christos oex.oe_key = (void *)&autogroup;
289 1.2 christos LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
290 1.1 lukem
291 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
292 1.1 lukem (void)op->o_bd->be_modify( &o, &sreply );
293 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
294 1.1 lukem
295 1.2 christos LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
296 1.2 christos
297 1.2 christos slap_mods_free( modlist, 1 );
298 1.2 christos
299 1.2 christos op->o_opid = opid;
300 1.1 lukem return sreply.sr_err;
301 1.1 lukem }
302 1.1 lukem
303 1.2 christos /*
304 1.2 christos ** e - the entry where to get the attribute values
305 1.2 christos ** age - the group from which the values will be deleted
306 1.2 christos */
307 1.2 christos static int
308 1.2 christos autogroup_delete_member_values_from_group( Operation *op, struct berval *dn, autogroup_entry_t *age, Attribute *attr )
309 1.2 christos {
310 1.2 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
311 1.2 christos Modifications modlist;
312 1.2 christos SlapReply sreply = {REP_RESULT};
313 1.2 christos slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
314 1.2 christos Operation o = *op;
315 1.2 christos unsigned long opid = op->o_opid;
316 1.2 christos OpExtra oex;
317 1.2 christos
318 1.2 christos Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_values_from_group removing <%s> from <%s>\n",
319 1.2 christos dn->bv_val, age->age_dn.bv_val, 0);
320 1.2 christos
321 1.2 christos modlist.sml_op = LDAP_MOD_DELETE;
322 1.2 christos modlist.sml_desc = age->age_def->agd_member_ad;
323 1.2 christos modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
324 1.2 christos modlist.sml_values = attr->a_vals;
325 1.2 christos modlist.sml_nvalues = attr->a_nvals;
326 1.2 christos modlist.sml_numvals = attr->a_numvals;
327 1.2 christos modlist.sml_flags = SLAP_MOD_INTERNAL;
328 1.2 christos modlist.sml_next = NULL;
329 1.2 christos
330 1.2 christos o.o_opid = 0;
331 1.2 christos o.o_tag = LDAP_REQ_MODIFY;
332 1.2 christos o.o_callback = &cb;
333 1.2 christos o.orm_modlist = &modlist;
334 1.2 christos o.o_dn = op->o_bd->be_rootdn;
335 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
336 1.2 christos o.o_req_dn = age->age_dn;
337 1.2 christos o.o_req_ndn = age->age_ndn;
338 1.2 christos o.o_permissive_modify = 1;
339 1.2 christos o.o_dont_replicate = 1;
340 1.2 christos o.orm_no_opattrs = 1;
341 1.2 christos o.o_managedsait = SLAP_CONTROL_CRITICAL;
342 1.2 christos o.o_relax = SLAP_CONTROL_CRITICAL;
343 1.2 christos
344 1.2 christos oex.oe_key = (void *)&autogroup;
345 1.2 christos LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
346 1.2 christos
347 1.2 christos o.o_bd->bd_info = (BackendInfo *)on->on_info;
348 1.2 christos (void)op->o_bd->be_modify( &o, &sreply );
349 1.2 christos o.o_bd->bd_info = (BackendInfo *)on;
350 1.2 christos op->o_opid = opid;
351 1.2 christos
352 1.2 christos LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
353 1.2 christos
354 1.2 christos return sreply.sr_err;
355 1.2 christos }
356 1.2 christos
357 1.1 lukem /*
358 1.1 lukem ** Callback used to add entries to a group,
359 1.1 lukem ** which are going to be written in the database
360 1.1 lukem ** (used in bi_op_add)
361 1.1 lukem ** The group is passed in autogroup_ga_t->agg_group
362 1.1 lukem */
363 1.1 lukem static int
364 1.1 lukem autogroup_member_search_cb( Operation *op, SlapReply *rs )
365 1.1 lukem {
366 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
367 1.1 lukem
368 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
369 1.1 lukem autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
370 1.1 lukem autogroup_entry_t *age = agg->agg_group;
371 1.2 christos autogroup_filter_t *agf = agg->agg_filter;
372 1.1 lukem Modification mod;
373 1.1 lukem const char *text = NULL;
374 1.1 lukem char textbuf[1024];
375 1.2 christos struct berval *vals, *nvals;
376 1.2 christos struct berval lvals[ 2 ], lnvals[ 2 ];
377 1.2 christos int numvals;
378 1.1 lukem
379 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
380 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
381 1.1 lukem
382 1.2 christos if ( agf->agf_anlist ) {
383 1.2 christos Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
384 1.2 christos if (attr) {
385 1.2 christos vals = attr->a_vals;
386 1.2 christos nvals = attr->a_nvals;
387 1.2 christos numvals = attr->a_numvals;
388 1.2 christos } else {
389 1.2 christos // Nothing to add
390 1.2 christos return 0;
391 1.2 christos }
392 1.2 christos } else {
393 1.2 christos lvals[ 0 ] = rs->sr_entry->e_name;
394 1.2 christos BER_BVZERO( &lvals[ 1 ] );
395 1.2 christos lnvals[ 0 ] = rs->sr_entry->e_nname;
396 1.2 christos BER_BVZERO( &lnvals[ 1 ] );
397 1.2 christos vals = lvals;
398 1.2 christos nvals = lnvals;
399 1.2 christos numvals = 1;
400 1.2 christos }
401 1.1 lukem
402 1.1 lukem mod.sm_op = LDAP_MOD_ADD;
403 1.1 lukem mod.sm_desc = age->age_def->agd_member_ad;
404 1.1 lukem mod.sm_type = age->age_def->agd_member_ad->ad_cname;
405 1.1 lukem mod.sm_values = vals;
406 1.1 lukem mod.sm_nvalues = nvals;
407 1.2 christos mod.sm_numvals = numvals;
408 1.1 lukem
409 1.1 lukem modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
410 1.1 lukem }
411 1.1 lukem
412 1.1 lukem return 0;
413 1.1 lukem }
414 1.1 lukem
415 1.1 lukem /*
416 1.1 lukem ** Callback used to add entries to a group, which is already in the database.
417 1.1 lukem ** (used in on_response)
418 1.1 lukem ** The group is passed in autogroup_ga_t->agg_group
419 1.1 lukem ** NOTE: Very slow.
420 1.1 lukem */
421 1.1 lukem static int
422 1.1 lukem autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
423 1.1 lukem {
424 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
425 1.1 lukem
426 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
427 1.1 lukem autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
428 1.1 lukem autogroup_entry_t *age = agg->agg_group;
429 1.2 christos autogroup_filter_t *agf = agg->agg_filter;
430 1.1 lukem Modifications *modlist;
431 1.2 christos struct berval *vals, *nvals;
432 1.2 christos struct berval lvals[ 2 ], lnvals[ 2 ];
433 1.2 christos int numvals;
434 1.1 lukem
435 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
436 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
437 1.1 lukem
438 1.2 christos if ( agf->agf_anlist ) {
439 1.2 christos Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
440 1.2 christos if (attr) {
441 1.2 christos vals = attr->a_vals;
442 1.2 christos nvals = attr->a_nvals;
443 1.2 christos numvals = attr->a_numvals;
444 1.2 christos } else {
445 1.2 christos // Nothing to add
446 1.2 christos return 0;
447 1.2 christos }
448 1.1 lukem } else {
449 1.2 christos lvals[ 0 ] = rs->sr_entry->e_name;
450 1.2 christos BER_BVZERO( &lvals[ 1 ] );
451 1.2 christos lnvals[ 0 ] = rs->sr_entry->e_nname;
452 1.2 christos BER_BVZERO( &lnvals[ 1 ] );
453 1.2 christos vals = lvals;
454 1.2 christos nvals = lnvals;
455 1.2 christos numvals = 1;
456 1.2 christos }
457 1.2 christos
458 1.2 christos if ( numvals ) {
459 1.2 christos modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
460 1.2 christos
461 1.2 christos modlist->sml_op = LDAP_MOD_ADD;
462 1.2 christos modlist->sml_desc = age->age_def->agd_member_ad;
463 1.2 christos modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
464 1.2 christos
465 1.2 christos ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
466 1.2 christos ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
467 1.2 christos modlist->sml_numvals = numvals;
468 1.2 christos
469 1.2 christos modlist->sml_flags = SLAP_MOD_INTERNAL;
470 1.2 christos modlist->sml_next = NULL;
471 1.2 christos
472 1.2 christos if ( agg->agg_mod == NULL ) {
473 1.2 christos agg->agg_mod = modlist;
474 1.2 christos agg->agg_mod_last = modlist;
475 1.2 christos } else {
476 1.2 christos agg->agg_mod_last->sml_next = modlist;
477 1.2 christos agg->agg_mod_last = modlist;
478 1.2 christos }
479 1.1 lukem }
480 1.1 lukem
481 1.1 lukem }
482 1.1 lukem
483 1.1 lukem return 0;
484 1.1 lukem }
485 1.1 lukem
486 1.1 lukem
487 1.1 lukem /*
488 1.1 lukem ** Adds all entries matching the passed filter to the specified group.
489 1.1 lukem ** If modify == 1, then we modify the group's entry in the database using be_modify.
490 1.1 lukem ** If modify == 0, then, we must supply a rw entry for the group,
491 1.1 lukem ** because we only modify the entry, without calling be_modify.
492 1.1 lukem ** e - the group entry, to which the members will be added
493 1.1 lukem ** age - the group
494 1.1 lukem ** agf - the filter
495 1.1 lukem */
496 1.1 lukem static int
497 1.1 lukem autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify)
498 1.1 lukem {
499 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
500 1.1 lukem Operation o = *op;
501 1.1 lukem SlapReply rs = { REP_SEARCH };
502 1.1 lukem slap_callback cb = { 0 };
503 1.1 lukem slap_callback null_cb = { NULL, slap_null_cb, NULL, NULL };
504 1.1 lukem autogroup_ga_t agg;
505 1.2 christos OpExtra oex;
506 1.1 lukem
507 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
508 1.1 lukem age->age_dn.bv_val, 0, 0);
509 1.1 lukem
510 1.1 lukem o.ors_attrsonly = 0;
511 1.1 lukem o.o_tag = LDAP_REQ_SEARCH;
512 1.1 lukem
513 1.2 christos o.o_dn = op->o_bd->be_rootdn;
514 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
515 1.1 lukem o.o_req_dn = agf->agf_dn;
516 1.1 lukem o.o_req_ndn = agf->agf_ndn;
517 1.1 lukem
518 1.1 lukem o.ors_filterstr = agf->agf_filterstr;
519 1.1 lukem o.ors_filter = agf->agf_filter;
520 1.1 lukem
521 1.1 lukem o.ors_scope = agf->agf_scope;
522 1.1 lukem o.ors_deref = LDAP_DEREF_NEVER;
523 1.1 lukem o.ors_limit = NULL;
524 1.1 lukem o.ors_tlimit = SLAP_NO_LIMIT;
525 1.1 lukem o.ors_slimit = SLAP_NO_LIMIT;
526 1.2 christos o.ors_attrs = agf->agf_anlist ? agf->agf_anlist : slap_anlist_no_attrs;
527 1.2 christos o.o_do_not_cache = 1;
528 1.1 lukem
529 1.1 lukem agg.agg_group = age;
530 1.2 christos agg.agg_filter = agf;
531 1.1 lukem agg.agg_mod = NULL;
532 1.1 lukem agg.agg_mod_last = NULL;
533 1.1 lukem agg.agg_entry = e;
534 1.1 lukem cb.sc_private = &agg;
535 1.1 lukem
536 1.1 lukem if ( modify == 1 ) {
537 1.1 lukem cb.sc_response = autogroup_member_search_modify_cb;
538 1.1 lukem } else {
539 1.1 lukem cb.sc_response = autogroup_member_search_cb;
540 1.1 lukem }
541 1.1 lukem
542 1.1 lukem cb.sc_cleanup = NULL;
543 1.1 lukem cb.sc_next = NULL;
544 1.1 lukem
545 1.1 lukem o.o_callback = &cb;
546 1.1 lukem
547 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
548 1.1 lukem op->o_bd->be_search( &o, &rs );
549 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
550 1.1 lukem
551 1.2 christos if ( modify == 1 && agg.agg_mod ) {
552 1.2 christos unsigned long opid = op->o_opid;
553 1.2 christos
554 1.2 christos rs_reinit( &rs, REP_RESULT );
555 1.2 christos
556 1.1 lukem o = *op;
557 1.2 christos o.o_opid = 0;
558 1.1 lukem o.o_callback = &null_cb;
559 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
560 1.1 lukem o.orm_modlist = agg.agg_mod;
561 1.2 christos o.o_dn = op->o_bd->be_rootdn;
562 1.2 christos o.o_ndn = op->o_bd->be_rootndn;
563 1.1 lukem o.o_req_dn = age->age_dn;
564 1.1 lukem o.o_req_ndn = age->age_ndn;
565 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
566 1.1 lukem o.o_managedsait = SLAP_CONTROL_NONCRITICAL;
567 1.1 lukem o.o_permissive_modify = 1;
568 1.2 christos o.o_dont_replicate = 1;
569 1.2 christos o.orm_no_opattrs = 1;
570 1.2 christos
571 1.2 christos oex.oe_key = (void *)&autogroup;
572 1.2 christos LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
573 1.1 lukem
574 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
575 1.1 lukem (void)op->o_bd->be_modify( &o, &rs );
576 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
577 1.1 lukem
578 1.2 christos LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
579 1.2 christos
580 1.1 lukem slap_mods_free(agg.agg_mod, 1);
581 1.2 christos op->o_opid = opid;
582 1.1 lukem }
583 1.1 lukem
584 1.1 lukem return 0;
585 1.1 lukem }
586 1.1 lukem
587 1.1 lukem /*
588 1.1 lukem ** Adds a group to the internal list from the passed entry.
589 1.1 lukem ** scan specifies whether to add all maching members to the group.
590 1.1 lukem ** modify specifies whether to modify the given group entry (when modify == 0),
591 1.1 lukem ** or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL).
592 1.1 lukem ** agi - pointer to the groups and the attribute definitions
593 1.1 lukem ** agd - the attribute definition of the added group
594 1.1 lukem ** e - the entry representing the group, can be NULL if the ndn is specified, and modify == 1
595 1.1 lukem ** ndn - the DN of the group, can be NULL if we give a non-NULL e
596 1.1 lukem */
597 1.1 lukem static int
598 1.1 lukem autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify)
599 1.1 lukem {
600 1.1 lukem autogroup_entry_t **agep = &agi->agi_entry;
601 1.1 lukem autogroup_filter_t *agf, *agf_prev = NULL;
602 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
603 1.1 lukem LDAPURLDesc *lud = NULL;
604 1.1 lukem Attribute *a;
605 1.1 lukem BerValue *bv, dn;
606 1.1 lukem int rc = 0, match = 1, null_entry = 0;
607 1.1 lukem
608 1.1 lukem if ( e == NULL ) {
609 1.1 lukem if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) !=
610 1.1 lukem LDAP_SUCCESS || e == NULL ) {
611 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot get entry for <%s>\n", ndn->bv_val, 0, 0);
612 1.1 lukem return 1;
613 1.1 lukem }
614 1.1 lukem
615 1.1 lukem null_entry = 1;
616 1.1 lukem }
617 1.1 lukem
618 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n",
619 1.1 lukem e->e_name.bv_val, 0, 0);
620 1.1 lukem
621 1.1 lukem if ( agi->agi_entry != NULL ) {
622 1.1 lukem for ( ; *agep ; agep = &(*agep)->age_next ) {
623 1.1 lukem dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*agep)->age_ndn );
624 1.1 lukem if ( match == 0 ) {
625 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
626 1.1 lukem return 1;
627 1.1 lukem }
628 1.1 lukem /* goto last */;
629 1.1 lukem }
630 1.1 lukem }
631 1.1 lukem
632 1.1 lukem
633 1.1 lukem *agep = (autogroup_entry_t *)ch_calloc( 1, sizeof( autogroup_entry_t ) );
634 1.1 lukem ldap_pvt_thread_mutex_init( &(*agep)->age_mutex );
635 1.1 lukem (*agep)->age_def = agd;
636 1.1 lukem (*agep)->age_filter = NULL;
637 1.2 christos (*agep)->age_mustrefresh = 0;
638 1.2 christos (*agep)->age_modrdn_olddnmodified = 0;
639 1.1 lukem
640 1.1 lukem ber_dupbv( &(*agep)->age_dn, &e->e_name );
641 1.1 lukem ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
642 1.1 lukem
643 1.1 lukem a = attrs_find( e->e_attrs, agd->agd_member_url_ad );
644 1.1 lukem
645 1.1 lukem if ( null_entry == 1 ) {
646 1.1 lukem a = attrs_dup( a );
647 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
648 1.1 lukem }
649 1.1 lukem
650 1.1 lukem if( a == NULL ) {
651 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0);
652 1.1 lukem } else {
653 1.1 lukem for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
654 1.1 lukem
655 1.1 lukem agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) );
656 1.1 lukem
657 1.1 lukem if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
658 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot parse url <%s>\n", bv->bv_val,0,0);
659 1.1 lukem /* FIXME: error? */
660 1.1 lukem ch_free( agf );
661 1.1 lukem continue;
662 1.1 lukem }
663 1.1 lukem
664 1.1 lukem agf->agf_scope = lud->lud_scope;
665 1.1 lukem
666 1.1 lukem if ( lud->lud_dn == NULL ) {
667 1.1 lukem BER_BVSTR( &dn, "" );
668 1.1 lukem } else {
669 1.1 lukem ber_str2bv( lud->lud_dn, 0, 0, &dn );
670 1.1 lukem }
671 1.1 lukem
672 1.1 lukem rc = dnPrettyNormal( NULL, &dn, &agf->agf_dn, &agf->agf_ndn, NULL );
673 1.1 lukem if ( rc != LDAP_SUCCESS ) {
674 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0);
675 1.1 lukem /* FIXME: error? */
676 1.1 lukem goto cleanup;
677 1.1 lukem }
678 1.1 lukem
679 1.1 lukem if ( lud->lud_filter != NULL ) {
680 1.1 lukem ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr);
681 1.1 lukem agf->agf_filter = str2filter( lud->lud_filter );
682 1.2 christos } else {
683 1.2 christos Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: URL filter is missing <%s>\n", bv->bv_val,0,0);
684 1.2 christos /* FIXME: error? */
685 1.2 christos goto cleanup;
686 1.2 christos }
687 1.2 christos
688 1.2 christos if ( lud->lud_attrs != NULL ) {
689 1.2 christos int i;
690 1.2 christos
691 1.2 christos for ( i=0 ; lud->lud_attrs[i]!=NULL ; i++) {
692 1.2 christos /* Just counting */;
693 1.2 christos }
694 1.2 christos
695 1.2 christos if ( i > 1 ) {
696 1.2 christos Debug( LDAP_DEBUG_ANY, "autogroup_add_group: too many attributes specified in url <%s>\n",
697 1.2 christos bv->bv_val, 0, 0);
698 1.2 christos /* FIXME: error? */
699 1.2 christos filter_free( agf->agf_filter );
700 1.2 christos ch_free( agf->agf_filterstr.bv_val );
701 1.2 christos ch_free( agf->agf_dn.bv_val );
702 1.2 christos ch_free( agf->agf_ndn.bv_val );
703 1.2 christos ldap_free_urldesc( lud );
704 1.2 christos ch_free( agf );
705 1.2 christos continue;
706 1.2 christos }
707 1.2 christos
708 1.2 christos agf->agf_anlist = str2anlist( NULL, lud->lud_attrs[0], "," );
709 1.2 christos
710 1.2 christos if ( agf->agf_anlist == NULL ) {
711 1.2 christos Debug( LDAP_DEBUG_ANY, "autogroup_add_group: unable to find AttributeDescription \"%s\".\n",
712 1.2 christos lud->lud_attrs[0], 0, 0 );
713 1.2 christos /* FIXME: error? */
714 1.2 christos filter_free( agf->agf_filter );
715 1.2 christos ch_free( agf->agf_filterstr.bv_val );
716 1.2 christos ch_free( agf->agf_dn.bv_val );
717 1.2 christos ch_free( agf->agf_ndn.bv_val );
718 1.2 christos ldap_free_urldesc( lud );
719 1.2 christos ch_free( agf );
720 1.2 christos continue;
721 1.2 christos }
722 1.2 christos }
723 1.1 lukem
724 1.1 lukem agf->agf_next = NULL;
725 1.1 lukem
726 1.1 lukem if( (*agep)->age_filter == NULL ) {
727 1.1 lukem (*agep)->age_filter = agf;
728 1.1 lukem }
729 1.1 lukem
730 1.1 lukem if( agf_prev != NULL ) {
731 1.1 lukem agf_prev->agf_next = agf;
732 1.1 lukem }
733 1.1 lukem
734 1.1 lukem agf_prev = agf;
735 1.1 lukem
736 1.1 lukem if ( scan == 1 ){
737 1.1 lukem autogroup_add_members_from_filter( op, e, (*agep), agf, modify );
738 1.1 lukem }
739 1.1 lukem
740 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: added memberURL DN <%s> with filter <%s>\n",
741 1.1 lukem agf->agf_ndn.bv_val, agf->agf_filterstr.bv_val, 0);
742 1.1 lukem
743 1.1 lukem ldap_free_urldesc( lud );
744 1.1 lukem
745 1.1 lukem continue;
746 1.1 lukem
747 1.1 lukem
748 1.1 lukem cleanup:;
749 1.1 lukem
750 1.2 christos ch_free( agf->agf_ndn.bv_val );
751 1.2 christos ch_free( agf->agf_dn.bv_val );
752 1.1 lukem ldap_free_urldesc( lud );
753 1.1 lukem ch_free( agf );
754 1.1 lukem }
755 1.1 lukem }
756 1.1 lukem
757 1.1 lukem if ( null_entry == 1 ) {
758 1.1 lukem attrs_free( a );
759 1.1 lukem }
760 1.1 lukem return rc;
761 1.1 lukem }
762 1.1 lukem
763 1.1 lukem /*
764 1.1 lukem ** Used when opening the database to add all existing
765 1.1 lukem ** groups from the database to our internal list.
766 1.1 lukem */
767 1.1 lukem static int
768 1.1 lukem autogroup_group_add_cb( Operation *op, SlapReply *rs )
769 1.1 lukem {
770 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
771 1.1 lukem
772 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
773 1.1 lukem autogroup_sc_t *ags = (autogroup_sc_t *)op->o_callback->sc_private;
774 1.1 lukem
775 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_group_add_cb <%s>\n",
776 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
777 1.1 lukem
778 1.1 lukem autogroup_add_group( op, ags->ags_info, ags->ags_def, rs->sr_entry, NULL, 0, 0);
779 1.1 lukem }
780 1.1 lukem
781 1.1 lukem return 0;
782 1.1 lukem }
783 1.1 lukem
784 1.2 christos typedef struct ag_addinfo {
785 1.2 christos slap_overinst *on;
786 1.2 christos Entry *e;
787 1.2 christos autogroup_def_t *agd;
788 1.2 christos } ag_addinfo;
789 1.2 christos
790 1.2 christos static int
791 1.2 christos autogroup_add_entry_cb( Operation *op, SlapReply *rs )
792 1.2 christos {
793 1.2 christos slap_callback *sc = op->o_callback;
794 1.2 christos ag_addinfo *aa = sc->sc_private;
795 1.2 christos slap_overinst *on = aa->on;
796 1.2 christos autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
797 1.2 christos BackendInfo *bi = op->o_bd->bd_info;
798 1.2 christos
799 1.2 christos if ( rs->sr_err != LDAP_SUCCESS )
800 1.2 christos goto done;
801 1.2 christos
802 1.2 christos op->o_bd->bd_info = (BackendInfo *)on;
803 1.2 christos ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
804 1.2 christos if ( aa->agd ) {
805 1.2 christos autogroup_add_group( op, agi, aa->agd, aa->e, NULL, 1 , 0);
806 1.2 christos } else {
807 1.2 christos autogroup_entry_t *age;
808 1.2 christos autogroup_filter_t *agf;
809 1.2 christos struct berval odn, ondn;
810 1.2 christos int rc;
811 1.2 christos
812 1.2 christos /* must use rootdn when calling test_filter */
813 1.2 christos odn = op->o_dn;
814 1.2 christos ondn = op->o_ndn;
815 1.2 christos op->o_dn = op->o_bd->be_rootdn;
816 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
817 1.2 christos
818 1.2 christos for ( age = agi->agi_entry; age ; age = age->age_next ) {
819 1.2 christos ldap_pvt_thread_mutex_lock( &age->age_mutex );
820 1.2 christos
821 1.2 christos /* Check if any of the filters are the suffix to the entry DN.
822 1.2 christos If yes, we can test that filter against the entry. */
823 1.2 christos
824 1.2 christos for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
825 1.2 christos if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
826 1.2 christos rc = test_filter( op, aa->e, agf->agf_filter );
827 1.2 christos if ( rc == LDAP_COMPARE_TRUE ) {
828 1.2 christos if ( agf->agf_anlist ) {
829 1.2 christos Attribute *a = attr_find( aa->e->e_attrs, agf->agf_anlist[0].an_desc );
830 1.2 christos if ( a )
831 1.2 christos autogroup_add_member_values_to_group( op, &op->o_req_dn, age, a );
832 1.2 christos } else {
833 1.2 christos autogroup_add_member_to_group( op, &aa->e->e_name, &aa->e->e_nname, age );
834 1.2 christos }
835 1.2 christos break;
836 1.2 christos }
837 1.2 christos }
838 1.2 christos }
839 1.2 christos ldap_pvt_thread_mutex_unlock( &age->age_mutex );
840 1.2 christos }
841 1.2 christos op->o_dn = odn;
842 1.2 christos op->o_ndn = ondn;
843 1.2 christos }
844 1.2 christos ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
845 1.2 christos
846 1.2 christos op->o_bd->bd_info = bi;
847 1.2 christos
848 1.2 christos done:
849 1.2 christos op->o_callback = sc->sc_next;
850 1.2 christos op->o_tmpfree( sc, op->o_tmpmemctx );
851 1.2 christos
852 1.2 christos return SLAP_CB_CONTINUE;
853 1.2 christos }
854 1.1 lukem
855 1.1 lukem /*
856 1.1 lukem ** When adding a group, we first strip any existing members,
857 1.1 lukem ** and add all which match the filters ourselfs.
858 1.1 lukem */
859 1.1 lukem static int
860 1.1 lukem autogroup_add_entry( Operation *op, SlapReply *rs)
861 1.1 lukem {
862 1.2 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
863 1.2 christos autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
864 1.1 lukem autogroup_def_t *agd = agi->agi_def;
865 1.2 christos slap_callback *sc = NULL;
866 1.2 christos ag_addinfo *aa = NULL;
867 1.1 lukem
868 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n",
869 1.1 lukem op->ora_e->e_name.bv_val, 0, 0);
870 1.1 lukem
871 1.2 christos sc = op->o_tmpcalloc( sizeof(slap_callback) + sizeof(ag_addinfo), 1, op->o_tmpmemctx );
872 1.2 christos sc->sc_private = (sc+1);
873 1.2 christos sc->sc_response = autogroup_add_entry_cb;
874 1.2 christos aa = sc->sc_private;
875 1.2 christos aa->on = on;
876 1.2 christos aa->e = op->ora_e;
877 1.2 christos sc->sc_next = op->o_callback;
878 1.2 christos op->o_callback = sc;
879 1.1 lukem
880 1.1 lukem /* Check if it's a group. */
881 1.1 lukem for ( ; agd ; agd = agd->agd_next ) {
882 1.1 lukem if ( is_entry_objectclass_or_sub( op->ora_e, agd->agd_oc ) ) {
883 1.1 lukem Modification mod;
884 1.1 lukem const char *text = NULL;
885 1.1 lukem char textbuf[1024];
886 1.1 lukem
887 1.1 lukem mod.sm_op = LDAP_MOD_DELETE;
888 1.1 lukem mod.sm_desc = agd->agd_member_ad;
889 1.1 lukem mod.sm_type = agd->agd_member_ad->ad_cname;
890 1.1 lukem mod.sm_values = NULL;
891 1.1 lukem mod.sm_nvalues = NULL;
892 1.1 lukem
893 1.1 lukem /* We don't want any member attributes added by the user. */
894 1.1 lukem modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
895 1.1 lukem
896 1.2 christos aa->agd = agd;
897 1.1 lukem
898 1.2 christos break;
899 1.1 lukem }
900 1.1 lukem }
901 1.1 lukem
902 1.1 lukem return SLAP_CB_CONTINUE;
903 1.1 lukem }
904 1.1 lukem
905 1.1 lukem /*
906 1.1 lukem ** agi - internal group and attribute definitions list
907 1.1 lukem ** e - the group to remove from the internal list
908 1.1 lukem */
909 1.1 lukem static int
910 1.1 lukem autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
911 1.1 lukem {
912 1.1 lukem autogroup_entry_t *age = agi->agi_entry,
913 1.1 lukem *age_prev = NULL,
914 1.1 lukem *age_next;
915 1.1 lukem int rc = 1;
916 1.1 lukem
917 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_group <%s>\n",
918 1.1 lukem age->age_dn.bv_val, 0, 0);
919 1.1 lukem
920 1.1 lukem for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
921 1.1 lukem age_next = age->age_next;
922 1.1 lukem
923 1.1 lukem if ( age == e ) {
924 1.1 lukem autogroup_filter_t *agf = age->age_filter,
925 1.1 lukem *agf_next;
926 1.1 lukem
927 1.1 lukem if ( age_prev != NULL ) {
928 1.1 lukem age_prev->age_next = age_next;
929 1.1 lukem } else {
930 1.1 lukem agi->agi_entry = NULL;
931 1.1 lukem }
932 1.1 lukem
933 1.1 lukem ch_free( age->age_dn.bv_val );
934 1.1 lukem ch_free( age->age_ndn.bv_val );
935 1.1 lukem
936 1.1 lukem for( agf_next = agf ; agf_next ; agf = agf_next ){
937 1.1 lukem agf_next = agf->agf_next;
938 1.1 lukem
939 1.1 lukem filter_free( agf->agf_filter );
940 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
941 1.1 lukem ch_free( agf->agf_dn.bv_val );
942 1.1 lukem ch_free( agf->agf_ndn.bv_val );
943 1.2 christos anlist_free( agf->agf_anlist, 1, NULL );
944 1.2 christos ch_free( agf );
945 1.1 lukem }
946 1.1 lukem
947 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
948 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
949 1.1 lukem ch_free( age );
950 1.1 lukem
951 1.1 lukem rc = 0;
952 1.1 lukem return rc;
953 1.1 lukem
954 1.1 lukem }
955 1.1 lukem }
956 1.1 lukem
957 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_delete_group: group <%s> not found, should not happen\n", age->age_dn.bv_val, 0, 0);
958 1.1 lukem
959 1.1 lukem return rc;
960 1.1 lukem
961 1.1 lukem }
962 1.1 lukem
963 1.1 lukem static int
964 1.1 lukem autogroup_delete_entry( Operation *op, SlapReply *rs)
965 1.1 lukem {
966 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
967 1.2 christos autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
968 1.2 christos autogroup_entry_t *age, *age_prev, *age_next;
969 1.1 lukem autogroup_filter_t *agf;
970 1.1 lukem Entry *e;
971 1.1 lukem int matched_group = 0, rc = 0;
972 1.2 christos struct berval odn, ondn;
973 1.2 christos OpExtra *oex;
974 1.2 christos
975 1.2 christos LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
976 1.2 christos if ( oex->oe_key == (void *)&autogroup )
977 1.2 christos return SLAP_CB_CONTINUE;
978 1.2 christos }
979 1.1 lukem
980 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
981 1.1 lukem
982 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
983 1.1 lukem
984 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
985 1.1 lukem LDAP_SUCCESS || e == NULL ) {
986 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_delete_entry: cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
987 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
988 1.1 lukem return SLAP_CB_CONTINUE;
989 1.1 lukem }
990 1.1 lukem
991 1.1 lukem /* Check if the entry to be deleted is one of our groups. */
992 1.2 christos for ( age_next = agi->agi_entry ; age_next ; age_prev = age ) {
993 1.2 christos age = age_next;
994 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
995 1.1 lukem age_next = age->age_next;
996 1.1 lukem
997 1.1 lukem if ( is_entry_objectclass_or_sub( e, age->age_def->agd_oc ) ) {
998 1.1 lukem int match = 1;
999 1.1 lukem
1000 1.1 lukem matched_group = 1;
1001 1.1 lukem
1002 1.1 lukem dnMatch( &match, 0, NULL, NULL, &e->e_nname, &age->age_ndn );
1003 1.1 lukem
1004 1.1 lukem if ( match == 0 ) {
1005 1.1 lukem autogroup_delete_group( agi, age );
1006 1.1 lukem break;
1007 1.1 lukem }
1008 1.1 lukem }
1009 1.1 lukem
1010 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1011 1.1 lukem }
1012 1.1 lukem
1013 1.1 lukem if ( matched_group == 1 ) {
1014 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1015 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1016 1.1 lukem return SLAP_CB_CONTINUE;
1017 1.1 lukem }
1018 1.1 lukem
1019 1.1 lukem /* Check if the entry matches any of the groups.
1020 1.1 lukem If yes, we can delete the entry from that group. */
1021 1.1 lukem
1022 1.2 christos odn = op->o_dn;
1023 1.2 christos ondn = op->o_ndn;
1024 1.2 christos op->o_dn = op->o_bd->be_rootdn;
1025 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
1026 1.2 christos
1027 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1028 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
1029 1.1 lukem
1030 1.1 lukem for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
1031 1.1 lukem if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
1032 1.1 lukem rc = test_filter( op, e, agf->agf_filter );
1033 1.1 lukem if ( rc == LDAP_COMPARE_TRUE ) {
1034 1.2 christos /* If the attribute is retrieved from the entry, we don't know what to delete
1035 1.2 christos ** So the group must be entirely refreshed
1036 1.2 christos ** But the refresh can't be done now because the entry is not deleted
1037 1.2 christos ** So the group is marked as mustrefresh
1038 1.2 christos */
1039 1.2 christos if ( agf->agf_anlist ) {
1040 1.2 christos age->age_mustrefresh = 1;
1041 1.2 christos } else {
1042 1.2 christos autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
1043 1.2 christos }
1044 1.1 lukem break;
1045 1.1 lukem }
1046 1.1 lukem }
1047 1.1 lukem }
1048 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1049 1.1 lukem }
1050 1.2 christos op->o_dn = odn;
1051 1.2 christos op->o_ndn = ondn;
1052 1.1 lukem
1053 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1054 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1055 1.1 lukem
1056 1.1 lukem return SLAP_CB_CONTINUE;
1057 1.1 lukem }
1058 1.1 lukem
1059 1.1 lukem static int
1060 1.1 lukem autogroup_response( Operation *op, SlapReply *rs )
1061 1.1 lukem {
1062 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1063 1.2 christos autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1064 1.1 lukem autogroup_def_t *agd = agi->agi_def;
1065 1.2 christos autogroup_entry_t *age;
1066 1.1 lukem autogroup_filter_t *agf;
1067 1.1 lukem BerValue new_dn, new_ndn, pdn;
1068 1.1 lukem Entry *e, *group;
1069 1.2 christos Attribute *a, *ea, *attrs;
1070 1.2 christos int is_olddn, is_newdn, is_value_refresh, dn_equal;
1071 1.2 christos OpExtra *oex;
1072 1.2 christos
1073 1.2 christos LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
1074 1.2 christos if ( oex->oe_key == (void *)&autogroup )
1075 1.2 christos break;
1076 1.2 christos }
1077 1.2 christos
1078 1.2 christos /* Handle all cases where a refresh of the group is needed */
1079 1.2 christos if ( op->o_tag == LDAP_REQ_DELETE || op->o_tag == LDAP_REQ_MODIFY ) {
1080 1.2 christos if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
1081 1.2 christos
1082 1.2 christos ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1083 1.2 christos
1084 1.2 christos for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1085 1.2 christos /* Request detected that the group must be refreshed */
1086 1.2 christos
1087 1.2 christos ldap_pvt_thread_mutex_lock( &age->age_mutex );
1088 1.2 christos
1089 1.2 christos if ( age->age_mustrefresh ) {
1090 1.2 christos autogroup_delete_member_from_group( op, NULL, NULL, age) ;
1091 1.2 christos
1092 1.2 christos for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1093 1.2 christos autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
1094 1.2 christos }
1095 1.2 christos }
1096 1.1 lukem
1097 1.2 christos ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1098 1.2 christos }
1099 1.2 christos
1100 1.2 christos ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1101 1.2 christos }
1102 1.2 christos } else if ( op->o_tag == LDAP_REQ_MODRDN ) {
1103 1.2 christos if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
1104 1.1 lukem
1105 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
1106 1.1 lukem
1107 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1108 1.1 lukem
1109 1.1 lukem if ( op->oq_modrdn.rs_newSup ) {
1110 1.1 lukem pdn = *op->oq_modrdn.rs_newSup;
1111 1.1 lukem } else {
1112 1.1 lukem dnParent( &op->o_req_dn, &pdn );
1113 1.1 lukem }
1114 1.1 lukem build_new_dn( &new_dn, &pdn, &op->orr_newrdn, op->o_tmpmemctx );
1115 1.1 lukem
1116 1.1 lukem if ( op->oq_modrdn.rs_nnewSup ) {
1117 1.1 lukem pdn = *op->oq_modrdn.rs_nnewSup;
1118 1.1 lukem } else {
1119 1.1 lukem dnParent( &op->o_req_ndn, &pdn );
1120 1.1 lukem }
1121 1.1 lukem build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, op->o_tmpmemctx );
1122 1.1 lukem
1123 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
1124 1.1 lukem
1125 1.1 lukem dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
1126 1.1 lukem
1127 1.1 lukem if ( overlay_entry_get_ov( op, &new_ndn, NULL, NULL, 0, &e, on ) !=
1128 1.1 lukem LDAP_SUCCESS || e == NULL ) {
1129 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get entry for <%s>\n", new_dn.bv_val, 0, 0);
1130 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1131 1.1 lukem return SLAP_CB_CONTINUE;
1132 1.1 lukem }
1133 1.1 lukem
1134 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
1135 1.1 lukem
1136 1.1 lukem
1137 1.1 lukem if ( a == NULL ) {
1138 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN entry <%s> has no objectClass\n", new_dn.bv_val, 0, 0);
1139 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1140 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1141 1.1 lukem return SLAP_CB_CONTINUE;
1142 1.1 lukem }
1143 1.1 lukem
1144 1.1 lukem
1145 1.1 lukem /* If a groups DN is modified, just update age_dn/ndn of that group with the new DN. */
1146 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
1147 1.1 lukem
1148 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
1149 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1150 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1151 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
1152 1.1 lukem op->o_tmpmemctx ) == 0 )
1153 1.1 lukem {
1154 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1155 1.1 lukem int match = 1;
1156 1.1 lukem
1157 1.1 lukem dnMatch( &match, 0, NULL, NULL, &age->age_ndn, &op->o_req_ndn );
1158 1.1 lukem if ( match == 0 ) {
1159 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN updating group's DN to <%s>\n", new_dn.bv_val, 0, 0);
1160 1.1 lukem ber_dupbv( &age->age_dn, &new_dn );
1161 1.1 lukem ber_dupbv( &age->age_ndn, &new_ndn );
1162 1.1 lukem
1163 1.1 lukem op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
1164 1.1 lukem op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
1165 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1166 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1167 1.1 lukem return SLAP_CB_CONTINUE;
1168 1.1 lukem }
1169 1.1 lukem }
1170 1.1 lukem
1171 1.1 lukem }
1172 1.1 lukem }
1173 1.1 lukem
1174 1.1 lukem /* For each group:
1175 1.1 lukem 1. check if the orginal entry's DN is in the group.
1176 1.1 lukem 2. chceck if the any of the group filter's base DN is a suffix of the new DN
1177 1.1 lukem
1178 1.1 lukem If 1 and 2 are both false, we do nothing.
1179 1.1 lukem If 1 and 2 is true, we remove the old DN from the group, and add the new DN.
1180 1.1 lukem If 1 is false, and 2 is true, we check the entry against the group's filters,
1181 1.1 lukem and add it's DN to the group.
1182 1.1 lukem If 1 is true, and 2 is false, we delete the entry's DN from the group.
1183 1.1 lukem */
1184 1.2 christos attrs = attrs_dup( e->e_attrs );
1185 1.2 christos overlay_entry_release_ov( op, e, 0, on );
1186 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1187 1.1 lukem is_olddn = 0;
1188 1.1 lukem is_newdn = 0;
1189 1.2 christos is_value_refresh = 0;
1190 1.2 christos
1191 1.2 christos ldap_pvt_thread_mutex_lock( &age->age_mutex );
1192 1.1 lukem
1193 1.2 christos if ( age->age_filter && age->age_filter->agf_anlist ) {
1194 1.2 christos ea = attrs_find( attrs, age->age_filter->agf_anlist[0].an_desc );
1195 1.2 christos }
1196 1.2 christos else {
1197 1.2 christos ea = NULL;
1198 1.2 christos }
1199 1.1 lukem
1200 1.2 christos if ( age->age_modrdn_olddnmodified ) {
1201 1.2 christos /* Resquest already marked this group to be updated */
1202 1.2 christos is_olddn = 1;
1203 1.2 christos is_value_refresh = 1;
1204 1.2 christos age->age_modrdn_olddnmodified = 0;
1205 1.2 christos } else {
1206 1.2 christos
1207 1.2 christos if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
1208 1.2 christos LDAP_SUCCESS || group == NULL ) {
1209 1.2 christos Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
1210 1.1 lukem
1211 1.2 christos op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
1212 1.2 christos op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
1213 1.1 lukem
1214 1.2 christos attrs_free( attrs );
1215 1.2 christos ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1216 1.2 christos ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1217 1.2 christos return SLAP_CB_CONTINUE;
1218 1.2 christos }
1219 1.1 lukem
1220 1.2 christos a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
1221 1.1 lukem
1222 1.2 christos if ( a != NULL ) {
1223 1.2 christos if ( value_find_ex( age->age_def->agd_member_ad,
1224 1.2 christos SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1225 1.2 christos SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1226 1.2 christos a->a_nvals, ea ? ea->a_nvals : &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
1227 1.2 christos {
1228 1.2 christos is_olddn = 1;
1229 1.2 christos }
1230 1.1 lukem
1231 1.1 lukem }
1232 1.1 lukem
1233 1.2 christos overlay_entry_release_ov( op, group, 0, on );
1234 1.2 christos
1235 1.1 lukem }
1236 1.1 lukem
1237 1.1 lukem for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1238 1.1 lukem if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
1239 1.2 christos /* TODO: should retest filter as it could imply conditions on the dn */
1240 1.1 lukem is_newdn = 1;
1241 1.1 lukem break;
1242 1.1 lukem }
1243 1.1 lukem }
1244 1.1 lukem
1245 1.1 lukem
1246 1.2 christos if ( is_value_refresh ) {
1247 1.2 christos if ( is_olddn != is_newdn ) {
1248 1.2 christos /* group refresh */
1249 1.2 christos autogroup_delete_member_from_group( op, NULL, NULL, age) ;
1250 1.2 christos
1251 1.2 christos for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1252 1.2 christos autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
1253 1.2 christos }
1254 1.2 christos }
1255 1.2 christos ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1256 1.2 christos continue;
1257 1.2 christos }
1258 1.1 lukem if ( is_olddn == 1 && is_newdn == 0 ) {
1259 1.2 christos if ( ea )
1260 1.2 christos autogroup_delete_member_values_from_group( op, &new_dn, age, ea );
1261 1.2 christos else
1262 1.2 christos autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1263 1.1 lukem } else
1264 1.1 lukem if ( is_olddn == 0 && is_newdn == 1 ) {
1265 1.2 christos Entry etmp;
1266 1.2 christos struct berval odn, ondn;
1267 1.2 christos etmp.e_name = op->o_req_dn;
1268 1.2 christos etmp.e_nname = op->o_req_ndn;
1269 1.2 christos etmp.e_attrs = attrs;
1270 1.2 christos odn = op->o_dn;
1271 1.2 christos ondn = op->o_ndn;
1272 1.2 christos op->o_dn = op->o_bd->be_rootdn;
1273 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
1274 1.2 christos
1275 1.1 lukem for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
1276 1.2 christos if ( test_filter( op, &etmp, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
1277 1.2 christos if ( ea ) {
1278 1.2 christos autogroup_add_member_values_to_group( op, &new_dn, age, ea );
1279 1.2 christos } else
1280 1.2 christos autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
1281 1.1 lukem break;
1282 1.1 lukem }
1283 1.1 lukem }
1284 1.2 christos op->o_dn = odn;
1285 1.2 christos op->o_ndn = ondn;
1286 1.1 lukem } else
1287 1.1 lukem if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
1288 1.2 christos if ( ea ) {
1289 1.2 christos /* group refresh */
1290 1.2 christos autogroup_delete_member_from_group( op, NULL, NULL, age) ;
1291 1.2 christos
1292 1.2 christos for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1293 1.2 christos autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
1294 1.2 christos }
1295 1.2 christos }
1296 1.2 christos else {
1297 1.2 christos autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1298 1.2 christos autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
1299 1.2 christos }
1300 1.1 lukem }
1301 1.1 lukem
1302 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1303 1.1 lukem }
1304 1.1 lukem
1305 1.1 lukem op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
1306 1.1 lukem op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
1307 1.1 lukem
1308 1.2 christos attrs_free( attrs );
1309 1.2 christos
1310 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1311 1.1 lukem }
1312 1.1 lukem }
1313 1.1 lukem
1314 1.1 lukem if ( op->o_tag == LDAP_REQ_MODIFY ) {
1315 1.2 christos if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
1316 1.2 christos Entry etmp;
1317 1.2 christos struct berval odn, ondn;
1318 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
1319 1.1 lukem
1320 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1321 1.1 lukem
1322 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
1323 1.1 lukem LDAP_SUCCESS || e == NULL ) {
1324 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
1325 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1326 1.1 lukem return SLAP_CB_CONTINUE;
1327 1.1 lukem }
1328 1.1 lukem
1329 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
1330 1.1 lukem
1331 1.1 lukem
1332 1.1 lukem if ( a == NULL ) {
1333 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
1334 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1335 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1336 1.1 lukem return SLAP_CB_CONTINUE;
1337 1.1 lukem }
1338 1.1 lukem
1339 1.1 lukem /* If we modify a group's memberURL, we have to delete all of it's members,
1340 1.1 lukem and add them anew, because we cannot tell from which memberURL a member was added. */
1341 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
1342 1.1 lukem
1343 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
1344 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1345 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1346 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
1347 1.1 lukem op->o_tmpmemctx ) == 0 )
1348 1.1 lukem {
1349 1.1 lukem Modifications *m;
1350 1.1 lukem int match = 1;
1351 1.1 lukem
1352 1.1 lukem m = op->orm_modlist;
1353 1.1 lukem
1354 1.2 christos for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1355 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
1356 1.1 lukem
1357 1.1 lukem dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
1358 1.1 lukem
1359 1.1 lukem if ( match == 0 ) {
1360 1.1 lukem for ( ; m ; m = m->sml_next ) {
1361 1.1 lukem if ( m->sml_desc == age->age_def->agd_member_url_ad ) {
1362 1.1 lukem autogroup_def_t *group_agd = age->age_def;
1363 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY changing memberURL for group <%s>\n",
1364 1.1 lukem op->o_req_dn.bv_val, 0, 0);
1365 1.1 lukem
1366 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1367 1.1 lukem
1368 1.1 lukem autogroup_delete_member_from_group( op, NULL, NULL, age );
1369 1.1 lukem autogroup_delete_group( agi, age );
1370 1.1 lukem
1371 1.1 lukem autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
1372 1.1 lukem
1373 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1374 1.1 lukem return SLAP_CB_CONTINUE;
1375 1.1 lukem }
1376 1.1 lukem }
1377 1.1 lukem
1378 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1379 1.1 lukem break;
1380 1.1 lukem }
1381 1.1 lukem
1382 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1383 1.1 lukem }
1384 1.1 lukem
1385 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1386 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1387 1.1 lukem return SLAP_CB_CONTINUE;
1388 1.1 lukem }
1389 1.1 lukem }
1390 1.1 lukem
1391 1.2 christos /* When modifying any of the attributes of an entry, we must
1392 1.1 lukem check if the entry is in any of our groups, and if
1393 1.1 lukem the modified entry maches any of the filters of that group.
1394 1.1 lukem
1395 1.1 lukem If the entry exists in a group, but the modified attributes do
1396 1.1 lukem not match any of the group's filters, we delete the entry from that group.
1397 1.1 lukem If the entry doesn't exist in a group, but matches a filter,
1398 1.1 lukem we add it to that group.
1399 1.1 lukem */
1400 1.2 christos attrs = attrs_dup( e->e_attrs );
1401 1.2 christos overlay_entry_release_ov( op, e, 0, on );
1402 1.2 christos etmp.e_name = op->o_req_dn;
1403 1.2 christos etmp.e_nname = op->o_req_ndn;
1404 1.2 christos etmp.e_attrs = attrs;
1405 1.2 christos odn = op->o_dn;
1406 1.2 christos ondn = op->o_ndn;
1407 1.2 christos op->o_dn = op->o_bd->be_rootdn;
1408 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
1409 1.2 christos
1410 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1411 1.1 lukem is_olddn = 0;
1412 1.1 lukem is_newdn = 0;
1413 1.1 lukem
1414 1.2 christos ldap_pvt_thread_mutex_lock( &age->age_mutex );
1415 1.1 lukem
1416 1.2 christos if ( age->age_filter && age->age_filter->agf_anlist ) {
1417 1.2 christos ea = attrs_find( attrs, age->age_filter->agf_anlist[0].an_desc );
1418 1.2 christos }
1419 1.2 christos else {
1420 1.2 christos ea = NULL;
1421 1.2 christos }
1422 1.1 lukem
1423 1.1 lukem if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
1424 1.1 lukem LDAP_SUCCESS || group == NULL ) {
1425 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n",
1426 1.1 lukem age->age_dn.bv_val, 0, 0);
1427 1.1 lukem
1428 1.2 christos attrs_free( attrs );
1429 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1430 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1431 1.2 christos op->o_dn = odn;
1432 1.2 christos op->o_ndn = ondn;
1433 1.1 lukem return SLAP_CB_CONTINUE;
1434 1.1 lukem }
1435 1.1 lukem
1436 1.1 lukem a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
1437 1.1 lukem
1438 1.1 lukem if ( a != NULL ) {
1439 1.1 lukem if ( value_find_ex( age->age_def->agd_member_ad,
1440 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1441 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1442 1.2 christos a->a_nvals, ea ? ea->a_nvals : &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
1443 1.1 lukem {
1444 1.1 lukem is_olddn = 1;
1445 1.1 lukem }
1446 1.1 lukem
1447 1.1 lukem }
1448 1.1 lukem
1449 1.1 lukem overlay_entry_release_ov( op, group, 0, on );
1450 1.1 lukem
1451 1.1 lukem for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1452 1.1 lukem if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
1453 1.2 christos if ( test_filter( op, &etmp, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
1454 1.1 lukem is_newdn = 1;
1455 1.1 lukem break;
1456 1.1 lukem }
1457 1.1 lukem }
1458 1.1 lukem }
1459 1.1 lukem
1460 1.1 lukem if ( is_olddn == 1 && is_newdn == 0 ) {
1461 1.2 christos if(ea)
1462 1.2 christos autogroup_delete_member_values_from_group( op, &op->o_req_dn, age, ea );
1463 1.2 christos else
1464 1.2 christos autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1465 1.1 lukem } else
1466 1.1 lukem if ( is_olddn == 0 && is_newdn == 1 ) {
1467 1.2 christos if(ea)
1468 1.2 christos autogroup_add_member_values_to_group( op, &op->o_req_dn, age, ea );
1469 1.2 christos else
1470 1.2 christos autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1471 1.1 lukem }
1472 1.1 lukem
1473 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1474 1.1 lukem }
1475 1.1 lukem
1476 1.2 christos op->o_dn = odn;
1477 1.2 christos op->o_ndn = ondn;
1478 1.2 christos attrs_free( attrs );
1479 1.2 christos
1480 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1481 1.1 lukem }
1482 1.1 lukem }
1483 1.1 lukem
1484 1.1 lukem return SLAP_CB_CONTINUE;
1485 1.1 lukem }
1486 1.1 lukem
1487 1.1 lukem /*
1488 1.2 christos ** Detect if filter contains a memberOf check for dn
1489 1.2 christos */
1490 1.2 christos static int
1491 1.2 christos autogroup_memberOf_filter( Filter *f, BerValue *dn, AttributeDescription *memberof_ad )
1492 1.2 christos {
1493 1.2 christos int result = 0;
1494 1.2 christos if ( f == NULL ) return 0;
1495 1.2 christos
1496 1.2 christos switch ( f->f_choice & SLAPD_FILTER_MASK ) {
1497 1.2 christos case LDAP_FILTER_AND:
1498 1.2 christos case LDAP_FILTER_OR:
1499 1.2 christos case LDAP_FILTER_NOT:
1500 1.2 christos for ( f = f->f_un.f_un_complex; f && !result; f = f->f_next ) {
1501 1.2 christos result = result || autogroup_memberOf_filter( f, dn, memberof_ad );
1502 1.2 christos }
1503 1.2 christos break;
1504 1.2 christos case LDAP_FILTER_EQUALITY:
1505 1.2 christos result = ( f->f_ava->aa_desc == memberof_ad &&
1506 1.2 christos ber_bvcmp( &f->f_ava->aa_value, dn ) == 0 );
1507 1.2 christos break;
1508 1.2 christos default:
1509 1.2 christos break;
1510 1.2 christos }
1511 1.2 christos
1512 1.2 christos return result;
1513 1.2 christos }
1514 1.2 christos
1515 1.2 christos /*
1516 1.1 lukem ** When modifing a group, we must deny any modifications to the member attribute,
1517 1.1 lukem ** because the group would be inconsistent.
1518 1.1 lukem */
1519 1.1 lukem static int
1520 1.1 lukem autogroup_modify_entry( Operation *op, SlapReply *rs)
1521 1.1 lukem {
1522 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1523 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1524 1.1 lukem autogroup_def_t *agd = agi->agi_def;
1525 1.2 christos autogroup_entry_t *age;
1526 1.1 lukem Entry *e;
1527 1.1 lukem Attribute *a;
1528 1.2 christos struct berval odn, ondn;
1529 1.2 christos OpExtra *oex;
1530 1.1 lukem
1531 1.2 christos LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
1532 1.2 christos if ( oex->oe_key == (void *)&autogroup )
1533 1.2 christos return SLAP_CB_CONTINUE;
1534 1.1 lukem }
1535 1.1 lukem
1536 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
1537 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1538 1.1 lukem
1539 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
1540 1.1 lukem LDAP_SUCCESS || e == NULL ) {
1541 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
1542 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1543 1.1 lukem return SLAP_CB_CONTINUE;
1544 1.1 lukem }
1545 1.1 lukem
1546 1.2 christos odn = op->o_dn;
1547 1.2 christos ondn = op->o_ndn;
1548 1.2 christos op->o_dn = op->o_bd->be_rootdn;
1549 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
1550 1.2 christos
1551 1.2 christos /* Must refresh groups if a matching member value is modified OR filter contains memberOf=DN */
1552 1.2 christos for ( age = agi->agi_entry; age ; age = age->age_next ) {
1553 1.2 christos autogroup_filter_t *agf;
1554 1.2 christos for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1555 1.2 christos if ( agf->agf_anlist ) {
1556 1.2 christos Modifications *m;
1557 1.2 christos for ( m = op->orm_modlist ; m ; m = m->sml_next ) {
1558 1.2 christos if ( m->sml_desc == agf->agf_anlist[0].an_desc ) {
1559 1.2 christos if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
1560 1.2 christos int rc = test_filter( op, e, agf->agf_filter );
1561 1.2 christos if ( rc == LDAP_COMPARE_TRUE ) {
1562 1.2 christos age->age_mustrefresh = 1;
1563 1.2 christos }
1564 1.2 christos }
1565 1.2 christos }
1566 1.2 christos }
1567 1.2 christos }
1568 1.2 christos
1569 1.2 christos if ( autogroup_memberOf_filter( agf->agf_filter, &op->o_req_ndn, agi->agi_memberof_ad ) ) {
1570 1.2 christos age->age_mustrefresh = 1;
1571 1.2 christos }
1572 1.2 christos }
1573 1.2 christos }
1574 1.2 christos op->o_dn = odn;
1575 1.2 christos op->o_ndn = ondn;
1576 1.2 christos
1577 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
1578 1.1 lukem
1579 1.1 lukem if ( a == NULL ) {
1580 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
1581 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1582 1.1 lukem return SLAP_CB_CONTINUE;
1583 1.1 lukem }
1584 1.1 lukem
1585 1.1 lukem
1586 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
1587 1.1 lukem
1588 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
1589 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1590 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1591 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
1592 1.1 lukem op->o_tmpmemctx ) == 0 )
1593 1.1 lukem {
1594 1.1 lukem Modifications *m;
1595 1.1 lukem int match = 1;
1596 1.1 lukem
1597 1.1 lukem m = op->orm_modlist;
1598 1.1 lukem
1599 1.2 christos for ( age = agi->agi_entry ; age ; age = age->age_next ) {
1600 1.1 lukem dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
1601 1.1 lukem
1602 1.1 lukem if ( match == 0 ) {
1603 1.1 lukem for ( ; m ; m = m->sml_next ) {
1604 1.1 lukem if ( m->sml_desc == age->age_def->agd_member_ad ) {
1605 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1606 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1607 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry attempted to modify group's <%s> member attribute\n", op->o_req_dn.bv_val, 0, 0);
1608 1.1 lukem send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to modify dynamic group member attribute");
1609 1.1 lukem return LDAP_CONSTRAINT_VIOLATION;
1610 1.1 lukem }
1611 1.1 lukem }
1612 1.1 lukem break;
1613 1.1 lukem }
1614 1.1 lukem }
1615 1.1 lukem
1616 1.2 christos /* an entry may only have one dynamic group class */
1617 1.2 christos break;
1618 1.2 christos }
1619 1.2 christos }
1620 1.2 christos
1621 1.2 christos overlay_entry_release_ov( op, e, 0, on );
1622 1.2 christos ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1623 1.2 christos return SLAP_CB_CONTINUE;
1624 1.2 christos }
1625 1.2 christos
1626 1.2 christos /*
1627 1.2 christos ** Detect if the olddn is part of a group and so if the group should be refreshed
1628 1.2 christos */
1629 1.2 christos static int
1630 1.2 christos autogroup_modrdn_entry( Operation *op, SlapReply *rs)
1631 1.2 christos {
1632 1.2 christos slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1633 1.2 christos autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1634 1.2 christos autogroup_entry_t *age;
1635 1.2 christos Entry *e;
1636 1.2 christos struct berval odn, ondn;
1637 1.2 christos OpExtra *oex;
1638 1.2 christos
1639 1.2 christos LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
1640 1.2 christos if ( oex->oe_key == (void *)&autogroup )
1641 1.1 lukem return SLAP_CB_CONTINUE;
1642 1.2 christos }
1643 1.2 christos
1644 1.2 christos Debug( LDAP_DEBUG_TRACE, "==> autogroup_modrdn_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
1645 1.2 christos ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1646 1.2 christos
1647 1.2 christos if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
1648 1.2 christos LDAP_SUCCESS || e == NULL ) {
1649 1.2 christos Debug( LDAP_DEBUG_TRACE, "autogroup_modrdn_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
1650 1.2 christos ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1651 1.2 christos return SLAP_CB_CONTINUE;
1652 1.2 christos }
1653 1.2 christos
1654 1.2 christos odn = op->o_dn;
1655 1.2 christos ondn = op->o_ndn;
1656 1.2 christos op->o_dn = op->o_bd->be_rootdn;
1657 1.2 christos op->o_ndn = op->o_bd->be_rootndn;
1658 1.2 christos
1659 1.2 christos /* Must check if a dn is modified */
1660 1.2 christos for ( age = agi->agi_entry; age ; age = age->age_next ) {
1661 1.2 christos autogroup_filter_t *agf;
1662 1.2 christos for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1663 1.2 christos if ( agf->agf_anlist ) {
1664 1.2 christos if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
1665 1.2 christos int rc = test_filter( op, e, agf->agf_filter );
1666 1.2 christos if ( rc == LDAP_COMPARE_TRUE ) {
1667 1.2 christos age->age_modrdn_olddnmodified = 1;
1668 1.2 christos }
1669 1.2 christos }
1670 1.2 christos }
1671 1.1 lukem }
1672 1.1 lukem }
1673 1.2 christos op->o_dn = odn;
1674 1.2 christos op->o_ndn = ondn;
1675 1.1 lukem
1676 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1677 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1678 1.1 lukem return SLAP_CB_CONTINUE;
1679 1.1 lukem }
1680 1.1 lukem
1681 1.1 lukem /*
1682 1.1 lukem ** Builds a filter for searching for the
1683 1.1 lukem ** group entries, according to the objectClass.
1684 1.1 lukem */
1685 1.1 lukem static int
1686 1.1 lukem autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
1687 1.1 lukem {
1688 1.1 lukem char *ptr;
1689 1.1 lukem
1690 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);
1691 1.1 lukem
1692 1.1 lukem op->ors_filterstr.bv_len = STRLENOF( "(=)" )
1693 1.1 lukem + slap_schema.si_ad_objectClass->ad_cname.bv_len
1694 1.1 lukem + agd->agd_oc->soc_cname.bv_len;
1695 1.1 lukem ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
1696 1.1 lukem *ptr++ = '(';
1697 1.1 lukem ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
1698 1.1 lukem *ptr++ = '=';
1699 1.1 lukem ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
1700 1.1 lukem *ptr++ = ')';
1701 1.1 lukem *ptr = '\0';
1702 1.1 lukem
1703 1.1 lukem op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
1704 1.1 lukem
1705 1.1 lukem assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
1706 1.1 lukem
1707 1.1 lukem return 0;
1708 1.1 lukem }
1709 1.1 lukem
1710 1.1 lukem enum {
1711 1.1 lukem AG_ATTRSET = 1,
1712 1.2 christos AG_MEMBER_OF_AD,
1713 1.1 lukem AG_LAST
1714 1.1 lukem };
1715 1.1 lukem
1716 1.1 lukem static ConfigDriver ag_cfgen;
1717 1.1 lukem
1718 1.1 lukem static ConfigTable agcfg[] = {
1719 1.1 lukem { "autogroup-attrset", "group-oc> <URL-ad> <member-ad",
1720 1.2 christos 4, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
1721 1.1 lukem "( OLcfgCtAt:2.1 NAME 'olcAGattrSet' "
1722 1.1 lukem "DESC 'Automatic groups: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
1723 1.1 lukem "EQUALITY caseIgnoreMatch "
1724 1.1 lukem "SYNTAX OMsDirectoryString "
1725 1.1 lukem "X-ORDERED 'VALUES' )",
1726 1.1 lukem NULL, NULL },
1727 1.2 christos
1728 1.2 christos { "autogroup-memberof-ad", "memberOf attribute",
1729 1.2 christos 2, 2, 0, ARG_MAGIC|AG_MEMBER_OF_AD, ag_cfgen,
1730 1.2 christos "( OLcfgCtAt:2.2 NAME 'olcAGmemberOfAd' "
1731 1.2 christos "DESC 'memberOf attribute' "
1732 1.2 christos "SYNTAX OMsDirectoryString SINGLE-VALUE )",
1733 1.2 christos NULL, NULL },
1734 1.2 christos
1735 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1736 1.1 lukem };
1737 1.1 lukem
1738 1.1 lukem static ConfigOCs agocs[] = {
1739 1.1 lukem { "( OLcfgCtOc:2.1 "
1740 1.1 lukem "NAME 'olcAutomaticGroups' "
1741 1.1 lukem "DESC 'Automatic groups configuration' "
1742 1.1 lukem "SUP olcOverlayConfig "
1743 1.2 christos "MAY ( "
1744 1.2 christos "olcAGattrSet "
1745 1.2 christos "$ olcAGmemberOfAd "
1746 1.2 christos ")"
1747 1.2 christos ")",
1748 1.1 lukem Cft_Overlay, agcfg, NULL, NULL },
1749 1.1 lukem { NULL, 0, NULL }
1750 1.1 lukem };
1751 1.1 lukem
1752 1.1 lukem
1753 1.1 lukem static int
1754 1.1 lukem ag_cfgen( ConfigArgs *c )
1755 1.1 lukem {
1756 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
1757 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1758 1.1 lukem autogroup_def_t *agd;
1759 1.1 lukem autogroup_entry_t *age;
1760 1.1 lukem
1761 1.1 lukem int rc = 0, i;
1762 1.1 lukem
1763 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_cfgen\n", 0, 0, 0);
1764 1.1 lukem
1765 1.1 lukem if( agi == NULL ) {
1766 1.1 lukem agi = (autogroup_info_t*)ch_calloc( 1, sizeof(autogroup_info_t) );
1767 1.1 lukem ldap_pvt_thread_mutex_init( &agi->agi_mutex );
1768 1.1 lukem agi->agi_def = NULL;
1769 1.1 lukem agi->agi_entry = NULL;
1770 1.1 lukem on->on_bi.bi_private = (void *)agi;
1771 1.1 lukem }
1772 1.1 lukem
1773 1.1 lukem agd = agi->agi_def;
1774 1.1 lukem age = agi->agi_entry;
1775 1.1 lukem
1776 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) {
1777 1.1 lukem
1778 1.2 christos switch( c->type ){
1779 1.2 christos case AG_ATTRSET:
1780 1.2 christos for ( i = 0 ; agd ; i++, agd = agd->agd_next ) {
1781 1.2 christos struct berval bv;
1782 1.2 christos char *ptr = c->cr_msg;
1783 1.2 christos
1784 1.2 christos assert(agd->agd_oc != NULL);
1785 1.2 christos assert(agd->agd_member_url_ad != NULL);
1786 1.2 christos assert(agd->agd_member_ad != NULL);
1787 1.2 christos
1788 1.2 christos ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
1789 1.2 christos SLAP_X_ORDERED_FMT "%s %s %s", i,
1790 1.2 christos agd->agd_oc->soc_cname.bv_val,
1791 1.2 christos agd->agd_member_url_ad->ad_cname.bv_val,
1792 1.2 christos agd->agd_member_ad->ad_cname.bv_val );
1793 1.2 christos
1794 1.2 christos bv.bv_val = c->cr_msg;
1795 1.2 christos bv.bv_len = ptr - bv.bv_val;
1796 1.2 christos value_add_one ( &c->rvalue_vals, &bv );
1797 1.2 christos
1798 1.2 christos }
1799 1.2 christos break;
1800 1.2 christos
1801 1.2 christos case AG_MEMBER_OF_AD:
1802 1.2 christos if ( agi->agi_memberof_ad != NULL ){
1803 1.2 christos value_add_one( &c->rvalue_vals, &agi->agi_memberof_ad->ad_cname );
1804 1.2 christos }
1805 1.2 christos break;
1806 1.1 lukem
1807 1.2 christos default:
1808 1.2 christos assert( 0 );
1809 1.2 christos return 1;
1810 1.2 christos }
1811 1.1 lukem
1812 1.1 lukem return rc;
1813 1.1 lukem
1814 1.1 lukem }else if ( c->op == LDAP_MOD_DELETE ) {
1815 1.1 lukem if ( c->valx < 0) {
1816 1.1 lukem autogroup_def_t *agd_next;
1817 1.1 lukem autogroup_entry_t *age_next;
1818 1.1 lukem autogroup_filter_t *agf = age->age_filter,
1819 1.1 lukem *agf_next;
1820 1.1 lukem
1821 1.1 lukem for ( agd_next = agd; agd_next; agd = agd_next ) {
1822 1.1 lukem agd_next = agd->agd_next;
1823 1.1 lukem
1824 1.1 lukem ch_free( agd );
1825 1.1 lukem }
1826 1.1 lukem
1827 1.1 lukem for ( age_next = age ; age_next ; age = age_next ) {
1828 1.1 lukem age_next = age->age_next;
1829 1.1 lukem
1830 1.1 lukem ch_free( age->age_dn.bv_val );
1831 1.1 lukem ch_free( age->age_ndn.bv_val );
1832 1.1 lukem
1833 1.1 lukem for( agf_next = agf ; agf_next ; agf = agf_next ){
1834 1.1 lukem agf_next = agf->agf_next;
1835 1.1 lukem
1836 1.1 lukem filter_free( agf->agf_filter );
1837 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
1838 1.1 lukem ch_free( agf->agf_dn.bv_val );
1839 1.1 lukem ch_free( agf->agf_ndn.bv_val );
1840 1.2 christos anlist_free( agf->agf_anlist, 1, NULL );
1841 1.2 christos ch_free( agf );
1842 1.1 lukem }
1843 1.1 lukem
1844 1.1 lukem ldap_pvt_thread_mutex_init( &age->age_mutex );
1845 1.1 lukem ch_free( age );
1846 1.1 lukem }
1847 1.1 lukem
1848 1.1 lukem ch_free( agi );
1849 1.1 lukem on->on_bi.bi_private = NULL;
1850 1.1 lukem
1851 1.1 lukem } else {
1852 1.1 lukem autogroup_def_t **agdp;
1853 1.1 lukem autogroup_entry_t *age_next, *age_prev;
1854 1.1 lukem autogroup_filter_t *agf,
1855 1.1 lukem *agf_next;
1856 1.1 lukem
1857 1.1 lukem for ( i = 0, agdp = &agi->agi_def;
1858 1.1 lukem i < c->valx; i++ )
1859 1.1 lukem {
1860 1.1 lukem if ( *agdp == NULL) {
1861 1.1 lukem return 1;
1862 1.1 lukem }
1863 1.1 lukem agdp = &(*agdp)->agd_next;
1864 1.1 lukem }
1865 1.1 lukem
1866 1.1 lukem agd = *agdp;
1867 1.1 lukem *agdp = agd->agd_next;
1868 1.1 lukem
1869 1.1 lukem for ( age_next = age , age_prev = NULL ; age_next ; age_prev = age, age = age_next ) {
1870 1.1 lukem age_next = age->age_next;
1871 1.1 lukem
1872 1.1 lukem if( age->age_def == agd ) {
1873 1.1 lukem agf = age->age_filter;
1874 1.1 lukem
1875 1.1 lukem ch_free( age->age_dn.bv_val );
1876 1.1 lukem ch_free( age->age_ndn.bv_val );
1877 1.1 lukem
1878 1.1 lukem for ( agf_next = agf; agf_next ; agf = agf_next ) {
1879 1.1 lukem agf_next = agf->agf_next;
1880 1.1 lukem filter_free( agf->agf_filter );
1881 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
1882 1.1 lukem ch_free( agf->agf_dn.bv_val );
1883 1.1 lukem ch_free( agf->agf_ndn.bv_val );
1884 1.2 christos anlist_free( agf->agf_anlist, 1, NULL );
1885 1.2 christos ch_free( agf );
1886 1.1 lukem }
1887 1.1 lukem
1888 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
1889 1.1 lukem ch_free( age );
1890 1.1 lukem
1891 1.1 lukem age = age_prev;
1892 1.1 lukem
1893 1.1 lukem if( age_prev != NULL ) {
1894 1.1 lukem age_prev->age_next = age_next;
1895 1.1 lukem }
1896 1.1 lukem }
1897 1.1 lukem }
1898 1.1 lukem
1899 1.1 lukem ch_free( agd );
1900 1.1 lukem agd = agi->agi_def;
1901 1.1 lukem
1902 1.1 lukem }
1903 1.1 lukem
1904 1.1 lukem return rc;
1905 1.1 lukem }
1906 1.1 lukem
1907 1.1 lukem switch(c->type){
1908 1.1 lukem case AG_ATTRSET: {
1909 1.1 lukem autogroup_def_t **agdp,
1910 1.1 lukem *agd_next = NULL;
1911 1.1 lukem ObjectClass *oc = NULL;
1912 1.1 lukem AttributeDescription *member_url_ad = NULL,
1913 1.1 lukem *member_ad = NULL;
1914 1.1 lukem const char *text;
1915 1.1 lukem
1916 1.1 lukem
1917 1.1 lukem oc = oc_find( c->argv[ 1 ] );
1918 1.1 lukem if( oc == NULL ){
1919 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1920 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1921 1.1 lukem "unable to find ObjectClass \"%s\"",
1922 1.1 lukem c->argv[ 1 ] );
1923 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1924 1.1 lukem c->log, c->cr_msg, 0 );
1925 1.1 lukem return 1;
1926 1.1 lukem }
1927 1.1 lukem
1928 1.1 lukem
1929 1.1 lukem rc = slap_str2ad( c->argv[ 2 ], &member_url_ad, &text );
1930 1.1 lukem if( rc != LDAP_SUCCESS ) {
1931 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1932 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1933 1.1 lukem "unable to find AttributeDescription \"%s\"",
1934 1.1 lukem c->argv[ 2 ] );
1935 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1936 1.1 lukem c->log, c->cr_msg, 0 );
1937 1.1 lukem return 1;
1938 1.1 lukem }
1939 1.1 lukem
1940 1.1 lukem if( !is_at_subtype( member_url_ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
1941 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1942 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1943 1.1 lukem "AttributeDescription \"%s\" ",
1944 1.1 lukem "must be of a subtype \"labeledURI\"",
1945 1.1 lukem c->argv[ 2 ] );
1946 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1947 1.1 lukem c->log, c->cr_msg, 0 );
1948 1.1 lukem return 1;
1949 1.1 lukem }
1950 1.1 lukem
1951 1.1 lukem rc = slap_str2ad( c->argv[3], &member_ad, &text );
1952 1.1 lukem if( rc != LDAP_SUCCESS ) {
1953 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1954 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1955 1.1 lukem "unable to find AttributeDescription \"%s\"",
1956 1.1 lukem c->argv[ 3 ] );
1957 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1958 1.1 lukem c->log, c->cr_msg, 0 );
1959 1.1 lukem return 1;
1960 1.1 lukem }
1961 1.1 lukem
1962 1.1 lukem for ( agdp = &agi->agi_def ; *agdp ; agdp = &(*agdp)->agd_next ) {
1963 1.1 lukem /* The same URL attribute / member attribute pair
1964 1.1 lukem * cannot be repeated */
1965 1.1 lukem
1966 1.1 lukem if ( (*agdp)->agd_member_url_ad == member_url_ad && (*agdp)->agd_member_ad == member_ad ) {
1967 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1968 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1969 1.1 lukem "URL attributeDescription \"%s\" already mapped",
1970 1.1 lukem member_ad->ad_cname.bv_val );
1971 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1972 1.1 lukem c->log, c->cr_msg, 0 );
1973 1.1 lukem /* return 1; //warning*/
1974 1.1 lukem }
1975 1.1 lukem }
1976 1.1 lukem
1977 1.1 lukem if ( c->valx > 0 ) {
1978 1.1 lukem int i;
1979 1.1 lukem
1980 1.1 lukem for ( i = 0, agdp = &agi->agi_def ;
1981 1.1 lukem i < c->valx; i++ )
1982 1.1 lukem {
1983 1.1 lukem if ( *agdp == NULL ) {
1984 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1985 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1986 1.1 lukem "invalid index {%d}",
1987 1.1 lukem c->valx );
1988 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1989 1.1 lukem c->log, c->cr_msg, 0 );
1990 1.1 lukem
1991 1.1 lukem return 1;
1992 1.1 lukem }
1993 1.1 lukem agdp = &(*agdp)->agd_next;
1994 1.1 lukem }
1995 1.1 lukem agd_next = *agdp;
1996 1.1 lukem
1997 1.1 lukem } else {
1998 1.1 lukem for ( agdp = &agi->agi_def; *agdp;
1999 1.1 lukem agdp = &(*agdp)->agd_next )
2000 1.1 lukem /* goto last */;
2001 1.1 lukem }
2002 1.1 lukem
2003 1.1 lukem *agdp = (autogroup_def_t *)ch_calloc( 1, sizeof(autogroup_info_t));
2004 1.1 lukem
2005 1.1 lukem (*agdp)->agd_oc = oc;
2006 1.1 lukem (*agdp)->agd_member_url_ad = member_url_ad;
2007 1.1 lukem (*agdp)->agd_member_ad = member_ad;
2008 1.1 lukem (*agdp)->agd_next = agd_next;
2009 1.1 lukem
2010 1.2 christos } break;
2011 1.2 christos
2012 1.2 christos case AG_MEMBER_OF_AD: {
2013 1.2 christos AttributeDescription *memberof_ad = NULL;
2014 1.2 christos const char *text;
2015 1.2 christos
2016 1.2 christos rc = slap_str2ad( c->argv[ 1 ], &memberof_ad, &text );
2017 1.2 christos if( rc != LDAP_SUCCESS ) {
2018 1.2 christos snprintf( c->cr_msg, sizeof( c->cr_msg ),
2019 1.2 christos "\"autogroup-memberof-ad <memberof-ad>\": "
2020 1.2 christos "unable to find AttributeDescription \"%s\"",
2021 1.2 christos c->argv[ 1 ] );
2022 1.2 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
2023 1.2 christos c->log, c->cr_msg, 0 );
2024 1.2 christos return 1;
2025 1.2 christos }
2026 1.2 christos
2027 1.2 christos if ( !is_at_syntax( memberof_ad->ad_type, SLAPD_DN_SYNTAX ) /* e.g. "member" */
2028 1.2 christos && !is_at_syntax( memberof_ad->ad_type, SLAPD_NAMEUID_SYNTAX ) ) /* e.g. "uniqueMember" */
2029 1.2 christos {
2030 1.2 christos snprintf( c->cr_msg, sizeof( c->cr_msg ),
2031 1.2 christos "memberof attribute=\"%s\" must either "
2032 1.2 christos "have DN (%s) or nameUID (%s) syntax",
2033 1.2 christos c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
2034 1.2 christos Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
2035 1.2 christos c->log, c->cr_msg, 0 );
2036 1.2 christos return 1;
2037 1.2 christos }
2038 1.2 christos
2039 1.2 christos agi->agi_memberof_ad = memberof_ad;
2040 1.1 lukem
2041 1.1 lukem } break;
2042 1.1 lukem
2043 1.1 lukem default:
2044 1.1 lukem rc = 1;
2045 1.1 lukem break;
2046 1.1 lukem }
2047 1.1 lukem
2048 1.1 lukem return rc;
2049 1.1 lukem }
2050 1.1 lukem
2051 1.2 christos extern int slapMode;
2052 1.2 christos
2053 1.1 lukem /*
2054 1.1 lukem ** Do a search for all the groups in the
2055 1.1 lukem ** database, and add them to out internal list.
2056 1.1 lukem */
2057 1.1 lukem static int
2058 1.1 lukem autogroup_db_open(
2059 1.1 lukem BackendDB *be,
2060 1.1 lukem ConfigReply *cr )
2061 1.1 lukem {
2062 1.2 christos slap_overinst *on = (slap_overinst *) be->bd_info;
2063 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
2064 1.1 lukem autogroup_def_t *agd;
2065 1.1 lukem autogroup_sc_t ags;
2066 1.1 lukem Operation *op;
2067 1.1 lukem slap_callback cb = { 0 };
2068 1.1 lukem
2069 1.1 lukem void *thrctx = ldap_pvt_thread_pool_context();
2070 1.1 lukem Connection conn = { 0 };
2071 1.1 lukem OperationBuffer opbuf;
2072 1.1 lukem
2073 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_open\n", 0, 0, 0);
2074 1.1 lukem
2075 1.2 christos if ( agi == NULL || !( slapMode & SLAP_SERVER_MODE )) {
2076 1.2 christos return 0;
2077 1.2 christos }
2078 1.2 christos
2079 1.1 lukem connection_fake_init( &conn, &opbuf, thrctx );
2080 1.1 lukem op = &opbuf.ob_op;
2081 1.1 lukem
2082 1.1 lukem op->ors_attrsonly = 0;
2083 1.1 lukem op->o_tag = LDAP_REQ_SEARCH;
2084 1.1 lukem op->o_dn = be->be_rootdn;
2085 1.1 lukem op->o_ndn = be->be_rootndn;
2086 1.1 lukem
2087 1.1 lukem op->o_req_dn = be->be_suffix[0];
2088 1.1 lukem op->o_req_ndn = be->be_nsuffix[0];
2089 1.1 lukem
2090 1.1 lukem op->ors_scope = LDAP_SCOPE_SUBTREE;
2091 1.1 lukem op->ors_deref = LDAP_DEREF_NEVER;
2092 1.1 lukem op->ors_limit = NULL;
2093 1.1 lukem op->ors_tlimit = SLAP_NO_LIMIT;
2094 1.1 lukem op->ors_slimit = SLAP_NO_LIMIT;
2095 1.1 lukem op->ors_attrs = slap_anlist_no_attrs;
2096 1.2 christos op->o_do_not_cache = 1;
2097 1.2 christos
2098 1.2 christos op->o_bd = be;
2099 1.2 christos op->o_bd->bd_info = (BackendInfo *)on->on_info;
2100 1.2 christos
2101 1.2 christos ags.ags_info = agi;
2102 1.2 christos cb.sc_private = &ags;
2103 1.2 christos cb.sc_response = autogroup_group_add_cb;
2104 1.2 christos cb.sc_cleanup = NULL;
2105 1.2 christos cb.sc_next = NULL;
2106 1.1 lukem
2107 1.2 christos op->o_callback = &cb;
2108 1.1 lukem
2109 1.1 lukem for (agd = agi->agi_def ; agd ; agd = agd->agd_next) {
2110 1.2 christos SlapReply rs = { REP_RESULT };
2111 1.1 lukem
2112 1.1 lukem autogroup_build_def_filter(agd, op);
2113 1.1 lukem
2114 1.1 lukem ags.ags_def = agd;
2115 1.1 lukem
2116 1.1 lukem op->o_bd->be_search( op, &rs );
2117 1.1 lukem
2118 1.2 christos filter_free_x( op, op->ors_filter, 1 );
2119 1.1 lukem op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
2120 1.1 lukem }
2121 1.2 christos
2122 1.2 christos if( ! agi->agi_memberof_ad ){
2123 1.2 christos int rc;
2124 1.2 christos const char *text = NULL;
2125 1.2 christos
2126 1.2 christos rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &agi->agi_memberof_ad, &text );
2127 1.2 christos if ( rc != LDAP_SUCCESS ) {
2128 1.2 christos Debug( LDAP_DEBUG_ANY, "autogroup_db_open: "
2129 1.2 christos "unable to find attribute=\"%s\": %s (%d)\n",
2130 1.2 christos SLAPD_MEMBEROF_ATTR, text, rc );
2131 1.2 christos return rc;
2132 1.2 christos }
2133 1.2 christos }
2134 1.1 lukem
2135 1.1 lukem return 0;
2136 1.1 lukem }
2137 1.1 lukem
2138 1.1 lukem static int
2139 1.1 lukem autogroup_db_close(
2140 1.1 lukem BackendDB *be,
2141 1.1 lukem ConfigReply *cr )
2142 1.1 lukem {
2143 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
2144 1.1 lukem
2145 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_close\n", 0, 0, 0);
2146 1.1 lukem
2147 1.1 lukem if ( on->on_bi.bi_private ) {
2148 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
2149 1.1 lukem autogroup_entry_t *age = agi->agi_entry,
2150 1.1 lukem *age_next;
2151 1.1 lukem autogroup_filter_t *agf, *agf_next;
2152 1.1 lukem
2153 1.1 lukem for ( age_next = age; age_next; age = age_next ) {
2154 1.1 lukem age_next = age->age_next;
2155 1.1 lukem
2156 1.1 lukem ch_free( age->age_dn.bv_val );
2157 1.1 lukem ch_free( age->age_ndn.bv_val );
2158 1.1 lukem
2159 1.1 lukem agf = age->age_filter;
2160 1.1 lukem
2161 1.1 lukem for ( agf_next = agf; agf_next; agf = agf_next ) {
2162 1.1 lukem agf_next = agf->agf_next;
2163 1.1 lukem
2164 1.1 lukem filter_free( agf->agf_filter );
2165 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
2166 1.1 lukem ch_free( agf->agf_dn.bv_val );
2167 1.1 lukem ch_free( agf->agf_ndn.bv_val );
2168 1.2 christos anlist_free( agf->agf_anlist, 1, NULL );
2169 1.1 lukem ch_free( agf );
2170 1.1 lukem }
2171 1.1 lukem
2172 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
2173 1.1 lukem ch_free( age );
2174 1.1 lukem }
2175 1.1 lukem }
2176 1.1 lukem
2177 1.1 lukem return 0;
2178 1.1 lukem }
2179 1.1 lukem
2180 1.1 lukem static int
2181 1.1 lukem autogroup_db_destroy(
2182 1.1 lukem BackendDB *be,
2183 1.1 lukem ConfigReply *cr )
2184 1.1 lukem {
2185 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
2186 1.1 lukem
2187 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_destroy\n", 0, 0, 0);
2188 1.1 lukem
2189 1.1 lukem if ( on->on_bi.bi_private ) {
2190 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
2191 1.1 lukem autogroup_def_t *agd = agi->agi_def,
2192 1.1 lukem *agd_next;
2193 1.1 lukem
2194 1.1 lukem for ( agd_next = agd; agd_next; agd = agd_next ) {
2195 1.1 lukem agd_next = agd->agd_next;
2196 1.1 lukem
2197 1.1 lukem ch_free( agd );
2198 1.1 lukem }
2199 1.1 lukem
2200 1.1 lukem ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
2201 1.1 lukem ch_free( agi );
2202 1.1 lukem }
2203 1.1 lukem
2204 1.1 lukem return 0;
2205 1.1 lukem }
2206 1.1 lukem
2207 1.1 lukem static
2208 1.1 lukem int
2209 1.1 lukem autogroup_initialize(void)
2210 1.1 lukem {
2211 1.1 lukem int rc = 0;
2212 1.1 lukem autogroup.on_bi.bi_type = "autogroup";
2213 1.1 lukem
2214 1.1 lukem autogroup.on_bi.bi_db_open = autogroup_db_open;
2215 1.1 lukem autogroup.on_bi.bi_db_close = autogroup_db_close;
2216 1.1 lukem autogroup.on_bi.bi_db_destroy = autogroup_db_destroy;
2217 1.1 lukem
2218 1.1 lukem autogroup.on_bi.bi_op_add = autogroup_add_entry;
2219 1.1 lukem autogroup.on_bi.bi_op_delete = autogroup_delete_entry;
2220 1.1 lukem autogroup.on_bi.bi_op_modify = autogroup_modify_entry;
2221 1.2 christos autogroup.on_bi.bi_op_modrdn = autogroup_modrdn_entry;
2222 1.1 lukem
2223 1.1 lukem autogroup.on_response = autogroup_response;
2224 1.1 lukem
2225 1.1 lukem autogroup.on_bi.bi_cf_ocs = agocs;
2226 1.1 lukem
2227 1.1 lukem rc = config_register_schema( agcfg, agocs );
2228 1.1 lukem if ( rc ) {
2229 1.1 lukem return rc;
2230 1.1 lukem }
2231 1.1 lukem
2232 1.1 lukem return overlay_register( &autogroup );
2233 1.1 lukem }
2234 1.1 lukem
2235 1.1 lukem int
2236 1.1 lukem init_module( int argc, char *argv[] )
2237 1.1 lukem {
2238 1.1 lukem return autogroup_initialize();
2239 1.1 lukem }
2240