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