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