autogroup.c revision 1.1.1.1 1 1.1 lukem /* autogroup.c - automatic group overlay */
2 1.1 lukem /* $OpenLDAP: pkg/ldap/contrib/slapd-modules/autogroup/autogroup.c,v 1.2.2.1 2008/02/08 23:00:43 quanah Exp $ */
3 1.1 lukem /*
4 1.1 lukem * Copyright 2007 Micha Szulczyski.
5 1.1 lukem * All rights reserved.
6 1.1 lukem *
7 1.1 lukem * Redistribution and use in source and binary forms, with or without
8 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
9 1.1 lukem * Public License.
10 1.1 lukem *
11 1.1 lukem * A copy of this license is available in the file LICENSE in the
12 1.1 lukem * top-level directory of the distribution or, alternatively, at
13 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
14 1.1 lukem */
15 1.1 lukem
16 1.1 lukem #include "portable.h"
17 1.1 lukem
18 1.1 lukem #include <stdio.h>
19 1.1 lukem
20 1.1 lukem #include <ac/string.h>
21 1.1 lukem
22 1.1 lukem #include "slap.h"
23 1.1 lukem #include "config.h"
24 1.1 lukem #include "lutil.h"
25 1.1 lukem
26 1.1 lukem /* Filter represents the memberURL of a group. */
27 1.1 lukem typedef struct autogroup_filter_t {
28 1.1 lukem struct berval agf_dn; /* The base DN in memberURL */
29 1.1 lukem struct berval agf_ndn;
30 1.1 lukem struct berval agf_filterstr;
31 1.1 lukem Filter *agf_filter;
32 1.1 lukem int agf_scope;
33 1.1 lukem struct autogroup_filter_t *agf_next;
34 1.1 lukem } autogroup_filter_t;
35 1.1 lukem
36 1.1 lukem /* Description of group attributes. */
37 1.1 lukem typedef struct autogroup_def_t {
38 1.1 lukem ObjectClass *agd_oc;
39 1.1 lukem AttributeDescription *agd_member_url_ad;
40 1.1 lukem AttributeDescription *agd_member_ad;
41 1.1 lukem struct autogroup_def_t *agd_next;
42 1.1 lukem } autogroup_def_t;
43 1.1 lukem
44 1.1 lukem /* Represents the group entry. */
45 1.1 lukem typedef struct autogroup_entry_t {
46 1.1 lukem BerValue age_dn;
47 1.1 lukem BerValue age_ndn;
48 1.1 lukem autogroup_filter_t *age_filter; /* List of filters made from memberURLs */
49 1.1 lukem autogroup_def_t *age_def; /* Attribute definition */
50 1.1 lukem ldap_pvt_thread_mutex_t age_mutex;
51 1.1 lukem struct autogroup_entry_t *age_next;
52 1.1 lukem } autogroup_entry_t;
53 1.1 lukem
54 1.1 lukem /* Holds pointers to attribute definitions and groups. */
55 1.1 lukem typedef struct autogroup_info_t {
56 1.1 lukem autogroup_def_t *agi_def; /* Group attributes definitions. */
57 1.1 lukem autogroup_entry_t *agi_entry; /* Group entries. */
58 1.1 lukem ldap_pvt_thread_mutex_t agi_mutex;
59 1.1 lukem } autogroup_info_t;
60 1.1 lukem
61 1.1 lukem /* Search callback for adding groups initially. */
62 1.1 lukem typedef struct autogroup_sc_t {
63 1.1 lukem autogroup_info_t *ags_info; /* Group definitions and entries. */
64 1.1 lukem autogroup_def_t *ags_def; /* Attributes definition of the group being added. */
65 1.1 lukem } autogroup_sc_t;
66 1.1 lukem
67 1.1 lukem /* Used for adding members, found when searching, to a group. */
68 1.1 lukem typedef struct autogroup_ga_t {
69 1.1 lukem autogroup_entry_t *agg_group; /* The group to which the members will be added. */
70 1.1 lukem Entry *agg_entry; /* Used in autogroup_member_search_cb to modify
71 1.1 lukem this entry with the search results. */
72 1.1 lukem
73 1.1 lukem Modifications *agg_mod; /* Used in autogroup_member_search_modify_cb to hold the
74 1.1 lukem search results which will be added to the group. */
75 1.1 lukem
76 1.1 lukem Modifications *agg_mod_last; /* Used in autogroup_member_search_modify_cb so we don't
77 1.1 lukem have to search for the last mod added. */
78 1.1 lukem } autogroup_ga_t;
79 1.1 lukem
80 1.1 lukem
81 1.1 lukem /*
82 1.1 lukem ** dn, ndn - the DN of the member to add
83 1.1 lukem ** age - the group to which the member DN will be added
84 1.1 lukem */
85 1.1 lukem static int
86 1.1 lukem autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
87 1.1 lukem {
88 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
89 1.1 lukem Modifications modlist;
90 1.1 lukem SlapReply sreply = {REP_RESULT};
91 1.1 lukem BerValue vals[ 2 ], nvals[ 2 ];
92 1.1 lukem slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
93 1.1 lukem Operation o = *op;
94 1.1 lukem
95 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_to_group adding <%s> to <%s>\n",
96 1.1 lukem dn->bv_val, age->age_dn.bv_val, 0);
97 1.1 lukem
98 1.1 lukem assert( dn != NULL );
99 1.1 lukem assert( ndn != NULL );
100 1.1 lukem
101 1.1 lukem vals[ 0 ] = *dn;
102 1.1 lukem BER_BVZERO( &vals[ 1 ] );
103 1.1 lukem nvals[ 0 ] = *ndn;
104 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
105 1.1 lukem
106 1.1 lukem modlist.sml_op = LDAP_MOD_ADD;
107 1.1 lukem modlist.sml_desc = age->age_def->agd_member_ad;
108 1.1 lukem modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
109 1.1 lukem modlist.sml_values = vals;
110 1.1 lukem modlist.sml_nvalues = nvals;
111 1.1 lukem modlist.sml_numvals = 1;
112 1.1 lukem modlist.sml_flags = SLAP_MOD_INTERNAL;
113 1.1 lukem modlist.sml_next = NULL;
114 1.1 lukem
115 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
116 1.1 lukem o.o_callback = &cb;
117 1.1 lukem o.orm_modlist = &modlist;
118 1.1 lukem o.o_req_dn = age->age_dn;
119 1.1 lukem o.o_req_ndn = age->age_ndn;
120 1.1 lukem o.o_permissive_modify = 1;
121 1.1 lukem o.o_managedsait = SLAP_CONTROL_CRITICAL;
122 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
123 1.1 lukem
124 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
125 1.1 lukem (void)op->o_bd->be_modify( &o, &sreply );
126 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
127 1.1 lukem
128 1.1 lukem return sreply.sr_err;
129 1.1 lukem }
130 1.1 lukem
131 1.1 lukem /*
132 1.1 lukem ** dn,ndn - the DN to be deleted
133 1.1 lukem ** age - the group from which the DN will be deleted
134 1.1 lukem ** If we pass a NULL dn and ndn, all members are deleted from the group.
135 1.1 lukem */
136 1.1 lukem static int
137 1.1 lukem autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
138 1.1 lukem {
139 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
140 1.1 lukem Modifications modlist;
141 1.1 lukem SlapReply sreply = {REP_RESULT};
142 1.1 lukem BerValue vals[ 2 ], nvals[ 2 ];
143 1.1 lukem slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
144 1.1 lukem Operation o = *op;
145 1.1 lukem
146 1.1 lukem if ( dn == NULL || ndn == NULL ) {
147 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
148 1.1 lukem age->age_dn.bv_val, 0 ,0);
149 1.1 lukem
150 1.1 lukem modlist.sml_values = NULL;
151 1.1 lukem modlist.sml_nvalues = NULL;
152 1.1 lukem modlist.sml_numvals = 0;
153 1.1 lukem } else {
154 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing <%s> from <%s>\n",
155 1.1 lukem dn->bv_val, age->age_dn.bv_val, 0);
156 1.1 lukem
157 1.1 lukem vals[ 0 ] = *dn;
158 1.1 lukem BER_BVZERO( &vals[ 1 ] );
159 1.1 lukem nvals[ 0 ] = *ndn;
160 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
161 1.1 lukem
162 1.1 lukem modlist.sml_values = vals;
163 1.1 lukem modlist.sml_nvalues = nvals;
164 1.1 lukem modlist.sml_numvals = 1;
165 1.1 lukem }
166 1.1 lukem
167 1.1 lukem
168 1.1 lukem modlist.sml_op = LDAP_MOD_DELETE;
169 1.1 lukem modlist.sml_desc = age->age_def->agd_member_ad;
170 1.1 lukem modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
171 1.1 lukem modlist.sml_flags = SLAP_MOD_INTERNAL;
172 1.1 lukem modlist.sml_next = NULL;
173 1.1 lukem
174 1.1 lukem o.o_callback = &cb;
175 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
176 1.1 lukem o.orm_modlist = &modlist;
177 1.1 lukem o.o_req_dn = age->age_dn;
178 1.1 lukem o.o_req_ndn = age->age_ndn;
179 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
180 1.1 lukem o.o_managedsait = SLAP_CONTROL_CRITICAL;
181 1.1 lukem o.o_permissive_modify = 1;
182 1.1 lukem
183 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
184 1.1 lukem (void)op->o_bd->be_modify( &o, &sreply );
185 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
186 1.1 lukem
187 1.1 lukem return sreply.sr_err;
188 1.1 lukem }
189 1.1 lukem
190 1.1 lukem /*
191 1.1 lukem ** Callback used to add entries to a group,
192 1.1 lukem ** which are going to be written in the database
193 1.1 lukem ** (used in bi_op_add)
194 1.1 lukem ** The group is passed in autogroup_ga_t->agg_group
195 1.1 lukem */
196 1.1 lukem static int
197 1.1 lukem autogroup_member_search_cb( Operation *op, SlapReply *rs )
198 1.1 lukem {
199 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
200 1.1 lukem
201 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
202 1.1 lukem
203 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
204 1.1 lukem autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
205 1.1 lukem autogroup_entry_t *age = agg->agg_group;
206 1.1 lukem Modification mod;
207 1.1 lukem const char *text = NULL;
208 1.1 lukem char textbuf[1024];
209 1.1 lukem struct berval vals[ 2 ], nvals[ 2 ];
210 1.1 lukem
211 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
212 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
213 1.1 lukem
214 1.1 lukem vals[ 0 ] = rs->sr_entry->e_name;
215 1.1 lukem BER_BVZERO( &vals[ 1 ] );
216 1.1 lukem nvals[ 0 ] = rs->sr_entry->e_nname;
217 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
218 1.1 lukem
219 1.1 lukem mod.sm_op = LDAP_MOD_ADD;
220 1.1 lukem mod.sm_desc = age->age_def->agd_member_ad;
221 1.1 lukem mod.sm_type = age->age_def->agd_member_ad->ad_cname;
222 1.1 lukem mod.sm_values = vals;
223 1.1 lukem mod.sm_nvalues = nvals;
224 1.1 lukem mod.sm_numvals = 1;
225 1.1 lukem
226 1.1 lukem modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
227 1.1 lukem }
228 1.1 lukem
229 1.1 lukem return 0;
230 1.1 lukem }
231 1.1 lukem
232 1.1 lukem /*
233 1.1 lukem ** Callback used to add entries to a group, which is already in the database.
234 1.1 lukem ** (used in on_response)
235 1.1 lukem ** The group is passed in autogroup_ga_t->agg_group
236 1.1 lukem ** NOTE: Very slow.
237 1.1 lukem */
238 1.1 lukem static int
239 1.1 lukem autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
240 1.1 lukem {
241 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
242 1.1 lukem
243 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
244 1.1 lukem
245 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
246 1.1 lukem autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
247 1.1 lukem autogroup_entry_t *age = agg->agg_group;
248 1.1 lukem Operation o = *op;
249 1.1 lukem Modifications *modlist;
250 1.1 lukem SlapReply sreply = {REP_RESULT};
251 1.1 lukem const char *text = NULL;
252 1.1 lukem char textbuf[1024];
253 1.1 lukem struct berval vals[ 2 ], nvals[ 2 ];
254 1.1 lukem slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
255 1.1 lukem
256 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
257 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
258 1.1 lukem
259 1.1 lukem vals[ 0 ] = rs->sr_entry->e_name;
260 1.1 lukem BER_BVZERO( &vals[ 1 ] );
261 1.1 lukem nvals[ 0 ] = rs->sr_entry->e_nname;
262 1.1 lukem BER_BVZERO( &nvals[ 1 ] );
263 1.1 lukem
264 1.1 lukem modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
265 1.1 lukem
266 1.1 lukem modlist->sml_op = LDAP_MOD_ADD;
267 1.1 lukem modlist->sml_desc = age->age_def->agd_member_ad;
268 1.1 lukem modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
269 1.1 lukem
270 1.1 lukem ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
271 1.1 lukem ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
272 1.1 lukem modlist->sml_numvals = 1;
273 1.1 lukem
274 1.1 lukem modlist->sml_flags = SLAP_MOD_INTERNAL;
275 1.1 lukem modlist->sml_next = NULL;
276 1.1 lukem
277 1.1 lukem if ( agg->agg_mod == NULL ) {
278 1.1 lukem agg->agg_mod = modlist;
279 1.1 lukem agg->agg_mod_last = modlist;
280 1.1 lukem } else {
281 1.1 lukem agg->agg_mod_last->sml_next = modlist;
282 1.1 lukem agg->agg_mod_last = modlist;
283 1.1 lukem }
284 1.1 lukem
285 1.1 lukem }
286 1.1 lukem
287 1.1 lukem return 0;
288 1.1 lukem }
289 1.1 lukem
290 1.1 lukem
291 1.1 lukem /*
292 1.1 lukem ** Adds all entries matching the passed filter to the specified group.
293 1.1 lukem ** If modify == 1, then we modify the group's entry in the database using be_modify.
294 1.1 lukem ** If modify == 0, then, we must supply a rw entry for the group,
295 1.1 lukem ** because we only modify the entry, without calling be_modify.
296 1.1 lukem ** e - the group entry, to which the members will be added
297 1.1 lukem ** age - the group
298 1.1 lukem ** agf - the filter
299 1.1 lukem */
300 1.1 lukem static int
301 1.1 lukem autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify)
302 1.1 lukem {
303 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
304 1.1 lukem Operation o = *op;
305 1.1 lukem SlapReply rs = { REP_SEARCH };
306 1.1 lukem slap_callback cb = { 0 };
307 1.1 lukem slap_callback null_cb = { NULL, slap_null_cb, NULL, NULL };
308 1.1 lukem autogroup_ga_t agg;
309 1.1 lukem
310 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
311 1.1 lukem age->age_dn.bv_val, 0, 0);
312 1.1 lukem
313 1.1 lukem o.ors_attrsonly = 0;
314 1.1 lukem o.o_tag = LDAP_REQ_SEARCH;
315 1.1 lukem
316 1.1 lukem o.o_req_dn = agf->agf_dn;
317 1.1 lukem o.o_req_ndn = agf->agf_ndn;
318 1.1 lukem
319 1.1 lukem o.ors_filterstr = agf->agf_filterstr;
320 1.1 lukem o.ors_filter = agf->agf_filter;
321 1.1 lukem
322 1.1 lukem o.ors_scope = agf->agf_scope;
323 1.1 lukem o.ors_deref = LDAP_DEREF_NEVER;
324 1.1 lukem o.ors_limit = NULL;
325 1.1 lukem o.ors_tlimit = SLAP_NO_LIMIT;
326 1.1 lukem o.ors_slimit = SLAP_NO_LIMIT;
327 1.1 lukem o.ors_attrs = slap_anlist_no_attrs;
328 1.1 lukem
329 1.1 lukem agg.agg_group = age;
330 1.1 lukem agg.agg_mod = NULL;
331 1.1 lukem agg.agg_mod_last = NULL;
332 1.1 lukem agg.agg_entry = e;
333 1.1 lukem cb.sc_private = &agg;
334 1.1 lukem
335 1.1 lukem if ( modify == 1 ) {
336 1.1 lukem cb.sc_response = autogroup_member_search_modify_cb;
337 1.1 lukem } else {
338 1.1 lukem cb.sc_response = autogroup_member_search_cb;
339 1.1 lukem }
340 1.1 lukem
341 1.1 lukem cb.sc_cleanup = NULL;
342 1.1 lukem cb.sc_next = NULL;
343 1.1 lukem
344 1.1 lukem o.o_callback = &cb;
345 1.1 lukem
346 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
347 1.1 lukem op->o_bd->be_search( &o, &rs );
348 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
349 1.1 lukem
350 1.1 lukem if ( modify == 1 ) {
351 1.1 lukem o = *op;
352 1.1 lukem o.o_callback = &null_cb;
353 1.1 lukem o.o_tag = LDAP_REQ_MODIFY;
354 1.1 lukem o.orm_modlist = agg.agg_mod;
355 1.1 lukem o.o_req_dn = age->age_dn;
356 1.1 lukem o.o_req_ndn = age->age_ndn;
357 1.1 lukem o.o_relax = SLAP_CONTROL_CRITICAL;
358 1.1 lukem o.o_managedsait = SLAP_CONTROL_NONCRITICAL;
359 1.1 lukem o.o_permissive_modify = 1;
360 1.1 lukem
361 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on->on_info;
362 1.1 lukem (void)op->o_bd->be_modify( &o, &rs );
363 1.1 lukem o.o_bd->bd_info = (BackendInfo *)on;
364 1.1 lukem
365 1.1 lukem slap_mods_free(agg.agg_mod, 1);
366 1.1 lukem }
367 1.1 lukem
368 1.1 lukem return 0;
369 1.1 lukem }
370 1.1 lukem
371 1.1 lukem /*
372 1.1 lukem ** Adds a group to the internal list from the passed entry.
373 1.1 lukem ** scan specifies whether to add all maching members to the group.
374 1.1 lukem ** modify specifies whether to modify the given group entry (when modify == 0),
375 1.1 lukem ** or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL).
376 1.1 lukem ** agi - pointer to the groups and the attribute definitions
377 1.1 lukem ** agd - the attribute definition of the added group
378 1.1 lukem ** e - the entry representing the group, can be NULL if the ndn is specified, and modify == 1
379 1.1 lukem ** ndn - the DN of the group, can be NULL if we give a non-NULL e
380 1.1 lukem */
381 1.1 lukem static int
382 1.1 lukem autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify)
383 1.1 lukem {
384 1.1 lukem autogroup_entry_t **agep = &agi->agi_entry;
385 1.1 lukem autogroup_filter_t *agf, *agf_prev = NULL;
386 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
387 1.1 lukem LDAPURLDesc *lud = NULL;
388 1.1 lukem Attribute *a;
389 1.1 lukem BerValue *bv, dn;
390 1.1 lukem int rc = 0, match = 1, null_entry = 0;
391 1.1 lukem
392 1.1 lukem if ( e == NULL ) {
393 1.1 lukem if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) !=
394 1.1 lukem LDAP_SUCCESS || e == NULL ) {
395 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot get entry for <%s>\n", ndn->bv_val, 0, 0);
396 1.1 lukem return 1;
397 1.1 lukem }
398 1.1 lukem
399 1.1 lukem null_entry = 1;
400 1.1 lukem }
401 1.1 lukem
402 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n",
403 1.1 lukem e->e_name.bv_val, 0, 0);
404 1.1 lukem
405 1.1 lukem if ( agi->agi_entry != NULL ) {
406 1.1 lukem for ( ; *agep ; agep = &(*agep)->age_next ) {
407 1.1 lukem dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*agep)->age_ndn );
408 1.1 lukem if ( match == 0 ) {
409 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
410 1.1 lukem return 1;
411 1.1 lukem }
412 1.1 lukem /* goto last */;
413 1.1 lukem }
414 1.1 lukem }
415 1.1 lukem
416 1.1 lukem
417 1.1 lukem *agep = (autogroup_entry_t *)ch_calloc( 1, sizeof( autogroup_entry_t ) );
418 1.1 lukem ldap_pvt_thread_mutex_init( &(*agep)->age_mutex );
419 1.1 lukem (*agep)->age_def = agd;
420 1.1 lukem (*agep)->age_filter = NULL;
421 1.1 lukem
422 1.1 lukem ber_dupbv( &(*agep)->age_dn, &e->e_name );
423 1.1 lukem ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
424 1.1 lukem
425 1.1 lukem a = attrs_find( e->e_attrs, agd->agd_member_url_ad );
426 1.1 lukem
427 1.1 lukem if ( null_entry == 1 ) {
428 1.1 lukem a = attrs_dup( a );
429 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
430 1.1 lukem }
431 1.1 lukem
432 1.1 lukem if( a == NULL ) {
433 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0);
434 1.1 lukem } else {
435 1.1 lukem for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
436 1.1 lukem
437 1.1 lukem agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) );
438 1.1 lukem
439 1.1 lukem if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
440 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot parse url <%s>\n", bv->bv_val,0,0);
441 1.1 lukem /* FIXME: error? */
442 1.1 lukem ch_free( agf );
443 1.1 lukem continue;
444 1.1 lukem }
445 1.1 lukem
446 1.1 lukem agf->agf_scope = lud->lud_scope;
447 1.1 lukem
448 1.1 lukem if ( lud->lud_dn == NULL ) {
449 1.1 lukem BER_BVSTR( &dn, "" );
450 1.1 lukem } else {
451 1.1 lukem ber_str2bv( lud->lud_dn, 0, 0, &dn );
452 1.1 lukem }
453 1.1 lukem
454 1.1 lukem rc = dnPrettyNormal( NULL, &dn, &agf->agf_dn, &agf->agf_ndn, NULL );
455 1.1 lukem if ( rc != LDAP_SUCCESS ) {
456 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0);
457 1.1 lukem /* FIXME: error? */
458 1.1 lukem goto cleanup;
459 1.1 lukem }
460 1.1 lukem
461 1.1 lukem if ( lud->lud_filter != NULL ) {
462 1.1 lukem ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr);
463 1.1 lukem agf->agf_filter = str2filter( lud->lud_filter );
464 1.1 lukem }
465 1.1 lukem
466 1.1 lukem agf->agf_next = NULL;
467 1.1 lukem
468 1.1 lukem
469 1.1 lukem if( (*agep)->age_filter == NULL ) {
470 1.1 lukem (*agep)->age_filter = agf;
471 1.1 lukem }
472 1.1 lukem
473 1.1 lukem if( agf_prev != NULL ) {
474 1.1 lukem agf_prev->agf_next = agf;
475 1.1 lukem }
476 1.1 lukem
477 1.1 lukem agf_prev = agf;
478 1.1 lukem
479 1.1 lukem if ( scan == 1 ){
480 1.1 lukem autogroup_add_members_from_filter( op, e, (*agep), agf, modify );
481 1.1 lukem }
482 1.1 lukem
483 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: added memberURL DN <%s> with filter <%s>\n",
484 1.1 lukem agf->agf_ndn.bv_val, agf->agf_filterstr.bv_val, 0);
485 1.1 lukem
486 1.1 lukem ldap_free_urldesc( lud );
487 1.1 lukem
488 1.1 lukem continue;
489 1.1 lukem
490 1.1 lukem
491 1.1 lukem cleanup:;
492 1.1 lukem
493 1.1 lukem ldap_free_urldesc( lud );
494 1.1 lukem ch_free( agf );
495 1.1 lukem }
496 1.1 lukem }
497 1.1 lukem
498 1.1 lukem if ( null_entry == 1 ) {
499 1.1 lukem attrs_free( a );
500 1.1 lukem }
501 1.1 lukem return rc;
502 1.1 lukem }
503 1.1 lukem
504 1.1 lukem /*
505 1.1 lukem ** Used when opening the database to add all existing
506 1.1 lukem ** groups from the database to our internal list.
507 1.1 lukem */
508 1.1 lukem static int
509 1.1 lukem autogroup_group_add_cb( Operation *op, SlapReply *rs )
510 1.1 lukem {
511 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
512 1.1 lukem
513 1.1 lukem assert( op->o_tag == LDAP_REQ_SEARCH );
514 1.1 lukem
515 1.1 lukem
516 1.1 lukem if ( rs->sr_type == REP_SEARCH ) {
517 1.1 lukem autogroup_sc_t *ags = (autogroup_sc_t *)op->o_callback->sc_private;
518 1.1 lukem
519 1.1 lukem Debug(LDAP_DEBUG_TRACE, "==> autogroup_group_add_cb <%s>\n",
520 1.1 lukem rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
521 1.1 lukem
522 1.1 lukem autogroup_add_group( op, ags->ags_info, ags->ags_def, rs->sr_entry, NULL, 0, 0);
523 1.1 lukem }
524 1.1 lukem
525 1.1 lukem return 0;
526 1.1 lukem }
527 1.1 lukem
528 1.1 lukem
529 1.1 lukem /*
530 1.1 lukem ** When adding a group, we first strip any existing members,
531 1.1 lukem ** and add all which match the filters ourselfs.
532 1.1 lukem */
533 1.1 lukem static int
534 1.1 lukem autogroup_add_entry( Operation *op, SlapReply *rs)
535 1.1 lukem {
536 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
537 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
538 1.1 lukem autogroup_def_t *agd = agi->agi_def;
539 1.1 lukem autogroup_entry_t *age = agi->agi_entry;
540 1.1 lukem autogroup_filter_t *agf;
541 1.1 lukem Attribute *a;
542 1.1 lukem int rc = 0;
543 1.1 lukem
544 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n",
545 1.1 lukem op->ora_e->e_name.bv_val, 0, 0);
546 1.1 lukem
547 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
548 1.1 lukem
549 1.1 lukem /* Check if it's a group. */
550 1.1 lukem for ( ; agd ; agd = agd->agd_next ) {
551 1.1 lukem if ( is_entry_objectclass_or_sub( op->ora_e, agd->agd_oc ) ) {
552 1.1 lukem Modification mod;
553 1.1 lukem const char *text = NULL;
554 1.1 lukem char textbuf[1024];
555 1.1 lukem
556 1.1 lukem mod.sm_op = LDAP_MOD_DELETE;
557 1.1 lukem mod.sm_desc = agd->agd_member_ad;
558 1.1 lukem mod.sm_type = agd->agd_member_ad->ad_cname;
559 1.1 lukem mod.sm_values = NULL;
560 1.1 lukem mod.sm_nvalues = NULL;
561 1.1 lukem
562 1.1 lukem /* We don't want any member attributes added by the user. */
563 1.1 lukem modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
564 1.1 lukem
565 1.1 lukem autogroup_add_group( op, agi, agd, op->ora_e, NULL, 1 , 0);
566 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
567 1.1 lukem return SLAP_CB_CONTINUE;
568 1.1 lukem }
569 1.1 lukem }
570 1.1 lukem
571 1.1 lukem for ( ; age ; age = age->age_next ) {
572 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
573 1.1 lukem
574 1.1 lukem /* Check if any of the filters are the suffix to the entry DN.
575 1.1 lukem If yes, we can test that filter against the entry. */
576 1.1 lukem
577 1.1 lukem for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
578 1.1 lukem if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
579 1.1 lukem rc = test_filter( op, op->ora_e, agf->agf_filter );
580 1.1 lukem if ( rc == LDAP_COMPARE_TRUE ) {
581 1.1 lukem autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
582 1.1 lukem break;
583 1.1 lukem }
584 1.1 lukem }
585 1.1 lukem }
586 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
587 1.1 lukem }
588 1.1 lukem
589 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
590 1.1 lukem
591 1.1 lukem return SLAP_CB_CONTINUE;
592 1.1 lukem }
593 1.1 lukem
594 1.1 lukem /*
595 1.1 lukem ** agi - internal group and attribute definitions list
596 1.1 lukem ** e - the group to remove from the internal list
597 1.1 lukem */
598 1.1 lukem static int
599 1.1 lukem autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
600 1.1 lukem {
601 1.1 lukem autogroup_entry_t *age = agi->agi_entry,
602 1.1 lukem *age_prev = NULL,
603 1.1 lukem *age_next;
604 1.1 lukem int rc = 1;
605 1.1 lukem
606 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_group <%s>\n",
607 1.1 lukem age->age_dn.bv_val, 0, 0);
608 1.1 lukem
609 1.1 lukem for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
610 1.1 lukem age_next = age->age_next;
611 1.1 lukem
612 1.1 lukem if ( age == e ) {
613 1.1 lukem autogroup_filter_t *agf = age->age_filter,
614 1.1 lukem *agf_next;
615 1.1 lukem
616 1.1 lukem if ( age_prev != NULL ) {
617 1.1 lukem age_prev->age_next = age_next;
618 1.1 lukem } else {
619 1.1 lukem agi->agi_entry = NULL;
620 1.1 lukem }
621 1.1 lukem
622 1.1 lukem ch_free( age->age_dn.bv_val );
623 1.1 lukem ch_free( age->age_ndn.bv_val );
624 1.1 lukem
625 1.1 lukem for( agf_next = agf ; agf_next ; agf = agf_next ){
626 1.1 lukem agf_next = agf->agf_next;
627 1.1 lukem
628 1.1 lukem filter_free( agf->agf_filter );
629 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
630 1.1 lukem ch_free( agf->agf_dn.bv_val );
631 1.1 lukem ch_free( agf->agf_ndn.bv_val );
632 1.1 lukem }
633 1.1 lukem
634 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
635 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
636 1.1 lukem ch_free( age );
637 1.1 lukem
638 1.1 lukem rc = 0;
639 1.1 lukem return rc;
640 1.1 lukem
641 1.1 lukem }
642 1.1 lukem }
643 1.1 lukem
644 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);
645 1.1 lukem
646 1.1 lukem return rc;
647 1.1 lukem
648 1.1 lukem }
649 1.1 lukem
650 1.1 lukem static int
651 1.1 lukem autogroup_delete_entry( Operation *op, SlapReply *rs)
652 1.1 lukem {
653 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
654 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
655 1.1 lukem autogroup_def_t *agd = agi->agi_def;
656 1.1 lukem autogroup_entry_t *age = agi->agi_entry,
657 1.1 lukem *age_prev, *age_next;
658 1.1 lukem autogroup_filter_t *agf;
659 1.1 lukem Entry *e;
660 1.1 lukem int matched_group = 0, rc = 0;
661 1.1 lukem
662 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
663 1.1 lukem
664 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
665 1.1 lukem
666 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
667 1.1 lukem LDAP_SUCCESS || e == NULL ) {
668 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_delete_entry: cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
669 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
670 1.1 lukem return SLAP_CB_CONTINUE;
671 1.1 lukem }
672 1.1 lukem
673 1.1 lukem /* Check if the entry to be deleted is one of our groups. */
674 1.1 lukem for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
675 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
676 1.1 lukem age_next = age->age_next;
677 1.1 lukem
678 1.1 lukem if ( is_entry_objectclass_or_sub( e, age->age_def->agd_oc ) ) {
679 1.1 lukem int match = 1;
680 1.1 lukem
681 1.1 lukem matched_group = 1;
682 1.1 lukem
683 1.1 lukem dnMatch( &match, 0, NULL, NULL, &e->e_nname, &age->age_ndn );
684 1.1 lukem
685 1.1 lukem if ( match == 0 ) {
686 1.1 lukem autogroup_filter_t *agf = age->age_filter,
687 1.1 lukem *agf_next;
688 1.1 lukem
689 1.1 lukem autogroup_delete_group( agi, age );
690 1.1 lukem break;
691 1.1 lukem }
692 1.1 lukem }
693 1.1 lukem
694 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
695 1.1 lukem }
696 1.1 lukem
697 1.1 lukem if ( matched_group == 1 ) {
698 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
699 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
700 1.1 lukem return SLAP_CB_CONTINUE;
701 1.1 lukem }
702 1.1 lukem
703 1.1 lukem /* Check if the entry matches any of the groups.
704 1.1 lukem If yes, we can delete the entry from that group. */
705 1.1 lukem
706 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
707 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
708 1.1 lukem
709 1.1 lukem for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
710 1.1 lukem if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
711 1.1 lukem rc = test_filter( op, e, agf->agf_filter );
712 1.1 lukem if ( rc == LDAP_COMPARE_TRUE ) {
713 1.1 lukem autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
714 1.1 lukem break;
715 1.1 lukem }
716 1.1 lukem }
717 1.1 lukem }
718 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
719 1.1 lukem }
720 1.1 lukem
721 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
722 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
723 1.1 lukem
724 1.1 lukem return SLAP_CB_CONTINUE;
725 1.1 lukem }
726 1.1 lukem
727 1.1 lukem static int
728 1.1 lukem autogroup_response( Operation *op, SlapReply *rs )
729 1.1 lukem {
730 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
731 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
732 1.1 lukem autogroup_def_t *agd = agi->agi_def;
733 1.1 lukem autogroup_entry_t *age = agi->agi_entry;
734 1.1 lukem autogroup_filter_t *agf;
735 1.1 lukem BerValue new_dn, new_ndn, pdn;
736 1.1 lukem Entry *e, *group;
737 1.1 lukem Attribute *a;
738 1.1 lukem int is_olddn, is_newdn, dn_equal;
739 1.1 lukem
740 1.1 lukem if ( op->o_tag == LDAP_REQ_MODRDN ) {
741 1.1 lukem if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
742 1.1 lukem
743 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
744 1.1 lukem
745 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
746 1.1 lukem
747 1.1 lukem if ( op->oq_modrdn.rs_newSup ) {
748 1.1 lukem pdn = *op->oq_modrdn.rs_newSup;
749 1.1 lukem } else {
750 1.1 lukem dnParent( &op->o_req_dn, &pdn );
751 1.1 lukem }
752 1.1 lukem build_new_dn( &new_dn, &pdn, &op->orr_newrdn, op->o_tmpmemctx );
753 1.1 lukem
754 1.1 lukem if ( op->oq_modrdn.rs_nnewSup ) {
755 1.1 lukem pdn = *op->oq_modrdn.rs_nnewSup;
756 1.1 lukem } else {
757 1.1 lukem dnParent( &op->o_req_ndn, &pdn );
758 1.1 lukem }
759 1.1 lukem build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, op->o_tmpmemctx );
760 1.1 lukem
761 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
762 1.1 lukem
763 1.1 lukem dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
764 1.1 lukem
765 1.1 lukem if ( overlay_entry_get_ov( op, &new_ndn, NULL, NULL, 0, &e, on ) !=
766 1.1 lukem LDAP_SUCCESS || e == NULL ) {
767 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get entry for <%s>\n", new_dn.bv_val, 0, 0);
768 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
769 1.1 lukem return SLAP_CB_CONTINUE;
770 1.1 lukem }
771 1.1 lukem
772 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
773 1.1 lukem
774 1.1 lukem
775 1.1 lukem if ( a == NULL ) {
776 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN entry <%s> has no objectClass\n", new_dn.bv_val, 0, 0);
777 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
778 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
779 1.1 lukem return SLAP_CB_CONTINUE;
780 1.1 lukem }
781 1.1 lukem
782 1.1 lukem
783 1.1 lukem /* If a groups DN is modified, just update age_dn/ndn of that group with the new DN. */
784 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
785 1.1 lukem
786 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
787 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
788 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
789 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
790 1.1 lukem op->o_tmpmemctx ) == 0 )
791 1.1 lukem {
792 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
793 1.1 lukem int match = 1;
794 1.1 lukem
795 1.1 lukem dnMatch( &match, 0, NULL, NULL, &age->age_ndn, &op->o_req_ndn );
796 1.1 lukem if ( match == 0 ) {
797 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN updating group's DN to <%s>\n", new_dn.bv_val, 0, 0);
798 1.1 lukem ber_dupbv( &age->age_dn, &new_dn );
799 1.1 lukem ber_dupbv( &age->age_ndn, &new_ndn );
800 1.1 lukem
801 1.1 lukem op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
802 1.1 lukem op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
803 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
804 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
805 1.1 lukem return SLAP_CB_CONTINUE;
806 1.1 lukem }
807 1.1 lukem }
808 1.1 lukem
809 1.1 lukem }
810 1.1 lukem }
811 1.1 lukem
812 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
813 1.1 lukem
814 1.1 lukem /* For each group:
815 1.1 lukem 1. check if the orginal entry's DN is in the group.
816 1.1 lukem 2. chceck if the any of the group filter's base DN is a suffix of the new DN
817 1.1 lukem
818 1.1 lukem If 1 and 2 are both false, we do nothing.
819 1.1 lukem If 1 and 2 is true, we remove the old DN from the group, and add the new DN.
820 1.1 lukem If 1 is false, and 2 is true, we check the entry against the group's filters,
821 1.1 lukem and add it's DN to the group.
822 1.1 lukem If 1 is true, and 2 is false, we delete the entry's DN from the group.
823 1.1 lukem */
824 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
825 1.1 lukem is_olddn = 0;
826 1.1 lukem is_newdn = 0;
827 1.1 lukem
828 1.1 lukem
829 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
830 1.1 lukem
831 1.1 lukem if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
832 1.1 lukem LDAP_SUCCESS || group == NULL ) {
833 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
834 1.1 lukem
835 1.1 lukem op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
836 1.1 lukem op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
837 1.1 lukem
838 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
839 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
840 1.1 lukem return SLAP_CB_CONTINUE;
841 1.1 lukem }
842 1.1 lukem
843 1.1 lukem a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
844 1.1 lukem
845 1.1 lukem if ( a != NULL ) {
846 1.1 lukem if ( value_find_ex( age->age_def->agd_member_ad,
847 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
848 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
849 1.1 lukem a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
850 1.1 lukem {
851 1.1 lukem is_olddn = 1;
852 1.1 lukem }
853 1.1 lukem
854 1.1 lukem }
855 1.1 lukem
856 1.1 lukem overlay_entry_release_ov( op, group, 0, on );
857 1.1 lukem
858 1.1 lukem for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
859 1.1 lukem if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
860 1.1 lukem is_newdn = 1;
861 1.1 lukem break;
862 1.1 lukem }
863 1.1 lukem }
864 1.1 lukem
865 1.1 lukem
866 1.1 lukem if ( is_olddn == 1 && is_newdn == 0 ) {
867 1.1 lukem autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
868 1.1 lukem } else
869 1.1 lukem if ( is_olddn == 0 && is_newdn == 1 ) {
870 1.1 lukem for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
871 1.1 lukem if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
872 1.1 lukem autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
873 1.1 lukem break;
874 1.1 lukem }
875 1.1 lukem }
876 1.1 lukem } else
877 1.1 lukem if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
878 1.1 lukem autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
879 1.1 lukem autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
880 1.1 lukem }
881 1.1 lukem
882 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
883 1.1 lukem }
884 1.1 lukem
885 1.1 lukem op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
886 1.1 lukem op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
887 1.1 lukem
888 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
889 1.1 lukem }
890 1.1 lukem }
891 1.1 lukem
892 1.1 lukem if ( op->o_tag == LDAP_REQ_MODIFY ) {
893 1.1 lukem if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op ) ) {
894 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
895 1.1 lukem
896 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
897 1.1 lukem
898 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
899 1.1 lukem LDAP_SUCCESS || e == NULL ) {
900 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
901 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
902 1.1 lukem return SLAP_CB_CONTINUE;
903 1.1 lukem }
904 1.1 lukem
905 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
906 1.1 lukem
907 1.1 lukem
908 1.1 lukem if ( a == NULL ) {
909 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
910 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
911 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
912 1.1 lukem return SLAP_CB_CONTINUE;
913 1.1 lukem }
914 1.1 lukem
915 1.1 lukem
916 1.1 lukem /* If we modify a group's memberURL, we have to delete all of it's members,
917 1.1 lukem and add them anew, because we cannot tell from which memberURL a member was added. */
918 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
919 1.1 lukem
920 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
921 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
922 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
923 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
924 1.1 lukem op->o_tmpmemctx ) == 0 )
925 1.1 lukem {
926 1.1 lukem Modifications *m;
927 1.1 lukem int match = 1;
928 1.1 lukem
929 1.1 lukem m = op->orm_modlist;
930 1.1 lukem
931 1.1 lukem for ( ; age ; age = age->age_next ) {
932 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
933 1.1 lukem
934 1.1 lukem dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
935 1.1 lukem
936 1.1 lukem if ( match == 0 ) {
937 1.1 lukem for ( ; m ; m = m->sml_next ) {
938 1.1 lukem if ( m->sml_desc == age->age_def->agd_member_url_ad ) {
939 1.1 lukem autogroup_def_t *group_agd = age->age_def;
940 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY changing memberURL for group <%s>\n",
941 1.1 lukem op->o_req_dn.bv_val, 0, 0);
942 1.1 lukem
943 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
944 1.1 lukem
945 1.1 lukem autogroup_delete_member_from_group( op, NULL, NULL, age );
946 1.1 lukem autogroup_delete_group( agi, age );
947 1.1 lukem
948 1.1 lukem autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
949 1.1 lukem
950 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
951 1.1 lukem return SLAP_CB_CONTINUE;
952 1.1 lukem }
953 1.1 lukem }
954 1.1 lukem
955 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
956 1.1 lukem break;
957 1.1 lukem }
958 1.1 lukem
959 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
960 1.1 lukem }
961 1.1 lukem
962 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
963 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
964 1.1 lukem return SLAP_CB_CONTINUE;
965 1.1 lukem }
966 1.1 lukem }
967 1.1 lukem
968 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
969 1.1 lukem
970 1.1 lukem /* When modifing any of the attributes of an entry, we must
971 1.1 lukem check if the entry is in any of our groups, and if
972 1.1 lukem the modified entry maches any of the filters of that group.
973 1.1 lukem
974 1.1 lukem If the entry exists in a group, but the modified attributes do
975 1.1 lukem not match any of the group's filters, we delete the entry from that group.
976 1.1 lukem If the entry doesn't exist in a group, but matches a filter,
977 1.1 lukem we add it to that group.
978 1.1 lukem */
979 1.1 lukem for ( age = agi->agi_entry ; age ; age = age->age_next ) {
980 1.1 lukem is_olddn = 0;
981 1.1 lukem is_newdn = 0;
982 1.1 lukem
983 1.1 lukem
984 1.1 lukem ldap_pvt_thread_mutex_lock( &age->age_mutex );
985 1.1 lukem
986 1.1 lukem if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
987 1.1 lukem LDAP_SUCCESS || group == NULL ) {
988 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n",
989 1.1 lukem age->age_dn.bv_val, 0, 0);
990 1.1 lukem
991 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
992 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
993 1.1 lukem return SLAP_CB_CONTINUE;
994 1.1 lukem }
995 1.1 lukem
996 1.1 lukem a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
997 1.1 lukem
998 1.1 lukem if ( a != NULL ) {
999 1.1 lukem if ( value_find_ex( age->age_def->agd_member_ad,
1000 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1001 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1002 1.1 lukem a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
1003 1.1 lukem {
1004 1.1 lukem is_olddn = 1;
1005 1.1 lukem }
1006 1.1 lukem
1007 1.1 lukem }
1008 1.1 lukem
1009 1.1 lukem overlay_entry_release_ov( op, group, 0, on );
1010 1.1 lukem
1011 1.1 lukem for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
1012 1.1 lukem if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
1013 1.1 lukem if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
1014 1.1 lukem is_newdn = 1;
1015 1.1 lukem break;
1016 1.1 lukem }
1017 1.1 lukem }
1018 1.1 lukem }
1019 1.1 lukem
1020 1.1 lukem if ( is_olddn == 1 && is_newdn == 0 ) {
1021 1.1 lukem autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1022 1.1 lukem } else
1023 1.1 lukem if ( is_olddn == 0 && is_newdn == 1 ) {
1024 1.1 lukem autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1025 1.1 lukem }
1026 1.1 lukem
1027 1.1 lukem ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1028 1.1 lukem }
1029 1.1 lukem
1030 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1031 1.1 lukem }
1032 1.1 lukem }
1033 1.1 lukem
1034 1.1 lukem return SLAP_CB_CONTINUE;
1035 1.1 lukem }
1036 1.1 lukem
1037 1.1 lukem /*
1038 1.1 lukem ** When modifing a group, we must deny any modifications to the member attribute,
1039 1.1 lukem ** because the group would be inconsistent.
1040 1.1 lukem */
1041 1.1 lukem static int
1042 1.1 lukem autogroup_modify_entry( Operation *op, SlapReply *rs)
1043 1.1 lukem {
1044 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1045 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1046 1.1 lukem autogroup_def_t *agd = agi->agi_def;
1047 1.1 lukem autogroup_entry_t *age = agi->agi_entry;
1048 1.1 lukem Entry *e;
1049 1.1 lukem Attribute *a;
1050 1.1 lukem
1051 1.1 lukem if ( get_manageDSAit( op ) ) {
1052 1.1 lukem return SLAP_CB_CONTINUE;
1053 1.1 lukem }
1054 1.1 lukem
1055 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
1056 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1057 1.1 lukem
1058 1.1 lukem if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
1059 1.1 lukem LDAP_SUCCESS || e == NULL ) {
1060 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
1061 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1062 1.1 lukem return SLAP_CB_CONTINUE;
1063 1.1 lukem }
1064 1.1 lukem
1065 1.1 lukem a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
1066 1.1 lukem
1067 1.1 lukem if ( a == NULL ) {
1068 1.1 lukem Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
1069 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1070 1.1 lukem return SLAP_CB_CONTINUE;
1071 1.1 lukem }
1072 1.1 lukem
1073 1.1 lukem
1074 1.1 lukem for ( ; agd; agd = agd->agd_next ) {
1075 1.1 lukem
1076 1.1 lukem if ( value_find_ex( slap_schema.si_ad_objectClass,
1077 1.1 lukem SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1078 1.1 lukem SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1079 1.1 lukem a->a_nvals, &agd->agd_oc->soc_cname,
1080 1.1 lukem op->o_tmpmemctx ) == 0 )
1081 1.1 lukem {
1082 1.1 lukem Modifications *m;
1083 1.1 lukem int match = 1;
1084 1.1 lukem
1085 1.1 lukem m = op->orm_modlist;
1086 1.1 lukem
1087 1.1 lukem for ( ; age ; age = age->age_next ) {
1088 1.1 lukem dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
1089 1.1 lukem
1090 1.1 lukem if ( match == 0 ) {
1091 1.1 lukem for ( ; m ; m = m->sml_next ) {
1092 1.1 lukem if ( m->sml_desc == age->age_def->agd_member_ad ) {
1093 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1094 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1095 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);
1096 1.1 lukem send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to modify dynamic group member attribute");
1097 1.1 lukem return LDAP_CONSTRAINT_VIOLATION;
1098 1.1 lukem }
1099 1.1 lukem }
1100 1.1 lukem break;
1101 1.1 lukem }
1102 1.1 lukem }
1103 1.1 lukem
1104 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1105 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1106 1.1 lukem return SLAP_CB_CONTINUE;
1107 1.1 lukem }
1108 1.1 lukem }
1109 1.1 lukem
1110 1.1 lukem overlay_entry_release_ov( op, e, 0, on );
1111 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1112 1.1 lukem return SLAP_CB_CONTINUE;
1113 1.1 lukem }
1114 1.1 lukem
1115 1.1 lukem /*
1116 1.1 lukem ** Builds a filter for searching for the
1117 1.1 lukem ** group entries, according to the objectClass.
1118 1.1 lukem */
1119 1.1 lukem static int
1120 1.1 lukem autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
1121 1.1 lukem {
1122 1.1 lukem char *ptr;
1123 1.1 lukem
1124 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);
1125 1.1 lukem
1126 1.1 lukem op->ors_filterstr.bv_len = STRLENOF( "(=)" )
1127 1.1 lukem + slap_schema.si_ad_objectClass->ad_cname.bv_len
1128 1.1 lukem + agd->agd_oc->soc_cname.bv_len;
1129 1.1 lukem ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
1130 1.1 lukem *ptr++ = '(';
1131 1.1 lukem ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
1132 1.1 lukem *ptr++ = '=';
1133 1.1 lukem ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
1134 1.1 lukem *ptr++ = ')';
1135 1.1 lukem *ptr = '\0';
1136 1.1 lukem
1137 1.1 lukem op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
1138 1.1 lukem
1139 1.1 lukem assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
1140 1.1 lukem
1141 1.1 lukem return 0;
1142 1.1 lukem }
1143 1.1 lukem
1144 1.1 lukem enum {
1145 1.1 lukem AG_ATTRSET = 1,
1146 1.1 lukem AG_LAST
1147 1.1 lukem };
1148 1.1 lukem
1149 1.1 lukem static ConfigDriver ag_cfgen;
1150 1.1 lukem
1151 1.1 lukem static ConfigTable agcfg[] = {
1152 1.1 lukem { "autogroup-attrset", "group-oc> <URL-ad> <member-ad",
1153 1.1 lukem 3, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
1154 1.1 lukem "( OLcfgCtAt:2.1 NAME 'olcAGattrSet' "
1155 1.1 lukem "DESC 'Automatic groups: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
1156 1.1 lukem "EQUALITY caseIgnoreMatch "
1157 1.1 lukem "SYNTAX OMsDirectoryString "
1158 1.1 lukem "X-ORDERED 'VALUES' )",
1159 1.1 lukem NULL, NULL },
1160 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1161 1.1 lukem };
1162 1.1 lukem
1163 1.1 lukem static ConfigOCs agocs[] = {
1164 1.1 lukem { "( OLcfgCtOc:2.1 "
1165 1.1 lukem "NAME 'olcAutomaticGroups' "
1166 1.1 lukem "DESC 'Automatic groups configuration' "
1167 1.1 lukem "SUP olcOverlayConfig "
1168 1.1 lukem "MAY olcAGattrSet )",
1169 1.1 lukem Cft_Overlay, agcfg, NULL, NULL },
1170 1.1 lukem { NULL, 0, NULL }
1171 1.1 lukem };
1172 1.1 lukem
1173 1.1 lukem
1174 1.1 lukem static int
1175 1.1 lukem ag_cfgen( ConfigArgs *c )
1176 1.1 lukem {
1177 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
1178 1.1 lukem autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
1179 1.1 lukem autogroup_def_t *agd;
1180 1.1 lukem autogroup_entry_t *age;
1181 1.1 lukem
1182 1.1 lukem int rc = 0, i;
1183 1.1 lukem
1184 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_cfgen\n", 0, 0, 0);
1185 1.1 lukem
1186 1.1 lukem if( agi == NULL ) {
1187 1.1 lukem agi = (autogroup_info_t*)ch_calloc( 1, sizeof(autogroup_info_t) );
1188 1.1 lukem ldap_pvt_thread_mutex_init( &agi->agi_mutex );
1189 1.1 lukem agi->agi_def = NULL;
1190 1.1 lukem agi->agi_entry = NULL;
1191 1.1 lukem on->on_bi.bi_private = (void *)agi;
1192 1.1 lukem }
1193 1.1 lukem
1194 1.1 lukem agd = agi->agi_def;
1195 1.1 lukem age = agi->agi_entry;
1196 1.1 lukem
1197 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) {
1198 1.1 lukem
1199 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1200 1.1 lukem
1201 1.1 lukem for ( i = 0 ; agd ; i++, agd = agd->agd_next ) {
1202 1.1 lukem struct berval bv;
1203 1.1 lukem char *ptr = c->cr_msg;
1204 1.1 lukem
1205 1.1 lukem assert(agd->agd_oc != NULL);
1206 1.1 lukem assert(agd->agd_member_url_ad != NULL);
1207 1.1 lukem assert(agd->agd_member_ad != NULL);
1208 1.1 lukem
1209 1.1 lukem ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
1210 1.1 lukem SLAP_X_ORDERED_FMT "%s %s %s", i,
1211 1.1 lukem agd->agd_oc->soc_cname.bv_val,
1212 1.1 lukem agd->agd_member_url_ad->ad_cname.bv_val,
1213 1.1 lukem agd->agd_member_ad->ad_cname.bv_val );
1214 1.1 lukem
1215 1.1 lukem bv.bv_val = c->cr_msg;
1216 1.1 lukem bv.bv_len = ptr - bv.bv_val;
1217 1.1 lukem value_add_one ( &c->rvalue_vals, &bv );
1218 1.1 lukem
1219 1.1 lukem }
1220 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1221 1.1 lukem
1222 1.1 lukem return rc;
1223 1.1 lukem
1224 1.1 lukem }else if ( c->op == LDAP_MOD_DELETE ) {
1225 1.1 lukem if ( c->valx < 0) {
1226 1.1 lukem autogroup_def_t *agd_next;
1227 1.1 lukem autogroup_entry_t *age_next;
1228 1.1 lukem autogroup_filter_t *agf = age->age_filter,
1229 1.1 lukem *agf_next;
1230 1.1 lukem
1231 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1232 1.1 lukem
1233 1.1 lukem for ( agd_next = agd; agd_next; agd = agd_next ) {
1234 1.1 lukem agd_next = agd->agd_next;
1235 1.1 lukem
1236 1.1 lukem ch_free( agd );
1237 1.1 lukem }
1238 1.1 lukem
1239 1.1 lukem for ( age_next = age ; age_next ; age = age_next ) {
1240 1.1 lukem age_next = age->age_next;
1241 1.1 lukem
1242 1.1 lukem ch_free( age->age_dn.bv_val );
1243 1.1 lukem ch_free( age->age_ndn.bv_val );
1244 1.1 lukem
1245 1.1 lukem for( agf_next = agf ; agf_next ; agf = agf_next ){
1246 1.1 lukem agf_next = agf->agf_next;
1247 1.1 lukem
1248 1.1 lukem filter_free( agf->agf_filter );
1249 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
1250 1.1 lukem ch_free( agf->agf_dn.bv_val );
1251 1.1 lukem ch_free( agf->agf_ndn.bv_val );
1252 1.1 lukem }
1253 1.1 lukem
1254 1.1 lukem ldap_pvt_thread_mutex_init( &age->age_mutex );
1255 1.1 lukem ch_free( age );
1256 1.1 lukem }
1257 1.1 lukem
1258 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1259 1.1 lukem
1260 1.1 lukem ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
1261 1.1 lukem ch_free( agi );
1262 1.1 lukem on->on_bi.bi_private = NULL;
1263 1.1 lukem
1264 1.1 lukem } else {
1265 1.1 lukem autogroup_def_t **agdp;
1266 1.1 lukem autogroup_entry_t *age_next, *age_prev;
1267 1.1 lukem autogroup_filter_t *agf,
1268 1.1 lukem *agf_next;
1269 1.1 lukem struct berval *bv;
1270 1.1 lukem
1271 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1272 1.1 lukem
1273 1.1 lukem for ( i = 0, agdp = &agi->agi_def;
1274 1.1 lukem i < c->valx; i++ )
1275 1.1 lukem {
1276 1.1 lukem if ( *agdp == NULL) {
1277 1.1 lukem return 1;
1278 1.1 lukem }
1279 1.1 lukem agdp = &(*agdp)->agd_next;
1280 1.1 lukem }
1281 1.1 lukem
1282 1.1 lukem agd = *agdp;
1283 1.1 lukem *agdp = agd->agd_next;
1284 1.1 lukem
1285 1.1 lukem for ( age_next = age , age_prev = NULL ; age_next ; age_prev = age, age = age_next ) {
1286 1.1 lukem age_next = age->age_next;
1287 1.1 lukem
1288 1.1 lukem if( age->age_def == agd ) {
1289 1.1 lukem agf = age->age_filter;
1290 1.1 lukem
1291 1.1 lukem ch_free( age->age_dn.bv_val );
1292 1.1 lukem ch_free( age->age_ndn.bv_val );
1293 1.1 lukem
1294 1.1 lukem for ( agf_next = agf; agf_next ; agf = agf_next ) {
1295 1.1 lukem agf_next = agf->agf_next;
1296 1.1 lukem filter_free( agf->agf_filter );
1297 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
1298 1.1 lukem ch_free( agf->agf_dn.bv_val );
1299 1.1 lukem ch_free( agf->agf_ndn.bv_val );
1300 1.1 lukem }
1301 1.1 lukem
1302 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
1303 1.1 lukem ch_free( age );
1304 1.1 lukem
1305 1.1 lukem age = age_prev;
1306 1.1 lukem
1307 1.1 lukem if( age_prev != NULL ) {
1308 1.1 lukem age_prev->age_next = age_next;
1309 1.1 lukem }
1310 1.1 lukem }
1311 1.1 lukem }
1312 1.1 lukem
1313 1.1 lukem ch_free( agd );
1314 1.1 lukem agd = agi->agi_def;
1315 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1316 1.1 lukem
1317 1.1 lukem }
1318 1.1 lukem
1319 1.1 lukem return rc;
1320 1.1 lukem }
1321 1.1 lukem
1322 1.1 lukem switch(c->type){
1323 1.1 lukem case AG_ATTRSET: {
1324 1.1 lukem autogroup_def_t **agdp,
1325 1.1 lukem *agd_next = NULL;
1326 1.1 lukem ObjectClass *oc = NULL;
1327 1.1 lukem AttributeDescription *member_url_ad = NULL,
1328 1.1 lukem *member_ad = NULL;
1329 1.1 lukem const char *text;
1330 1.1 lukem
1331 1.1 lukem
1332 1.1 lukem oc = oc_find( c->argv[ 1 ] );
1333 1.1 lukem if( oc == NULL ){
1334 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1335 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1336 1.1 lukem "unable to find ObjectClass \"%s\"",
1337 1.1 lukem c->argv[ 1 ] );
1338 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1339 1.1 lukem c->log, c->cr_msg, 0 );
1340 1.1 lukem return 1;
1341 1.1 lukem }
1342 1.1 lukem
1343 1.1 lukem
1344 1.1 lukem rc = slap_str2ad( c->argv[ 2 ], &member_url_ad, &text );
1345 1.1 lukem if( rc != LDAP_SUCCESS ) {
1346 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1347 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1348 1.1 lukem "unable to find AttributeDescription \"%s\"",
1349 1.1 lukem c->argv[ 2 ] );
1350 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1351 1.1 lukem c->log, c->cr_msg, 0 );
1352 1.1 lukem return 1;
1353 1.1 lukem }
1354 1.1 lukem
1355 1.1 lukem if( !is_at_subtype( member_url_ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
1356 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1357 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1358 1.1 lukem "AttributeDescription \"%s\" ",
1359 1.1 lukem "must be of a subtype \"labeledURI\"",
1360 1.1 lukem c->argv[ 2 ] );
1361 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1362 1.1 lukem c->log, c->cr_msg, 0 );
1363 1.1 lukem return 1;
1364 1.1 lukem }
1365 1.1 lukem
1366 1.1 lukem rc = slap_str2ad( c->argv[3], &member_ad, &text );
1367 1.1 lukem if( rc != LDAP_SUCCESS ) {
1368 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1369 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1370 1.1 lukem "unable to find AttributeDescription \"%s\"",
1371 1.1 lukem c->argv[ 3 ] );
1372 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1373 1.1 lukem c->log, c->cr_msg, 0 );
1374 1.1 lukem return 1;
1375 1.1 lukem }
1376 1.1 lukem
1377 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1378 1.1 lukem
1379 1.1 lukem for ( agdp = &agi->agi_def ; *agdp ; agdp = &(*agdp)->agd_next ) {
1380 1.1 lukem /* The same URL attribute / member attribute pair
1381 1.1 lukem * cannot be repeated */
1382 1.1 lukem
1383 1.1 lukem if ( (*agdp)->agd_member_url_ad == member_url_ad && (*agdp)->agd_member_ad == member_ad ) {
1384 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1385 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1386 1.1 lukem "URL attributeDescription \"%s\" already mapped",
1387 1.1 lukem member_ad->ad_cname.bv_val );
1388 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1389 1.1 lukem c->log, c->cr_msg, 0 );
1390 1.1 lukem /* return 1; //warning*/
1391 1.1 lukem }
1392 1.1 lukem }
1393 1.1 lukem
1394 1.1 lukem if ( c->valx > 0 ) {
1395 1.1 lukem int i;
1396 1.1 lukem
1397 1.1 lukem for ( i = 0, agdp = &agi->agi_def ;
1398 1.1 lukem i < c->valx; i++ )
1399 1.1 lukem {
1400 1.1 lukem if ( *agdp == NULL ) {
1401 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
1402 1.1 lukem "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1403 1.1 lukem "invalid index {%d}",
1404 1.1 lukem c->valx );
1405 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1406 1.1 lukem c->log, c->cr_msg, 0 );
1407 1.1 lukem
1408 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1409 1.1 lukem return 1;
1410 1.1 lukem }
1411 1.1 lukem agdp = &(*agdp)->agd_next;
1412 1.1 lukem }
1413 1.1 lukem agd_next = *agdp;
1414 1.1 lukem
1415 1.1 lukem } else {
1416 1.1 lukem for ( agdp = &agi->agi_def; *agdp;
1417 1.1 lukem agdp = &(*agdp)->agd_next )
1418 1.1 lukem /* goto last */;
1419 1.1 lukem }
1420 1.1 lukem
1421 1.1 lukem *agdp = (autogroup_def_t *)ch_calloc( 1, sizeof(autogroup_info_t));
1422 1.1 lukem
1423 1.1 lukem (*agdp)->agd_oc = oc;
1424 1.1 lukem (*agdp)->agd_member_url_ad = member_url_ad;
1425 1.1 lukem (*agdp)->agd_member_ad = member_ad;
1426 1.1 lukem (*agdp)->agd_next = agd_next;
1427 1.1 lukem
1428 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1429 1.1 lukem
1430 1.1 lukem } break;
1431 1.1 lukem
1432 1.1 lukem default:
1433 1.1 lukem rc = 1;
1434 1.1 lukem break;
1435 1.1 lukem }
1436 1.1 lukem
1437 1.1 lukem return rc;
1438 1.1 lukem }
1439 1.1 lukem
1440 1.1 lukem /*
1441 1.1 lukem ** Do a search for all the groups in the
1442 1.1 lukem ** database, and add them to out internal list.
1443 1.1 lukem */
1444 1.1 lukem static int
1445 1.1 lukem autogroup_db_open(
1446 1.1 lukem BackendDB *be,
1447 1.1 lukem ConfigReply *cr )
1448 1.1 lukem {
1449 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info,
1450 1.1 lukem *on_bd;
1451 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
1452 1.1 lukem autogroup_def_t *agd;
1453 1.1 lukem autogroup_sc_t ags;
1454 1.1 lukem Operation *op;
1455 1.1 lukem SlapReply rs = { REP_RESULT };
1456 1.1 lukem slap_callback cb = { 0 };
1457 1.1 lukem
1458 1.1 lukem void *thrctx = ldap_pvt_thread_pool_context();
1459 1.1 lukem Connection conn = { 0 };
1460 1.1 lukem OperationBuffer opbuf;
1461 1.1 lukem BerValue bv;
1462 1.1 lukem char *ptr;
1463 1.1 lukem int rc = 0;
1464 1.1 lukem
1465 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_open\n", 0, 0, 0);
1466 1.1 lukem
1467 1.1 lukem connection_fake_init( &conn, &opbuf, thrctx );
1468 1.1 lukem op = &opbuf.ob_op;
1469 1.1 lukem
1470 1.1 lukem op->ors_attrsonly = 0;
1471 1.1 lukem op->o_tag = LDAP_REQ_SEARCH;
1472 1.1 lukem op->o_dn = be->be_rootdn;
1473 1.1 lukem op->o_ndn = be->be_rootndn;
1474 1.1 lukem
1475 1.1 lukem op->o_req_dn = be->be_suffix[0];
1476 1.1 lukem op->o_req_ndn = be->be_nsuffix[0];
1477 1.1 lukem
1478 1.1 lukem op->ors_scope = LDAP_SCOPE_SUBTREE;
1479 1.1 lukem op->ors_deref = LDAP_DEREF_NEVER;
1480 1.1 lukem op->ors_limit = NULL;
1481 1.1 lukem op->ors_tlimit = SLAP_NO_LIMIT;
1482 1.1 lukem op->ors_slimit = SLAP_NO_LIMIT;
1483 1.1 lukem op->ors_attrs = slap_anlist_no_attrs;
1484 1.1 lukem
1485 1.1 lukem op->o_bd = select_backend(&op->o_req_ndn, 0);
1486 1.1 lukem
1487 1.1 lukem ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1488 1.1 lukem for (agd = agi->agi_def ; agd ; agd = agd->agd_next) {
1489 1.1 lukem
1490 1.1 lukem autogroup_build_def_filter(agd, op);
1491 1.1 lukem
1492 1.1 lukem
1493 1.1 lukem ags.ags_info = agi;
1494 1.1 lukem ags.ags_def = agd;
1495 1.1 lukem cb.sc_private = &ags;
1496 1.1 lukem cb.sc_response = autogroup_group_add_cb;
1497 1.1 lukem cb.sc_cleanup = NULL;
1498 1.1 lukem cb.sc_next = NULL;
1499 1.1 lukem
1500 1.1 lukem op->o_callback = &cb;
1501 1.1 lukem
1502 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1503 1.1 lukem op->o_bd->be_search( op, &rs );
1504 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on;
1505 1.1 lukem
1506 1.1 lukem filter_free_x( op, op->ors_filter );
1507 1.1 lukem op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
1508 1.1 lukem }
1509 1.1 lukem ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1510 1.1 lukem
1511 1.1 lukem return 0;
1512 1.1 lukem }
1513 1.1 lukem
1514 1.1 lukem static int
1515 1.1 lukem autogroup_db_close(
1516 1.1 lukem BackendDB *be,
1517 1.1 lukem ConfigReply *cr )
1518 1.1 lukem {
1519 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1520 1.1 lukem
1521 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_close\n", 0, 0, 0);
1522 1.1 lukem
1523 1.1 lukem if ( on->on_bi.bi_private ) {
1524 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
1525 1.1 lukem autogroup_entry_t *age = agi->agi_entry,
1526 1.1 lukem *age_next;
1527 1.1 lukem autogroup_filter_t *agf, *agf_next;
1528 1.1 lukem
1529 1.1 lukem for ( age_next = age; age_next; age = age_next ) {
1530 1.1 lukem age_next = age->age_next;
1531 1.1 lukem
1532 1.1 lukem ch_free( age->age_dn.bv_val );
1533 1.1 lukem ch_free( age->age_ndn.bv_val );
1534 1.1 lukem
1535 1.1 lukem agf = age->age_filter;
1536 1.1 lukem
1537 1.1 lukem for ( agf_next = agf; agf_next; agf = agf_next ) {
1538 1.1 lukem agf_next = agf->agf_next;
1539 1.1 lukem
1540 1.1 lukem filter_free( agf->agf_filter );
1541 1.1 lukem ch_free( agf->agf_filterstr.bv_val );
1542 1.1 lukem ch_free( agf->agf_dn.bv_val );
1543 1.1 lukem ch_free( agf->agf_ndn.bv_val );
1544 1.1 lukem ch_free( agf );
1545 1.1 lukem }
1546 1.1 lukem
1547 1.1 lukem ldap_pvt_thread_mutex_destroy( &age->age_mutex );
1548 1.1 lukem ch_free( age );
1549 1.1 lukem }
1550 1.1 lukem }
1551 1.1 lukem
1552 1.1 lukem return 0;
1553 1.1 lukem }
1554 1.1 lukem
1555 1.1 lukem static int
1556 1.1 lukem autogroup_db_destroy(
1557 1.1 lukem BackendDB *be,
1558 1.1 lukem ConfigReply *cr )
1559 1.1 lukem {
1560 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1561 1.1 lukem
1562 1.1 lukem Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_destroy\n", 0, 0, 0);
1563 1.1 lukem
1564 1.1 lukem if ( on->on_bi.bi_private ) {
1565 1.1 lukem autogroup_info_t *agi = on->on_bi.bi_private;
1566 1.1 lukem autogroup_def_t *agd = agi->agi_def,
1567 1.1 lukem *agd_next;
1568 1.1 lukem
1569 1.1 lukem for ( agd_next = agd; agd_next; agd = agd_next ) {
1570 1.1 lukem agd_next = agd->agd_next;
1571 1.1 lukem
1572 1.1 lukem ch_free( agd );
1573 1.1 lukem }
1574 1.1 lukem
1575 1.1 lukem ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
1576 1.1 lukem ch_free( agi );
1577 1.1 lukem }
1578 1.1 lukem
1579 1.1 lukem return 0;
1580 1.1 lukem }
1581 1.1 lukem
1582 1.1 lukem static slap_overinst autogroup = { { NULL } };
1583 1.1 lukem
1584 1.1 lukem static
1585 1.1 lukem int
1586 1.1 lukem autogroup_initialize(void)
1587 1.1 lukem {
1588 1.1 lukem int rc = 0;
1589 1.1 lukem autogroup.on_bi.bi_type = "autogroup";
1590 1.1 lukem
1591 1.1 lukem autogroup.on_bi.bi_db_open = autogroup_db_open;
1592 1.1 lukem autogroup.on_bi.bi_db_close = autogroup_db_close;
1593 1.1 lukem autogroup.on_bi.bi_db_destroy = autogroup_db_destroy;
1594 1.1 lukem
1595 1.1 lukem autogroup.on_bi.bi_op_add = autogroup_add_entry;
1596 1.1 lukem autogroup.on_bi.bi_op_delete = autogroup_delete_entry;
1597 1.1 lukem autogroup.on_bi.bi_op_modify = autogroup_modify_entry;
1598 1.1 lukem
1599 1.1 lukem autogroup.on_response = autogroup_response;
1600 1.1 lukem
1601 1.1 lukem autogroup.on_bi.bi_cf_ocs = agocs;
1602 1.1 lukem
1603 1.1 lukem rc = config_register_schema( agcfg, agocs );
1604 1.1 lukem if ( rc ) {
1605 1.1 lukem return rc;
1606 1.1 lukem }
1607 1.1 lukem
1608 1.1 lukem return overlay_register( &autogroup );
1609 1.1 lukem }
1610 1.1 lukem
1611 1.1 lukem int
1612 1.1 lukem init_module( int argc, char *argv[] )
1613 1.1 lukem {
1614 1.1 lukem return autogroup_initialize();
1615 1.1 lukem }
1616