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