rwm.c revision 1.1.1.1 1 1.1 lukem /* rwm.c - rewrite/remap operations */
2 1.1 lukem /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/rwm.c,v 1.70.2.10 2008/02/15 18:11:46 quanah Exp $ */
3 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 1.1 lukem *
5 1.1 lukem * Copyright 2003-2008 The OpenLDAP Foundation.
6 1.1 lukem * Portions Copyright 2003 Pierangelo Masarati.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem
18 1.1 lukem #include "portable.h"
19 1.1 lukem
20 1.1 lukem #ifdef SLAPD_OVER_RWM
21 1.1 lukem
22 1.1 lukem #include <stdio.h>
23 1.1 lukem
24 1.1 lukem #include <ac/string.h>
25 1.1 lukem
26 1.1 lukem #include "slap.h"
27 1.1 lukem #include "config.h"
28 1.1 lukem #include "lutil.h"
29 1.1 lukem #include "rwm.h"
30 1.1 lukem
31 1.1 lukem typedef struct rwm_op_state {
32 1.1 lukem ber_tag_t r_tag;
33 1.1 lukem struct berval ro_dn;
34 1.1 lukem struct berval ro_ndn;
35 1.1 lukem struct berval r_dn;
36 1.1 lukem struct berval r_ndn;
37 1.1 lukem AttributeName *mapped_attrs;
38 1.1 lukem OpRequest o_request;
39 1.1 lukem } rwm_op_state;
40 1.1 lukem
41 1.1 lukem static int
42 1.1 lukem rwm_db_destroy( BackendDB *be, ConfigReply *cr );
43 1.1 lukem
44 1.1 lukem typedef struct rwm_op_cb {
45 1.1 lukem slap_callback cb;
46 1.1 lukem rwm_op_state ros;
47 1.1 lukem } rwm_op_cb;
48 1.1 lukem
49 1.1 lukem static int
50 1.1 lukem rwm_op_cleanup( Operation *op, SlapReply *rs )
51 1.1 lukem {
52 1.1 lukem slap_callback *cb = op->o_callback;
53 1.1 lukem rwm_op_state *ros = cb->sc_private;
54 1.1 lukem
55 1.1 lukem if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
56 1.1 lukem op->o_abandon || rs->sr_err == SLAPD_ABANDON ) {
57 1.1 lukem
58 1.1 lukem op->o_req_dn = ros->ro_dn;
59 1.1 lukem op->o_req_ndn = ros->ro_ndn;
60 1.1 lukem
61 1.1 lukem if ( !BER_BVISNULL( &ros->r_dn )
62 1.1 lukem && ros->r_dn.bv_val != ros->r_ndn.bv_val )
63 1.1 lukem {
64 1.1 lukem ch_free( ros->r_dn.bv_val );
65 1.1 lukem BER_BVZERO( &ros->r_dn );
66 1.1 lukem }
67 1.1 lukem
68 1.1 lukem if ( !BER_BVISNULL( &ros->r_ndn ) ) {
69 1.1 lukem ch_free( ros->r_ndn.bv_val );
70 1.1 lukem BER_BVZERO( &ros->r_ndn );
71 1.1 lukem }
72 1.1 lukem
73 1.1 lukem switch( ros->r_tag ) {
74 1.1 lukem case LDAP_REQ_COMPARE:
75 1.1 lukem if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
76 1.1 lukem op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
77 1.1 lukem op->orc_ava = ros->orc_ava;
78 1.1 lukem break;
79 1.1 lukem case LDAP_REQ_MODIFY:
80 1.1 lukem slap_mods_free( op->orm_modlist, 1 );
81 1.1 lukem op->orm_modlist = ros->orm_modlist;
82 1.1 lukem break;
83 1.1 lukem case LDAP_REQ_MODRDN:
84 1.1 lukem if ( op->orr_newSup != ros->orr_newSup ) {
85 1.1 lukem ch_free( op->orr_newSup->bv_val );
86 1.1 lukem ch_free( op->orr_nnewSup->bv_val );
87 1.1 lukem op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
88 1.1 lukem op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
89 1.1 lukem op->orr_newSup = ros->orr_newSup;
90 1.1 lukem op->orr_nnewSup = ros->orr_nnewSup;
91 1.1 lukem }
92 1.1 lukem break;
93 1.1 lukem case LDAP_REQ_SEARCH:
94 1.1 lukem ch_free( ros->mapped_attrs );
95 1.1 lukem filter_free_x( op, op->ors_filter );
96 1.1 lukem ch_free( op->ors_filterstr.bv_val );
97 1.1 lukem op->ors_attrs = ros->ors_attrs;
98 1.1 lukem op->ors_filter = ros->ors_filter;
99 1.1 lukem op->ors_filterstr = ros->ors_filterstr;
100 1.1 lukem break;
101 1.1 lukem case LDAP_REQ_EXTENDED:
102 1.1 lukem if ( op->ore_reqdata != ros->ore_reqdata ) {
103 1.1 lukem ber_bvfree( op->ore_reqdata );
104 1.1 lukem op->ore_reqdata = ros->ore_reqdata;
105 1.1 lukem }
106 1.1 lukem break;
107 1.1 lukem default: break;
108 1.1 lukem }
109 1.1 lukem op->o_callback = op->o_callback->sc_next;
110 1.1 lukem op->o_tmpfree( cb, op->o_tmpmemctx );
111 1.1 lukem }
112 1.1 lukem
113 1.1 lukem return SLAP_CB_CONTINUE;
114 1.1 lukem }
115 1.1 lukem
116 1.1 lukem static rwm_op_cb *
117 1.1 lukem rwm_callback_get( Operation *op, SlapReply *rs )
118 1.1 lukem {
119 1.1 lukem rwm_op_cb *roc = NULL;
120 1.1 lukem
121 1.1 lukem roc = op->o_tmpalloc( sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
122 1.1 lukem roc->cb.sc_cleanup = rwm_op_cleanup;
123 1.1 lukem roc->cb.sc_response = NULL;
124 1.1 lukem roc->cb.sc_next = op->o_callback;
125 1.1 lukem roc->cb.sc_private = &roc->ros;
126 1.1 lukem roc->ros.r_tag = op->o_tag;
127 1.1 lukem roc->ros.ro_dn = op->o_req_dn;
128 1.1 lukem roc->ros.ro_ndn = op->o_req_ndn;
129 1.1 lukem roc->ros.o_request = op->o_request;
130 1.1 lukem BER_BVZERO( &roc->ros.r_dn );
131 1.1 lukem BER_BVZERO( &roc->ros.r_ndn );
132 1.1 lukem
133 1.1 lukem return roc;
134 1.1 lukem }
135 1.1 lukem
136 1.1 lukem
137 1.1 lukem static int
138 1.1 lukem rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
139 1.1 lukem rwm_op_state *ros )
140 1.1 lukem {
141 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
142 1.1 lukem struct ldaprwmap *rwmap =
143 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
144 1.1 lukem
145 1.1 lukem struct berval dn = BER_BVNULL,
146 1.1 lukem ndn = BER_BVNULL;
147 1.1 lukem int rc = 0;
148 1.1 lukem dncookie dc;
149 1.1 lukem
150 1.1 lukem /*
151 1.1 lukem * Rewrite the dn if needed
152 1.1 lukem */
153 1.1 lukem dc.rwmap = rwmap;
154 1.1 lukem dc.conn = op->o_conn;
155 1.1 lukem dc.rs = rs;
156 1.1 lukem dc.ctx = (char *)cookie;
157 1.1 lukem
158 1.1 lukem /* NOTE: in those cases where only the ndn is available,
159 1.1 lukem * and the caller sets op->o_req_dn = op->o_req_ndn,
160 1.1 lukem * only rewrite the op->o_req_ndn and use it as
161 1.1 lukem * op->o_req_dn as well */
162 1.1 lukem ndn = op->o_req_ndn;
163 1.1 lukem if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
164 1.1 lukem dn = op->o_req_dn;
165 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
166 1.1 lukem } else {
167 1.1 lukem rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
168 1.1 lukem }
169 1.1 lukem
170 1.1 lukem if ( rc != LDAP_SUCCESS ) {
171 1.1 lukem return rc;
172 1.1 lukem }
173 1.1 lukem
174 1.1 lukem if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
175 1.1 lukem || ndn.bv_val == op->o_req_ndn.bv_val )
176 1.1 lukem {
177 1.1 lukem return LDAP_SUCCESS;
178 1.1 lukem }
179 1.1 lukem
180 1.1 lukem if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
181 1.1 lukem op->o_req_dn = dn;
182 1.1 lukem ros->r_dn = dn;
183 1.1 lukem } else {
184 1.1 lukem op->o_req_dn = ndn;
185 1.1 lukem }
186 1.1 lukem op->o_req_ndn = ndn;
187 1.1 lukem ros->r_ndn = ndn;
188 1.1 lukem
189 1.1 lukem return LDAP_SUCCESS;
190 1.1 lukem }
191 1.1 lukem
192 1.1 lukem static int
193 1.1 lukem rwm_op_add( Operation *op, SlapReply *rs )
194 1.1 lukem {
195 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
196 1.1 lukem struct ldaprwmap *rwmap =
197 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
198 1.1 lukem
199 1.1 lukem int rc,
200 1.1 lukem i;
201 1.1 lukem Attribute **ap = NULL;
202 1.1 lukem char *olddn = op->o_req_dn.bv_val;
203 1.1 lukem int isupdate;
204 1.1 lukem
205 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
206 1.1 lukem
207 1.1 lukem rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
208 1.1 lukem if ( rc != LDAP_SUCCESS ) {
209 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
210 1.1 lukem send_ldap_error( op, rs, rc, "addDN massage error" );
211 1.1 lukem return -1;
212 1.1 lukem }
213 1.1 lukem
214 1.1 lukem if ( olddn != op->o_req_dn.bv_val ) {
215 1.1 lukem ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
216 1.1 lukem ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
217 1.1 lukem }
218 1.1 lukem
219 1.1 lukem /* Count number of attributes in entry */
220 1.1 lukem isupdate = be_shadow_update( op );
221 1.1 lukem for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
222 1.1 lukem Attribute *a;
223 1.1 lukem
224 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
225 1.1 lukem (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
226 1.1 lukem {
227 1.1 lukem int j, last;
228 1.1 lukem
229 1.1 lukem last = (*ap)->a_numvals - 1;
230 1.1 lukem for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
231 1.1 lukem struct ldapmapping *mapping = NULL;
232 1.1 lukem
233 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
234 1.1 lukem &mapping, RWM_MAP );
235 1.1 lukem if ( mapping == NULL ) {
236 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
237 1.1 lukem /* FIXME: we allow to remove objectClasses as well;
238 1.1 lukem * if the resulting entry is inconsistent, that's
239 1.1 lukem * the relayed database's business...
240 1.1 lukem */
241 1.1 lukem ch_free( (*ap)->a_vals[ j ].bv_val );
242 1.1 lukem if ( last > j ) {
243 1.1 lukem (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
244 1.1 lukem }
245 1.1 lukem BER_BVZERO( &(*ap)->a_vals[ last ] );
246 1.1 lukem (*ap)->a_numvals--;
247 1.1 lukem last--;
248 1.1 lukem j--;
249 1.1 lukem }
250 1.1 lukem
251 1.1 lukem } else {
252 1.1 lukem ch_free( (*ap)->a_vals[ j ].bv_val );
253 1.1 lukem ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
254 1.1 lukem }
255 1.1 lukem }
256 1.1 lukem
257 1.1 lukem } else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
258 1.1 lukem {
259 1.1 lukem goto next_attr;
260 1.1 lukem
261 1.1 lukem } else {
262 1.1 lukem struct ldapmapping *mapping = NULL;
263 1.1 lukem
264 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
265 1.1 lukem &mapping, RWM_MAP );
266 1.1 lukem if ( mapping == NULL ) {
267 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
268 1.1 lukem goto cleanup_attr;
269 1.1 lukem }
270 1.1 lukem }
271 1.1 lukem
272 1.1 lukem if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
273 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
274 1.1 lukem {
275 1.1 lukem /*
276 1.1 lukem * FIXME: rewrite could fail; in this case
277 1.1 lukem * the operation should give up, right?
278 1.1 lukem */
279 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
280 1.1 lukem (*ap)->a_vals,
281 1.1 lukem (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
282 1.1 lukem if ( rc ) {
283 1.1 lukem goto cleanup_attr;
284 1.1 lukem }
285 1.1 lukem
286 1.1 lukem } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
287 1.1 lukem rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
288 1.1 lukem (*ap)->a_vals,
289 1.1 lukem (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
290 1.1 lukem if ( rc != LDAP_SUCCESS ) {
291 1.1 lukem goto cleanup_attr;
292 1.1 lukem }
293 1.1 lukem }
294 1.1 lukem
295 1.1 lukem if ( mapping != NULL ) {
296 1.1 lukem assert( mapping->m_dst_ad != NULL );
297 1.1 lukem (*ap)->a_desc = mapping->m_dst_ad;
298 1.1 lukem }
299 1.1 lukem }
300 1.1 lukem
301 1.1 lukem next_attr:;
302 1.1 lukem ap = &(*ap)->a_next;
303 1.1 lukem continue;
304 1.1 lukem
305 1.1 lukem cleanup_attr:;
306 1.1 lukem /* FIXME: leaking attribute/values? */
307 1.1 lukem a = *ap;
308 1.1 lukem
309 1.1 lukem *ap = (*ap)->a_next;
310 1.1 lukem attr_free( a );
311 1.1 lukem }
312 1.1 lukem
313 1.1 lukem op->o_callback = &roc->cb;
314 1.1 lukem
315 1.1 lukem return SLAP_CB_CONTINUE;
316 1.1 lukem }
317 1.1 lukem
318 1.1 lukem static int
319 1.1 lukem rwm_conn_init( BackendDB *be, Connection *conn )
320 1.1 lukem {
321 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
322 1.1 lukem struct ldaprwmap *rwmap =
323 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
324 1.1 lukem
325 1.1 lukem ( void )rewrite_session_init( rwmap->rwm_rw, conn );
326 1.1 lukem
327 1.1 lukem return SLAP_CB_CONTINUE;
328 1.1 lukem }
329 1.1 lukem
330 1.1 lukem static int
331 1.1 lukem rwm_conn_destroy( BackendDB *be, Connection *conn )
332 1.1 lukem {
333 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
334 1.1 lukem struct ldaprwmap *rwmap =
335 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
336 1.1 lukem
337 1.1 lukem ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
338 1.1 lukem
339 1.1 lukem return SLAP_CB_CONTINUE;
340 1.1 lukem }
341 1.1 lukem
342 1.1 lukem static int
343 1.1 lukem rwm_op_bind( Operation *op, SlapReply *rs )
344 1.1 lukem {
345 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
346 1.1 lukem int rc;
347 1.1 lukem
348 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
349 1.1 lukem
350 1.1 lukem rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
351 1.1 lukem if ( rc != LDAP_SUCCESS ) {
352 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
353 1.1 lukem send_ldap_error( op, rs, rc, "bindDN massage error" );
354 1.1 lukem return -1;
355 1.1 lukem }
356 1.1 lukem
357 1.1 lukem op->o_callback = &roc->cb;
358 1.1 lukem
359 1.1 lukem return SLAP_CB_CONTINUE;
360 1.1 lukem }
361 1.1 lukem
362 1.1 lukem static int
363 1.1 lukem rwm_op_unbind( Operation *op, SlapReply *rs )
364 1.1 lukem {
365 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
366 1.1 lukem struct ldaprwmap *rwmap =
367 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
368 1.1 lukem
369 1.1 lukem rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
370 1.1 lukem
371 1.1 lukem return SLAP_CB_CONTINUE;
372 1.1 lukem }
373 1.1 lukem
374 1.1 lukem static int
375 1.1 lukem rwm_op_compare( Operation *op, SlapReply *rs )
376 1.1 lukem {
377 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
378 1.1 lukem struct ldaprwmap *rwmap =
379 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
380 1.1 lukem
381 1.1 lukem int rc;
382 1.1 lukem struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
383 1.1 lukem
384 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
385 1.1 lukem
386 1.1 lukem rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
387 1.1 lukem if ( rc != LDAP_SUCCESS ) {
388 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
389 1.1 lukem send_ldap_error( op, rs, rc, "compareDN massage error" );
390 1.1 lukem return -1;
391 1.1 lukem }
392 1.1 lukem
393 1.1 lukem /* if the attribute is an objectClass, try to remap its value */
394 1.1 lukem if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
395 1.1 lukem || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
396 1.1 lukem {
397 1.1 lukem rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
398 1.1 lukem &mapped_vals[0], RWM_MAP );
399 1.1 lukem if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
400 1.1 lukem {
401 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
402 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
403 1.1 lukem return -1;
404 1.1 lukem
405 1.1 lukem } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
406 1.1 lukem ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
407 1.1 lukem op->o_tmpmemctx );
408 1.1 lukem }
409 1.1 lukem
410 1.1 lukem } else {
411 1.1 lukem struct ldapmapping *mapping = NULL;
412 1.1 lukem AttributeDescription *ad = op->orc_ava->aa_desc;
413 1.1 lukem
414 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
415 1.1 lukem &mapping, RWM_MAP );
416 1.1 lukem if ( mapping == NULL ) {
417 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
418 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
419 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
420 1.1 lukem return -1;
421 1.1 lukem }
422 1.1 lukem
423 1.1 lukem } else {
424 1.1 lukem assert( mapping->m_dst_ad != NULL );
425 1.1 lukem ad = mapping->m_dst_ad;
426 1.1 lukem }
427 1.1 lukem
428 1.1 lukem if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
429 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
430 1.1 lukem {
431 1.1 lukem struct berval *mapped_valsp[2];
432 1.1 lukem
433 1.1 lukem mapped_valsp[0] = &mapped_vals[0];
434 1.1 lukem mapped_valsp[1] = &mapped_vals[1];
435 1.1 lukem
436 1.1 lukem mapped_vals[0] = op->orc_ava->aa_value;
437 1.1 lukem
438 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
439 1.1 lukem
440 1.1 lukem if ( rc != LDAP_SUCCESS ) {
441 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
442 1.1 lukem send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
443 1.1 lukem return -1;
444 1.1 lukem }
445 1.1 lukem
446 1.1 lukem if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
447 1.1 lukem /* NOTE: if we get here, rwm_dnattr_rewrite()
448 1.1 lukem * already freed the old value, so now
449 1.1 lukem * it's invalid */
450 1.1 lukem ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
451 1.1 lukem op->o_tmpmemctx );
452 1.1 lukem ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
453 1.1 lukem }
454 1.1 lukem }
455 1.1 lukem op->orc_ava->aa_desc = ad;
456 1.1 lukem }
457 1.1 lukem
458 1.1 lukem op->o_callback = &roc->cb;
459 1.1 lukem
460 1.1 lukem return SLAP_CB_CONTINUE;
461 1.1 lukem }
462 1.1 lukem
463 1.1 lukem static int
464 1.1 lukem rwm_op_delete( Operation *op, SlapReply *rs )
465 1.1 lukem {
466 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
467 1.1 lukem int rc;
468 1.1 lukem
469 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
470 1.1 lukem
471 1.1 lukem rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
472 1.1 lukem if ( rc != LDAP_SUCCESS ) {
473 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
474 1.1 lukem send_ldap_error( op, rs, rc, "deleteDN massage error" );
475 1.1 lukem return -1;
476 1.1 lukem }
477 1.1 lukem
478 1.1 lukem op->o_callback = &roc->cb;
479 1.1 lukem
480 1.1 lukem return SLAP_CB_CONTINUE;
481 1.1 lukem }
482 1.1 lukem
483 1.1 lukem static int
484 1.1 lukem rwm_op_modify( Operation *op, SlapReply *rs )
485 1.1 lukem {
486 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
487 1.1 lukem struct ldaprwmap *rwmap =
488 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
489 1.1 lukem
490 1.1 lukem int isupdate;
491 1.1 lukem Modifications **mlp;
492 1.1 lukem int rc;
493 1.1 lukem
494 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
495 1.1 lukem
496 1.1 lukem rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
497 1.1 lukem if ( rc != LDAP_SUCCESS ) {
498 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
499 1.1 lukem send_ldap_error( op, rs, rc, "modifyDN massage error" );
500 1.1 lukem return -1;
501 1.1 lukem }
502 1.1 lukem
503 1.1 lukem isupdate = be_shadow_update( op );
504 1.1 lukem for ( mlp = &op->orm_modlist; *mlp; ) {
505 1.1 lukem int is_oc = 0;
506 1.1 lukem Modifications *ml = *mlp;
507 1.1 lukem struct ldapmapping *mapping = NULL;
508 1.1 lukem
509 1.1 lukem /* ml points to a temporary mod until needs duplication */
510 1.1 lukem if ( ml->sml_desc == slap_schema.si_ad_objectClass
511 1.1 lukem || ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
512 1.1 lukem {
513 1.1 lukem is_oc = 1;
514 1.1 lukem
515 1.1 lukem } else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
516 1.1 lukem {
517 1.1 lukem ml = ch_malloc( sizeof( Modifications ) );
518 1.1 lukem *ml = **mlp;
519 1.1 lukem if ( (*mlp)->sml_values ) {
520 1.1 lukem ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
521 1.1 lukem if ( (*mlp)->sml_nvalues ) {
522 1.1 lukem ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
523 1.1 lukem }
524 1.1 lukem }
525 1.1 lukem *mlp = ml;
526 1.1 lukem goto next_mod;
527 1.1 lukem
528 1.1 lukem } else {
529 1.1 lukem int drop_missing;
530 1.1 lukem
531 1.1 lukem drop_missing = rwm_mapping( &rwmap->rwm_at,
532 1.1 lukem &ml->sml_desc->ad_cname,
533 1.1 lukem &mapping, RWM_MAP );
534 1.1 lukem if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
535 1.1 lukem {
536 1.1 lukem goto cleanup_mod;
537 1.1 lukem }
538 1.1 lukem }
539 1.1 lukem
540 1.1 lukem /* duplicate the modlist */
541 1.1 lukem ml = ch_malloc( sizeof( Modifications ));
542 1.1 lukem *ml = **mlp;
543 1.1 lukem *mlp = ml;
544 1.1 lukem
545 1.1 lukem if ( ml->sml_values != NULL ) {
546 1.1 lukem int i, num;
547 1.1 lukem struct berval *bva;
548 1.1 lukem
549 1.1 lukem for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
550 1.1 lukem /* count values */ ;
551 1.1 lukem
552 1.1 lukem bva = ch_malloc( (num+1) * sizeof( struct berval ));
553 1.1 lukem for (i=0; i<num; i++)
554 1.1 lukem ber_dupbv( &bva[i], &ml->sml_values[i] );
555 1.1 lukem BER_BVZERO( &bva[i] );
556 1.1 lukem ml->sml_values = bva;
557 1.1 lukem
558 1.1 lukem if ( ml->sml_nvalues ) {
559 1.1 lukem bva = ch_malloc( (num+1) * sizeof( struct berval ));
560 1.1 lukem for (i=0; i<num; i++)
561 1.1 lukem ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
562 1.1 lukem BER_BVZERO( &bva[i] );
563 1.1 lukem ml->sml_nvalues = bva;
564 1.1 lukem }
565 1.1 lukem
566 1.1 lukem if ( is_oc ) {
567 1.1 lukem int last, j;
568 1.1 lukem
569 1.1 lukem last = num-1;
570 1.1 lukem
571 1.1 lukem for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
572 1.1 lukem struct ldapmapping *oc_mapping = NULL;
573 1.1 lukem
574 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
575 1.1 lukem &oc_mapping, RWM_MAP );
576 1.1 lukem if ( oc_mapping == NULL ) {
577 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
578 1.1 lukem /* FIXME: we allow to remove objectClasses as well;
579 1.1 lukem * if the resulting entry is inconsistent, that's
580 1.1 lukem * the relayed database's business...
581 1.1 lukem */
582 1.1 lukem if ( last > j ) {
583 1.1 lukem ch_free( ml->sml_values[ j ].bv_val );
584 1.1 lukem ml->sml_values[ j ] = ml->sml_values[ last ];
585 1.1 lukem }
586 1.1 lukem BER_BVZERO( &ml->sml_values[ last ] );
587 1.1 lukem last--;
588 1.1 lukem j--;
589 1.1 lukem }
590 1.1 lukem
591 1.1 lukem } else {
592 1.1 lukem ch_free( ml->sml_values[ j ].bv_val );
593 1.1 lukem ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
594 1.1 lukem }
595 1.1 lukem }
596 1.1 lukem
597 1.1 lukem } else {
598 1.1 lukem if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
599 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
600 1.1 lukem {
601 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
602 1.1 lukem ml->sml_values,
603 1.1 lukem ml->sml_nvalues ? &ml->sml_nvalues : NULL );
604 1.1 lukem
605 1.1 lukem } else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
606 1.1 lukem rc = rwm_referral_rewrite( op, rs,
607 1.1 lukem "referralAttrDN",
608 1.1 lukem ml->sml_values,
609 1.1 lukem ml->sml_nvalues ? &ml->sml_nvalues : NULL );
610 1.1 lukem if ( rc != LDAP_SUCCESS ) {
611 1.1 lukem goto cleanup_mod;
612 1.1 lukem }
613 1.1 lukem }
614 1.1 lukem
615 1.1 lukem if ( rc != LDAP_SUCCESS ) {
616 1.1 lukem goto cleanup_mod;
617 1.1 lukem }
618 1.1 lukem }
619 1.1 lukem }
620 1.1 lukem
621 1.1 lukem next_mod:;
622 1.1 lukem if ( mapping != NULL ) {
623 1.1 lukem /* use new attribute description */
624 1.1 lukem assert( mapping->m_dst_ad != NULL );
625 1.1 lukem ml->sml_desc = mapping->m_dst_ad;
626 1.1 lukem }
627 1.1 lukem
628 1.1 lukem mlp = &ml->sml_next;
629 1.1 lukem continue;
630 1.1 lukem
631 1.1 lukem cleanup_mod:;
632 1.1 lukem ml = *mlp;
633 1.1 lukem *mlp = (*mlp)->sml_next;
634 1.1 lukem slap_mod_free( &ml->sml_mod, 0 );
635 1.1 lukem free( ml );
636 1.1 lukem }
637 1.1 lukem
638 1.1 lukem op->o_callback = &roc->cb;
639 1.1 lukem
640 1.1 lukem return SLAP_CB_CONTINUE;
641 1.1 lukem }
642 1.1 lukem
643 1.1 lukem static int
644 1.1 lukem rwm_op_modrdn( Operation *op, SlapReply *rs )
645 1.1 lukem {
646 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
647 1.1 lukem struct ldaprwmap *rwmap =
648 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
649 1.1 lukem
650 1.1 lukem int rc;
651 1.1 lukem
652 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
653 1.1 lukem
654 1.1 lukem if ( op->orr_newSup ) {
655 1.1 lukem dncookie dc;
656 1.1 lukem struct berval nnewSup = BER_BVNULL;
657 1.1 lukem struct berval newSup = BER_BVNULL;
658 1.1 lukem
659 1.1 lukem /*
660 1.1 lukem * Rewrite the new superior, if defined and required
661 1.1 lukem */
662 1.1 lukem dc.rwmap = rwmap;
663 1.1 lukem dc.conn = op->o_conn;
664 1.1 lukem dc.rs = rs;
665 1.1 lukem dc.ctx = "newSuperiorDN";
666 1.1 lukem newSup = *op->orr_newSup;
667 1.1 lukem nnewSup = *op->orr_nnewSup;
668 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
669 1.1 lukem if ( rc != LDAP_SUCCESS ) {
670 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
671 1.1 lukem send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
672 1.1 lukem return -1;
673 1.1 lukem }
674 1.1 lukem
675 1.1 lukem if ( op->orr_newSup->bv_val != newSup.bv_val ) {
676 1.1 lukem op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
677 1.1 lukem op->o_tmpmemctx );
678 1.1 lukem op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
679 1.1 lukem op->o_tmpmemctx );
680 1.1 lukem *op->orr_newSup = newSup;
681 1.1 lukem *op->orr_nnewSup = nnewSup;
682 1.1 lukem }
683 1.1 lukem }
684 1.1 lukem
685 1.1 lukem /*
686 1.1 lukem * Rewrite the dn, if needed
687 1.1 lukem */
688 1.1 lukem rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
689 1.1 lukem if ( rc != LDAP_SUCCESS ) {
690 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
691 1.1 lukem send_ldap_error( op, rs, rc, "renameDN massage error" );
692 1.1 lukem if ( op->orr_newSup != roc->ros.orr_newSup ) {
693 1.1 lukem ch_free( op->orr_newSup->bv_val );
694 1.1 lukem ch_free( op->orr_nnewSup->bv_val );
695 1.1 lukem op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
696 1.1 lukem op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
697 1.1 lukem op->orr_newSup = roc->ros.orr_newSup;
698 1.1 lukem op->orr_nnewSup = roc->ros.orr_nnewSup;
699 1.1 lukem }
700 1.1 lukem return -1;
701 1.1 lukem }
702 1.1 lukem
703 1.1 lukem /* TODO: rewrite newRDN, attribute types,
704 1.1 lukem * values of DN-valued attributes ... */
705 1.1 lukem
706 1.1 lukem op->o_callback = &roc->cb;
707 1.1 lukem
708 1.1 lukem return SLAP_CB_CONTINUE;
709 1.1 lukem }
710 1.1 lukem
711 1.1 lukem
712 1.1 lukem static int
713 1.1 lukem rwm_swap_attrs( Operation *op, SlapReply *rs )
714 1.1 lukem {
715 1.1 lukem slap_callback *cb = op->o_callback;
716 1.1 lukem rwm_op_state *ros = cb->sc_private;
717 1.1 lukem
718 1.1 lukem rs->sr_attrs = ros->ors_attrs;
719 1.1 lukem
720 1.1 lukem /* other overlays might have touched op->ors_attrs,
721 1.1 lukem * so we restore the original version here, otherwise
722 1.1 lukem * attribute-mapping might fail */
723 1.1 lukem op->ors_attrs = ros->mapped_attrs;
724 1.1 lukem
725 1.1 lukem return SLAP_CB_CONTINUE;
726 1.1 lukem }
727 1.1 lukem
728 1.1 lukem static int
729 1.1 lukem rwm_op_search( Operation *op, SlapReply *rs )
730 1.1 lukem {
731 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
732 1.1 lukem struct ldaprwmap *rwmap =
733 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
734 1.1 lukem
735 1.1 lukem int rc;
736 1.1 lukem dncookie dc;
737 1.1 lukem
738 1.1 lukem struct berval fstr = BER_BVNULL;
739 1.1 lukem Filter *f = NULL;
740 1.1 lukem
741 1.1 lukem AttributeName *an = NULL;
742 1.1 lukem
743 1.1 lukem char *text = NULL;
744 1.1 lukem
745 1.1 lukem rwm_op_cb *roc = rwm_callback_get( op, rs );
746 1.1 lukem
747 1.1 lukem rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
748 1.1 lukem "searchFilter", op->ors_filterstr.bv_val );
749 1.1 lukem if ( rc == LDAP_SUCCESS )
750 1.1 lukem rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
751 1.1 lukem if ( rc != LDAP_SUCCESS ) {
752 1.1 lukem text = "searchDN massage error";
753 1.1 lukem goto error_return;
754 1.1 lukem }
755 1.1 lukem
756 1.1 lukem /*
757 1.1 lukem * Rewrite the dn if needed
758 1.1 lukem */
759 1.1 lukem dc.rwmap = rwmap;
760 1.1 lukem dc.conn = op->o_conn;
761 1.1 lukem dc.rs = rs;
762 1.1 lukem dc.ctx = "searchFilterAttrDN";
763 1.1 lukem
764 1.1 lukem rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
765 1.1 lukem if ( rc != LDAP_SUCCESS ) {
766 1.1 lukem text = "searchFilter/searchFilterAttrDN massage error";
767 1.1 lukem goto error_return;
768 1.1 lukem }
769 1.1 lukem
770 1.1 lukem f = str2filter_x( op, fstr.bv_val );
771 1.1 lukem
772 1.1 lukem if ( f == NULL ) {
773 1.1 lukem text = "massaged filter parse error";
774 1.1 lukem goto error_return;
775 1.1 lukem }
776 1.1 lukem
777 1.1 lukem op->ors_filter = f;
778 1.1 lukem op->ors_filterstr = fstr;
779 1.1 lukem
780 1.1 lukem rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
781 1.1 lukem op->ors_attrs, &an, RWM_MAP );
782 1.1 lukem if ( rc != LDAP_SUCCESS ) {
783 1.1 lukem text = "attribute list mapping error";
784 1.1 lukem goto error_return;
785 1.1 lukem }
786 1.1 lukem
787 1.1 lukem op->ors_attrs = an;
788 1.1 lukem /* store the mapped Attributes for later usage, in
789 1.1 lukem * the case that other overlays change op->ors_attrs */
790 1.1 lukem roc->ros.mapped_attrs = an;
791 1.1 lukem roc->cb.sc_response = rwm_swap_attrs;
792 1.1 lukem
793 1.1 lukem op->o_callback = &roc->cb;
794 1.1 lukem
795 1.1 lukem return SLAP_CB_CONTINUE;
796 1.1 lukem
797 1.1 lukem error_return:;
798 1.1 lukem if ( an != NULL ) {
799 1.1 lukem ch_free( an );
800 1.1 lukem }
801 1.1 lukem
802 1.1 lukem if ( f != NULL ) {
803 1.1 lukem filter_free_x( op, f );
804 1.1 lukem }
805 1.1 lukem
806 1.1 lukem if ( !BER_BVISNULL( &fstr ) ) {
807 1.1 lukem ch_free( fstr.bv_val );
808 1.1 lukem }
809 1.1 lukem
810 1.1 lukem op->oq_search = roc->ros.oq_search;
811 1.1 lukem
812 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
813 1.1 lukem send_ldap_error( op, rs, rc, text );
814 1.1 lukem
815 1.1 lukem return -1;
816 1.1 lukem
817 1.1 lukem }
818 1.1 lukem
819 1.1 lukem static int
820 1.1 lukem rwm_exop_passwd( Operation *op, SlapReply *rs )
821 1.1 lukem {
822 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
823 1.1 lukem int rc;
824 1.1 lukem rwm_op_cb *roc;
825 1.1 lukem
826 1.1 lukem struct berval id = BER_BVNULL,
827 1.1 lukem pwold = BER_BVNULL,
828 1.1 lukem pwnew = BER_BVNULL;
829 1.1 lukem BerElement *ber = NULL;
830 1.1 lukem
831 1.1 lukem if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
832 1.1 lukem return LDAP_SUCCESS;
833 1.1 lukem }
834 1.1 lukem
835 1.1 lukem if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
836 1.1 lukem rs->sr_err = LDAP_OTHER;
837 1.1 lukem return rs->sr_err;
838 1.1 lukem }
839 1.1 lukem
840 1.1 lukem rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
841 1.1 lukem &pwold, &pwnew, &rs->sr_text );
842 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
843 1.1 lukem return rs->sr_err;
844 1.1 lukem }
845 1.1 lukem
846 1.1 lukem if ( !BER_BVISNULL( &id ) ) {
847 1.1 lukem char idNul = id.bv_val[id.bv_len];
848 1.1 lukem id.bv_val[id.bv_len] = '\0';
849 1.1 lukem rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
850 1.1 lukem &op->o_req_ndn, op->o_tmpmemctx );
851 1.1 lukem id.bv_val[id.bv_len] = idNul;
852 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
853 1.1 lukem rs->sr_text = "Invalid DN";
854 1.1 lukem return rs->sr_err;
855 1.1 lukem }
856 1.1 lukem
857 1.1 lukem } else {
858 1.1 lukem ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
859 1.1 lukem ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
860 1.1 lukem }
861 1.1 lukem
862 1.1 lukem roc = rwm_callback_get( op, rs );
863 1.1 lukem
864 1.1 lukem rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
865 1.1 lukem if ( rc != LDAP_SUCCESS ) {
866 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
867 1.1 lukem send_ldap_error( op, rs, rc, "extendedDN massage error" );
868 1.1 lukem return -1;
869 1.1 lukem }
870 1.1 lukem
871 1.1 lukem ber = ber_alloc_t( LBER_USE_DER );
872 1.1 lukem if ( !ber ) {
873 1.1 lukem rs->sr_err = LDAP_OTHER;
874 1.1 lukem rs->sr_text = "No memory";
875 1.1 lukem return rs->sr_err;
876 1.1 lukem }
877 1.1 lukem ber_printf( ber, "{" );
878 1.1 lukem if ( !BER_BVISNULL( &id )) {
879 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
880 1.1 lukem &op->o_req_dn );
881 1.1 lukem }
882 1.1 lukem if ( !BER_BVISNULL( &pwold )) {
883 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
884 1.1 lukem }
885 1.1 lukem if ( !BER_BVISNULL( &pwnew )) {
886 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
887 1.1 lukem }
888 1.1 lukem ber_printf( ber, "N}" );
889 1.1 lukem ber_flatten( ber, &op->ore_reqdata );
890 1.1 lukem ber_free( ber, 1 );
891 1.1 lukem
892 1.1 lukem op->o_callback = &roc->cb;
893 1.1 lukem
894 1.1 lukem return SLAP_CB_CONTINUE;
895 1.1 lukem }
896 1.1 lukem
897 1.1 lukem static struct exop {
898 1.1 lukem struct berval oid;
899 1.1 lukem BI_op_extended *extended;
900 1.1 lukem } exop_table[] = {
901 1.1 lukem { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
902 1.1 lukem { BER_BVNULL, NULL }
903 1.1 lukem };
904 1.1 lukem
905 1.1 lukem static int
906 1.1 lukem rwm_extended( Operation *op, SlapReply *rs )
907 1.1 lukem {
908 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
909 1.1 lukem int rc;
910 1.1 lukem rwm_op_cb *roc;
911 1.1 lukem
912 1.1 lukem int i;
913 1.1 lukem
914 1.1 lukem for ( i = 0; exop_table[i].extended != NULL; i++ ) {
915 1.1 lukem if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
916 1.1 lukem {
917 1.1 lukem rc = exop_table[i].extended( op, rs );
918 1.1 lukem switch ( rc ) {
919 1.1 lukem case LDAP_SUCCESS:
920 1.1 lukem break;
921 1.1 lukem
922 1.1 lukem case SLAP_CB_CONTINUE:
923 1.1 lukem case SLAPD_ABANDON:
924 1.1 lukem return rc;
925 1.1 lukem
926 1.1 lukem default:
927 1.1 lukem send_ldap_result( op, rs );
928 1.1 lukem return rc;
929 1.1 lukem }
930 1.1 lukem break;
931 1.1 lukem }
932 1.1 lukem }
933 1.1 lukem
934 1.1 lukem roc = rwm_callback_get( op, rs );
935 1.1 lukem
936 1.1 lukem rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
937 1.1 lukem if ( rc != LDAP_SUCCESS ) {
938 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
939 1.1 lukem send_ldap_error( op, rs, rc, "extendedDN massage error" );
940 1.1 lukem return -1;
941 1.1 lukem }
942 1.1 lukem
943 1.1 lukem /* TODO: rewrite/map extended data ? ... */
944 1.1 lukem op->o_callback = &roc->cb;
945 1.1 lukem
946 1.1 lukem return SLAP_CB_CONTINUE;
947 1.1 lukem }
948 1.1 lukem
949 1.1 lukem static int
950 1.1 lukem rwm_matched( Operation *op, SlapReply *rs )
951 1.1 lukem {
952 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
953 1.1 lukem struct ldaprwmap *rwmap =
954 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
955 1.1 lukem
956 1.1 lukem struct berval dn, mdn;
957 1.1 lukem dncookie dc;
958 1.1 lukem int rc;
959 1.1 lukem
960 1.1 lukem if ( rs->sr_matched == NULL ) {
961 1.1 lukem return SLAP_CB_CONTINUE;
962 1.1 lukem }
963 1.1 lukem
964 1.1 lukem dc.rwmap = rwmap;
965 1.1 lukem dc.conn = op->o_conn;
966 1.1 lukem dc.rs = rs;
967 1.1 lukem dc.ctx = "matchedDN";
968 1.1 lukem ber_str2bv( rs->sr_matched, 0, 0, &dn );
969 1.1 lukem mdn = dn;
970 1.1 lukem rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
971 1.1 lukem if ( rc != LDAP_SUCCESS ) {
972 1.1 lukem rs->sr_err = rc;
973 1.1 lukem rs->sr_text = "Rewrite error";
974 1.1 lukem return 1;
975 1.1 lukem }
976 1.1 lukem
977 1.1 lukem if ( mdn.bv_val != dn.bv_val ) {
978 1.1 lukem if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
979 1.1 lukem ch_free( (void *)rs->sr_matched );
980 1.1 lukem
981 1.1 lukem } else {
982 1.1 lukem rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
983 1.1 lukem }
984 1.1 lukem rs->sr_matched = mdn.bv_val;
985 1.1 lukem }
986 1.1 lukem
987 1.1 lukem return SLAP_CB_CONTINUE;
988 1.1 lukem }
989 1.1 lukem
990 1.1 lukem static int
991 1.1 lukem rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
992 1.1 lukem {
993 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
994 1.1 lukem struct ldaprwmap *rwmap =
995 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
996 1.1 lukem
997 1.1 lukem dncookie dc;
998 1.1 lukem int rc;
999 1.1 lukem Attribute **ap;
1000 1.1 lukem int isupdate;
1001 1.1 lukem int check_duplicate_attrs = 0;
1002 1.1 lukem
1003 1.1 lukem /*
1004 1.1 lukem * Rewrite the dn attrs, if needed
1005 1.1 lukem */
1006 1.1 lukem dc.rwmap = rwmap;
1007 1.1 lukem dc.conn = op->o_conn;
1008 1.1 lukem dc.rs = NULL;
1009 1.1 lukem
1010 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1011 1.1 lukem * so we need to select those attributes we are willing
1012 1.1 lukem * to return, and remap them accordingly */
1013 1.1 lukem
1014 1.1 lukem /* FIXME: in principle, one could map an attribute
1015 1.1 lukem * on top of another, which already exists.
1016 1.1 lukem * As such, in the end there might exist more than
1017 1.1 lukem * one instance of an attribute.
1018 1.1 lukem * We should at least check if this occurs, and issue
1019 1.1 lukem * an error (because multiple instances of attrs in
1020 1.1 lukem * response are not valid), or merge the values (what
1021 1.1 lukem * about duplicate values?) */
1022 1.1 lukem isupdate = be_shadow_update( op );
1023 1.1 lukem for ( ap = a_first; *ap; ) {
1024 1.1 lukem struct ldapmapping *mapping = NULL;
1025 1.1 lukem int drop_missing;
1026 1.1 lukem int last = -1;
1027 1.1 lukem Attribute *a;
1028 1.1 lukem
1029 1.1 lukem if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
1030 1.1 lukem {
1031 1.1 lukem /* go on */ ;
1032 1.1 lukem
1033 1.1 lukem } else {
1034 1.1 lukem if ( op->ors_attrs != NULL &&
1035 1.1 lukem !SLAP_USERATTRS( rs->sr_attr_flags ) &&
1036 1.1 lukem !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
1037 1.1 lukem {
1038 1.1 lukem goto cleanup_attr;
1039 1.1 lukem }
1040 1.1 lukem
1041 1.1 lukem drop_missing = rwm_mapping( &rwmap->rwm_at,
1042 1.1 lukem &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
1043 1.1 lukem if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
1044 1.1 lukem {
1045 1.1 lukem goto cleanup_attr;
1046 1.1 lukem }
1047 1.1 lukem if ( mapping != NULL ) {
1048 1.1 lukem assert( mapping->m_dst_ad != NULL );
1049 1.1 lukem
1050 1.1 lukem /* try to normalize mapped Attributes if the original
1051 1.1 lukem * AttributeType was not normalized */
1052 1.1 lukem if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS) &&
1053 1.1 lukem (!(*ap)->a_desc->ad_type->sat_equality ||
1054 1.1 lukem !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
1055 1.1 lukem mapping->m_dst_ad->ad_type->sat_equality &&
1056 1.1 lukem mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
1057 1.1 lukem {
1058 1.1 lukem int i = 0;
1059 1.1 lukem
1060 1.1 lukem last = (*ap)->a_numvals;
1061 1.1 lukem if ( last )
1062 1.1 lukem {
1063 1.1 lukem (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
1064 1.1 lukem
1065 1.1 lukem for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
1066 1.1 lukem int rc;
1067 1.1 lukem /*
1068 1.1 lukem * check that each value is valid per syntax
1069 1.1 lukem * and pretty if appropriate
1070 1.1 lukem */
1071 1.1 lukem rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
1072 1.1 lukem SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
1073 1.1 lukem mapping->m_dst_ad->ad_type->sat_syntax,
1074 1.1 lukem mapping->m_dst_ad->ad_type->sat_equality,
1075 1.1 lukem &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
1076 1.1 lukem NULL );
1077 1.1 lukem
1078 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1079 1.1 lukem BER_BVZERO( &(*ap)->a_nvals[i] );
1080 1.1 lukem }
1081 1.1 lukem }
1082 1.1 lukem BER_BVZERO( &(*ap)->a_nvals[i] );
1083 1.1 lukem }
1084 1.1 lukem }
1085 1.1 lukem
1086 1.1 lukem /* rewrite the attribute description */
1087 1.1 lukem (*ap)->a_desc = mapping->m_dst_ad;
1088 1.1 lukem
1089 1.1 lukem /* will need to check for duplicate attrs */
1090 1.1 lukem check_duplicate_attrs++;
1091 1.1 lukem }
1092 1.1 lukem }
1093 1.1 lukem
1094 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
1095 1.1 lukem if ( stripEntryDN ) {
1096 1.1 lukem /* will be generated by frontend */
1097 1.1 lukem goto cleanup_attr;
1098 1.1 lukem }
1099 1.1 lukem
1100 1.1 lukem } else if ( !isupdate
1101 1.1 lukem && !get_relax( op )
1102 1.1 lukem && (*ap)->a_desc->ad_type->sat_no_user_mod
1103 1.1 lukem && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
1104 1.1 lukem {
1105 1.1 lukem goto next_attr;
1106 1.1 lukem }
1107 1.1 lukem
1108 1.1 lukem if ( last == -1 ) { /* not yet counted */
1109 1.1 lukem last = (*ap)->a_numvals;
1110 1.1 lukem }
1111 1.1 lukem
1112 1.1 lukem if ( last == 0 ) {
1113 1.1 lukem /* empty? leave it in place because of attrsonly and vlv */
1114 1.1 lukem goto next_attr;
1115 1.1 lukem }
1116 1.1 lukem last--;
1117 1.1 lukem
1118 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
1119 1.1 lukem || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
1120 1.1 lukem {
1121 1.1 lukem struct berval *bv;
1122 1.1 lukem
1123 1.1 lukem for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1124 1.1 lukem struct berval mapped;
1125 1.1 lukem
1126 1.1 lukem rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
1127 1.1 lukem if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
1128 1.1 lukem remove_oc:;
1129 1.1 lukem ch_free( bv[0].bv_val );
1130 1.1 lukem BER_BVZERO( &bv[0] );
1131 1.1 lukem if ( &(*ap)->a_vals[last] > &bv[0] ) {
1132 1.1 lukem bv[0] = (*ap)->a_vals[last];
1133 1.1 lukem BER_BVZERO( &(*ap)->a_vals[last] );
1134 1.1 lukem }
1135 1.1 lukem last--;
1136 1.1 lukem bv--;
1137 1.1 lukem
1138 1.1 lukem } else if ( mapped.bv_val != bv[0].bv_val ) {
1139 1.1 lukem int i;
1140 1.1 lukem
1141 1.1 lukem for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
1142 1.1 lukem if ( &(*ap)->a_vals[ i ] == bv ) {
1143 1.1 lukem continue;
1144 1.1 lukem }
1145 1.1 lukem
1146 1.1 lukem if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
1147 1.1 lukem break;
1148 1.1 lukem }
1149 1.1 lukem }
1150 1.1 lukem
1151 1.1 lukem if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
1152 1.1 lukem goto remove_oc;
1153 1.1 lukem }
1154 1.1 lukem
1155 1.1 lukem /*
1156 1.1 lukem * FIXME: after LBER_FREEing
1157 1.1 lukem * the value is replaced by
1158 1.1 lukem * ch_alloc'ed memory
1159 1.1 lukem */
1160 1.1 lukem ber_bvreplace( &bv[0], &mapped );
1161 1.1 lukem
1162 1.1 lukem /* FIXME: will need to check
1163 1.1 lukem * if the structuralObjectClass
1164 1.1 lukem * changed */
1165 1.1 lukem }
1166 1.1 lukem }
1167 1.1 lukem
1168 1.1 lukem /*
1169 1.1 lukem * It is necessary to try to rewrite attributes with
1170 1.1 lukem * dn syntax because they might be used in ACLs as
1171 1.1 lukem * members of groups; since ACLs are applied to the
1172 1.1 lukem * rewritten stuff, no dn-based subject clause could
1173 1.1 lukem * be used at the ldap backend side (see
1174 1.1 lukem * http://www.OpenLDAP.org/faq/data/cache/452.html)
1175 1.1 lukem * The problem can be overcome by moving the dn-based
1176 1.1 lukem * ACLs to the target directory server, and letting
1177 1.1 lukem * everything pass thru the ldap backend. */
1178 1.1 lukem /* FIXME: handle distinguishedName-like syntaxes, like
1179 1.1 lukem * nameAndOptionalUID */
1180 1.1 lukem } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
1181 1.1 lukem || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
1182 1.1 lukem {
1183 1.1 lukem dc.ctx = "searchAttrDN";
1184 1.1 lukem rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
1185 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1186 1.1 lukem goto cleanup_attr;
1187 1.1 lukem }
1188 1.1 lukem
1189 1.1 lukem } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
1190 1.1 lukem dc.ctx = "searchAttrDN";
1191 1.1 lukem rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
1192 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1193 1.1 lukem goto cleanup_attr;
1194 1.1 lukem }
1195 1.1 lukem }
1196 1.1 lukem
1197 1.1 lukem
1198 1.1 lukem next_attr:;
1199 1.1 lukem ap = &(*ap)->a_next;
1200 1.1 lukem continue;
1201 1.1 lukem
1202 1.1 lukem cleanup_attr:;
1203 1.1 lukem a = *ap;
1204 1.1 lukem *ap = (*ap)->a_next;
1205 1.1 lukem
1206 1.1 lukem attr_free( a );
1207 1.1 lukem }
1208 1.1 lukem
1209 1.1 lukem /* only check if some mapping occurred */
1210 1.1 lukem if ( check_duplicate_attrs ) {
1211 1.1 lukem for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
1212 1.1 lukem Attribute **tap;
1213 1.1 lukem
1214 1.1 lukem for ( tap = &(*ap)->a_next; *tap != NULL; ) {
1215 1.1 lukem if ( (*tap)->a_desc == (*ap)->a_desc ) {
1216 1.1 lukem Entry e = { 0 };
1217 1.1 lukem Modification mod = { 0 };
1218 1.1 lukem const char *text = NULL;
1219 1.1 lukem char textbuf[ SLAP_TEXT_BUFLEN ];
1220 1.1 lukem Attribute *next = (*tap)->a_next;
1221 1.1 lukem
1222 1.1 lukem BER_BVSTR( &e.e_name, "" );
1223 1.1 lukem BER_BVSTR( &e.e_nname, "" );
1224 1.1 lukem e.e_attrs = *ap;
1225 1.1 lukem mod.sm_op = LDAP_MOD_ADD;
1226 1.1 lukem mod.sm_desc = (*ap)->a_desc;
1227 1.1 lukem mod.sm_type = mod.sm_desc->ad_cname;
1228 1.1 lukem mod.sm_numvals = (*tap)->a_numvals;
1229 1.1 lukem mod.sm_values = (*tap)->a_vals;
1230 1.1 lukem if ( (*tap)->a_nvals != (*tap)->a_vals ) {
1231 1.1 lukem mod.sm_nvalues = (*tap)->a_nvals;
1232 1.1 lukem }
1233 1.1 lukem
1234 1.1 lukem (void)modify_add_values( &e, &mod,
1235 1.1 lukem /* permissive */ 1,
1236 1.1 lukem &text, textbuf, sizeof( textbuf ) );
1237 1.1 lukem
1238 1.1 lukem /* should not insert new attrs! */
1239 1.1 lukem assert( e.e_attrs == *ap );
1240 1.1 lukem
1241 1.1 lukem attr_free( *tap );
1242 1.1 lukem *tap = next;
1243 1.1 lukem
1244 1.1 lukem } else {
1245 1.1 lukem tap = &(*tap)->a_next;
1246 1.1 lukem }
1247 1.1 lukem }
1248 1.1 lukem }
1249 1.1 lukem }
1250 1.1 lukem
1251 1.1 lukem return 0;
1252 1.1 lukem }
1253 1.1 lukem
1254 1.1 lukem static int
1255 1.1 lukem rwm_send_entry( Operation *op, SlapReply *rs )
1256 1.1 lukem {
1257 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1258 1.1 lukem struct ldaprwmap *rwmap =
1259 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1260 1.1 lukem
1261 1.1 lukem Entry *e = NULL;
1262 1.1 lukem slap_mask_t flags;
1263 1.1 lukem struct berval dn = BER_BVNULL,
1264 1.1 lukem ndn = BER_BVNULL;
1265 1.1 lukem dncookie dc;
1266 1.1 lukem int rc;
1267 1.1 lukem
1268 1.1 lukem assert( rs->sr_entry != NULL );
1269 1.1 lukem
1270 1.1 lukem /*
1271 1.1 lukem * Rewrite the dn of the result, if needed
1272 1.1 lukem */
1273 1.1 lukem dc.rwmap = rwmap;
1274 1.1 lukem dc.conn = op->o_conn;
1275 1.1 lukem dc.rs = NULL;
1276 1.1 lukem dc.ctx = "searchEntryDN";
1277 1.1 lukem
1278 1.1 lukem e = rs->sr_entry;
1279 1.1 lukem flags = rs->sr_flags;
1280 1.1 lukem if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
1281 1.1 lukem /* FIXME: all we need to duplicate are:
1282 1.1 lukem * - dn
1283 1.1 lukem * - ndn
1284 1.1 lukem * - attributes that are requested
1285 1.1 lukem * - no values if attrsonly is set
1286 1.1 lukem */
1287 1.1 lukem
1288 1.1 lukem e = entry_dup( e );
1289 1.1 lukem if ( e == NULL ) {
1290 1.1 lukem rc = LDAP_NO_MEMORY;
1291 1.1 lukem goto fail;
1292 1.1 lukem }
1293 1.1 lukem
1294 1.1 lukem flags &= ~REP_ENTRY_MUSTRELEASE;
1295 1.1 lukem flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
1296 1.1 lukem }
1297 1.1 lukem
1298 1.1 lukem /*
1299 1.1 lukem * Note: this may fail if the target host(s) schema differs
1300 1.1 lukem * from the one known to the meta, and a DN with unknown
1301 1.1 lukem * attributes is returned.
1302 1.1 lukem */
1303 1.1 lukem dn = e->e_name;
1304 1.1 lukem ndn = e->e_nname;
1305 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1306 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1307 1.1 lukem rc = 1;
1308 1.1 lukem goto fail;
1309 1.1 lukem }
1310 1.1 lukem
1311 1.1 lukem if ( e->e_name.bv_val != dn.bv_val ) {
1312 1.1 lukem ch_free( e->e_name.bv_val );
1313 1.1 lukem ch_free( e->e_nname.bv_val );
1314 1.1 lukem
1315 1.1 lukem e->e_name = dn;
1316 1.1 lukem e->e_nname = ndn;
1317 1.1 lukem }
1318 1.1 lukem
1319 1.1 lukem /* TODO: map entry attribute types, objectclasses
1320 1.1 lukem * and dn-valued attribute values */
1321 1.1 lukem
1322 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1323 1.1 lukem * so we need to select those attributes we are willing
1324 1.1 lukem * to return, and remap them accordingly */
1325 1.1 lukem (void)rwm_attrs( op, rs, &e->e_attrs, 1 );
1326 1.1 lukem
1327 1.1 lukem if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1328 1.1 lukem be_entry_release_rw( op, rs->sr_entry, 0 );
1329 1.1 lukem }
1330 1.1 lukem
1331 1.1 lukem rs->sr_entry = e;
1332 1.1 lukem rs->sr_flags = flags;
1333 1.1 lukem
1334 1.1 lukem return SLAP_CB_CONTINUE;
1335 1.1 lukem
1336 1.1 lukem fail:;
1337 1.1 lukem if ( e != NULL && e != rs->sr_entry ) {
1338 1.1 lukem if ( e->e_name.bv_val == dn.bv_val ) {
1339 1.1 lukem BER_BVZERO( &e->e_name );
1340 1.1 lukem }
1341 1.1 lukem
1342 1.1 lukem if ( e->e_nname.bv_val == ndn.bv_val ) {
1343 1.1 lukem BER_BVZERO( &e->e_nname );
1344 1.1 lukem }
1345 1.1 lukem
1346 1.1 lukem entry_free( e );
1347 1.1 lukem }
1348 1.1 lukem
1349 1.1 lukem if ( !BER_BVISNULL( &dn ) ) {
1350 1.1 lukem ch_free( dn.bv_val );
1351 1.1 lukem }
1352 1.1 lukem
1353 1.1 lukem if ( !BER_BVISNULL( &ndn ) ) {
1354 1.1 lukem ch_free( ndn.bv_val );
1355 1.1 lukem }
1356 1.1 lukem
1357 1.1 lukem return rc;
1358 1.1 lukem }
1359 1.1 lukem
1360 1.1 lukem static int
1361 1.1 lukem rwm_operational( Operation *op, SlapReply *rs )
1362 1.1 lukem {
1363 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1364 1.1 lukem * so we need to select those attributes we are willing
1365 1.1 lukem * to return, and remap them accordingly */
1366 1.1 lukem if ( rs->sr_operational_attrs ) {
1367 1.1 lukem rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
1368 1.1 lukem }
1369 1.1 lukem
1370 1.1 lukem return SLAP_CB_CONTINUE;
1371 1.1 lukem }
1372 1.1 lukem
1373 1.1 lukem #if 0
1374 1.1 lukem /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1375 1.1 lukem * rewritten for subsequent operations; fine for plain suffixmassage,
1376 1.1 lukem * but destroys everything else */
1377 1.1 lukem static int
1378 1.1 lukem rwm_chk_referrals( Operation *op, SlapReply *rs )
1379 1.1 lukem {
1380 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1381 1.1 lukem int rc;
1382 1.1 lukem
1383 1.1 lukem rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1384 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1385 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1386 1.1 lukem send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1387 1.1 lukem return -1;
1388 1.1 lukem }
1389 1.1 lukem
1390 1.1 lukem return SLAP_CB_CONTINUE;
1391 1.1 lukem }
1392 1.1 lukem #endif
1393 1.1 lukem
1394 1.1 lukem static int
1395 1.1 lukem rwm_rw_config(
1396 1.1 lukem BackendDB *be,
1397 1.1 lukem const char *fname,
1398 1.1 lukem int lineno,
1399 1.1 lukem int argc,
1400 1.1 lukem char **argv )
1401 1.1 lukem {
1402 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1403 1.1 lukem struct ldaprwmap *rwmap =
1404 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1405 1.1 lukem
1406 1.1 lukem return rewrite_parse( rwmap->rwm_rw,
1407 1.1 lukem fname, lineno, argc, argv );
1408 1.1 lukem
1409 1.1 lukem return 0;
1410 1.1 lukem }
1411 1.1 lukem
1412 1.1 lukem static int
1413 1.1 lukem rwm_suffixmassage_config(
1414 1.1 lukem BackendDB *be,
1415 1.1 lukem const char *fname,
1416 1.1 lukem int lineno,
1417 1.1 lukem int argc,
1418 1.1 lukem char **argv )
1419 1.1 lukem {
1420 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1421 1.1 lukem struct ldaprwmap *rwmap =
1422 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1423 1.1 lukem
1424 1.1 lukem struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1425 1.1 lukem int massaged;
1426 1.1 lukem int rc;
1427 1.1 lukem
1428 1.1 lukem /*
1429 1.1 lukem * syntax:
1430 1.1 lukem *
1431 1.1 lukem * suffixmassage [<suffix>] <massaged suffix>
1432 1.1 lukem *
1433 1.1 lukem * the [<suffix>] field must be defined as a valid suffix
1434 1.1 lukem * for the current database;
1435 1.1 lukem * the <massaged suffix> shouldn't have already been
1436 1.1 lukem * defined as a valid suffix for the current server
1437 1.1 lukem */
1438 1.1 lukem if ( argc == 2 ) {
1439 1.1 lukem if ( be->be_suffix == NULL ) {
1440 1.1 lukem fprintf( stderr, "%s: line %d: "
1441 1.1 lukem " \"suffixMassage [<suffix>]"
1442 1.1 lukem " <massaged suffix>\" without "
1443 1.1 lukem "<suffix> part requires database "
1444 1.1 lukem "suffix be defined first.\n",
1445 1.1 lukem fname, lineno );
1446 1.1 lukem return 1;
1447 1.1 lukem }
1448 1.1 lukem bvnc = be->be_suffix[ 0 ];
1449 1.1 lukem massaged = 1;
1450 1.1 lukem
1451 1.1 lukem } else if ( argc == 3 ) {
1452 1.1 lukem ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1453 1.1 lukem massaged = 2;
1454 1.1 lukem
1455 1.1 lukem } else {
1456 1.1 lukem fprintf( stderr, "%s: line %d: syntax is"
1457 1.1 lukem " \"suffixMassage [<suffix>]"
1458 1.1 lukem " <massaged suffix>\"\n",
1459 1.1 lukem fname, lineno );
1460 1.1 lukem return 1;
1461 1.1 lukem }
1462 1.1 lukem
1463 1.1 lukem if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1464 1.1 lukem fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1465 1.1 lukem fname, lineno, bvnc.bv_val );
1466 1.1 lukem return 1;
1467 1.1 lukem }
1468 1.1 lukem
1469 1.1 lukem ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1470 1.1 lukem if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1471 1.1 lukem fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1472 1.1 lukem fname, lineno, brnc.bv_val );
1473 1.1 lukem free( nvnc.bv_val );
1474 1.1 lukem free( pvnc.bv_val );
1475 1.1 lukem return 1;
1476 1.1 lukem }
1477 1.1 lukem
1478 1.1 lukem /*
1479 1.1 lukem * The suffix massaging is emulated
1480 1.1 lukem * by means of the rewrite capabilities
1481 1.1 lukem */
1482 1.1 lukem rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1483 1.1 lukem &pvnc, &nvnc, &prnc, &nrnc );
1484 1.1 lukem free( nvnc.bv_val );
1485 1.1 lukem free( pvnc.bv_val );
1486 1.1 lukem free( nrnc.bv_val );
1487 1.1 lukem free( prnc.bv_val );
1488 1.1 lukem
1489 1.1 lukem return rc;
1490 1.1 lukem }
1491 1.1 lukem
1492 1.1 lukem static int
1493 1.1 lukem rwm_m_config(
1494 1.1 lukem BackendDB *be,
1495 1.1 lukem const char *fname,
1496 1.1 lukem int lineno,
1497 1.1 lukem int argc,
1498 1.1 lukem char **argv )
1499 1.1 lukem {
1500 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1501 1.1 lukem struct ldaprwmap *rwmap =
1502 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1503 1.1 lukem
1504 1.1 lukem /* objectclass/attribute mapping */
1505 1.1 lukem return rwm_map_config( &rwmap->rwm_oc,
1506 1.1 lukem &rwmap->rwm_at,
1507 1.1 lukem fname, lineno, argc, argv );
1508 1.1 lukem }
1509 1.1 lukem
1510 1.1 lukem static int
1511 1.1 lukem rwm_response( Operation *op, SlapReply *rs )
1512 1.1 lukem {
1513 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1514 1.1 lukem struct ldaprwmap *rwmap =
1515 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1516 1.1 lukem
1517 1.1 lukem int rc;
1518 1.1 lukem
1519 1.1 lukem if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1520 1.1 lukem return rwm_send_entry( op, rs );
1521 1.1 lukem }
1522 1.1 lukem
1523 1.1 lukem switch( op->o_tag ) {
1524 1.1 lukem case LDAP_REQ_SEARCH:
1525 1.1 lukem case LDAP_REQ_BIND:
1526 1.1 lukem case LDAP_REQ_ADD:
1527 1.1 lukem case LDAP_REQ_DELETE:
1528 1.1 lukem case LDAP_REQ_MODRDN:
1529 1.1 lukem case LDAP_REQ_MODIFY:
1530 1.1 lukem case LDAP_REQ_COMPARE:
1531 1.1 lukem case LDAP_REQ_EXTENDED:
1532 1.1 lukem if ( rs->sr_ref ) {
1533 1.1 lukem dncookie dc;
1534 1.1 lukem
1535 1.1 lukem /*
1536 1.1 lukem * Rewrite the dn of the referrals, if needed
1537 1.1 lukem */
1538 1.1 lukem dc.rwmap = rwmap;
1539 1.1 lukem dc.conn = op->o_conn;
1540 1.1 lukem dc.rs = NULL;
1541 1.1 lukem dc.ctx = "referralDN";
1542 1.1 lukem rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1543 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1544 1.1 lukem rc = 1;
1545 1.1 lukem break;
1546 1.1 lukem }
1547 1.1 lukem }
1548 1.1 lukem rc = rwm_matched( op, rs );
1549 1.1 lukem break;
1550 1.1 lukem
1551 1.1 lukem default:
1552 1.1 lukem rc = SLAP_CB_CONTINUE;
1553 1.1 lukem break;
1554 1.1 lukem }
1555 1.1 lukem
1556 1.1 lukem return rc;
1557 1.1 lukem }
1558 1.1 lukem
1559 1.1 lukem static int
1560 1.1 lukem rwm_db_config(
1561 1.1 lukem BackendDB *be,
1562 1.1 lukem const char *fname,
1563 1.1 lukem int lineno,
1564 1.1 lukem int argc,
1565 1.1 lukem char **argv )
1566 1.1 lukem {
1567 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1568 1.1 lukem struct ldaprwmap *rwmap =
1569 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1570 1.1 lukem
1571 1.1 lukem int rc = 0;
1572 1.1 lukem char *argv0 = NULL;
1573 1.1 lukem
1574 1.1 lukem if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1575 1.1 lukem argv0 = argv[ 0 ];
1576 1.1 lukem argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1577 1.1 lukem }
1578 1.1 lukem
1579 1.1 lukem if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1580 1.1 lukem rc = rwm_rw_config( be, fname, lineno, argc, argv );
1581 1.1 lukem
1582 1.1 lukem } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1583 1.1 lukem rc = rwm_m_config( be, fname, lineno, argc, argv );
1584 1.1 lukem
1585 1.1 lukem } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1586 1.1 lukem rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1587 1.1 lukem
1588 1.1 lukem } else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
1589 1.1 lukem if ( argc != 2 ) {
1590 1.1 lukem fprintf( stderr,
1591 1.1 lukem "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
1592 1.1 lukem fname, lineno );
1593 1.1 lukem return( 1 );
1594 1.1 lukem }
1595 1.1 lukem
1596 1.1 lukem if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1597 1.1 lukem rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
1598 1.1 lukem
1599 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1600 1.1 lukem rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
1601 1.1 lukem
1602 1.1 lukem /* TODO: not implemented yet */
1603 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1604 1.1 lukem fprintf( stderr,
1605 1.1 lukem "%s: line %d: \"discover\" not supported yet "
1606 1.1 lukem "in \"t-f-support {no|yes|discover}\".\n",
1607 1.1 lukem fname, lineno );
1608 1.1 lukem return( 1 );
1609 1.1 lukem #if 0
1610 1.1 lukem rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
1611 1.1 lukem #endif
1612 1.1 lukem
1613 1.1 lukem } else {
1614 1.1 lukem fprintf( stderr,
1615 1.1 lukem "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
1616 1.1 lukem fname, lineno, argv[ 1 ] );
1617 1.1 lukem return 1;
1618 1.1 lukem }
1619 1.1 lukem
1620 1.1 lukem } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) == 0 ) {
1621 1.1 lukem if ( argc !=2 ) {
1622 1.1 lukem fprintf( stderr,
1623 1.1 lukem "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
1624 1.1 lukem fname, lineno );
1625 1.1 lukem return( 1 );
1626 1.1 lukem }
1627 1.1 lukem
1628 1.1 lukem if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1629 1.1 lukem rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
1630 1.1 lukem
1631 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1632 1.1 lukem rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
1633 1.1 lukem }
1634 1.1 lukem
1635 1.1 lukem } else {
1636 1.1 lukem rc = SLAP_CONF_UNKNOWN;
1637 1.1 lukem }
1638 1.1 lukem
1639 1.1 lukem if ( argv0 ) {
1640 1.1 lukem argv[ 0 ] = argv0;
1641 1.1 lukem }
1642 1.1 lukem
1643 1.1 lukem return rc;
1644 1.1 lukem }
1645 1.1 lukem
1646 1.1 lukem /*
1647 1.1 lukem * dynamic configuration...
1648 1.1 lukem */
1649 1.1 lukem
1650 1.1 lukem enum {
1651 1.1 lukem /* rewrite */
1652 1.1 lukem RWM_CF_REWRITE = 1,
1653 1.1 lukem RWM_CF_SUFFIXMASSAGE,
1654 1.1 lukem
1655 1.1 lukem /* map */
1656 1.1 lukem RWM_CF_MAP,
1657 1.1 lukem RWM_CF_T_F_SUPPORT,
1658 1.1 lukem RWM_CF_NORMALIZE_MAPPED,
1659 1.1 lukem
1660 1.1 lukem RWM_CF_LAST
1661 1.1 lukem };
1662 1.1 lukem
1663 1.1 lukem static slap_verbmasks t_f_mode[] = {
1664 1.1 lukem { BER_BVC( "yes" ), RWM_F_SUPPORT_T_F },
1665 1.1 lukem { BER_BVC( "discover" ), RWM_F_SUPPORT_T_F_DISCOVER },
1666 1.1 lukem { BER_BVC( "no" ), RWM_F_NONE },
1667 1.1 lukem { BER_BVNULL, 0 }
1668 1.1 lukem };
1669 1.1 lukem
1670 1.1 lukem static ConfigDriver rwm_cf_gen;
1671 1.1 lukem
1672 1.1 lukem static ConfigTable rwmcfg[] = {
1673 1.1 lukem { "rwm-rewrite", "rewrite",
1674 1.1 lukem 2, 0, STRLENOF("rwm-rewrite"),
1675 1.1 lukem ARG_MAGIC|ARG_QUOTE|RWM_CF_REWRITE, rwm_cf_gen,
1676 1.1 lukem "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
1677 1.1 lukem "DESC 'Rewrites strings' "
1678 1.1 lukem "EQUALITY caseIgnoreMatch "
1679 1.1 lukem "SYNTAX OMsDirectoryString "
1680 1.1 lukem "X-ORDERED 'VALUES' )",
1681 1.1 lukem NULL, NULL },
1682 1.1 lukem
1683 1.1 lukem { "rwm-suffixmassage", "[virtual]> <real",
1684 1.1 lukem 2, 3, 0, ARG_MAGIC|RWM_CF_SUFFIXMASSAGE, rwm_cf_gen,
1685 1.1 lukem NULL, NULL, NULL },
1686 1.1 lukem
1687 1.1 lukem { "rwm-t-f-support", "true|false|discover",
1688 1.1 lukem 2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
1689 1.1 lukem "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
1690 1.1 lukem "DESC 'Absolute filters support' "
1691 1.1 lukem "SYNTAX OMsDirectoryString "
1692 1.1 lukem "SINGLE-VALUE )",
1693 1.1 lukem NULL, NULL },
1694 1.1 lukem
1695 1.1 lukem { "rwm-map", "{objectClass|attribute}",
1696 1.1 lukem 2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
1697 1.1 lukem "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
1698 1.1 lukem "DESC 'maps attributes/objectClasses' "
1699 1.1 lukem "SYNTAX OMsDirectoryString "
1700 1.1 lukem "X-ORDERED 'VALUES' )",
1701 1.1 lukem NULL, NULL },
1702 1.1 lukem
1703 1.1 lukem { "rwm-normalize-mapped-attrs", "true|false",
1704 1.1 lukem 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
1705 1.1 lukem "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
1706 1.1 lukem "DESC 'Normalize mapped attributes/objectClasses' "
1707 1.1 lukem "SYNTAX OMsBoolean "
1708 1.1 lukem "SINGLE-VALUE )",
1709 1.1 lukem NULL, NULL },
1710 1.1 lukem
1711 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1712 1.1 lukem };
1713 1.1 lukem
1714 1.1 lukem static ConfigOCs rwmocs[] = {
1715 1.1 lukem { "( OLcfgOvOc:16.1 "
1716 1.1 lukem "NAME 'olcRwmConfig' "
1717 1.1 lukem "DESC 'Rewrite/remap configuration' "
1718 1.1 lukem "SUP olcOverlayConfig "
1719 1.1 lukem "MAY ( "
1720 1.1 lukem "olcRwmRewrite $ "
1721 1.1 lukem "olcRwmTFSupport $ "
1722 1.1 lukem "olcRwmMap $ "
1723 1.1 lukem "olcRwmNormalizeMapped "
1724 1.1 lukem ") )",
1725 1.1 lukem Cft_Overlay, rwmcfg, NULL, NULL },
1726 1.1 lukem { NULL, 0, NULL }
1727 1.1 lukem };
1728 1.1 lukem
1729 1.1 lukem static void
1730 1.1 lukem slap_rewrite_unparse( BerVarray in, BerVarray *out )
1731 1.1 lukem {
1732 1.1 lukem int i;
1733 1.1 lukem BerVarray bva = NULL;
1734 1.1 lukem char ibuf[32], *ptr;
1735 1.1 lukem struct berval idx;
1736 1.1 lukem
1737 1.1 lukem assert( in != NULL );
1738 1.1 lukem
1739 1.1 lukem for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
1740 1.1 lukem /* count'em */ ;
1741 1.1 lukem
1742 1.1 lukem if ( i == 0 ) {
1743 1.1 lukem return;
1744 1.1 lukem }
1745 1.1 lukem
1746 1.1 lukem idx.bv_val = ibuf;
1747 1.1 lukem
1748 1.1 lukem bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
1749 1.1 lukem BER_BVZERO( &bva[ 0 ] );
1750 1.1 lukem
1751 1.1 lukem for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1752 1.1 lukem idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
1753 1.1 lukem if ( idx.bv_len >= sizeof( ibuf ) ) {
1754 1.1 lukem ber_bvarray_free( bva );
1755 1.1 lukem return;
1756 1.1 lukem }
1757 1.1 lukem
1758 1.1 lukem bva[i].bv_len = idx.bv_len + in[i].bv_len;
1759 1.1 lukem bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
1760 1.1 lukem ptr = lutil_strcopy( bva[i].bv_val, ibuf );
1761 1.1 lukem ptr = lutil_strcopy( ptr, in[i].bv_val );
1762 1.1 lukem *ptr = '\0';
1763 1.1 lukem BER_BVZERO( &bva[ i + 1 ] );
1764 1.1 lukem }
1765 1.1 lukem
1766 1.1 lukem *out = bva;
1767 1.1 lukem }
1768 1.1 lukem
1769 1.1 lukem static int
1770 1.1 lukem rwm_cf_gen( ConfigArgs *c )
1771 1.1 lukem {
1772 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
1773 1.1 lukem struct ldaprwmap *rwmap =
1774 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1775 1.1 lukem
1776 1.1 lukem BackendDB db;
1777 1.1 lukem char *argv0;
1778 1.1 lukem int rc = 0;
1779 1.1 lukem
1780 1.1 lukem db = *c->be;
1781 1.1 lukem db.bd_info = c->bi;
1782 1.1 lukem
1783 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) {
1784 1.1 lukem struct berval bv = BER_BVNULL;
1785 1.1 lukem
1786 1.1 lukem switch ( c->type ) {
1787 1.1 lukem case RWM_CF_REWRITE:
1788 1.1 lukem if ( rwmap->rwm_bva_rewrite == NULL ) {
1789 1.1 lukem rc = 1;
1790 1.1 lukem
1791 1.1 lukem } else {
1792 1.1 lukem slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
1793 1.1 lukem if ( !c->rvalue_vals ) {
1794 1.1 lukem rc = 1;
1795 1.1 lukem }
1796 1.1 lukem }
1797 1.1 lukem break;
1798 1.1 lukem
1799 1.1 lukem case RWM_CF_T_F_SUPPORT:
1800 1.1 lukem enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
1801 1.1 lukem if ( BER_BVISNULL( &bv ) ) {
1802 1.1 lukem /* there's something wrong... */
1803 1.1 lukem assert( 0 );
1804 1.1 lukem rc = 1;
1805 1.1 lukem
1806 1.1 lukem } else {
1807 1.1 lukem value_add_one( &c->rvalue_vals, &bv );
1808 1.1 lukem }
1809 1.1 lukem break;
1810 1.1 lukem
1811 1.1 lukem case RWM_CF_MAP:
1812 1.1 lukem if ( rwmap->rwm_bva_map == NULL ) {
1813 1.1 lukem rc = 1;
1814 1.1 lukem
1815 1.1 lukem } else {
1816 1.1 lukem value_add( &c->rvalue_vals, rwmap->rwm_bva_map );
1817 1.1 lukem }
1818 1.1 lukem break;
1819 1.1 lukem
1820 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
1821 1.1 lukem c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
1822 1.1 lukem break;
1823 1.1 lukem
1824 1.1 lukem default:
1825 1.1 lukem assert( 0 );
1826 1.1 lukem rc = 1;
1827 1.1 lukem }
1828 1.1 lukem
1829 1.1 lukem return rc;
1830 1.1 lukem
1831 1.1 lukem } else if ( c->op == LDAP_MOD_DELETE ) {
1832 1.1 lukem switch ( c->type ) {
1833 1.1 lukem case RWM_CF_REWRITE:
1834 1.1 lukem if ( c->valx >= 0 ) {
1835 1.1 lukem /* single modification is not allowed */
1836 1.1 lukem rc = 1;
1837 1.1 lukem
1838 1.1 lukem } else if ( rwmap->rwm_rw != NULL ) {
1839 1.1 lukem rewrite_info_delete( &rwmap->rwm_rw );
1840 1.1 lukem assert( rwmap->rwm_rw == NULL );
1841 1.1 lukem
1842 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_rewrite );
1843 1.1 lukem rwmap->rwm_bva_rewrite = NULL;
1844 1.1 lukem }
1845 1.1 lukem break;
1846 1.1 lukem
1847 1.1 lukem case RWM_CF_T_F_SUPPORT:
1848 1.1 lukem rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
1849 1.1 lukem break;
1850 1.1 lukem
1851 1.1 lukem case RWM_CF_MAP:
1852 1.1 lukem if ( c->valx >= 0 ) {
1853 1.1 lukem /* single modification is not allowed */
1854 1.1 lukem rc = 1;
1855 1.1 lukem
1856 1.1 lukem } else {
1857 1.1 lukem avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
1858 1.1 lukem avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
1859 1.1 lukem avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
1860 1.1 lukem avl_free( rwmap->rwm_at.map, rwm_mapping_free );
1861 1.1 lukem
1862 1.1 lukem rwmap->rwm_oc.remap = NULL;
1863 1.1 lukem rwmap->rwm_oc.map = NULL;
1864 1.1 lukem rwmap->rwm_at.remap = NULL;
1865 1.1 lukem rwmap->rwm_at.map = NULL;
1866 1.1 lukem
1867 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_map );
1868 1.1 lukem rwmap->rwm_bva_map = NULL;
1869 1.1 lukem }
1870 1.1 lukem break;
1871 1.1 lukem
1872 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
1873 1.1 lukem rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
1874 1.1 lukem break;
1875 1.1 lukem
1876 1.1 lukem default:
1877 1.1 lukem return 1;
1878 1.1 lukem }
1879 1.1 lukem return rc;
1880 1.1 lukem }
1881 1.1 lukem
1882 1.1 lukem switch ( c->type ) {
1883 1.1 lukem case RWM_CF_REWRITE:
1884 1.1 lukem argv0 = c->argv[ 0 ];
1885 1.1 lukem c->argv[ 0 ] += STRLENOF( "rwm-" );
1886 1.1 lukem rc = rwm_rw_config( &db, c->fname, c->lineno, c->argc, c->argv );
1887 1.1 lukem c->argv[ 0 ] = argv0;
1888 1.1 lukem if ( rc ) {
1889 1.1 lukem return 1;
1890 1.1 lukem
1891 1.1 lukem } else {
1892 1.1 lukem char *line;
1893 1.1 lukem struct berval bv;
1894 1.1 lukem
1895 1.1 lukem line = ldap_charray2str( c->argv, "\" \"" );
1896 1.1 lukem if ( line != NULL ) {
1897 1.1 lukem int len = strlen( c->argv[ 0 ] );
1898 1.1 lukem
1899 1.1 lukem ber_str2bv( line, 0, 0, &bv );
1900 1.1 lukem AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
1901 1.1 lukem bv.bv_len - ( len + 1 ) );
1902 1.1 lukem bv.bv_val[ bv.bv_len - 1 ] = '"';
1903 1.1 lukem ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
1904 1.1 lukem }
1905 1.1 lukem }
1906 1.1 lukem break;
1907 1.1 lukem
1908 1.1 lukem case RWM_CF_SUFFIXMASSAGE:
1909 1.1 lukem argv0 = c->argv[ 0 ];
1910 1.1 lukem c->argv[ 0 ] += STRLENOF( "rwm-" );
1911 1.1 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno, c->argc, c->argv );
1912 1.1 lukem c->argv[ 0 ] = argv0;
1913 1.1 lukem if ( rc ) {
1914 1.1 lukem return 1;
1915 1.1 lukem
1916 1.1 lukem } else {
1917 1.1 lukem char *line;
1918 1.1 lukem struct berval bv;
1919 1.1 lukem
1920 1.1 lukem /* FIXME: not optimal; in fact, this keeps track
1921 1.1 lukem * of the fact that a set of rules was added
1922 1.1 lukem * using the rwm-suffixmassage shortcut, but the
1923 1.1 lukem * rules are not clarified */
1924 1.1 lukem
1925 1.1 lukem line = ldap_charray2str( c->argv, "\" \"" );
1926 1.1 lukem if ( line != NULL ) {
1927 1.1 lukem int len = strlen( c->argv[ 0 ] );
1928 1.1 lukem
1929 1.1 lukem ber_str2bv( line, 0, 0, &bv );
1930 1.1 lukem AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
1931 1.1 lukem bv.bv_len - ( len + 1 ) );
1932 1.1 lukem bv.bv_val[ bv.bv_len - 1 ] = '"';
1933 1.1 lukem ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
1934 1.1 lukem }
1935 1.1 lukem }
1936 1.1 lukem break;
1937 1.1 lukem
1938 1.1 lukem case RWM_CF_T_F_SUPPORT:
1939 1.1 lukem rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
1940 1.1 lukem if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
1941 1.1 lukem return 1;
1942 1.1 lukem }
1943 1.1 lukem
1944 1.1 lukem rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
1945 1.1 lukem rwmap->rwm_flags |= t_f_mode[ rc ].mask;
1946 1.1 lukem rc = 0;
1947 1.1 lukem break;
1948 1.1 lukem
1949 1.1 lukem case RWM_CF_MAP:
1950 1.1 lukem argv0 = c->argv[ 0 ];
1951 1.1 lukem c->argv[ 0 ] += STRLENOF( "rwm-" );
1952 1.1 lukem rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
1953 1.1 lukem c->argv[ 0 ] = argv0;
1954 1.1 lukem if ( rc ) {
1955 1.1 lukem return 1;
1956 1.1 lukem
1957 1.1 lukem } else {
1958 1.1 lukem char *line;
1959 1.1 lukem struct berval bv;
1960 1.1 lukem
1961 1.1 lukem line = ldap_charray2str( &c->argv[ 1 ], " " );
1962 1.1 lukem if ( line != NULL ) {
1963 1.1 lukem ber_str2bv( line, 0, 0, &bv );
1964 1.1 lukem ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
1965 1.1 lukem }
1966 1.1 lukem }
1967 1.1 lukem break;
1968 1.1 lukem
1969 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
1970 1.1 lukem if ( c->value_int ) {
1971 1.1 lukem rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
1972 1.1 lukem } else {
1973 1.1 lukem rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
1974 1.1 lukem }
1975 1.1 lukem break;
1976 1.1 lukem
1977 1.1 lukem default:
1978 1.1 lukem assert( 0 );
1979 1.1 lukem return 1;
1980 1.1 lukem }
1981 1.1 lukem
1982 1.1 lukem return rc;
1983 1.1 lukem }
1984 1.1 lukem
1985 1.1 lukem static int
1986 1.1 lukem rwm_db_init(
1987 1.1 lukem BackendDB *be,
1988 1.1 lukem ConfigReply *cr )
1989 1.1 lukem {
1990 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1991 1.1 lukem struct ldaprwmap *rwmap;
1992 1.1 lukem char *rargv[ 3 ];
1993 1.1 lukem int rc = 0;
1994 1.1 lukem
1995 1.1 lukem rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
1996 1.1 lukem
1997 1.1 lukem rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
1998 1.1 lukem if ( rwmap->rwm_rw == NULL ) {
1999 1.1 lukem rc = -1;
2000 1.1 lukem goto error_return;
2001 1.1 lukem }
2002 1.1 lukem
2003 1.1 lukem /* this rewriteContext by default must be null;
2004 1.1 lukem * rules can be added if required */
2005 1.1 lukem rargv[ 0 ] = "rewriteContext";
2006 1.1 lukem rargv[ 1 ] = "searchFilter";
2007 1.1 lukem rargv[ 2 ] = NULL;
2008 1.1 lukem rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
2009 1.1 lukem
2010 1.1 lukem rargv[ 0 ] = "rewriteContext";
2011 1.1 lukem rargv[ 1 ] = "default";
2012 1.1 lukem rargv[ 2 ] = NULL;
2013 1.1 lukem rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
2014 1.1 lukem
2015 1.1 lukem error_return:;
2016 1.1 lukem on->on_bi.bi_private = (void *)rwmap;
2017 1.1 lukem
2018 1.1 lukem if ( rc ) {
2019 1.1 lukem (void)rwm_db_destroy( be, NULL );
2020 1.1 lukem }
2021 1.1 lukem
2022 1.1 lukem return rc;
2023 1.1 lukem }
2024 1.1 lukem
2025 1.1 lukem static int
2026 1.1 lukem rwm_db_destroy(
2027 1.1 lukem BackendDB *be,
2028 1.1 lukem ConfigReply *cr )
2029 1.1 lukem {
2030 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
2031 1.1 lukem int rc = 0;
2032 1.1 lukem
2033 1.1 lukem if ( on->on_bi.bi_private ) {
2034 1.1 lukem struct ldaprwmap *rwmap =
2035 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
2036 1.1 lukem
2037 1.1 lukem if ( rwmap->rwm_rw ) {
2038 1.1 lukem rewrite_info_delete( &rwmap->rwm_rw );
2039 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_rewrite );
2040 1.1 lukem }
2041 1.1 lukem
2042 1.1 lukem avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2043 1.1 lukem avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2044 1.1 lukem avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2045 1.1 lukem avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2046 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_map );
2047 1.1 lukem
2048 1.1 lukem ch_free( rwmap );
2049 1.1 lukem }
2050 1.1 lukem
2051 1.1 lukem return rc;
2052 1.1 lukem }
2053 1.1 lukem
2054 1.1 lukem static slap_overinst rwm = { { NULL } };
2055 1.1 lukem
2056 1.1 lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2057 1.1 lukem static
2058 1.1 lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2059 1.1 lukem int
2060 1.1 lukem rwm_initialize( void )
2061 1.1 lukem {
2062 1.1 lukem int rc;
2063 1.1 lukem
2064 1.1 lukem /* Make sure we don't exceed the bits reserved for userland */
2065 1.1 lukem config_check_userland( RWM_CF_LAST );
2066 1.1 lukem
2067 1.1 lukem memset( &rwm, 0, sizeof( slap_overinst ) );
2068 1.1 lukem
2069 1.1 lukem rwm.on_bi.bi_type = "rwm";
2070 1.1 lukem rwm.on_bi.bi_flags =
2071 1.1 lukem SLAPO_BFLAG_SINGLE |
2072 1.1 lukem 0;
2073 1.1 lukem
2074 1.1 lukem rwm.on_bi.bi_db_init = rwm_db_init;
2075 1.1 lukem rwm.on_bi.bi_db_config = rwm_db_config;
2076 1.1 lukem rwm.on_bi.bi_db_destroy = rwm_db_destroy;
2077 1.1 lukem
2078 1.1 lukem rwm.on_bi.bi_op_bind = rwm_op_bind;
2079 1.1 lukem rwm.on_bi.bi_op_search = rwm_op_search;
2080 1.1 lukem rwm.on_bi.bi_op_compare = rwm_op_compare;
2081 1.1 lukem rwm.on_bi.bi_op_modify = rwm_op_modify;
2082 1.1 lukem rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
2083 1.1 lukem rwm.on_bi.bi_op_add = rwm_op_add;
2084 1.1 lukem rwm.on_bi.bi_op_delete = rwm_op_delete;
2085 1.1 lukem rwm.on_bi.bi_op_unbind = rwm_op_unbind;
2086 1.1 lukem rwm.on_bi.bi_extended = rwm_extended;
2087 1.1 lukem
2088 1.1 lukem rwm.on_bi.bi_operational = rwm_operational;
2089 1.1 lukem rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
2090 1.1 lukem
2091 1.1 lukem rwm.on_bi.bi_connection_init = rwm_conn_init;
2092 1.1 lukem rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
2093 1.1 lukem
2094 1.1 lukem rwm.on_response = rwm_response;
2095 1.1 lukem
2096 1.1 lukem rwm.on_bi.bi_cf_ocs = rwmocs;
2097 1.1 lukem
2098 1.1 lukem rc = config_register_schema( rwmcfg, rwmocs );
2099 1.1 lukem if ( rc ) {
2100 1.1 lukem return rc;
2101 1.1 lukem }
2102 1.1 lukem
2103 1.1 lukem return overlay_register( &rwm );
2104 1.1 lukem }
2105 1.1 lukem
2106 1.1 lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2107 1.1 lukem int
2108 1.1 lukem init_module( int argc, char *argv[] )
2109 1.1 lukem {
2110 1.1 lukem return rwm_initialize();
2111 1.1 lukem }
2112 1.1 lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2113 1.1 lukem
2114 1.1 lukem #endif /* SLAPD_OVER_RWM */
2115