rwm.c revision 1.1.1.8 1 1.1.1.6 christos /* $NetBSD: rwm.c,v 1.1.1.8 2020/08/11 13:12:15 christos Exp $ */
2 1.1.1.2 lukem
3 1.1 lukem /* rwm.c - rewrite/remap operations */
4 1.1.1.4 tron /* $OpenLDAP$ */
5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 lukem *
7 1.1.1.8 christos * Copyright 2003-2020 The OpenLDAP Foundation.
8 1.1 lukem * Portions Copyright 2003 Pierangelo Masarati.
9 1.1 lukem * All rights reserved.
10 1.1 lukem *
11 1.1 lukem * Redistribution and use in source and binary forms, with or without
12 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
13 1.1 lukem * Public License.
14 1.1 lukem *
15 1.1 lukem * A copy of this license is available in the file LICENSE in the
16 1.1 lukem * top-level directory of the distribution or, alternatively, at
17 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
18 1.1 lukem */
19 1.1 lukem
20 1.1.1.5 christos #include <sys/cdefs.h>
21 1.1.1.6 christos __RCSID("$NetBSD: rwm.c,v 1.1.1.8 2020/08/11 13:12:15 christos Exp $");
22 1.1.1.5 christos
23 1.1 lukem #include "portable.h"
24 1.1 lukem
25 1.1 lukem #ifdef SLAPD_OVER_RWM
26 1.1 lukem
27 1.1 lukem #include <stdio.h>
28 1.1 lukem
29 1.1 lukem #include <ac/string.h>
30 1.1 lukem
31 1.1 lukem #include "slap.h"
32 1.1 lukem #include "config.h"
33 1.1 lukem #include "lutil.h"
34 1.1 lukem #include "rwm.h"
35 1.1 lukem
36 1.1 lukem typedef struct rwm_op_state {
37 1.1 lukem ber_tag_t r_tag;
38 1.1 lukem struct berval ro_dn;
39 1.1 lukem struct berval ro_ndn;
40 1.1 lukem struct berval r_dn;
41 1.1 lukem struct berval r_ndn;
42 1.1.1.4 tron struct berval rx_dn;
43 1.1.1.4 tron struct berval rx_ndn;
44 1.1 lukem AttributeName *mapped_attrs;
45 1.1 lukem OpRequest o_request;
46 1.1 lukem } rwm_op_state;
47 1.1 lukem
48 1.1 lukem typedef struct rwm_op_cb {
49 1.1 lukem slap_callback cb;
50 1.1 lukem rwm_op_state ros;
51 1.1 lukem } rwm_op_cb;
52 1.1 lukem
53 1.1 lukem static int
54 1.1.1.2 lukem rwm_db_destroy( BackendDB *be, ConfigReply *cr );
55 1.1 lukem
56 1.1.1.2 lukem static int
57 1.1.1.2 lukem rwm_send_entry( Operation *op, SlapReply *rs );
58 1.1 lukem
59 1.1.1.2 lukem static void
60 1.1.1.2 lukem rwm_op_rollback( Operation *op, SlapReply *rs, rwm_op_state *ros )
61 1.1.1.2 lukem {
62 1.1.1.4 tron /* in case of successful extended operation cleanup
63 1.1.1.4 tron * gets called *after* (ITS#6632); this hack counts
64 1.1.1.4 tron * on others to cleanup our o_req_dn/o_req_ndn,
65 1.1.1.4 tron * while we cleanup theirs. */
66 1.1.1.4 tron if ( ros->r_tag == LDAP_REQ_EXTENDED && rs->sr_err == LDAP_SUCCESS ) {
67 1.1.1.4 tron if ( !BER_BVISNULL( &ros->rx_dn ) ) {
68 1.1.1.4 tron ch_free( ros->rx_dn.bv_val );
69 1.1.1.4 tron }
70 1.1.1.4 tron if ( !BER_BVISNULL( &ros->rx_ndn ) ) {
71 1.1.1.4 tron ch_free( ros->rx_ndn.bv_val );
72 1.1.1.4 tron }
73 1.1 lukem
74 1.1.1.4 tron } else {
75 1.1.1.4 tron if ( !BER_BVISNULL( &ros->ro_dn ) ) {
76 1.1.1.4 tron op->o_req_dn = ros->ro_dn;
77 1.1.1.4 tron }
78 1.1.1.4 tron if ( !BER_BVISNULL( &ros->ro_ndn ) ) {
79 1.1.1.4 tron op->o_req_ndn = ros->ro_ndn;
80 1.1.1.4 tron }
81 1.1 lukem
82 1.1.1.4 tron if ( !BER_BVISNULL( &ros->r_dn )
83 1.1.1.4 tron && ros->r_dn.bv_val != ros->ro_dn.bv_val )
84 1.1.1.4 tron {
85 1.1.1.4 tron assert( ros->r_dn.bv_val != ros->r_ndn.bv_val );
86 1.1.1.4 tron ch_free( ros->r_dn.bv_val );
87 1.1.1.4 tron }
88 1.1.1.4 tron
89 1.1.1.4 tron if ( !BER_BVISNULL( &ros->r_ndn )
90 1.1.1.4 tron && ros->r_ndn.bv_val != ros->ro_ndn.bv_val )
91 1.1.1.4 tron {
92 1.1.1.4 tron ch_free( ros->r_ndn.bv_val );
93 1.1.1.4 tron }
94 1.1.1.2 lukem }
95 1.1 lukem
96 1.1.1.4 tron BER_BVZERO( &ros->r_dn );
97 1.1.1.4 tron BER_BVZERO( &ros->r_ndn );
98 1.1.1.2 lukem BER_BVZERO( &ros->ro_dn );
99 1.1.1.2 lukem BER_BVZERO( &ros->ro_ndn );
100 1.1.1.4 tron BER_BVZERO( &ros->rx_dn );
101 1.1.1.4 tron BER_BVZERO( &ros->rx_ndn );
102 1.1.1.2 lukem
103 1.1.1.2 lukem switch( ros->r_tag ) {
104 1.1.1.2 lukem case LDAP_REQ_COMPARE:
105 1.1.1.2 lukem if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
106 1.1.1.2 lukem op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
107 1.1.1.2 lukem op->orc_ava = ros->orc_ava;
108 1.1.1.2 lukem break;
109 1.1.1.2 lukem case LDAP_REQ_MODIFY:
110 1.1.1.2 lukem slap_mods_free( op->orm_modlist, 1 );
111 1.1.1.2 lukem op->orm_modlist = ros->orm_modlist;
112 1.1.1.2 lukem break;
113 1.1.1.2 lukem case LDAP_REQ_MODRDN:
114 1.1.1.2 lukem if ( op->orr_newSup != ros->orr_newSup ) {
115 1.1.1.4 tron if ( op->orr_newSup ) {
116 1.1.1.4 tron ch_free( op->orr_newSup->bv_val );
117 1.1.1.4 tron ch_free( op->orr_nnewSup->bv_val );
118 1.1.1.4 tron op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
119 1.1.1.4 tron op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
120 1.1.1.4 tron }
121 1.1.1.2 lukem op->orr_newSup = ros->orr_newSup;
122 1.1.1.2 lukem op->orr_nnewSup = ros->orr_nnewSup;
123 1.1.1.2 lukem }
124 1.1.1.2 lukem if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
125 1.1.1.2 lukem ch_free( op->orr_newrdn.bv_val );
126 1.1.1.2 lukem ch_free( op->orr_nnewrdn.bv_val );
127 1.1.1.2 lukem op->orr_newrdn = ros->orr_newrdn;
128 1.1.1.2 lukem op->orr_nnewrdn = ros->orr_nnewrdn;
129 1.1.1.2 lukem }
130 1.1.1.2 lukem break;
131 1.1.1.2 lukem case LDAP_REQ_SEARCH:
132 1.1.1.3 adam op->o_tmpfree( ros->mapped_attrs, op->o_tmpmemctx );
133 1.1.1.2 lukem op->ors_attrs = ros->ors_attrs;
134 1.1.1.7 christos if ( op->ors_filter != ros->ors_filter ) {
135 1.1.1.7 christos filter_free_x( op, op->ors_filter, 1 );
136 1.1.1.7 christos op->ors_filter = ros->ors_filter;
137 1.1.1.7 christos }
138 1.1.1.7 christos if ( op->ors_filterstr.bv_val != ros->ors_filterstr.bv_val ) {
139 1.1.1.7 christos op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
140 1.1.1.7 christos op->ors_filterstr = ros->ors_filterstr;
141 1.1.1.7 christos }
142 1.1.1.2 lukem break;
143 1.1.1.2 lukem case LDAP_REQ_EXTENDED:
144 1.1.1.2 lukem if ( op->ore_reqdata != ros->ore_reqdata ) {
145 1.1.1.2 lukem ber_bvfree( op->ore_reqdata );
146 1.1.1.2 lukem op->ore_reqdata = ros->ore_reqdata;
147 1.1 lukem }
148 1.1.1.2 lukem break;
149 1.1.1.2 lukem case LDAP_REQ_BIND:
150 1.1.1.2 lukem if ( rs->sr_err == LDAP_SUCCESS ) {
151 1.1.1.2 lukem #if 0
152 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
153 1.1.1.2 lukem /* too late, c_mutex released */
154 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "*** DN: \"%s\" => \"%s\"\n",
155 1.1.1.2 lukem op->o_conn->c_ndn.bv_val,
156 1.1.1.2 lukem op->o_req_ndn.bv_val );
157 1.1.1.2 lukem ber_bvreplace( &op->o_conn->c_ndn,
158 1.1.1.2 lukem &op->o_req_ndn );
159 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
160 1.1.1.2 lukem #endif
161 1.1.1.2 lukem }
162 1.1.1.2 lukem break;
163 1.1.1.2 lukem default: break;
164 1.1.1.2 lukem }
165 1.1.1.2 lukem }
166 1.1.1.2 lukem
167 1.1.1.2 lukem static int
168 1.1.1.2 lukem rwm_op_cleanup( Operation *op, SlapReply *rs )
169 1.1.1.2 lukem {
170 1.1.1.2 lukem slap_callback *cb = op->o_callback;
171 1.1.1.2 lukem rwm_op_state *ros = cb->sc_private;
172 1.1.1.2 lukem
173 1.1.1.2 lukem if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
174 1.1.1.2 lukem op->o_abandon || rs->sr_err == SLAPD_ABANDON )
175 1.1.1.2 lukem {
176 1.1.1.2 lukem rwm_op_rollback( op, rs, ros );
177 1.1.1.2 lukem
178 1.1 lukem op->o_callback = op->o_callback->sc_next;
179 1.1 lukem op->o_tmpfree( cb, op->o_tmpmemctx );
180 1.1 lukem }
181 1.1 lukem
182 1.1 lukem return SLAP_CB_CONTINUE;
183 1.1 lukem }
184 1.1 lukem
185 1.1 lukem static rwm_op_cb *
186 1.1.1.4 tron rwm_callback_get( Operation *op )
187 1.1 lukem {
188 1.1.1.4 tron rwm_op_cb *roc;
189 1.1 lukem
190 1.1.1.5 christos roc = op->o_tmpcalloc( 1, sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
191 1.1 lukem roc->cb.sc_cleanup = rwm_op_cleanup;
192 1.1 lukem roc->cb.sc_response = NULL;
193 1.1 lukem roc->cb.sc_next = op->o_callback;
194 1.1 lukem roc->cb.sc_private = &roc->ros;
195 1.1 lukem roc->ros.r_tag = op->o_tag;
196 1.1 lukem roc->ros.ro_dn = op->o_req_dn;
197 1.1 lukem roc->ros.ro_ndn = op->o_req_ndn;
198 1.1 lukem BER_BVZERO( &roc->ros.r_dn );
199 1.1 lukem BER_BVZERO( &roc->ros.r_ndn );
200 1.1.1.4 tron BER_BVZERO( &roc->ros.rx_dn );
201 1.1.1.4 tron BER_BVZERO( &roc->ros.rx_ndn );
202 1.1.1.4 tron roc->ros.mapped_attrs = NULL;
203 1.1.1.4 tron roc->ros.o_request = op->o_request;
204 1.1 lukem
205 1.1 lukem return roc;
206 1.1 lukem }
207 1.1 lukem
208 1.1 lukem
209 1.1 lukem static int
210 1.1 lukem rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
211 1.1 lukem rwm_op_state *ros )
212 1.1 lukem {
213 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
214 1.1 lukem struct ldaprwmap *rwmap =
215 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
216 1.1 lukem
217 1.1 lukem struct berval dn = BER_BVNULL,
218 1.1 lukem ndn = BER_BVNULL;
219 1.1 lukem int rc = 0;
220 1.1 lukem dncookie dc;
221 1.1 lukem
222 1.1 lukem /*
223 1.1 lukem * Rewrite the dn if needed
224 1.1 lukem */
225 1.1 lukem dc.rwmap = rwmap;
226 1.1 lukem dc.conn = op->o_conn;
227 1.1 lukem dc.rs = rs;
228 1.1 lukem dc.ctx = (char *)cookie;
229 1.1 lukem
230 1.1 lukem /* NOTE: in those cases where only the ndn is available,
231 1.1 lukem * and the caller sets op->o_req_dn = op->o_req_ndn,
232 1.1 lukem * only rewrite the op->o_req_ndn and use it as
233 1.1 lukem * op->o_req_dn as well */
234 1.1 lukem ndn = op->o_req_ndn;
235 1.1 lukem if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
236 1.1 lukem dn = op->o_req_dn;
237 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
238 1.1 lukem } else {
239 1.1 lukem rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
240 1.1 lukem }
241 1.1 lukem
242 1.1 lukem if ( rc != LDAP_SUCCESS ) {
243 1.1 lukem return rc;
244 1.1 lukem }
245 1.1 lukem
246 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 )
247 1.1 lukem || ndn.bv_val == op->o_req_ndn.bv_val )
248 1.1 lukem {
249 1.1 lukem return LDAP_SUCCESS;
250 1.1 lukem }
251 1.1 lukem
252 1.1 lukem if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
253 1.1 lukem op->o_req_dn = dn;
254 1.1.1.2 lukem assert( BER_BVISNULL( &ros->r_dn ) );
255 1.1 lukem ros->r_dn = dn;
256 1.1 lukem } else {
257 1.1 lukem op->o_req_dn = ndn;
258 1.1 lukem }
259 1.1 lukem op->o_req_ndn = ndn;
260 1.1.1.2 lukem assert( BER_BVISNULL( &ros->r_ndn ) );
261 1.1 lukem ros->r_ndn = ndn;
262 1.1 lukem
263 1.1.1.4 tron if ( ros->r_tag == LDAP_REQ_EXTENDED ) {
264 1.1.1.4 tron ros->rx_dn = ros->r_dn;
265 1.1.1.4 tron ros->rx_ndn = ros->r_ndn;
266 1.1.1.4 tron }
267 1.1.1.4 tron
268 1.1 lukem return LDAP_SUCCESS;
269 1.1 lukem }
270 1.1 lukem
271 1.1 lukem static int
272 1.1 lukem rwm_op_add( Operation *op, SlapReply *rs )
273 1.1 lukem {
274 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
275 1.1 lukem struct ldaprwmap *rwmap =
276 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
277 1.1 lukem
278 1.1 lukem int rc,
279 1.1 lukem i;
280 1.1 lukem Attribute **ap = NULL;
281 1.1 lukem char *olddn = op->o_req_dn.bv_val;
282 1.1 lukem int isupdate;
283 1.1 lukem
284 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
285 1.1 lukem
286 1.1 lukem rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
287 1.1 lukem if ( rc != LDAP_SUCCESS ) {
288 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
289 1.1 lukem send_ldap_error( op, rs, rc, "addDN massage error" );
290 1.1 lukem return -1;
291 1.1 lukem }
292 1.1 lukem
293 1.1 lukem if ( olddn != op->o_req_dn.bv_val ) {
294 1.1 lukem ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
295 1.1 lukem ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
296 1.1 lukem }
297 1.1 lukem
298 1.1 lukem /* Count number of attributes in entry */
299 1.1 lukem isupdate = be_shadow_update( op );
300 1.1 lukem for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
301 1.1 lukem Attribute *a;
302 1.1 lukem
303 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
304 1.1 lukem (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
305 1.1 lukem {
306 1.1 lukem int j, last;
307 1.1 lukem
308 1.1 lukem last = (*ap)->a_numvals - 1;
309 1.1 lukem for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
310 1.1 lukem struct ldapmapping *mapping = NULL;
311 1.1 lukem
312 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
313 1.1 lukem &mapping, RWM_MAP );
314 1.1 lukem if ( mapping == NULL ) {
315 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
316 1.1 lukem /* FIXME: we allow to remove objectClasses as well;
317 1.1 lukem * if the resulting entry is inconsistent, that's
318 1.1 lukem * the relayed database's business...
319 1.1 lukem */
320 1.1 lukem ch_free( (*ap)->a_vals[ j ].bv_val );
321 1.1 lukem if ( last > j ) {
322 1.1 lukem (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
323 1.1 lukem }
324 1.1 lukem BER_BVZERO( &(*ap)->a_vals[ last ] );
325 1.1 lukem (*ap)->a_numvals--;
326 1.1 lukem last--;
327 1.1 lukem j--;
328 1.1 lukem }
329 1.1 lukem
330 1.1 lukem } else {
331 1.1 lukem ch_free( (*ap)->a_vals[ j ].bv_val );
332 1.1 lukem ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
333 1.1 lukem }
334 1.1 lukem }
335 1.1 lukem
336 1.1 lukem } else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
337 1.1 lukem {
338 1.1 lukem goto next_attr;
339 1.1 lukem
340 1.1 lukem } else {
341 1.1 lukem struct ldapmapping *mapping = NULL;
342 1.1 lukem
343 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
344 1.1 lukem &mapping, RWM_MAP );
345 1.1 lukem if ( mapping == NULL ) {
346 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
347 1.1 lukem goto cleanup_attr;
348 1.1 lukem }
349 1.1 lukem }
350 1.1 lukem
351 1.1 lukem if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
352 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
353 1.1 lukem {
354 1.1 lukem /*
355 1.1 lukem * FIXME: rewrite could fail; in this case
356 1.1 lukem * the operation should give up, right?
357 1.1 lukem */
358 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
359 1.1 lukem (*ap)->a_vals,
360 1.1 lukem (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
361 1.1 lukem if ( rc ) {
362 1.1 lukem goto cleanup_attr;
363 1.1 lukem }
364 1.1 lukem
365 1.1 lukem } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
366 1.1 lukem rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
367 1.1 lukem (*ap)->a_vals,
368 1.1 lukem (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
369 1.1 lukem if ( rc != LDAP_SUCCESS ) {
370 1.1 lukem goto cleanup_attr;
371 1.1 lukem }
372 1.1 lukem }
373 1.1 lukem
374 1.1 lukem if ( mapping != NULL ) {
375 1.1 lukem assert( mapping->m_dst_ad != NULL );
376 1.1 lukem (*ap)->a_desc = mapping->m_dst_ad;
377 1.1 lukem }
378 1.1 lukem }
379 1.1 lukem
380 1.1 lukem next_attr:;
381 1.1 lukem ap = &(*ap)->a_next;
382 1.1 lukem continue;
383 1.1 lukem
384 1.1 lukem cleanup_attr:;
385 1.1 lukem /* FIXME: leaking attribute/values? */
386 1.1 lukem a = *ap;
387 1.1 lukem
388 1.1 lukem *ap = (*ap)->a_next;
389 1.1 lukem attr_free( a );
390 1.1 lukem }
391 1.1 lukem
392 1.1 lukem op->o_callback = &roc->cb;
393 1.1 lukem
394 1.1 lukem return SLAP_CB_CONTINUE;
395 1.1 lukem }
396 1.1 lukem
397 1.1 lukem static int
398 1.1 lukem rwm_conn_init( BackendDB *be, Connection *conn )
399 1.1 lukem {
400 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
401 1.1 lukem struct ldaprwmap *rwmap =
402 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
403 1.1 lukem
404 1.1 lukem ( void )rewrite_session_init( rwmap->rwm_rw, conn );
405 1.1 lukem
406 1.1 lukem return SLAP_CB_CONTINUE;
407 1.1 lukem }
408 1.1 lukem
409 1.1 lukem static int
410 1.1 lukem rwm_conn_destroy( BackendDB *be, Connection *conn )
411 1.1 lukem {
412 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
413 1.1 lukem struct ldaprwmap *rwmap =
414 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
415 1.1 lukem
416 1.1 lukem ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
417 1.1 lukem
418 1.1 lukem return SLAP_CB_CONTINUE;
419 1.1 lukem }
420 1.1 lukem
421 1.1 lukem static int
422 1.1 lukem rwm_op_bind( Operation *op, SlapReply *rs )
423 1.1 lukem {
424 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
425 1.1 lukem int rc;
426 1.1 lukem
427 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
428 1.1 lukem
429 1.1 lukem rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
430 1.1 lukem if ( rc != LDAP_SUCCESS ) {
431 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
432 1.1 lukem send_ldap_error( op, rs, rc, "bindDN massage error" );
433 1.1 lukem return -1;
434 1.1 lukem }
435 1.1 lukem
436 1.1.1.2 lukem overlay_callback_after_backover( op, &roc->cb, 1 );
437 1.1 lukem
438 1.1 lukem return SLAP_CB_CONTINUE;
439 1.1 lukem }
440 1.1 lukem
441 1.1 lukem static int
442 1.1 lukem rwm_op_unbind( Operation *op, SlapReply *rs )
443 1.1 lukem {
444 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
445 1.1 lukem struct ldaprwmap *rwmap =
446 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
447 1.1 lukem
448 1.1 lukem rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
449 1.1 lukem
450 1.1 lukem return SLAP_CB_CONTINUE;
451 1.1 lukem }
452 1.1 lukem
453 1.1 lukem static int
454 1.1 lukem rwm_op_compare( Operation *op, SlapReply *rs )
455 1.1 lukem {
456 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
457 1.1 lukem struct ldaprwmap *rwmap =
458 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
459 1.1 lukem
460 1.1 lukem int rc;
461 1.1 lukem struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
462 1.1 lukem
463 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
464 1.1 lukem
465 1.1 lukem rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
466 1.1 lukem if ( rc != LDAP_SUCCESS ) {
467 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
468 1.1 lukem send_ldap_error( op, rs, rc, "compareDN massage error" );
469 1.1 lukem return -1;
470 1.1 lukem }
471 1.1 lukem
472 1.1 lukem /* if the attribute is an objectClass, try to remap its value */
473 1.1 lukem if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
474 1.1 lukem || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
475 1.1 lukem {
476 1.1 lukem rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
477 1.1 lukem &mapped_vals[0], RWM_MAP );
478 1.1 lukem if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
479 1.1 lukem {
480 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
481 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
482 1.1 lukem return -1;
483 1.1 lukem
484 1.1 lukem } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
485 1.1 lukem ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
486 1.1 lukem op->o_tmpmemctx );
487 1.1 lukem }
488 1.1 lukem
489 1.1 lukem } else {
490 1.1 lukem struct ldapmapping *mapping = NULL;
491 1.1 lukem AttributeDescription *ad = op->orc_ava->aa_desc;
492 1.1 lukem
493 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
494 1.1 lukem &mapping, RWM_MAP );
495 1.1 lukem if ( mapping == NULL ) {
496 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
497 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
498 1.1 lukem send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
499 1.1 lukem return -1;
500 1.1 lukem }
501 1.1 lukem
502 1.1 lukem } else {
503 1.1 lukem assert( mapping->m_dst_ad != NULL );
504 1.1 lukem ad = mapping->m_dst_ad;
505 1.1 lukem }
506 1.1 lukem
507 1.1 lukem if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
508 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
509 1.1 lukem {
510 1.1 lukem struct berval *mapped_valsp[2];
511 1.1 lukem
512 1.1 lukem mapped_valsp[0] = &mapped_vals[0];
513 1.1 lukem mapped_valsp[1] = &mapped_vals[1];
514 1.1 lukem
515 1.1 lukem mapped_vals[0] = op->orc_ava->aa_value;
516 1.1 lukem
517 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
518 1.1 lukem
519 1.1 lukem if ( rc != LDAP_SUCCESS ) {
520 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
521 1.1 lukem send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
522 1.1 lukem return -1;
523 1.1 lukem }
524 1.1 lukem
525 1.1 lukem if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
526 1.1 lukem /* NOTE: if we get here, rwm_dnattr_rewrite()
527 1.1 lukem * already freed the old value, so now
528 1.1 lukem * it's invalid */
529 1.1 lukem ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
530 1.1 lukem op->o_tmpmemctx );
531 1.1 lukem ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
532 1.1 lukem }
533 1.1 lukem }
534 1.1 lukem op->orc_ava->aa_desc = ad;
535 1.1 lukem }
536 1.1 lukem
537 1.1 lukem op->o_callback = &roc->cb;
538 1.1 lukem
539 1.1 lukem return SLAP_CB_CONTINUE;
540 1.1 lukem }
541 1.1 lukem
542 1.1 lukem static int
543 1.1 lukem rwm_op_delete( Operation *op, SlapReply *rs )
544 1.1 lukem {
545 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
546 1.1 lukem int rc;
547 1.1 lukem
548 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
549 1.1 lukem
550 1.1 lukem rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
551 1.1 lukem if ( rc != LDAP_SUCCESS ) {
552 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
553 1.1 lukem send_ldap_error( op, rs, rc, "deleteDN massage error" );
554 1.1 lukem return -1;
555 1.1 lukem }
556 1.1 lukem
557 1.1 lukem op->o_callback = &roc->cb;
558 1.1 lukem
559 1.1 lukem return SLAP_CB_CONTINUE;
560 1.1 lukem }
561 1.1 lukem
562 1.1 lukem static int
563 1.1 lukem rwm_op_modify( Operation *op, SlapReply *rs )
564 1.1 lukem {
565 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
566 1.1 lukem struct ldaprwmap *rwmap =
567 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
568 1.1 lukem
569 1.1 lukem int isupdate;
570 1.1 lukem Modifications **mlp;
571 1.1 lukem int rc;
572 1.1 lukem
573 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
574 1.1 lukem
575 1.1 lukem rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
576 1.1 lukem if ( rc != LDAP_SUCCESS ) {
577 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
578 1.1 lukem send_ldap_error( op, rs, rc, "modifyDN massage error" );
579 1.1 lukem return -1;
580 1.1 lukem }
581 1.1 lukem
582 1.1 lukem isupdate = be_shadow_update( op );
583 1.1 lukem for ( mlp = &op->orm_modlist; *mlp; ) {
584 1.1 lukem int is_oc = 0;
585 1.1 lukem Modifications *ml = *mlp;
586 1.1 lukem struct ldapmapping *mapping = NULL;
587 1.1 lukem
588 1.1 lukem /* ml points to a temporary mod until needs duplication */
589 1.1 lukem if ( ml->sml_desc == slap_schema.si_ad_objectClass
590 1.1 lukem || ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
591 1.1 lukem {
592 1.1 lukem is_oc = 1;
593 1.1 lukem
594 1.1 lukem } else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
595 1.1 lukem {
596 1.1 lukem ml = ch_malloc( sizeof( Modifications ) );
597 1.1 lukem *ml = **mlp;
598 1.1 lukem if ( (*mlp)->sml_values ) {
599 1.1 lukem ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
600 1.1 lukem if ( (*mlp)->sml_nvalues ) {
601 1.1 lukem ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
602 1.1 lukem }
603 1.1 lukem }
604 1.1 lukem *mlp = ml;
605 1.1 lukem goto next_mod;
606 1.1 lukem
607 1.1 lukem } else {
608 1.1 lukem int drop_missing;
609 1.1 lukem
610 1.1 lukem drop_missing = rwm_mapping( &rwmap->rwm_at,
611 1.1 lukem &ml->sml_desc->ad_cname,
612 1.1 lukem &mapping, RWM_MAP );
613 1.1 lukem if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
614 1.1 lukem {
615 1.1.1.4 tron goto skip_mod;
616 1.1 lukem }
617 1.1 lukem }
618 1.1 lukem
619 1.1 lukem /* duplicate the modlist */
620 1.1 lukem ml = ch_malloc( sizeof( Modifications ));
621 1.1 lukem *ml = **mlp;
622 1.1 lukem *mlp = ml;
623 1.1 lukem
624 1.1 lukem if ( ml->sml_values != NULL ) {
625 1.1 lukem int i, num;
626 1.1 lukem struct berval *bva;
627 1.1 lukem
628 1.1 lukem for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
629 1.1 lukem /* count values */ ;
630 1.1 lukem
631 1.1 lukem bva = ch_malloc( (num+1) * sizeof( struct berval ));
632 1.1 lukem for (i=0; i<num; i++)
633 1.1 lukem ber_dupbv( &bva[i], &ml->sml_values[i] );
634 1.1 lukem BER_BVZERO( &bva[i] );
635 1.1 lukem ml->sml_values = bva;
636 1.1 lukem
637 1.1 lukem if ( ml->sml_nvalues ) {
638 1.1 lukem bva = ch_malloc( (num+1) * sizeof( struct berval ));
639 1.1 lukem for (i=0; i<num; i++)
640 1.1 lukem ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
641 1.1 lukem BER_BVZERO( &bva[i] );
642 1.1 lukem ml->sml_nvalues = bva;
643 1.1 lukem }
644 1.1 lukem
645 1.1 lukem if ( is_oc ) {
646 1.1 lukem int last, j;
647 1.1 lukem
648 1.1 lukem last = num-1;
649 1.1 lukem
650 1.1 lukem for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
651 1.1 lukem struct ldapmapping *oc_mapping = NULL;
652 1.1 lukem
653 1.1 lukem ( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
654 1.1 lukem &oc_mapping, RWM_MAP );
655 1.1 lukem if ( oc_mapping == NULL ) {
656 1.1 lukem if ( rwmap->rwm_at.drop_missing ) {
657 1.1 lukem /* FIXME: we allow to remove objectClasses as well;
658 1.1 lukem * if the resulting entry is inconsistent, that's
659 1.1 lukem * the relayed database's business...
660 1.1 lukem */
661 1.1 lukem if ( last > j ) {
662 1.1 lukem ch_free( ml->sml_values[ j ].bv_val );
663 1.1 lukem ml->sml_values[ j ] = ml->sml_values[ last ];
664 1.1 lukem }
665 1.1 lukem BER_BVZERO( &ml->sml_values[ last ] );
666 1.1 lukem last--;
667 1.1 lukem j--;
668 1.1 lukem }
669 1.1 lukem
670 1.1 lukem } else {
671 1.1 lukem ch_free( ml->sml_values[ j ].bv_val );
672 1.1 lukem ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
673 1.1 lukem }
674 1.1 lukem }
675 1.1 lukem
676 1.1 lukem } else {
677 1.1 lukem if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
678 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
679 1.1 lukem {
680 1.1 lukem rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
681 1.1 lukem ml->sml_values,
682 1.1 lukem ml->sml_nvalues ? &ml->sml_nvalues : NULL );
683 1.1 lukem
684 1.1 lukem } else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
685 1.1 lukem rc = rwm_referral_rewrite( op, rs,
686 1.1 lukem "referralAttrDN",
687 1.1 lukem ml->sml_values,
688 1.1 lukem ml->sml_nvalues ? &ml->sml_nvalues : NULL );
689 1.1 lukem if ( rc != LDAP_SUCCESS ) {
690 1.1 lukem goto cleanup_mod;
691 1.1 lukem }
692 1.1 lukem }
693 1.1 lukem
694 1.1 lukem if ( rc != LDAP_SUCCESS ) {
695 1.1 lukem goto cleanup_mod;
696 1.1 lukem }
697 1.1 lukem }
698 1.1 lukem }
699 1.1 lukem
700 1.1 lukem next_mod:;
701 1.1 lukem if ( mapping != NULL ) {
702 1.1 lukem /* use new attribute description */
703 1.1 lukem assert( mapping->m_dst_ad != NULL );
704 1.1 lukem ml->sml_desc = mapping->m_dst_ad;
705 1.1 lukem }
706 1.1 lukem
707 1.1 lukem mlp = &ml->sml_next;
708 1.1 lukem continue;
709 1.1 lukem
710 1.1.1.4 tron skip_mod:;
711 1.1.1.4 tron *mlp = (*mlp)->sml_next;
712 1.1.1.4 tron continue;
713 1.1.1.4 tron
714 1.1 lukem cleanup_mod:;
715 1.1 lukem ml = *mlp;
716 1.1 lukem *mlp = (*mlp)->sml_next;
717 1.1 lukem slap_mod_free( &ml->sml_mod, 0 );
718 1.1 lukem free( ml );
719 1.1 lukem }
720 1.1 lukem
721 1.1 lukem op->o_callback = &roc->cb;
722 1.1 lukem
723 1.1 lukem return SLAP_CB_CONTINUE;
724 1.1 lukem }
725 1.1 lukem
726 1.1 lukem static int
727 1.1 lukem rwm_op_modrdn( Operation *op, SlapReply *rs )
728 1.1 lukem {
729 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
730 1.1 lukem struct ldaprwmap *rwmap =
731 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
732 1.1 lukem
733 1.1 lukem int rc;
734 1.1.1.2 lukem dncookie dc;
735 1.1 lukem
736 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
737 1.1 lukem
738 1.1 lukem if ( op->orr_newSup ) {
739 1.1 lukem struct berval nnewSup = BER_BVNULL;
740 1.1 lukem struct berval newSup = BER_BVNULL;
741 1.1 lukem
742 1.1 lukem /*
743 1.1 lukem * Rewrite the new superior, if defined and required
744 1.1 lukem */
745 1.1 lukem dc.rwmap = rwmap;
746 1.1 lukem dc.conn = op->o_conn;
747 1.1 lukem dc.rs = rs;
748 1.1 lukem dc.ctx = "newSuperiorDN";
749 1.1 lukem newSup = *op->orr_newSup;
750 1.1 lukem nnewSup = *op->orr_nnewSup;
751 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
752 1.1 lukem if ( rc != LDAP_SUCCESS ) {
753 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
754 1.1 lukem send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
755 1.1 lukem return -1;
756 1.1 lukem }
757 1.1 lukem
758 1.1 lukem if ( op->orr_newSup->bv_val != newSup.bv_val ) {
759 1.1 lukem op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
760 1.1 lukem op->o_tmpmemctx );
761 1.1 lukem op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
762 1.1 lukem op->o_tmpmemctx );
763 1.1 lukem *op->orr_newSup = newSup;
764 1.1 lukem *op->orr_nnewSup = nnewSup;
765 1.1 lukem }
766 1.1 lukem }
767 1.1 lukem
768 1.1 lukem /*
769 1.1.1.2 lukem * Rewrite the newRDN, if needed
770 1.1.1.2 lukem */
771 1.1.1.2 lukem {
772 1.1.1.2 lukem struct berval newrdn = BER_BVNULL;
773 1.1.1.2 lukem struct berval nnewrdn = BER_BVNULL;
774 1.1.1.2 lukem
775 1.1.1.2 lukem dc.rwmap = rwmap;
776 1.1.1.2 lukem dc.conn = op->o_conn;
777 1.1.1.2 lukem dc.rs = rs;
778 1.1.1.2 lukem dc.ctx = "newRDN";
779 1.1.1.2 lukem newrdn = op->orr_newrdn;
780 1.1.1.2 lukem nnewrdn = op->orr_nnewrdn;
781 1.1.1.2 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
782 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
783 1.1.1.2 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
784 1.1.1.2 lukem send_ldap_error( op, rs, rc, "newRDN massage error" );
785 1.1.1.2 lukem goto err;
786 1.1.1.2 lukem }
787 1.1.1.2 lukem
788 1.1.1.2 lukem if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
789 1.1.1.2 lukem op->orr_newrdn = newrdn;
790 1.1.1.2 lukem op->orr_nnewrdn = nnewrdn;
791 1.1.1.2 lukem }
792 1.1.1.2 lukem }
793 1.1.1.2 lukem
794 1.1.1.2 lukem /*
795 1.1 lukem * Rewrite the dn, if needed
796 1.1 lukem */
797 1.1 lukem rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
798 1.1 lukem if ( rc != LDAP_SUCCESS ) {
799 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
800 1.1 lukem send_ldap_error( op, rs, rc, "renameDN massage error" );
801 1.1.1.2 lukem goto err;
802 1.1.1.2 lukem }
803 1.1.1.2 lukem
804 1.1.1.2 lukem op->o_callback = &roc->cb;
805 1.1.1.2 lukem
806 1.1.1.2 lukem rc = SLAP_CB_CONTINUE;
807 1.1.1.2 lukem
808 1.1.1.2 lukem if ( 0 ) {
809 1.1.1.2 lukem err:;
810 1.1 lukem if ( op->orr_newSup != roc->ros.orr_newSup ) {
811 1.1 lukem ch_free( op->orr_newSup->bv_val );
812 1.1 lukem ch_free( op->orr_nnewSup->bv_val );
813 1.1 lukem op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
814 1.1 lukem op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
815 1.1 lukem op->orr_newSup = roc->ros.orr_newSup;
816 1.1 lukem op->orr_nnewSup = roc->ros.orr_nnewSup;
817 1.1 lukem }
818 1.1 lukem
819 1.1.1.2 lukem if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
820 1.1.1.2 lukem ch_free( op->orr_newrdn.bv_val );
821 1.1.1.2 lukem ch_free( op->orr_nnewrdn.bv_val );
822 1.1.1.2 lukem op->orr_newrdn = roc->ros.orr_newrdn;
823 1.1.1.2 lukem op->orr_nnewrdn = roc->ros.orr_nnewrdn;
824 1.1.1.2 lukem }
825 1.1.1.2 lukem }
826 1.1 lukem
827 1.1.1.2 lukem return rc;
828 1.1 lukem }
829 1.1 lukem
830 1.1 lukem
831 1.1 lukem static int
832 1.1 lukem rwm_swap_attrs( Operation *op, SlapReply *rs )
833 1.1 lukem {
834 1.1 lukem slap_callback *cb = op->o_callback;
835 1.1 lukem rwm_op_state *ros = cb->sc_private;
836 1.1 lukem
837 1.1 lukem rs->sr_attrs = ros->ors_attrs;
838 1.1 lukem
839 1.1 lukem /* other overlays might have touched op->ors_attrs,
840 1.1 lukem * so we restore the original version here, otherwise
841 1.1 lukem * attribute-mapping might fail */
842 1.1 lukem op->ors_attrs = ros->mapped_attrs;
843 1.1 lukem
844 1.1 lukem return SLAP_CB_CONTINUE;
845 1.1 lukem }
846 1.1 lukem
847 1.1.1.2 lukem /*
848 1.1.1.2 lukem * NOTE: this implementation of get/release entry is probably far from
849 1.1.1.2 lukem * optimal. The rationale consists in intercepting the request directed
850 1.1.1.2 lukem * to the underlying database, in order to rewrite/remap the request,
851 1.1.1.2 lukem * perform it using the modified data, duplicate the resulting entry
852 1.1.1.2 lukem * and finally free it when release is called.
853 1.1.1.2 lukem * This implies that subsequent overlays are not called, as the request
854 1.1.1.2 lukem * is directly shunted to the underlying database.
855 1.1.1.2 lukem */
856 1.1.1.2 lukem static int
857 1.1.1.2 lukem rwm_entry_release_rw( Operation *op, Entry *e, int rw )
858 1.1.1.2 lukem {
859 1.1.1.2 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
860 1.1.1.2 lukem
861 1.1.1.2 lukem /* can't be ours */
862 1.1.1.2 lukem if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
863 1.1.1.2 lukem return SLAP_CB_CONTINUE;
864 1.1.1.2 lukem }
865 1.1.1.2 lukem
866 1.1.1.2 lukem /* just free entry if (probably) ours */
867 1.1.1.2 lukem if ( e->e_private == NULL && BER_BVISNULL( &e->e_bv ) ) {
868 1.1.1.2 lukem entry_free( e );
869 1.1.1.2 lukem return LDAP_SUCCESS;
870 1.1.1.2 lukem }
871 1.1.1.2 lukem
872 1.1.1.2 lukem return SLAP_CB_CONTINUE;
873 1.1.1.2 lukem }
874 1.1.1.2 lukem
875 1.1.1.2 lukem static int
876 1.1.1.2 lukem rwm_entry_get_rw( Operation *op, struct berval *ndn,
877 1.1.1.2 lukem ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
878 1.1.1.2 lukem {
879 1.1.1.2 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
880 1.1.1.2 lukem int rc;
881 1.1.1.2 lukem BackendDB db;
882 1.1.1.2 lukem Operation op2;
883 1.1.1.2 lukem SlapReply rs = { REP_SEARCH };
884 1.1.1.2 lukem
885 1.1.1.2 lukem rwm_op_state ros = { 0 };
886 1.1.1.2 lukem struct berval mndn = BER_BVNULL;
887 1.1.1.2 lukem
888 1.1.1.2 lukem if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
889 1.1.1.2 lukem return SLAP_CB_CONTINUE;
890 1.1.1.2 lukem }
891 1.1.1.2 lukem
892 1.1.1.2 lukem /* massage DN */
893 1.1.1.2 lukem op2.o_tag = LDAP_REQ_SEARCH;
894 1.1.1.2 lukem op2 = *op;
895 1.1.1.2 lukem op2.o_req_dn = *ndn;
896 1.1.1.2 lukem op2.o_req_ndn = *ndn;
897 1.1.1.2 lukem rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
898 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
899 1.1.1.2 lukem return LDAP_OTHER;
900 1.1.1.2 lukem }
901 1.1.1.2 lukem
902 1.1.1.2 lukem mndn = BER_BVISNULL( &ros.r_ndn ) ? *ndn : ros.r_ndn;
903 1.1.1.2 lukem
904 1.1.1.2 lukem /* map attribute & objectClass */
905 1.1.1.2 lukem if ( at != NULL ) {
906 1.1.1.2 lukem }
907 1.1.1.2 lukem
908 1.1.1.2 lukem if ( oc != NULL ) {
909 1.1.1.2 lukem }
910 1.1.1.2 lukem
911 1.1.1.2 lukem /* fetch entry */
912 1.1.1.2 lukem db = *op->o_bd;
913 1.1.1.2 lukem op2.o_bd = &db;
914 1.1.1.2 lukem op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
915 1.1.1.2 lukem op2.ors_attrs = slap_anlist_all_attributes;
916 1.1.1.2 lukem rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &mndn, oc, at, rw, ep );
917 1.1.1.2 lukem if ( rc == LDAP_SUCCESS && *ep != NULL ) {
918 1.1.1.2 lukem /* we assume be_entry_release() needs to be called */
919 1.1.1.2 lukem rs.sr_flags = REP_ENTRY_MUSTRELEASE;
920 1.1.1.2 lukem rs.sr_entry = *ep;
921 1.1.1.2 lukem
922 1.1.1.2 lukem /* duplicate & release */
923 1.1.1.2 lukem op2.o_bd->bd_info = (BackendInfo *)on;
924 1.1.1.2 lukem rc = rwm_send_entry( &op2, &rs );
925 1.1.1.4 tron RS_ASSERT( rs.sr_flags & REP_ENTRY_MUSTFLUSH );
926 1.1.1.2 lukem if ( rc == SLAP_CB_CONTINUE ) {
927 1.1.1.2 lukem *ep = rs.sr_entry;
928 1.1.1.2 lukem rc = LDAP_SUCCESS;
929 1.1.1.4 tron } else {
930 1.1.1.4 tron assert( rc != LDAP_SUCCESS && rs.sr_entry == *ep );
931 1.1.1.4 tron *ep = NULL;
932 1.1.1.4 tron op2.o_bd->bd_info = (BackendInfo *)on->on_info;
933 1.1.1.4 tron be_entry_release_r( &op2, rs.sr_entry );
934 1.1.1.4 tron op2.o_bd->bd_info = (BackendInfo *)on;
935 1.1.1.2 lukem }
936 1.1.1.2 lukem }
937 1.1.1.2 lukem
938 1.1.1.2 lukem if ( !BER_BVISNULL( &ros.r_ndn) && ros.r_ndn.bv_val != ndn->bv_val ) {
939 1.1.1.2 lukem op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
940 1.1.1.2 lukem }
941 1.1.1.2 lukem
942 1.1.1.2 lukem return rc;
943 1.1.1.2 lukem }
944 1.1.1.2 lukem
945 1.1 lukem static int
946 1.1 lukem rwm_op_search( Operation *op, SlapReply *rs )
947 1.1 lukem {
948 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
949 1.1 lukem struct ldaprwmap *rwmap =
950 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
951 1.1 lukem
952 1.1 lukem int rc;
953 1.1 lukem dncookie dc;
954 1.1 lukem
955 1.1 lukem struct berval fstr = BER_BVNULL;
956 1.1 lukem Filter *f = NULL;
957 1.1 lukem
958 1.1 lukem AttributeName *an = NULL;
959 1.1 lukem
960 1.1 lukem char *text = NULL;
961 1.1 lukem
962 1.1.1.4 tron rwm_op_cb *roc = rwm_callback_get( op );
963 1.1 lukem
964 1.1 lukem rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
965 1.1 lukem "searchFilter", op->ors_filterstr.bv_val );
966 1.1 lukem if ( rc == LDAP_SUCCESS )
967 1.1 lukem rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
968 1.1 lukem if ( rc != LDAP_SUCCESS ) {
969 1.1 lukem text = "searchDN massage error";
970 1.1 lukem goto error_return;
971 1.1 lukem }
972 1.1 lukem
973 1.1 lukem /*
974 1.1 lukem * Rewrite the dn if needed
975 1.1 lukem */
976 1.1 lukem dc.rwmap = rwmap;
977 1.1 lukem dc.conn = op->o_conn;
978 1.1 lukem dc.rs = rs;
979 1.1 lukem dc.ctx = "searchFilterAttrDN";
980 1.1 lukem
981 1.1 lukem rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
982 1.1 lukem if ( rc != LDAP_SUCCESS ) {
983 1.1 lukem text = "searchFilter/searchFilterAttrDN massage error";
984 1.1 lukem goto error_return;
985 1.1 lukem }
986 1.1 lukem
987 1.1 lukem f = str2filter_x( op, fstr.bv_val );
988 1.1 lukem
989 1.1 lukem if ( f == NULL ) {
990 1.1 lukem text = "massaged filter parse error";
991 1.1 lukem goto error_return;
992 1.1 lukem }
993 1.1 lukem
994 1.1 lukem op->ors_filter = f;
995 1.1 lukem op->ors_filterstr = fstr;
996 1.1 lukem
997 1.1.1.3 adam rc = rwm_map_attrnames( op, &rwmap->rwm_at, &rwmap->rwm_oc,
998 1.1 lukem op->ors_attrs, &an, RWM_MAP );
999 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1000 1.1 lukem text = "attribute list mapping error";
1001 1.1 lukem goto error_return;
1002 1.1 lukem }
1003 1.1 lukem
1004 1.1 lukem op->ors_attrs = an;
1005 1.1 lukem /* store the mapped Attributes for later usage, in
1006 1.1 lukem * the case that other overlays change op->ors_attrs */
1007 1.1 lukem roc->ros.mapped_attrs = an;
1008 1.1 lukem roc->cb.sc_response = rwm_swap_attrs;
1009 1.1 lukem
1010 1.1 lukem op->o_callback = &roc->cb;
1011 1.1 lukem
1012 1.1 lukem return SLAP_CB_CONTINUE;
1013 1.1 lukem
1014 1.1 lukem error_return:;
1015 1.1 lukem if ( an != NULL ) {
1016 1.1 lukem ch_free( an );
1017 1.1 lukem }
1018 1.1 lukem
1019 1.1 lukem if ( f != NULL ) {
1020 1.1.1.2 lukem filter_free_x( op, f, 1 );
1021 1.1 lukem }
1022 1.1 lukem
1023 1.1 lukem if ( !BER_BVISNULL( &fstr ) ) {
1024 1.1.1.3 adam op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1025 1.1 lukem }
1026 1.1 lukem
1027 1.1.1.2 lukem rwm_op_rollback( op, rs, &roc->ros );
1028 1.1 lukem op->oq_search = roc->ros.oq_search;
1029 1.1.1.2 lukem op->o_tmpfree( roc, op->o_tmpmemctx );
1030 1.1 lukem
1031 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1032 1.1 lukem send_ldap_error( op, rs, rc, text );
1033 1.1 lukem
1034 1.1 lukem return -1;
1035 1.1 lukem
1036 1.1 lukem }
1037 1.1 lukem
1038 1.1 lukem static int
1039 1.1 lukem rwm_exop_passwd( Operation *op, SlapReply *rs )
1040 1.1 lukem {
1041 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1042 1.1 lukem int rc;
1043 1.1 lukem rwm_op_cb *roc;
1044 1.1 lukem
1045 1.1 lukem struct berval id = BER_BVNULL,
1046 1.1 lukem pwold = BER_BVNULL,
1047 1.1 lukem pwnew = BER_BVNULL;
1048 1.1 lukem BerElement *ber = NULL;
1049 1.1 lukem
1050 1.1 lukem if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
1051 1.1 lukem return LDAP_SUCCESS;
1052 1.1 lukem }
1053 1.1 lukem
1054 1.1 lukem if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
1055 1.1 lukem rs->sr_err = LDAP_OTHER;
1056 1.1 lukem return rs->sr_err;
1057 1.1 lukem }
1058 1.1 lukem
1059 1.1 lukem rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
1060 1.1 lukem &pwold, &pwnew, &rs->sr_text );
1061 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
1062 1.1 lukem return rs->sr_err;
1063 1.1 lukem }
1064 1.1 lukem
1065 1.1 lukem if ( !BER_BVISNULL( &id ) ) {
1066 1.1 lukem char idNul = id.bv_val[id.bv_len];
1067 1.1 lukem id.bv_val[id.bv_len] = '\0';
1068 1.1 lukem rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
1069 1.1 lukem &op->o_req_ndn, op->o_tmpmemctx );
1070 1.1 lukem id.bv_val[id.bv_len] = idNul;
1071 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
1072 1.1 lukem rs->sr_text = "Invalid DN";
1073 1.1 lukem return rs->sr_err;
1074 1.1 lukem }
1075 1.1 lukem
1076 1.1 lukem } else {
1077 1.1 lukem ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
1078 1.1 lukem ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
1079 1.1 lukem }
1080 1.1 lukem
1081 1.1.1.4 tron roc = rwm_callback_get( op );
1082 1.1 lukem
1083 1.1 lukem rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1084 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1085 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1086 1.1 lukem send_ldap_error( op, rs, rc, "extendedDN massage error" );
1087 1.1 lukem return -1;
1088 1.1 lukem }
1089 1.1 lukem
1090 1.1 lukem ber = ber_alloc_t( LBER_USE_DER );
1091 1.1 lukem if ( !ber ) {
1092 1.1 lukem rs->sr_err = LDAP_OTHER;
1093 1.1 lukem rs->sr_text = "No memory";
1094 1.1 lukem return rs->sr_err;
1095 1.1 lukem }
1096 1.1 lukem ber_printf( ber, "{" );
1097 1.1 lukem if ( !BER_BVISNULL( &id )) {
1098 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
1099 1.1 lukem &op->o_req_dn );
1100 1.1 lukem }
1101 1.1 lukem if ( !BER_BVISNULL( &pwold )) {
1102 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
1103 1.1 lukem }
1104 1.1 lukem if ( !BER_BVISNULL( &pwnew )) {
1105 1.1 lukem ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
1106 1.1 lukem }
1107 1.1 lukem ber_printf( ber, "N}" );
1108 1.1 lukem ber_flatten( ber, &op->ore_reqdata );
1109 1.1 lukem ber_free( ber, 1 );
1110 1.1 lukem
1111 1.1 lukem op->o_callback = &roc->cb;
1112 1.1 lukem
1113 1.1 lukem return SLAP_CB_CONTINUE;
1114 1.1 lukem }
1115 1.1 lukem
1116 1.1 lukem static struct exop {
1117 1.1 lukem struct berval oid;
1118 1.1 lukem BI_op_extended *extended;
1119 1.1 lukem } exop_table[] = {
1120 1.1 lukem { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
1121 1.1 lukem { BER_BVNULL, NULL }
1122 1.1 lukem };
1123 1.1 lukem
1124 1.1 lukem static int
1125 1.1 lukem rwm_extended( Operation *op, SlapReply *rs )
1126 1.1 lukem {
1127 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1128 1.1 lukem int rc;
1129 1.1 lukem rwm_op_cb *roc;
1130 1.1 lukem
1131 1.1 lukem int i;
1132 1.1 lukem
1133 1.1 lukem for ( i = 0; exop_table[i].extended != NULL; i++ ) {
1134 1.1 lukem if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
1135 1.1 lukem {
1136 1.1 lukem rc = exop_table[i].extended( op, rs );
1137 1.1 lukem switch ( rc ) {
1138 1.1 lukem case LDAP_SUCCESS:
1139 1.1 lukem break;
1140 1.1 lukem
1141 1.1 lukem case SLAP_CB_CONTINUE:
1142 1.1 lukem case SLAPD_ABANDON:
1143 1.1 lukem return rc;
1144 1.1 lukem
1145 1.1 lukem default:
1146 1.1 lukem send_ldap_result( op, rs );
1147 1.1 lukem return rc;
1148 1.1 lukem }
1149 1.1 lukem break;
1150 1.1 lukem }
1151 1.1 lukem }
1152 1.1 lukem
1153 1.1.1.4 tron roc = rwm_callback_get( op );
1154 1.1 lukem
1155 1.1 lukem rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1156 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1157 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1158 1.1 lukem send_ldap_error( op, rs, rc, "extendedDN massage error" );
1159 1.1 lukem return -1;
1160 1.1 lukem }
1161 1.1 lukem
1162 1.1 lukem /* TODO: rewrite/map extended data ? ... */
1163 1.1 lukem op->o_callback = &roc->cb;
1164 1.1 lukem
1165 1.1 lukem return SLAP_CB_CONTINUE;
1166 1.1 lukem }
1167 1.1 lukem
1168 1.1.1.4 tron static void
1169 1.1 lukem rwm_matched( Operation *op, SlapReply *rs )
1170 1.1 lukem {
1171 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1172 1.1 lukem struct ldaprwmap *rwmap =
1173 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1174 1.1 lukem
1175 1.1 lukem struct berval dn, mdn;
1176 1.1 lukem dncookie dc;
1177 1.1 lukem int rc;
1178 1.1 lukem
1179 1.1 lukem if ( rs->sr_matched == NULL ) {
1180 1.1.1.4 tron return;
1181 1.1 lukem }
1182 1.1 lukem
1183 1.1 lukem dc.rwmap = rwmap;
1184 1.1 lukem dc.conn = op->o_conn;
1185 1.1 lukem dc.rs = rs;
1186 1.1 lukem dc.ctx = "matchedDN";
1187 1.1 lukem ber_str2bv( rs->sr_matched, 0, 0, &dn );
1188 1.1 lukem mdn = dn;
1189 1.1 lukem rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
1190 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1191 1.1 lukem rs->sr_err = rc;
1192 1.1 lukem rs->sr_text = "Rewrite error";
1193 1.1 lukem
1194 1.1.1.4 tron } else if ( mdn.bv_val != dn.bv_val ) {
1195 1.1 lukem if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
1196 1.1 lukem ch_free( (void *)rs->sr_matched );
1197 1.1 lukem
1198 1.1 lukem } else {
1199 1.1 lukem rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
1200 1.1 lukem }
1201 1.1 lukem rs->sr_matched = mdn.bv_val;
1202 1.1 lukem }
1203 1.1 lukem }
1204 1.1 lukem
1205 1.1 lukem static int
1206 1.1 lukem rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
1207 1.1 lukem {
1208 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1209 1.1 lukem struct ldaprwmap *rwmap =
1210 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1211 1.1 lukem
1212 1.1 lukem dncookie dc;
1213 1.1 lukem int rc;
1214 1.1 lukem Attribute **ap;
1215 1.1 lukem int isupdate;
1216 1.1 lukem int check_duplicate_attrs = 0;
1217 1.1 lukem
1218 1.1 lukem /*
1219 1.1 lukem * Rewrite the dn attrs, if needed
1220 1.1 lukem */
1221 1.1 lukem dc.rwmap = rwmap;
1222 1.1 lukem dc.conn = op->o_conn;
1223 1.1 lukem dc.rs = NULL;
1224 1.1 lukem
1225 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1226 1.1 lukem * so we need to select those attributes we are willing
1227 1.1 lukem * to return, and remap them accordingly */
1228 1.1 lukem
1229 1.1 lukem /* FIXME: in principle, one could map an attribute
1230 1.1 lukem * on top of another, which already exists.
1231 1.1 lukem * As such, in the end there might exist more than
1232 1.1 lukem * one instance of an attribute.
1233 1.1 lukem * We should at least check if this occurs, and issue
1234 1.1 lukem * an error (because multiple instances of attrs in
1235 1.1 lukem * response are not valid), or merge the values (what
1236 1.1 lukem * about duplicate values?) */
1237 1.1 lukem isupdate = be_shadow_update( op );
1238 1.1 lukem for ( ap = a_first; *ap; ) {
1239 1.1 lukem struct ldapmapping *mapping = NULL;
1240 1.1 lukem int drop_missing;
1241 1.1 lukem int last = -1;
1242 1.1 lukem Attribute *a;
1243 1.1 lukem
1244 1.1.1.2 lukem if ( ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS ) &&
1245 1.1.1.2 lukem op->ors_attrs != NULL &&
1246 1.1.1.2 lukem !SLAP_USERATTRS( rs->sr_attr_flags ) &&
1247 1.1.1.2 lukem !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
1248 1.1 lukem {
1249 1.1.1.2 lukem goto cleanup_attr;
1250 1.1.1.2 lukem }
1251 1.1 lukem
1252 1.1.1.2 lukem drop_missing = rwm_mapping( &rwmap->rwm_at,
1253 1.1.1.2 lukem &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
1254 1.1.1.2 lukem if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
1255 1.1.1.2 lukem {
1256 1.1.1.2 lukem goto cleanup_attr;
1257 1.1.1.2 lukem }
1258 1.1.1.2 lukem if ( mapping != NULL ) {
1259 1.1.1.2 lukem assert( mapping->m_dst_ad != NULL );
1260 1.1 lukem
1261 1.1.1.2 lukem /* try to normalize mapped Attributes if the original
1262 1.1.1.2 lukem * AttributeType was not normalized */
1263 1.1.1.2 lukem if ( (!(*ap)->a_desc->ad_type->sat_equality ||
1264 1.1.1.2 lukem !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
1265 1.1.1.2 lukem mapping->m_dst_ad->ad_type->sat_equality &&
1266 1.1.1.2 lukem mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
1267 1.1.1.2 lukem {
1268 1.1.1.2 lukem if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS))
1269 1.1 lukem {
1270 1.1 lukem int i = 0;
1271 1.1 lukem
1272 1.1 lukem last = (*ap)->a_numvals;
1273 1.1 lukem if ( last )
1274 1.1 lukem {
1275 1.1 lukem (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
1276 1.1 lukem
1277 1.1 lukem for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
1278 1.1 lukem int rc;
1279 1.1 lukem /*
1280 1.1 lukem * check that each value is valid per syntax
1281 1.1 lukem * and pretty if appropriate
1282 1.1 lukem */
1283 1.1 lukem rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
1284 1.1 lukem SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
1285 1.1 lukem mapping->m_dst_ad->ad_type->sat_syntax,
1286 1.1 lukem mapping->m_dst_ad->ad_type->sat_equality,
1287 1.1 lukem &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
1288 1.1 lukem NULL );
1289 1.1 lukem
1290 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1291 1.1.1.4 tron /* FIXME: this is wrong, putting a non-normalized value
1292 1.1.1.4 tron * into nvals. But when a proxy sends us bogus data,
1293 1.1.1.4 tron * we still need to give it to the client, even if it
1294 1.1.1.4 tron * violates the syntax. I.e., we don't want to silently
1295 1.1.1.4 tron * drop things and trigger an apparent data loss.
1296 1.1.1.4 tron */
1297 1.1.1.4 tron ber_dupbv( &(*ap)->a_nvals[i], &(*ap)->a_vals[i] );
1298 1.1 lukem }
1299 1.1 lukem }
1300 1.1 lukem BER_BVZERO( &(*ap)->a_nvals[i] );
1301 1.1 lukem }
1302 1.1.1.2 lukem
1303 1.1.1.2 lukem } else {
1304 1.1.1.2 lukem assert( (*ap)->a_nvals == (*ap)->a_vals );
1305 1.1.1.2 lukem (*ap)->a_nvals = NULL;
1306 1.1.1.2 lukem ber_bvarray_dup_x( &(*ap)->a_nvals, (*ap)->a_vals, NULL );
1307 1.1 lukem }
1308 1.1.1.2 lukem }
1309 1.1 lukem
1310 1.1.1.2 lukem /* rewrite the attribute description */
1311 1.1.1.2 lukem (*ap)->a_desc = mapping->m_dst_ad;
1312 1.1 lukem
1313 1.1.1.2 lukem /* will need to check for duplicate attrs */
1314 1.1.1.2 lukem check_duplicate_attrs++;
1315 1.1 lukem }
1316 1.1 lukem
1317 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
1318 1.1 lukem if ( stripEntryDN ) {
1319 1.1 lukem /* will be generated by frontend */
1320 1.1 lukem goto cleanup_attr;
1321 1.1 lukem }
1322 1.1 lukem
1323 1.1 lukem } else if ( !isupdate
1324 1.1 lukem && !get_relax( op )
1325 1.1 lukem && (*ap)->a_desc->ad_type->sat_no_user_mod
1326 1.1 lukem && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
1327 1.1 lukem {
1328 1.1 lukem goto next_attr;
1329 1.1 lukem }
1330 1.1 lukem
1331 1.1 lukem if ( last == -1 ) { /* not yet counted */
1332 1.1 lukem last = (*ap)->a_numvals;
1333 1.1 lukem }
1334 1.1 lukem
1335 1.1 lukem if ( last == 0 ) {
1336 1.1 lukem /* empty? leave it in place because of attrsonly and vlv */
1337 1.1 lukem goto next_attr;
1338 1.1 lukem }
1339 1.1 lukem last--;
1340 1.1 lukem
1341 1.1 lukem if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
1342 1.1 lukem || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
1343 1.1 lukem {
1344 1.1 lukem struct berval *bv;
1345 1.1 lukem
1346 1.1 lukem for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1347 1.1 lukem struct berval mapped;
1348 1.1 lukem
1349 1.1 lukem rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
1350 1.1 lukem if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
1351 1.1 lukem remove_oc:;
1352 1.1 lukem ch_free( bv[0].bv_val );
1353 1.1 lukem BER_BVZERO( &bv[0] );
1354 1.1 lukem if ( &(*ap)->a_vals[last] > &bv[0] ) {
1355 1.1 lukem bv[0] = (*ap)->a_vals[last];
1356 1.1 lukem BER_BVZERO( &(*ap)->a_vals[last] );
1357 1.1 lukem }
1358 1.1 lukem last--;
1359 1.1 lukem bv--;
1360 1.1 lukem
1361 1.1.1.2 lukem } else if ( mapped.bv_val != bv[0].bv_val
1362 1.1.1.2 lukem && ber_bvstrcasecmp( &mapped, &bv[0] ) != 0 )
1363 1.1.1.2 lukem {
1364 1.1 lukem int i;
1365 1.1 lukem
1366 1.1 lukem for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
1367 1.1 lukem if ( &(*ap)->a_vals[ i ] == bv ) {
1368 1.1 lukem continue;
1369 1.1 lukem }
1370 1.1 lukem
1371 1.1 lukem if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
1372 1.1 lukem break;
1373 1.1 lukem }
1374 1.1 lukem }
1375 1.1 lukem
1376 1.1 lukem if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
1377 1.1 lukem goto remove_oc;
1378 1.1 lukem }
1379 1.1 lukem
1380 1.1 lukem /*
1381 1.1 lukem * FIXME: after LBER_FREEing
1382 1.1 lukem * the value is replaced by
1383 1.1 lukem * ch_alloc'ed memory
1384 1.1 lukem */
1385 1.1 lukem ber_bvreplace( &bv[0], &mapped );
1386 1.1 lukem
1387 1.1 lukem /* FIXME: will need to check
1388 1.1 lukem * if the structuralObjectClass
1389 1.1 lukem * changed */
1390 1.1 lukem }
1391 1.1 lukem }
1392 1.1 lukem
1393 1.1 lukem /*
1394 1.1 lukem * It is necessary to try to rewrite attributes with
1395 1.1 lukem * dn syntax because they might be used in ACLs as
1396 1.1 lukem * members of groups; since ACLs are applied to the
1397 1.1 lukem * rewritten stuff, no dn-based subject clause could
1398 1.1 lukem * be used at the ldap backend side (see
1399 1.1 lukem * http://www.OpenLDAP.org/faq/data/cache/452.html)
1400 1.1 lukem * The problem can be overcome by moving the dn-based
1401 1.1 lukem * ACLs to the target directory server, and letting
1402 1.1 lukem * everything pass thru the ldap backend. */
1403 1.1 lukem /* FIXME: handle distinguishedName-like syntaxes, like
1404 1.1 lukem * nameAndOptionalUID */
1405 1.1 lukem } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
1406 1.1 lukem || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
1407 1.1 lukem {
1408 1.1 lukem dc.ctx = "searchAttrDN";
1409 1.1.1.2 lukem rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals, (*ap)->a_nvals );
1410 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1411 1.1 lukem goto cleanup_attr;
1412 1.1 lukem }
1413 1.1 lukem
1414 1.1 lukem } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
1415 1.1 lukem dc.ctx = "searchAttrDN";
1416 1.1 lukem rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
1417 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1418 1.1 lukem goto cleanup_attr;
1419 1.1 lukem }
1420 1.1 lukem }
1421 1.1 lukem
1422 1.1 lukem
1423 1.1 lukem next_attr:;
1424 1.1 lukem ap = &(*ap)->a_next;
1425 1.1 lukem continue;
1426 1.1 lukem
1427 1.1 lukem cleanup_attr:;
1428 1.1 lukem a = *ap;
1429 1.1 lukem *ap = (*ap)->a_next;
1430 1.1 lukem
1431 1.1 lukem attr_free( a );
1432 1.1 lukem }
1433 1.1 lukem
1434 1.1 lukem /* only check if some mapping occurred */
1435 1.1 lukem if ( check_duplicate_attrs ) {
1436 1.1 lukem for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
1437 1.1 lukem Attribute **tap;
1438 1.1 lukem
1439 1.1 lukem for ( tap = &(*ap)->a_next; *tap != NULL; ) {
1440 1.1 lukem if ( (*tap)->a_desc == (*ap)->a_desc ) {
1441 1.1 lukem Entry e = { 0 };
1442 1.1 lukem Modification mod = { 0 };
1443 1.1 lukem const char *text = NULL;
1444 1.1 lukem char textbuf[ SLAP_TEXT_BUFLEN ];
1445 1.1 lukem Attribute *next = (*tap)->a_next;
1446 1.1 lukem
1447 1.1 lukem BER_BVSTR( &e.e_name, "" );
1448 1.1 lukem BER_BVSTR( &e.e_nname, "" );
1449 1.1 lukem e.e_attrs = *ap;
1450 1.1 lukem mod.sm_op = LDAP_MOD_ADD;
1451 1.1 lukem mod.sm_desc = (*ap)->a_desc;
1452 1.1 lukem mod.sm_type = mod.sm_desc->ad_cname;
1453 1.1 lukem mod.sm_numvals = (*tap)->a_numvals;
1454 1.1 lukem mod.sm_values = (*tap)->a_vals;
1455 1.1 lukem if ( (*tap)->a_nvals != (*tap)->a_vals ) {
1456 1.1 lukem mod.sm_nvalues = (*tap)->a_nvals;
1457 1.1 lukem }
1458 1.1 lukem
1459 1.1 lukem (void)modify_add_values( &e, &mod,
1460 1.1 lukem /* permissive */ 1,
1461 1.1 lukem &text, textbuf, sizeof( textbuf ) );
1462 1.1 lukem
1463 1.1 lukem /* should not insert new attrs! */
1464 1.1 lukem assert( e.e_attrs == *ap );
1465 1.1 lukem
1466 1.1 lukem attr_free( *tap );
1467 1.1 lukem *tap = next;
1468 1.1 lukem
1469 1.1 lukem } else {
1470 1.1 lukem tap = &(*tap)->a_next;
1471 1.1 lukem }
1472 1.1 lukem }
1473 1.1 lukem }
1474 1.1 lukem }
1475 1.1 lukem
1476 1.1 lukem return 0;
1477 1.1 lukem }
1478 1.1 lukem
1479 1.1.1.4 tron /* Should return SLAP_CB_CONTINUE or failure, never LDAP_SUCCESS. */
1480 1.1 lukem static int
1481 1.1 lukem rwm_send_entry( Operation *op, SlapReply *rs )
1482 1.1 lukem {
1483 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1484 1.1 lukem struct ldaprwmap *rwmap =
1485 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1486 1.1 lukem
1487 1.1 lukem Entry *e = NULL;
1488 1.1 lukem struct berval dn = BER_BVNULL,
1489 1.1 lukem ndn = BER_BVNULL;
1490 1.1 lukem dncookie dc;
1491 1.1 lukem int rc;
1492 1.1 lukem
1493 1.1 lukem assert( rs->sr_entry != NULL );
1494 1.1 lukem
1495 1.1 lukem /*
1496 1.1 lukem * Rewrite the dn of the result, if needed
1497 1.1 lukem */
1498 1.1 lukem dc.rwmap = rwmap;
1499 1.1 lukem dc.conn = op->o_conn;
1500 1.1 lukem dc.rs = NULL;
1501 1.1 lukem dc.ctx = "searchEntryDN";
1502 1.1 lukem
1503 1.1 lukem e = rs->sr_entry;
1504 1.1 lukem if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
1505 1.1 lukem /* FIXME: all we need to duplicate are:
1506 1.1 lukem * - dn
1507 1.1 lukem * - ndn
1508 1.1 lukem * - attributes that are requested
1509 1.1 lukem * - no values if attrsonly is set
1510 1.1 lukem */
1511 1.1 lukem e = entry_dup( e );
1512 1.1 lukem if ( e == NULL ) {
1513 1.1 lukem rc = LDAP_NO_MEMORY;
1514 1.1 lukem goto fail;
1515 1.1 lukem }
1516 1.1.1.4 tron } else if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1517 1.1.1.4 tron /* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible
1518 1.1.1.4 tron * with REP_ENTRY_MODIFIABLE */
1519 1.1.1.4 tron RS_ASSERT( 0 );
1520 1.1.1.4 tron rc = 1;
1521 1.1.1.4 tron goto fail;
1522 1.1 lukem }
1523 1.1 lukem
1524 1.1 lukem /*
1525 1.1 lukem * Note: this may fail if the target host(s) schema differs
1526 1.1 lukem * from the one known to the meta, and a DN with unknown
1527 1.1 lukem * attributes is returned.
1528 1.1 lukem */
1529 1.1 lukem dn = e->e_name;
1530 1.1 lukem ndn = e->e_nname;
1531 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1532 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1533 1.1 lukem rc = 1;
1534 1.1 lukem goto fail;
1535 1.1 lukem }
1536 1.1 lukem
1537 1.1 lukem if ( e->e_name.bv_val != dn.bv_val ) {
1538 1.1 lukem ch_free( e->e_name.bv_val );
1539 1.1 lukem ch_free( e->e_nname.bv_val );
1540 1.1 lukem
1541 1.1 lukem e->e_name = dn;
1542 1.1 lukem e->e_nname = ndn;
1543 1.1 lukem }
1544 1.1 lukem
1545 1.1 lukem /* TODO: map entry attribute types, objectclasses
1546 1.1 lukem * and dn-valued attribute values */
1547 1.1 lukem
1548 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1549 1.1 lukem * so we need to select those attributes we are willing
1550 1.1 lukem * to return, and remap them accordingly */
1551 1.1 lukem (void)rwm_attrs( op, rs, &e->e_attrs, 1 );
1552 1.1 lukem
1553 1.1.1.4 tron if ( e != rs->sr_entry ) {
1554 1.1.1.4 tron /* Reimplementing rs_replace_entry(), I suppose to
1555 1.1.1.4 tron * bypass our own dubious rwm_entry_release_rw() */
1556 1.1.1.4 tron if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1557 1.1.1.4 tron rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
1558 1.1.1.4 tron op->o_bd->bd_info = (BackendInfo *)on->on_info;
1559 1.1.1.4 tron be_entry_release_r( op, rs->sr_entry );
1560 1.1.1.4 tron op->o_bd->bd_info = (BackendInfo *)on;
1561 1.1.1.4 tron } else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
1562 1.1.1.4 tron entry_free( rs->sr_entry );
1563 1.1.1.3 adam }
1564 1.1.1.4 tron rs->sr_entry = e;
1565 1.1.1.4 tron rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
1566 1.1 lukem }
1567 1.1 lukem
1568 1.1 lukem return SLAP_CB_CONTINUE;
1569 1.1 lukem
1570 1.1 lukem fail:;
1571 1.1 lukem if ( e != NULL && e != rs->sr_entry ) {
1572 1.1 lukem if ( e->e_name.bv_val == dn.bv_val ) {
1573 1.1 lukem BER_BVZERO( &e->e_name );
1574 1.1 lukem }
1575 1.1 lukem
1576 1.1 lukem if ( e->e_nname.bv_val == ndn.bv_val ) {
1577 1.1 lukem BER_BVZERO( &e->e_nname );
1578 1.1 lukem }
1579 1.1 lukem
1580 1.1 lukem entry_free( e );
1581 1.1 lukem }
1582 1.1 lukem
1583 1.1 lukem if ( !BER_BVISNULL( &dn ) ) {
1584 1.1 lukem ch_free( dn.bv_val );
1585 1.1 lukem }
1586 1.1 lukem
1587 1.1 lukem if ( !BER_BVISNULL( &ndn ) ) {
1588 1.1 lukem ch_free( ndn.bv_val );
1589 1.1 lukem }
1590 1.1 lukem
1591 1.1 lukem return rc;
1592 1.1 lukem }
1593 1.1 lukem
1594 1.1 lukem static int
1595 1.1 lukem rwm_operational( Operation *op, SlapReply *rs )
1596 1.1 lukem {
1597 1.1 lukem /* FIXME: the entries are in the remote mapping form;
1598 1.1 lukem * so we need to select those attributes we are willing
1599 1.1 lukem * to return, and remap them accordingly */
1600 1.1 lukem if ( rs->sr_operational_attrs ) {
1601 1.1 lukem rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
1602 1.1 lukem }
1603 1.1 lukem
1604 1.1 lukem return SLAP_CB_CONTINUE;
1605 1.1 lukem }
1606 1.1 lukem
1607 1.1 lukem #if 0
1608 1.1 lukem /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1609 1.1 lukem * rewritten for subsequent operations; fine for plain suffixmassage,
1610 1.1 lukem * but destroys everything else */
1611 1.1 lukem static int
1612 1.1 lukem rwm_chk_referrals( Operation *op, SlapReply *rs )
1613 1.1 lukem {
1614 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1615 1.1 lukem int rc;
1616 1.1 lukem
1617 1.1 lukem rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1618 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1619 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on->on_info;
1620 1.1 lukem send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1621 1.1 lukem return -1;
1622 1.1 lukem }
1623 1.1 lukem
1624 1.1 lukem return SLAP_CB_CONTINUE;
1625 1.1 lukem }
1626 1.1 lukem #endif
1627 1.1 lukem
1628 1.1 lukem static int
1629 1.1 lukem rwm_rw_config(
1630 1.1 lukem BackendDB *be,
1631 1.1 lukem const char *fname,
1632 1.1 lukem int lineno,
1633 1.1 lukem int argc,
1634 1.1 lukem char **argv )
1635 1.1 lukem {
1636 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1637 1.1 lukem struct ldaprwmap *rwmap =
1638 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1639 1.1 lukem
1640 1.1 lukem return rewrite_parse( rwmap->rwm_rw,
1641 1.1 lukem fname, lineno, argc, argv );
1642 1.1 lukem
1643 1.1 lukem return 0;
1644 1.1 lukem }
1645 1.1 lukem
1646 1.1 lukem static int
1647 1.1 lukem rwm_suffixmassage_config(
1648 1.1 lukem BackendDB *be,
1649 1.1 lukem const char *fname,
1650 1.1 lukem int lineno,
1651 1.1 lukem int argc,
1652 1.1 lukem char **argv )
1653 1.1 lukem {
1654 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1655 1.1 lukem struct ldaprwmap *rwmap =
1656 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1657 1.1 lukem
1658 1.1 lukem struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1659 1.1 lukem int massaged;
1660 1.1 lukem int rc;
1661 1.1 lukem
1662 1.1 lukem /*
1663 1.1 lukem * syntax:
1664 1.1 lukem *
1665 1.1 lukem * suffixmassage [<suffix>] <massaged suffix>
1666 1.1 lukem *
1667 1.1 lukem * the [<suffix>] field must be defined as a valid suffix
1668 1.1 lukem * for the current database;
1669 1.1 lukem * the <massaged suffix> shouldn't have already been
1670 1.1 lukem * defined as a valid suffix for the current server
1671 1.1 lukem */
1672 1.1 lukem if ( argc == 2 ) {
1673 1.1 lukem if ( be->be_suffix == NULL ) {
1674 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1675 1.1 lukem " \"suffixMassage [<suffix>]"
1676 1.1 lukem " <massaged suffix>\" without "
1677 1.1 lukem "<suffix> part requires database "
1678 1.1 lukem "suffix be defined first.\n",
1679 1.1.1.3 adam fname, lineno, 0 );
1680 1.1 lukem return 1;
1681 1.1 lukem }
1682 1.1 lukem bvnc = be->be_suffix[ 0 ];
1683 1.1 lukem massaged = 1;
1684 1.1 lukem
1685 1.1 lukem } else if ( argc == 3 ) {
1686 1.1 lukem ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1687 1.1 lukem massaged = 2;
1688 1.1 lukem
1689 1.1 lukem } else {
1690 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is"
1691 1.1 lukem " \"suffixMassage [<suffix>]"
1692 1.1 lukem " <massaged suffix>\"\n",
1693 1.1.1.3 adam fname, lineno, 0 );
1694 1.1 lukem return 1;
1695 1.1 lukem }
1696 1.1 lukem
1697 1.1 lukem if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1698 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1699 1.1 lukem fname, lineno, bvnc.bv_val );
1700 1.1 lukem return 1;
1701 1.1 lukem }
1702 1.1 lukem
1703 1.1 lukem ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1704 1.1 lukem if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1705 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1706 1.1 lukem fname, lineno, brnc.bv_val );
1707 1.1 lukem free( nvnc.bv_val );
1708 1.1 lukem free( pvnc.bv_val );
1709 1.1 lukem return 1;
1710 1.1 lukem }
1711 1.1 lukem
1712 1.1 lukem /*
1713 1.1 lukem * The suffix massaging is emulated
1714 1.1 lukem * by means of the rewrite capabilities
1715 1.1 lukem */
1716 1.1 lukem rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1717 1.1 lukem &pvnc, &nvnc, &prnc, &nrnc );
1718 1.1 lukem free( nvnc.bv_val );
1719 1.1 lukem free( pvnc.bv_val );
1720 1.1 lukem free( nrnc.bv_val );
1721 1.1 lukem free( prnc.bv_val );
1722 1.1 lukem
1723 1.1 lukem return rc;
1724 1.1 lukem }
1725 1.1 lukem
1726 1.1 lukem static int
1727 1.1 lukem rwm_m_config(
1728 1.1 lukem BackendDB *be,
1729 1.1 lukem const char *fname,
1730 1.1 lukem int lineno,
1731 1.1 lukem int argc,
1732 1.1 lukem char **argv )
1733 1.1 lukem {
1734 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1735 1.1 lukem struct ldaprwmap *rwmap =
1736 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1737 1.1 lukem
1738 1.1 lukem /* objectclass/attribute mapping */
1739 1.1 lukem return rwm_map_config( &rwmap->rwm_oc,
1740 1.1 lukem &rwmap->rwm_at,
1741 1.1 lukem fname, lineno, argc, argv );
1742 1.1 lukem }
1743 1.1 lukem
1744 1.1 lukem static int
1745 1.1 lukem rwm_response( Operation *op, SlapReply *rs )
1746 1.1 lukem {
1747 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1748 1.1 lukem struct ldaprwmap *rwmap =
1749 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1750 1.1 lukem
1751 1.1 lukem int rc;
1752 1.1 lukem
1753 1.1 lukem if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1754 1.1 lukem return rwm_send_entry( op, rs );
1755 1.1 lukem }
1756 1.1 lukem
1757 1.1 lukem switch( op->o_tag ) {
1758 1.1 lukem case LDAP_REQ_SEARCH:
1759 1.1 lukem case LDAP_REQ_BIND:
1760 1.1 lukem case LDAP_REQ_ADD:
1761 1.1 lukem case LDAP_REQ_DELETE:
1762 1.1 lukem case LDAP_REQ_MODRDN:
1763 1.1 lukem case LDAP_REQ_MODIFY:
1764 1.1 lukem case LDAP_REQ_COMPARE:
1765 1.1 lukem case LDAP_REQ_EXTENDED:
1766 1.1 lukem if ( rs->sr_ref ) {
1767 1.1 lukem dncookie dc;
1768 1.1 lukem
1769 1.1 lukem /*
1770 1.1 lukem * Rewrite the dn of the referrals, if needed
1771 1.1 lukem */
1772 1.1 lukem dc.rwmap = rwmap;
1773 1.1 lukem dc.conn = op->o_conn;
1774 1.1 lukem dc.rs = NULL;
1775 1.1 lukem dc.ctx = "referralDN";
1776 1.1 lukem rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1777 1.1.1.4 tron /* FIXME: impossible, so far */
1778 1.1 lukem if ( rc != LDAP_SUCCESS ) {
1779 1.1.1.4 tron rs->sr_err = rc;
1780 1.1 lukem break;
1781 1.1 lukem }
1782 1.1 lukem }
1783 1.1 lukem
1784 1.1.1.4 tron rwm_matched( op, rs );
1785 1.1 lukem break;
1786 1.1 lukem }
1787 1.1 lukem
1788 1.1.1.4 tron return SLAP_CB_CONTINUE;
1789 1.1 lukem }
1790 1.1 lukem
1791 1.1 lukem static int
1792 1.1 lukem rwm_db_config(
1793 1.1 lukem BackendDB *be,
1794 1.1 lukem const char *fname,
1795 1.1 lukem int lineno,
1796 1.1 lukem int argc,
1797 1.1 lukem char **argv )
1798 1.1 lukem {
1799 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
1800 1.1 lukem struct ldaprwmap *rwmap =
1801 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
1802 1.1 lukem
1803 1.1 lukem int rc = 0;
1804 1.1 lukem char *argv0 = NULL;
1805 1.1 lukem
1806 1.1 lukem if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1807 1.1 lukem argv0 = argv[ 0 ];
1808 1.1 lukem argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1809 1.1 lukem }
1810 1.1 lukem
1811 1.1 lukem if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1812 1.1 lukem rc = rwm_rw_config( be, fname, lineno, argc, argv );
1813 1.1 lukem
1814 1.1 lukem } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1815 1.1 lukem rc = rwm_m_config( be, fname, lineno, argc, argv );
1816 1.1 lukem
1817 1.1 lukem } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1818 1.1 lukem rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1819 1.1 lukem
1820 1.1 lukem } else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
1821 1.1 lukem if ( argc != 2 ) {
1822 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
1823 1.1 lukem "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
1824 1.1.1.3 adam fname, lineno, 0 );
1825 1.1 lukem return( 1 );
1826 1.1 lukem }
1827 1.1 lukem
1828 1.1 lukem if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1829 1.1 lukem rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
1830 1.1 lukem
1831 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1832 1.1 lukem rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
1833 1.1 lukem
1834 1.1 lukem /* TODO: not implemented yet */
1835 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1836 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
1837 1.1 lukem "%s: line %d: \"discover\" not supported yet "
1838 1.1 lukem "in \"t-f-support {no|yes|discover}\".\n",
1839 1.1.1.3 adam fname, lineno, 0 );
1840 1.1 lukem return( 1 );
1841 1.1 lukem #if 0
1842 1.1 lukem rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
1843 1.1 lukem #endif
1844 1.1 lukem
1845 1.1 lukem } else {
1846 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
1847 1.1 lukem "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
1848 1.1 lukem fname, lineno, argv[ 1 ] );
1849 1.1 lukem return 1;
1850 1.1 lukem }
1851 1.1 lukem
1852 1.1 lukem } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) == 0 ) {
1853 1.1 lukem if ( argc !=2 ) {
1854 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
1855 1.1 lukem "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
1856 1.1.1.3 adam fname, lineno, 0 );
1857 1.1 lukem return( 1 );
1858 1.1 lukem }
1859 1.1 lukem
1860 1.1 lukem if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1861 1.1 lukem rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
1862 1.1 lukem
1863 1.1 lukem } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1864 1.1 lukem rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
1865 1.1 lukem }
1866 1.1 lukem
1867 1.1 lukem } else {
1868 1.1 lukem rc = SLAP_CONF_UNKNOWN;
1869 1.1 lukem }
1870 1.1 lukem
1871 1.1 lukem if ( argv0 ) {
1872 1.1 lukem argv[ 0 ] = argv0;
1873 1.1 lukem }
1874 1.1 lukem
1875 1.1 lukem return rc;
1876 1.1 lukem }
1877 1.1 lukem
1878 1.1 lukem /*
1879 1.1 lukem * dynamic configuration...
1880 1.1 lukem */
1881 1.1 lukem
1882 1.1 lukem enum {
1883 1.1 lukem /* rewrite */
1884 1.1 lukem RWM_CF_REWRITE = 1,
1885 1.1 lukem
1886 1.1 lukem /* map */
1887 1.1 lukem RWM_CF_MAP,
1888 1.1 lukem RWM_CF_T_F_SUPPORT,
1889 1.1 lukem RWM_CF_NORMALIZE_MAPPED,
1890 1.1.1.2 lukem RWM_CF_DROP_UNREQUESTED,
1891 1.1 lukem
1892 1.1 lukem RWM_CF_LAST
1893 1.1 lukem };
1894 1.1 lukem
1895 1.1 lukem static slap_verbmasks t_f_mode[] = {
1896 1.1.1.2 lukem { BER_BVC( "true" ), RWM_F_SUPPORT_T_F },
1897 1.1 lukem { BER_BVC( "yes" ), RWM_F_SUPPORT_T_F },
1898 1.1 lukem { BER_BVC( "discover" ), RWM_F_SUPPORT_T_F_DISCOVER },
1899 1.1.1.2 lukem { BER_BVC( "false" ), RWM_F_NONE },
1900 1.1 lukem { BER_BVC( "no" ), RWM_F_NONE },
1901 1.1 lukem { BER_BVNULL, 0 }
1902 1.1 lukem };
1903 1.1 lukem
1904 1.1 lukem static ConfigDriver rwm_cf_gen;
1905 1.1 lukem
1906 1.1 lukem static ConfigTable rwmcfg[] = {
1907 1.1 lukem { "rwm-rewrite", "rewrite",
1908 1.1 lukem 2, 0, STRLENOF("rwm-rewrite"),
1909 1.1.1.2 lukem ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1910 1.1 lukem "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
1911 1.1 lukem "DESC 'Rewrites strings' "
1912 1.1 lukem "EQUALITY caseIgnoreMatch "
1913 1.1 lukem "SYNTAX OMsDirectoryString "
1914 1.1 lukem "X-ORDERED 'VALUES' )",
1915 1.1 lukem NULL, NULL },
1916 1.1 lukem
1917 1.1 lukem { "rwm-suffixmassage", "[virtual]> <real",
1918 1.1.1.2 lukem 2, 3, 0, ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1919 1.1 lukem NULL, NULL, NULL },
1920 1.1 lukem
1921 1.1 lukem { "rwm-t-f-support", "true|false|discover",
1922 1.1 lukem 2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
1923 1.1 lukem "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
1924 1.1 lukem "DESC 'Absolute filters support' "
1925 1.1 lukem "SYNTAX OMsDirectoryString "
1926 1.1 lukem "SINGLE-VALUE )",
1927 1.1 lukem NULL, NULL },
1928 1.1 lukem
1929 1.1 lukem { "rwm-map", "{objectClass|attribute}",
1930 1.1 lukem 2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
1931 1.1 lukem "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
1932 1.1 lukem "DESC 'maps attributes/objectClasses' "
1933 1.1.1.3 adam "EQUALITY caseIgnoreMatch "
1934 1.1 lukem "SYNTAX OMsDirectoryString "
1935 1.1 lukem "X-ORDERED 'VALUES' )",
1936 1.1 lukem NULL, NULL },
1937 1.1 lukem
1938 1.1 lukem { "rwm-normalize-mapped-attrs", "true|false",
1939 1.1 lukem 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
1940 1.1 lukem "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
1941 1.1 lukem "DESC 'Normalize mapped attributes/objectClasses' "
1942 1.1 lukem "SYNTAX OMsBoolean "
1943 1.1 lukem "SINGLE-VALUE )",
1944 1.1 lukem NULL, NULL },
1945 1.1 lukem
1946 1.1.1.2 lukem { "rwm-drop-unrequested-attrs", "true|false",
1947 1.1.1.2 lukem 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_DROP_UNREQUESTED, rwm_cf_gen,
1948 1.1.1.2 lukem "( OLcfgOvAt:16.5 NAME 'olcRwmDropUnrequested' "
1949 1.1.1.2 lukem "DESC 'Drop unrequested attributes' "
1950 1.1.1.2 lukem "SYNTAX OMsBoolean "
1951 1.1.1.2 lukem "SINGLE-VALUE )",
1952 1.1.1.2 lukem NULL, NULL },
1953 1.1.1.2 lukem
1954 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1955 1.1 lukem };
1956 1.1 lukem
1957 1.1 lukem static ConfigOCs rwmocs[] = {
1958 1.1 lukem { "( OLcfgOvOc:16.1 "
1959 1.1 lukem "NAME 'olcRwmConfig' "
1960 1.1 lukem "DESC 'Rewrite/remap configuration' "
1961 1.1 lukem "SUP olcOverlayConfig "
1962 1.1 lukem "MAY ( "
1963 1.1 lukem "olcRwmRewrite $ "
1964 1.1 lukem "olcRwmTFSupport $ "
1965 1.1 lukem "olcRwmMap $ "
1966 1.1.1.5 christos "olcRwmNormalizeMapped $ "
1967 1.1.1.5 christos "olcRwmDropUnrequested"
1968 1.1 lukem ") )",
1969 1.1 lukem Cft_Overlay, rwmcfg, NULL, NULL },
1970 1.1 lukem { NULL, 0, NULL }
1971 1.1 lukem };
1972 1.1 lukem
1973 1.1 lukem static void
1974 1.1.1.3 adam slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
1975 1.1 lukem {
1976 1.1 lukem int i;
1977 1.1 lukem BerVarray bva = NULL;
1978 1.1 lukem char ibuf[32], *ptr;
1979 1.1 lukem struct berval idx;
1980 1.1 lukem
1981 1.1 lukem assert( in != NULL );
1982 1.1 lukem
1983 1.1 lukem for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
1984 1.1 lukem /* count'em */ ;
1985 1.1 lukem
1986 1.1 lukem if ( i == 0 ) {
1987 1.1 lukem return;
1988 1.1 lukem }
1989 1.1 lukem
1990 1.1 lukem idx.bv_val = ibuf;
1991 1.1 lukem
1992 1.1 lukem bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
1993 1.1 lukem BER_BVZERO( &bva[ 0 ] );
1994 1.1 lukem
1995 1.1 lukem for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1996 1.1 lukem idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
1997 1.1 lukem if ( idx.bv_len >= sizeof( ibuf ) ) {
1998 1.1 lukem ber_bvarray_free( bva );
1999 1.1 lukem return;
2000 1.1 lukem }
2001 1.1 lukem
2002 1.1 lukem bva[i].bv_len = idx.bv_len + in[i].bv_len;
2003 1.1 lukem bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
2004 1.1 lukem ptr = lutil_strcopy( bva[i].bv_val, ibuf );
2005 1.1 lukem ptr = lutil_strcopy( ptr, in[i].bv_val );
2006 1.1 lukem *ptr = '\0';
2007 1.1 lukem BER_BVZERO( &bva[ i + 1 ] );
2008 1.1 lukem }
2009 1.1 lukem
2010 1.1 lukem *out = bva;
2011 1.1 lukem }
2012 1.1 lukem
2013 1.1 lukem static int
2014 1.1.1.3 adam rwm_bva_add(
2015 1.1.1.3 adam BerVarray *bva,
2016 1.1.1.2 lukem int idx,
2017 1.1.1.2 lukem char **argv )
2018 1.1.1.2 lukem {
2019 1.1.1.2 lukem char *line;
2020 1.1.1.2 lukem struct berval bv;
2021 1.1.1.2 lukem
2022 1.1.1.2 lukem line = ldap_charray2str( argv, "\" \"" );
2023 1.1.1.2 lukem if ( line != NULL ) {
2024 1.1.1.2 lukem int len = strlen( argv[ 0 ] );
2025 1.1.1.2 lukem
2026 1.1.1.2 lukem ber_str2bv( line, 0, 0, &bv );
2027 1.1.1.2 lukem AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
2028 1.1.1.2 lukem bv.bv_len - ( len + 1 ) );
2029 1.1.1.2 lukem bv.bv_val[ bv.bv_len - 1 ] = '"';
2030 1.1.1.2 lukem
2031 1.1.1.2 lukem if ( idx == -1 ) {
2032 1.1.1.3 adam ber_bvarray_add( bva, &bv );
2033 1.1.1.2 lukem
2034 1.1.1.2 lukem } else {
2035 1.1.1.3 adam (*bva)[ idx ] = bv;
2036 1.1.1.2 lukem }
2037 1.1.1.3 adam
2038 1.1.1.3 adam return 0;
2039 1.1.1.2 lukem }
2040 1.1.1.2 lukem
2041 1.1.1.3 adam return -1;
2042 1.1.1.3 adam }
2043 1.1.1.3 adam
2044 1.1.1.3 adam static int
2045 1.1.1.3 adam rwm_bva_rewrite_add(
2046 1.1.1.3 adam struct ldaprwmap *rwmap,
2047 1.1.1.3 adam int idx,
2048 1.1.1.3 adam char **argv )
2049 1.1.1.3 adam {
2050 1.1.1.3 adam return rwm_bva_add( &rwmap->rwm_bva_rewrite, idx, argv );
2051 1.1.1.3 adam }
2052 1.1.1.3 adam
2053 1.1.1.4 tron #ifdef unused
2054 1.1.1.3 adam static int
2055 1.1.1.3 adam rwm_bva_map_add(
2056 1.1.1.3 adam struct ldaprwmap *rwmap,
2057 1.1.1.3 adam int idx,
2058 1.1.1.3 adam char **argv )
2059 1.1.1.3 adam {
2060 1.1.1.3 adam return rwm_bva_add( &rwmap->rwm_bva_map, idx, argv );
2061 1.1.1.2 lukem }
2062 1.1.1.4 tron #endif /* unused */
2063 1.1.1.2 lukem
2064 1.1.1.2 lukem static int
2065 1.1.1.2 lukem rwm_info_init( struct rewrite_info ** rwm_rw )
2066 1.1.1.2 lukem {
2067 1.1.1.2 lukem char *rargv[ 3 ];
2068 1.1.1.2 lukem
2069 1.1.1.2 lukem *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
2070 1.1.1.2 lukem if ( *rwm_rw == NULL ) {
2071 1.1.1.2 lukem return -1;
2072 1.1.1.2 lukem }
2073 1.1.1.2 lukem
2074 1.1.1.2 lukem /* this rewriteContext by default must be null;
2075 1.1.1.2 lukem * rules can be added if required */
2076 1.1.1.2 lukem rargv[ 0 ] = "rewriteContext";
2077 1.1.1.2 lukem rargv[ 1 ] = "searchFilter";
2078 1.1.1.2 lukem rargv[ 2 ] = NULL;
2079 1.1.1.2 lukem rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
2080 1.1.1.2 lukem
2081 1.1.1.2 lukem rargv[ 0 ] = "rewriteContext";
2082 1.1.1.2 lukem rargv[ 1 ] = "default";
2083 1.1.1.2 lukem rargv[ 2 ] = NULL;
2084 1.1.1.2 lukem rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
2085 1.1.1.2 lukem
2086 1.1.1.2 lukem return 0;
2087 1.1.1.2 lukem }
2088 1.1.1.2 lukem
2089 1.1.1.2 lukem static int
2090 1.1 lukem rwm_cf_gen( ConfigArgs *c )
2091 1.1 lukem {
2092 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
2093 1.1 lukem struct ldaprwmap *rwmap =
2094 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
2095 1.1 lukem
2096 1.1 lukem BackendDB db;
2097 1.1 lukem char *argv0;
2098 1.1.1.2 lukem int idx0 = 0;
2099 1.1 lukem int rc = 0;
2100 1.1 lukem
2101 1.1 lukem db = *c->be;
2102 1.1 lukem db.bd_info = c->bi;
2103 1.1 lukem
2104 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) {
2105 1.1 lukem struct berval bv = BER_BVNULL;
2106 1.1 lukem
2107 1.1 lukem switch ( c->type ) {
2108 1.1 lukem case RWM_CF_REWRITE:
2109 1.1 lukem if ( rwmap->rwm_bva_rewrite == NULL ) {
2110 1.1 lukem rc = 1;
2111 1.1 lukem
2112 1.1 lukem } else {
2113 1.1.1.3 adam slap_bv_x_ordered_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
2114 1.1 lukem if ( !c->rvalue_vals ) {
2115 1.1 lukem rc = 1;
2116 1.1 lukem }
2117 1.1 lukem }
2118 1.1 lukem break;
2119 1.1 lukem
2120 1.1 lukem case RWM_CF_T_F_SUPPORT:
2121 1.1 lukem enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
2122 1.1 lukem if ( BER_BVISNULL( &bv ) ) {
2123 1.1 lukem /* there's something wrong... */
2124 1.1 lukem assert( 0 );
2125 1.1 lukem rc = 1;
2126 1.1 lukem
2127 1.1 lukem } else {
2128 1.1 lukem value_add_one( &c->rvalue_vals, &bv );
2129 1.1 lukem }
2130 1.1 lukem break;
2131 1.1 lukem
2132 1.1 lukem case RWM_CF_MAP:
2133 1.1 lukem if ( rwmap->rwm_bva_map == NULL ) {
2134 1.1 lukem rc = 1;
2135 1.1 lukem
2136 1.1 lukem } else {
2137 1.1.1.3 adam slap_bv_x_ordered_unparse( rwmap->rwm_bva_map, &c->rvalue_vals );
2138 1.1.1.3 adam if ( !c->rvalue_vals ) {
2139 1.1.1.3 adam rc = 1;
2140 1.1.1.3 adam }
2141 1.1 lukem }
2142 1.1 lukem break;
2143 1.1 lukem
2144 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
2145 1.1 lukem c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
2146 1.1 lukem break;
2147 1.1 lukem
2148 1.1.1.2 lukem case RWM_CF_DROP_UNREQUESTED:
2149 1.1.1.2 lukem c->value_int = ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS );
2150 1.1.1.2 lukem break;
2151 1.1.1.2 lukem
2152 1.1 lukem default:
2153 1.1 lukem assert( 0 );
2154 1.1 lukem rc = 1;
2155 1.1 lukem }
2156 1.1 lukem
2157 1.1 lukem return rc;
2158 1.1 lukem
2159 1.1 lukem } else if ( c->op == LDAP_MOD_DELETE ) {
2160 1.1 lukem switch ( c->type ) {
2161 1.1 lukem case RWM_CF_REWRITE:
2162 1.1 lukem if ( c->valx >= 0 ) {
2163 1.1.1.2 lukem int i;
2164 1.1.1.2 lukem
2165 1.1.1.2 lukem for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2166 1.1.1.2 lukem /* count'em */ ;
2167 1.1.1.2 lukem
2168 1.1.1.3 adam if ( c->valx >= i ) {
2169 1.1.1.2 lukem rc = 1;
2170 1.1.1.2 lukem break;
2171 1.1.1.2 lukem }
2172 1.1.1.2 lukem
2173 1.1.1.2 lukem ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
2174 1.1.1.2 lukem for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
2175 1.1.1.2 lukem {
2176 1.1.1.2 lukem rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
2177 1.1.1.2 lukem }
2178 1.1.1.2 lukem BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
2179 1.1.1.2 lukem
2180 1.1.1.2 lukem rewrite_info_delete( &rwmap->rwm_rw );
2181 1.1.1.2 lukem assert( rwmap->rwm_rw == NULL );
2182 1.1.1.2 lukem
2183 1.1.1.2 lukem rc = rwm_info_init( &rwmap->rwm_rw );
2184 1.1.1.2 lukem
2185 1.1.1.2 lukem for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2186 1.1.1.2 lukem {
2187 1.1.1.3 adam ConfigArgs ca = { 0 };
2188 1.1.1.3 adam
2189 1.1.1.2 lukem ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2190 1.1.1.2 lukem ca.argc = 0;
2191 1.1.1.5 christos init_config_argv( &ca );
2192 1.1.1.5 christos config_parse_ldif( &ca );
2193 1.1.1.5 christos
2194 1.1.1.5 christos argv0 = ca.argv[ 0 ];
2195 1.1.1.5 christos ca.argv[ 0 ] += STRLENOF( "rwm-" );
2196 1.1.1.5 christos
2197 1.1.1.2 lukem if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2198 1.1.1.2 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2199 1.1.1.2 lukem ca.argc, ca.argv );
2200 1.1.1.2 lukem
2201 1.1.1.2 lukem } else {
2202 1.1.1.2 lukem rc = rwm_rw_config( &db, c->fname, c->lineno,
2203 1.1.1.2 lukem ca.argc, ca.argv );
2204 1.1.1.2 lukem }
2205 1.1.1.2 lukem
2206 1.1.1.5 christos ca.argv[ 0 ] = argv0;
2207 1.1.1.5 christos
2208 1.1.1.2 lukem ch_free( ca.tline );
2209 1.1.1.3 adam ch_free( ca.argv );
2210 1.1.1.2 lukem
2211 1.1.1.2 lukem assert( rc == 0 );
2212 1.1.1.2 lukem }
2213 1.1 lukem
2214 1.1 lukem } else if ( rwmap->rwm_rw != NULL ) {
2215 1.1 lukem rewrite_info_delete( &rwmap->rwm_rw );
2216 1.1 lukem assert( rwmap->rwm_rw == NULL );
2217 1.1 lukem
2218 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_rewrite );
2219 1.1 lukem rwmap->rwm_bva_rewrite = NULL;
2220 1.1.1.2 lukem
2221 1.1.1.2 lukem rc = rwm_info_init( &rwmap->rwm_rw );
2222 1.1 lukem }
2223 1.1 lukem break;
2224 1.1 lukem
2225 1.1 lukem case RWM_CF_T_F_SUPPORT:
2226 1.1 lukem rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2227 1.1 lukem break;
2228 1.1 lukem
2229 1.1 lukem case RWM_CF_MAP:
2230 1.1 lukem if ( c->valx >= 0 ) {
2231 1.1.1.3 adam struct ldapmap rwm_oc = rwmap->rwm_oc;
2232 1.1.1.3 adam struct ldapmap rwm_at = rwmap->rwm_at;
2233 1.1.1.3 adam char *argv[5];
2234 1.1.1.3 adam int cnt = 0;
2235 1.1.1.3 adam
2236 1.1.1.3 adam if ( rwmap->rwm_bva_map ) {
2237 1.1.1.3 adam for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2238 1.1.1.3 adam /* count */ ;
2239 1.1.1.3 adam }
2240 1.1.1.3 adam
2241 1.1.1.3 adam if ( c->valx >= cnt ) {
2242 1.1.1.3 adam rc = 1;
2243 1.1.1.3 adam break;
2244 1.1.1.3 adam }
2245 1.1.1.3 adam
2246 1.1.1.3 adam memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2247 1.1.1.3 adam memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2248 1.1.1.3 adam
2249 1.1.1.3 adam /* re-parse all mappings except the one
2250 1.1.1.3 adam * that needs to be eliminated */
2251 1.1.1.3 adam argv[0] = "map";
2252 1.1.1.3 adam for ( cnt = 0; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2253 1.1.1.3 adam ConfigArgs ca = { 0 };
2254 1.1.1.3 adam
2255 1.1.1.3 adam if ( cnt == c->valx ) {
2256 1.1.1.3 adam continue;
2257 1.1.1.3 adam }
2258 1.1.1.3 adam
2259 1.1.1.3 adam ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2260 1.1.1.3 adam ca.argc = 0;
2261 1.1.1.5 christos init_config_argv( &ca );
2262 1.1.1.5 christos config_parse_ldif( &ca );
2263 1.1.1.3 adam
2264 1.1.1.3 adam argv[1] = ca.argv[0];
2265 1.1.1.3 adam argv[2] = ca.argv[1];
2266 1.1.1.3 adam argv[3] = ca.argv[2];
2267 1.1.1.3 adam argv[4] = ca.argv[3];
2268 1.1.1.3 adam
2269 1.1.1.3 adam rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2270 1.1.1.3 adam
2271 1.1.1.3 adam ch_free( ca.tline );
2272 1.1.1.3 adam ch_free( ca.argv );
2273 1.1.1.3 adam
2274 1.1.1.3 adam /* in case of failure, restore
2275 1.1.1.3 adam * the existing mapping */
2276 1.1.1.3 adam if ( rc ) {
2277 1.1.1.3 adam avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2278 1.1.1.3 adam avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2279 1.1.1.3 adam avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2280 1.1.1.3 adam avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2281 1.1.1.3 adam rwmap->rwm_oc = rwm_oc;
2282 1.1.1.3 adam rwmap->rwm_at = rwm_at;
2283 1.1.1.3 adam break;
2284 1.1.1.3 adam }
2285 1.1.1.3 adam }
2286 1.1.1.3 adam
2287 1.1.1.3 adam /* in case of success, destroy the old mapping
2288 1.1.1.3 adam * and eliminate the deleted one */
2289 1.1.1.3 adam if ( rc == 0 ) {
2290 1.1.1.3 adam avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2291 1.1.1.3 adam avl_free( rwm_oc.map, rwm_mapping_free );
2292 1.1.1.3 adam avl_free( rwm_at.remap, rwm_mapping_dst_free );
2293 1.1.1.3 adam avl_free( rwm_at.map, rwm_mapping_free );
2294 1.1.1.3 adam
2295 1.1.1.3 adam ber_memfree( rwmap->rwm_bva_map[ c->valx ].bv_val );
2296 1.1.1.3 adam for ( cnt = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2297 1.1.1.3 adam rwmap->rwm_bva_map[ cnt ] = rwmap->rwm_bva_map[ cnt + 1 ];
2298 1.1.1.3 adam }
2299 1.1.1.3 adam }
2300 1.1 lukem
2301 1.1 lukem } else {
2302 1.1 lukem avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2303 1.1 lukem avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2304 1.1 lukem avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2305 1.1 lukem avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2306 1.1 lukem
2307 1.1 lukem rwmap->rwm_oc.remap = NULL;
2308 1.1 lukem rwmap->rwm_oc.map = NULL;
2309 1.1 lukem rwmap->rwm_at.remap = NULL;
2310 1.1 lukem rwmap->rwm_at.map = NULL;
2311 1.1 lukem
2312 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_map );
2313 1.1 lukem rwmap->rwm_bva_map = NULL;
2314 1.1 lukem }
2315 1.1 lukem break;
2316 1.1 lukem
2317 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
2318 1.1 lukem rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2319 1.1 lukem break;
2320 1.1 lukem
2321 1.1.1.2 lukem case RWM_CF_DROP_UNREQUESTED:
2322 1.1.1.2 lukem rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2323 1.1.1.2 lukem break;
2324 1.1.1.2 lukem
2325 1.1 lukem default:
2326 1.1 lukem return 1;
2327 1.1 lukem }
2328 1.1 lukem return rc;
2329 1.1 lukem }
2330 1.1 lukem
2331 1.1.1.2 lukem if ( strncasecmp( c->argv[ 0 ], "olcRwm", STRLENOF( "olcRwm" ) ) == 0 ) {
2332 1.1.1.2 lukem idx0 = 1;
2333 1.1.1.2 lukem }
2334 1.1.1.2 lukem
2335 1.1 lukem switch ( c->type ) {
2336 1.1 lukem case RWM_CF_REWRITE:
2337 1.1.1.2 lukem if ( c->valx >= 0 ) {
2338 1.1.1.2 lukem struct rewrite_info *rwm_rw = rwmap->rwm_rw;
2339 1.1.1.2 lukem int i, last;
2340 1.1.1.2 lukem
2341 1.1.1.2 lukem for ( last = 0; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
2342 1.1.1.2 lukem /* count'em */ ;
2343 1.1.1.2 lukem
2344 1.1.1.2 lukem if ( c->valx > last ) {
2345 1.1.1.2 lukem c->valx = last;
2346 1.1.1.2 lukem }
2347 1.1.1.2 lukem
2348 1.1.1.2 lukem rwmap->rwm_rw = NULL;
2349 1.1.1.2 lukem rc = rwm_info_init( &rwmap->rwm_rw );
2350 1.1.1.2 lukem
2351 1.1.1.2 lukem for ( i = 0; i < c->valx; i++ ) {
2352 1.1.1.3 adam ConfigArgs ca = { 0 };
2353 1.1.1.3 adam
2354 1.1.1.2 lukem ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2355 1.1.1.2 lukem ca.argc = 0;
2356 1.1.1.5 christos init_config_argv( &ca );
2357 1.1.1.5 christos config_parse_ldif( &ca );
2358 1.1.1.2 lukem
2359 1.1.1.2 lukem argv0 = ca.argv[ 0 ];
2360 1.1.1.2 lukem ca.argv[ 0 ] += STRLENOF( "rwm-" );
2361 1.1.1.2 lukem
2362 1.1.1.2 lukem if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2363 1.1.1.2 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2364 1.1.1.2 lukem ca.argc, ca.argv );
2365 1.1 lukem
2366 1.1.1.2 lukem } else {
2367 1.1.1.2 lukem rc = rwm_rw_config( &db, c->fname, c->lineno,
2368 1.1.1.2 lukem ca.argc, ca.argv );
2369 1.1.1.2 lukem }
2370 1.1 lukem
2371 1.1.1.2 lukem ca.argv[ 0 ] = argv0;
2372 1.1 lukem
2373 1.1.1.2 lukem ch_free( ca.tline );
2374 1.1.1.3 adam ch_free( ca.argv );
2375 1.1.1.2 lukem
2376 1.1.1.2 lukem assert( rc == 0 );
2377 1.1 lukem }
2378 1.1 lukem
2379 1.1.1.2 lukem argv0 = c->argv[ idx0 ];
2380 1.1.1.2 lukem if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2381 1.1.1.2 lukem return 1;
2382 1.1.1.2 lukem }
2383 1.1.1.2 lukem c->argv[ idx0 ] += STRLENOF( "rwm-" );
2384 1.1.1.2 lukem if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2385 1.1.1.2 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2386 1.1.1.2 lukem c->argc - idx0, &c->argv[ idx0 ] );
2387 1.1 lukem
2388 1.1.1.2 lukem } else {
2389 1.1.1.2 lukem rc = rwm_rw_config( &db, c->fname, c->lineno,
2390 1.1.1.2 lukem c->argc - idx0, &c->argv[ idx0 ] );
2391 1.1.1.2 lukem }
2392 1.1.1.2 lukem c->argv[ idx0 ] = argv0;
2393 1.1.1.2 lukem if ( rc != 0 ) {
2394 1.1.1.2 lukem rewrite_info_delete( &rwmap->rwm_rw );
2395 1.1.1.2 lukem assert( rwmap->rwm_rw == NULL );
2396 1.1 lukem
2397 1.1.1.2 lukem rwmap->rwm_rw = rwm_rw;
2398 1.1.1.2 lukem return 1;
2399 1.1.1.2 lukem }
2400 1.1 lukem
2401 1.1.1.2 lukem for ( i = c->valx; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2402 1.1.1.2 lukem {
2403 1.1.1.3 adam ConfigArgs ca = { 0 };
2404 1.1.1.3 adam
2405 1.1.1.2 lukem ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2406 1.1.1.2 lukem ca.argc = 0;
2407 1.1.1.5 christos init_config_argv( &ca );
2408 1.1.1.5 christos config_parse_ldif( &ca );
2409 1.1.1.2 lukem
2410 1.1.1.2 lukem argv0 = ca.argv[ 0 ];
2411 1.1.1.2 lukem ca.argv[ 0 ] += STRLENOF( "rwm-" );
2412 1.1.1.2 lukem
2413 1.1.1.2 lukem if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2414 1.1.1.2 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2415 1.1.1.2 lukem ca.argc, ca.argv );
2416 1.1 lukem
2417 1.1.1.2 lukem } else {
2418 1.1.1.2 lukem rc = rwm_rw_config( &db, c->fname, c->lineno,
2419 1.1.1.2 lukem ca.argc, ca.argv );
2420 1.1.1.2 lukem }
2421 1.1.1.2 lukem
2422 1.1.1.2 lukem ca.argv[ 0 ] = argv0;
2423 1.1.1.2 lukem
2424 1.1.1.2 lukem ch_free( ca.tline );
2425 1.1.1.3 adam ch_free( ca.argv );
2426 1.1.1.2 lukem
2427 1.1.1.2 lukem assert( rc == 0 );
2428 1.1 lukem }
2429 1.1.1.2 lukem
2430 1.1.1.2 lukem rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
2431 1.1.1.2 lukem ( last + 2 )*sizeof( struct berval ) );
2432 1.1.1.2 lukem BER_BVZERO( &rwmap->rwm_bva_rewrite[last+1] );
2433 1.1.1.2 lukem
2434 1.1.1.2 lukem for ( i = last - 1; i >= c->valx; i-- )
2435 1.1.1.2 lukem {
2436 1.1.1.2 lukem rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
2437 1.1.1.2 lukem }
2438 1.1.1.2 lukem
2439 1.1.1.2 lukem rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
2440 1.1.1.2 lukem
2441 1.1.1.2 lukem rewrite_info_delete( &rwm_rw );
2442 1.1.1.2 lukem assert( rwm_rw == NULL );
2443 1.1.1.2 lukem
2444 1.1.1.2 lukem break;
2445 1.1.1.2 lukem }
2446 1.1.1.2 lukem
2447 1.1.1.2 lukem argv0 = c->argv[ idx0 ];
2448 1.1.1.2 lukem if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2449 1.1.1.2 lukem return 1;
2450 1.1.1.2 lukem }
2451 1.1.1.2 lukem c->argv[ idx0 ] += STRLENOF( "rwm-" );
2452 1.1.1.2 lukem if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2453 1.1.1.2 lukem rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2454 1.1.1.2 lukem c->argc - idx0, &c->argv[ idx0 ] );
2455 1.1.1.2 lukem
2456 1.1.1.2 lukem } else {
2457 1.1.1.2 lukem rc = rwm_rw_config( &db, c->fname, c->lineno,
2458 1.1.1.2 lukem c->argc - idx0, &c->argv[ idx0 ] );
2459 1.1.1.2 lukem }
2460 1.1.1.2 lukem c->argv[ idx0 ] = argv0;
2461 1.1.1.2 lukem if ( rc ) {
2462 1.1.1.2 lukem return 1;
2463 1.1.1.2 lukem
2464 1.1.1.2 lukem } else {
2465 1.1.1.2 lukem rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
2466 1.1 lukem }
2467 1.1 lukem break;
2468 1.1 lukem
2469 1.1 lukem case RWM_CF_T_F_SUPPORT:
2470 1.1 lukem rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
2471 1.1 lukem if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
2472 1.1 lukem return 1;
2473 1.1 lukem }
2474 1.1 lukem
2475 1.1 lukem rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2476 1.1 lukem rwmap->rwm_flags |= t_f_mode[ rc ].mask;
2477 1.1 lukem rc = 0;
2478 1.1 lukem break;
2479 1.1 lukem
2480 1.1 lukem case RWM_CF_MAP:
2481 1.1.1.2 lukem if ( c->valx >= 0 ) {
2482 1.1.1.3 adam struct ldapmap rwm_oc = rwmap->rwm_oc;
2483 1.1.1.3 adam struct ldapmap rwm_at = rwmap->rwm_at;
2484 1.1.1.3 adam char *argv[5];
2485 1.1.1.3 adam int cnt = 0;
2486 1.1.1.3 adam
2487 1.1.1.3 adam if ( rwmap->rwm_bva_map ) {
2488 1.1.1.3 adam for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2489 1.1.1.3 adam /* count */ ;
2490 1.1.1.3 adam }
2491 1.1.1.3 adam
2492 1.1.1.3 adam if ( c->valx >= cnt ) {
2493 1.1.1.3 adam c->valx = cnt;
2494 1.1.1.3 adam }
2495 1.1.1.3 adam
2496 1.1.1.3 adam memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2497 1.1.1.3 adam memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2498 1.1.1.3 adam
2499 1.1.1.3 adam /* re-parse all mappings, including the one
2500 1.1.1.3 adam * that needs to be added */
2501 1.1.1.3 adam argv[0] = "map";
2502 1.1.1.3 adam for ( cnt = 0; cnt < c->valx; cnt++ ) {
2503 1.1.1.3 adam ConfigArgs ca = { 0 };
2504 1.1.1.3 adam
2505 1.1.1.3 adam ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2506 1.1.1.3 adam ca.argc = 0;
2507 1.1.1.5 christos init_config_argv( &ca );
2508 1.1.1.5 christos config_parse_ldif( &ca );
2509 1.1.1.3 adam
2510 1.1.1.3 adam argv[1] = ca.argv[0];
2511 1.1.1.3 adam argv[2] = ca.argv[1];
2512 1.1.1.3 adam argv[3] = ca.argv[2];
2513 1.1.1.3 adam argv[4] = ca.argv[3];
2514 1.1.1.3 adam
2515 1.1.1.3 adam rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2516 1.1.1.3 adam
2517 1.1.1.3 adam ch_free( ca.tline );
2518 1.1.1.3 adam ch_free( ca.argv );
2519 1.1.1.3 adam
2520 1.1.1.3 adam /* in case of failure, restore
2521 1.1.1.3 adam * the existing mapping */
2522 1.1.1.3 adam if ( rc ) {
2523 1.1.1.3 adam goto rwmmap_fail;
2524 1.1.1.3 adam }
2525 1.1.1.3 adam }
2526 1.1.1.3 adam
2527 1.1.1.3 adam argv0 = c->argv[0];
2528 1.1.1.3 adam c->argv[0] = "map";
2529 1.1.1.3 adam rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2530 1.1.1.3 adam c->argv[0] = argv0;
2531 1.1.1.3 adam if ( rc ) {
2532 1.1.1.3 adam goto rwmmap_fail;
2533 1.1.1.3 adam }
2534 1.1.1.3 adam
2535 1.1.1.3 adam if ( rwmap->rwm_bva_map ) {
2536 1.1.1.3 adam for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2537 1.1.1.3 adam ConfigArgs ca = { 0 };
2538 1.1.1.3 adam
2539 1.1.1.3 adam ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2540 1.1.1.3 adam ca.argc = 0;
2541 1.1.1.5 christos init_config_argv( &ca );
2542 1.1.1.5 christos config_parse_ldif( &ca );
2543 1.1.1.3 adam
2544 1.1.1.3 adam argv[1] = ca.argv[0];
2545 1.1.1.3 adam argv[2] = ca.argv[1];
2546 1.1.1.3 adam argv[3] = ca.argv[2];
2547 1.1.1.3 adam argv[4] = ca.argv[3];
2548 1.1.1.3 adam
2549 1.1.1.3 adam rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2550 1.1.1.3 adam
2551 1.1.1.3 adam ch_free( ca.tline );
2552 1.1.1.3 adam ch_free( ca.argv );
2553 1.1.1.3 adam
2554 1.1.1.3 adam /* in case of failure, restore
2555 1.1.1.3 adam * the existing mapping */
2556 1.1.1.3 adam if ( rc ) {
2557 1.1.1.3 adam goto rwmmap_fail;
2558 1.1.1.3 adam }
2559 1.1.1.3 adam }
2560 1.1.1.3 adam }
2561 1.1.1.3 adam
2562 1.1.1.3 adam /* in case of success, destroy the old mapping
2563 1.1.1.3 adam * and add the new one */
2564 1.1.1.3 adam if ( rc == 0 ) {
2565 1.1.1.3 adam BerVarray tmp;
2566 1.1.1.3 adam struct berval bv, *bvp = &bv;
2567 1.1.1.3 adam
2568 1.1.1.3 adam if ( rwm_bva_add( &bvp, 0, &c->argv[ idx0 ] ) ) {
2569 1.1.1.3 adam rc = 1;
2570 1.1.1.3 adam goto rwmmap_fail;
2571 1.1.1.3 adam }
2572 1.1.1.3 adam
2573 1.1.1.3 adam tmp = ber_memrealloc( rwmap->rwm_bva_map,
2574 1.1.1.3 adam sizeof( struct berval )*( cnt + 2 ) );
2575 1.1.1.3 adam if ( tmp == NULL ) {
2576 1.1.1.3 adam ber_memfree( bv.bv_val );
2577 1.1.1.3 adam rc = 1;
2578 1.1.1.3 adam goto rwmmap_fail;
2579 1.1.1.3 adam }
2580 1.1.1.3 adam rwmap->rwm_bva_map = tmp;
2581 1.1.1.3 adam BER_BVZERO( &rwmap->rwm_bva_map[ cnt + 1 ] );
2582 1.1.1.3 adam
2583 1.1.1.3 adam avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2584 1.1.1.3 adam avl_free( rwm_oc.map, rwm_mapping_free );
2585 1.1.1.3 adam avl_free( rwm_at.remap, rwm_mapping_dst_free );
2586 1.1.1.3 adam avl_free( rwm_at.map, rwm_mapping_free );
2587 1.1.1.3 adam
2588 1.1.1.3 adam for ( ; cnt-- > c->valx; ) {
2589 1.1.1.3 adam rwmap->rwm_bva_map[ cnt + 1 ] = rwmap->rwm_bva_map[ cnt ];
2590 1.1.1.3 adam }
2591 1.1.1.3 adam rwmap->rwm_bva_map[ c->valx ] = bv;
2592 1.1.1.3 adam
2593 1.1.1.3 adam } else {
2594 1.1.1.3 adam rwmmap_fail:;
2595 1.1.1.3 adam avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2596 1.1.1.3 adam avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2597 1.1.1.3 adam avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2598 1.1.1.3 adam avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2599 1.1.1.3 adam rwmap->rwm_oc = rwm_oc;
2600 1.1.1.3 adam rwmap->rwm_at = rwm_at;
2601 1.1.1.3 adam }
2602 1.1.1.3 adam
2603 1.1.1.3 adam break;
2604 1.1.1.2 lukem }
2605 1.1.1.2 lukem
2606 1.1 lukem argv0 = c->argv[ 0 ];
2607 1.1 lukem c->argv[ 0 ] += STRLENOF( "rwm-" );
2608 1.1 lukem rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2609 1.1 lukem c->argv[ 0 ] = argv0;
2610 1.1 lukem if ( rc ) {
2611 1.1 lukem return 1;
2612 1.1 lukem
2613 1.1 lukem } else {
2614 1.1 lukem char *line;
2615 1.1 lukem struct berval bv;
2616 1.1 lukem
2617 1.1 lukem line = ldap_charray2str( &c->argv[ 1 ], " " );
2618 1.1 lukem if ( line != NULL ) {
2619 1.1 lukem ber_str2bv( line, 0, 0, &bv );
2620 1.1 lukem ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
2621 1.1 lukem }
2622 1.1 lukem }
2623 1.1 lukem break;
2624 1.1 lukem
2625 1.1 lukem case RWM_CF_NORMALIZE_MAPPED:
2626 1.1 lukem if ( c->value_int ) {
2627 1.1 lukem rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
2628 1.1 lukem } else {
2629 1.1 lukem rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2630 1.1 lukem }
2631 1.1 lukem break;
2632 1.1 lukem
2633 1.1.1.2 lukem case RWM_CF_DROP_UNREQUESTED:
2634 1.1.1.2 lukem if ( c->value_int ) {
2635 1.1.1.2 lukem rwmap->rwm_flags |= RWM_F_DROP_UNREQUESTED_ATTRS;
2636 1.1.1.2 lukem } else {
2637 1.1.1.2 lukem rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2638 1.1.1.2 lukem }
2639 1.1.1.2 lukem break;
2640 1.1.1.2 lukem
2641 1.1 lukem default:
2642 1.1 lukem assert( 0 );
2643 1.1 lukem return 1;
2644 1.1 lukem }
2645 1.1 lukem
2646 1.1 lukem return rc;
2647 1.1 lukem }
2648 1.1 lukem
2649 1.1 lukem static int
2650 1.1 lukem rwm_db_init(
2651 1.1 lukem BackendDB *be,
2652 1.1 lukem ConfigReply *cr )
2653 1.1 lukem {
2654 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
2655 1.1 lukem struct ldaprwmap *rwmap;
2656 1.1 lukem int rc = 0;
2657 1.1 lukem
2658 1.1 lukem rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
2659 1.1 lukem
2660 1.1.1.2 lukem /* default */
2661 1.1.1.2 lukem rwmap->rwm_flags = RWM_F_DROP_UNREQUESTED_ATTRS;
2662 1.1 lukem
2663 1.1.1.2 lukem rc = rwm_info_init( &rwmap->rwm_rw );
2664 1.1 lukem
2665 1.1 lukem on->on_bi.bi_private = (void *)rwmap;
2666 1.1 lukem
2667 1.1 lukem if ( rc ) {
2668 1.1 lukem (void)rwm_db_destroy( be, NULL );
2669 1.1 lukem }
2670 1.1 lukem
2671 1.1 lukem return rc;
2672 1.1 lukem }
2673 1.1 lukem
2674 1.1 lukem static int
2675 1.1 lukem rwm_db_destroy(
2676 1.1 lukem BackendDB *be,
2677 1.1 lukem ConfigReply *cr )
2678 1.1 lukem {
2679 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info;
2680 1.1 lukem int rc = 0;
2681 1.1 lukem
2682 1.1 lukem if ( on->on_bi.bi_private ) {
2683 1.1 lukem struct ldaprwmap *rwmap =
2684 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private;
2685 1.1 lukem
2686 1.1 lukem if ( rwmap->rwm_rw ) {
2687 1.1 lukem rewrite_info_delete( &rwmap->rwm_rw );
2688 1.1.1.2 lukem if ( rwmap->rwm_bva_rewrite )
2689 1.1.1.2 lukem ber_bvarray_free( rwmap->rwm_bva_rewrite );
2690 1.1 lukem }
2691 1.1 lukem
2692 1.1 lukem avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2693 1.1 lukem avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2694 1.1 lukem avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2695 1.1 lukem avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2696 1.1 lukem ber_bvarray_free( rwmap->rwm_bva_map );
2697 1.1 lukem
2698 1.1 lukem ch_free( rwmap );
2699 1.1 lukem }
2700 1.1 lukem
2701 1.1 lukem return rc;
2702 1.1 lukem }
2703 1.1 lukem
2704 1.1 lukem static slap_overinst rwm = { { NULL } };
2705 1.1 lukem
2706 1.1 lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2707 1.1 lukem static
2708 1.1 lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2709 1.1 lukem int
2710 1.1 lukem rwm_initialize( void )
2711 1.1 lukem {
2712 1.1 lukem int rc;
2713 1.1 lukem
2714 1.1 lukem /* Make sure we don't exceed the bits reserved for userland */
2715 1.1 lukem config_check_userland( RWM_CF_LAST );
2716 1.1 lukem
2717 1.1 lukem memset( &rwm, 0, sizeof( slap_overinst ) );
2718 1.1 lukem
2719 1.1 lukem rwm.on_bi.bi_type = "rwm";
2720 1.1 lukem rwm.on_bi.bi_flags =
2721 1.1 lukem SLAPO_BFLAG_SINGLE |
2722 1.1 lukem 0;
2723 1.1 lukem
2724 1.1 lukem rwm.on_bi.bi_db_init = rwm_db_init;
2725 1.1 lukem rwm.on_bi.bi_db_config = rwm_db_config;
2726 1.1 lukem rwm.on_bi.bi_db_destroy = rwm_db_destroy;
2727 1.1 lukem
2728 1.1 lukem rwm.on_bi.bi_op_bind = rwm_op_bind;
2729 1.1 lukem rwm.on_bi.bi_op_search = rwm_op_search;
2730 1.1 lukem rwm.on_bi.bi_op_compare = rwm_op_compare;
2731 1.1 lukem rwm.on_bi.bi_op_modify = rwm_op_modify;
2732 1.1 lukem rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
2733 1.1 lukem rwm.on_bi.bi_op_add = rwm_op_add;
2734 1.1 lukem rwm.on_bi.bi_op_delete = rwm_op_delete;
2735 1.1 lukem rwm.on_bi.bi_op_unbind = rwm_op_unbind;
2736 1.1 lukem rwm.on_bi.bi_extended = rwm_extended;
2737 1.1.1.2 lukem #if 1 /* TODO */
2738 1.1.1.2 lukem rwm.on_bi.bi_entry_release_rw = rwm_entry_release_rw;
2739 1.1.1.2 lukem rwm.on_bi.bi_entry_get_rw = rwm_entry_get_rw;
2740 1.1.1.2 lukem #endif
2741 1.1 lukem
2742 1.1 lukem rwm.on_bi.bi_operational = rwm_operational;
2743 1.1 lukem rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
2744 1.1 lukem
2745 1.1 lukem rwm.on_bi.bi_connection_init = rwm_conn_init;
2746 1.1 lukem rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
2747 1.1 lukem
2748 1.1 lukem rwm.on_response = rwm_response;
2749 1.1 lukem
2750 1.1 lukem rwm.on_bi.bi_cf_ocs = rwmocs;
2751 1.1 lukem
2752 1.1 lukem rc = config_register_schema( rwmcfg, rwmocs );
2753 1.1 lukem if ( rc ) {
2754 1.1 lukem return rc;
2755 1.1 lukem }
2756 1.1 lukem
2757 1.1 lukem return overlay_register( &rwm );
2758 1.1 lukem }
2759 1.1 lukem
2760 1.1 lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2761 1.1 lukem int
2762 1.1 lukem init_module( int argc, char *argv[] )
2763 1.1 lukem {
2764 1.1 lukem return rwm_initialize();
2765 1.1 lukem }
2766 1.1 lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2767 1.1 lukem
2768 1.1 lukem #endif /* SLAPD_OVER_RWM */
2769