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