]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwm.c
Sync with HEAD
[openldap] / servers / slapd / overlays / rwm.c
1 /* rwm.c - rewrite/remap operations */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2005 The OpenLDAP Foundation.
6  * Portions Copyright 2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include "portable.h"
19
20 #ifdef SLAPD_OVER_RWM
21
22 #include <stdio.h>
23
24 #include <ac/string.h>
25
26 #include "slap.h"
27 #include "rwm.h"
28
29 static int
30 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
31 {
32         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
33         struct ldaprwmap        *rwmap = 
34                         (struct ldaprwmap *)on->on_bi.bi_private;
35
36         struct berval           dn = BER_BVNULL,
37                                 ndn = BER_BVNULL;
38         int                     rc = 0;
39         dncookie                dc;
40
41         /*
42          * Rewrite the dn if needed
43          */
44         dc.rwmap = rwmap;
45 #ifdef ENABLE_REWRITE
46         dc.conn = op->o_conn;
47         dc.rs = rs;
48         dc.ctx = (char *)cookie;
49 #else /* ! ENABLE_REWRITE */
50         dc.tofrom = ((int *)cookie)[0];
51         dc.normalized = 0;
52 #endif /* ! ENABLE_REWRITE */
53
54         /* NOTE: in those cases where only the ndn is available,
55          * and the caller sets op->o_req_dn = op->o_req_ndn,
56          * only rewrite the op->o_req_ndn and use it as 
57          * op->o_req_dn as well */
58         ndn = op->o_req_ndn;
59         if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
60                 dn = op->o_req_dn;
61                 rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
62         } else {
63                 rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
64         }
65
66         if ( rc != LDAP_SUCCESS ) {
67                 return rc;
68         }
69
70         if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
71                         || ndn.bv_val == op->o_req_ndn.bv_val )
72         {
73                 return LDAP_SUCCESS;
74         }
75
76         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
77         op->o_req_ndn = ndn;
78         if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
79                 op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
80                 op->o_req_dn = dn;
81         } else {
82                 op->o_req_dn = ndn;
83         }
84
85         return LDAP_SUCCESS;
86 }
87
88 static int
89 rwm_op_add( Operation *op, SlapReply *rs )
90 {
91         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
92         struct ldaprwmap        *rwmap = 
93                         (struct ldaprwmap *)on->on_bi.bi_private;
94
95         int                     rc,
96                                 i;
97         Attribute               **ap = NULL;
98         char                    *olddn = op->o_req_dn.bv_val;
99         int                     isupdate;
100
101 #ifdef ENABLE_REWRITE
102         rc = rwm_op_dn_massage( op, rs, "addDN" );
103 #else /* ! ENABLE_REWRITE */
104         rc = 1;
105         rc = rwm_op_dn_massage( op, rs, &rc );
106 #endif /* ! ENABLE_REWRITE */
107         if ( rc != LDAP_SUCCESS ) {
108                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
109                 send_ldap_error( op, rs, rc, "addDN massage error" );
110                 return -1;
111         }
112
113         if ( olddn != op->o_req_dn.bv_val ) {
114                 ch_free( op->ora_e->e_name.bv_val );
115                 ch_free( op->ora_e->e_nname.bv_val );
116
117                 ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
118                 ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
119         }
120
121         /* Count number of attributes in entry */ 
122         isupdate = be_shadow_update( op );
123         for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
124                 Attribute       *a;
125
126                 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
127                                 (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
128                 {
129                         int             j, last;
130
131                         for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ )
132                                         /* count values */ ;
133                         last--;
134                         for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
135                                 struct ldapmapping      *mapping = NULL;
136
137                                 ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
138                                                 &mapping, RWM_MAP );
139                                 if ( mapping == NULL ) {
140                                         if ( rwmap->rwm_at.drop_missing ) {
141                                                 /* FIXME: we allow to remove objectClasses as well;
142                                                  * if the resulting entry is inconsistent, that's
143                                                  * the relayed database's business...
144                                                  */
145                                                 ch_free( (*ap)->a_vals[ j ].bv_val );
146                                                 if ( last > j ) {
147                                                         (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
148                                                 }
149                                                 BER_BVZERO( &(*ap)->a_vals[ last ] );
150                                                 last--;
151                                                 j--;
152                                         }
153
154                                 } else {
155                                         ch_free( (*ap)->a_vals[ j ].bv_val );
156                                         ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
157                                 }
158                         }
159
160                 } else if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod ) {
161                         goto next_attr;
162
163                 } else {
164                         struct ldapmapping      *mapping = NULL;
165
166                         ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
167                                         &mapping, RWM_MAP );
168                         if ( mapping == NULL ) {
169                                 if ( rwmap->rwm_at.drop_missing ) {
170                                         goto cleanup_attr;
171                                 }
172                         }
173
174                         if ( (*ap)->a_desc->ad_type->sat_syntax
175                                         == slap_schema.si_syn_distinguishedName )
176                         {
177                                 /*
178                                  * FIXME: rewrite could fail; in this case
179                                  * the operation should give up, right?
180                                  */
181 #ifdef ENABLE_REWRITE
182                                 rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
183                                                 (*ap)->a_vals,
184                                                 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
185 #else /* ! ENABLE_REWRITE */
186                                 rc = 1;
187                                 rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals,
188                                                 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
189 #endif /* ! ENABLE_REWRITE */
190                                 if ( rc ) {
191                                         goto cleanup_attr;
192                                 }
193
194                         } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
195 #ifdef ENABLE_REWRITE
196                                 rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
197                                                 (*ap)->a_vals,
198                                                 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
199 #else /* ! ENABLE_REWRITE */
200                                 rc = 1;
201                                 rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
202                                                 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
203 #endif /* ! ENABLE_REWRITE */
204                                 if ( rc != LDAP_SUCCESS ) {
205                                         goto cleanup_attr;
206                                 }
207                         }
208                 
209                         if ( mapping != NULL ) {
210                                 assert( mapping->m_dst_ad );
211                                 (*ap)->a_desc = mapping->m_dst_ad;
212                         }
213                 }
214
215 next_attr:;
216                 ap = &(*ap)->a_next;
217                 continue;
218
219 cleanup_attr:;
220                 /* FIXME: leaking attribute/values? */
221                 a = *ap;
222
223                 *ap = (*ap)->a_next;
224                 attr_free( a );
225         }
226
227         /* TODO: map attribute types, values of DN-valued attributes ... */
228         return SLAP_CB_CONTINUE;
229 }
230
231 static int
232 rwm_op_bind( Operation *op, SlapReply *rs )
233 {
234         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
235         struct ldaprwmap        *rwmap = 
236                         (struct ldaprwmap *)on->on_bi.bi_private;
237         int                     rc;
238
239 #ifdef ENABLE_REWRITE
240         ( void )rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
241         ( void )rewrite_session_init( rwmap->rwm_rw, op->o_conn );
242
243         rc = rwm_op_dn_massage( op, rs, "bindDN" );
244 #else /* ! ENABLE_REWRITE */
245         rc = 1;
246         rc = rwm_op_dn_massage( op, rs, &rc );
247 #endif /* ! ENABLE_REWRITE */
248         if ( rc != LDAP_SUCCESS ) {
249                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
250                 send_ldap_error( op, rs, rc, "bindDN massage error" );
251                 return -1;
252         }
253
254         return SLAP_CB_CONTINUE;
255 }
256
257 static int
258 rwm_op_unbind( Operation *op, SlapReply *rs )
259 {
260         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
261         struct ldaprwmap        *rwmap = 
262                         (struct ldaprwmap *)on->on_bi.bi_private;
263
264 #ifdef ENABLE_REWRITE
265         rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
266 #endif /* ENABLE_REWRITE */
267
268         return SLAP_CB_CONTINUE;
269 }
270
271 static int
272 rwm_op_compare( Operation *op, SlapReply *rs )
273 {
274         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
275         struct ldaprwmap        *rwmap = 
276                         (struct ldaprwmap *)on->on_bi.bi_private;
277
278         int                     rc;
279         struct berval           mapped_at = BER_BVNULL,
280                                 mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
281
282 #ifdef ENABLE_REWRITE
283         rc = rwm_op_dn_massage( op, rs, "compareDN" );
284 #else /* ! ENABLE_REWRITE */
285         rc = 1;
286         rc = rwm_op_dn_massage( op, rs, &rc );
287 #endif /* ! ENABLE_REWRITE */
288         if ( rc != LDAP_SUCCESS ) {
289                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
290                 send_ldap_error( op, rs, rc, "compareDN massage error" );
291                 return -1;
292         }
293
294         /* if the attribute is an objectClass, try to remap its value */
295         if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
296                         || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
297         {
298                 rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
299                                 &mapped_vals[0], RWM_MAP );
300                 if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
301                 {
302                         op->o_bd->bd_info = (BackendInfo *)on->on_info;
303                         send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
304                         return -1;
305
306                 } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
307                         free( op->orc_ava->aa_value.bv_val );
308                         op->orc_ava->aa_value = mapped_vals[0];
309                 }
310                 mapped_at = op->orc_ava->aa_desc->ad_cname;
311
312         } else {
313                 struct ldapmapping      *mapping = NULL;
314                 AttributeDescription    *ad = op->orc_ava->aa_desc;
315
316                 ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
317                                 &mapping, RWM_MAP );
318                 if ( mapping == NULL ) {
319                         if ( rwmap->rwm_at.drop_missing ) {
320                                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
321                                 send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
322                                 return -1;
323                         }
324
325                 } else {
326                         assert( mapping->m_dst_ad );
327                         ad = mapping->m_dst_ad;
328                 }
329
330                 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
331                 {
332                         struct berval   *mapped_valsp[2];
333                         
334                         mapped_valsp[0] = &mapped_vals[0];
335                         mapped_valsp[1] = &mapped_vals[1];
336
337                         mapped_vals[0] = op->orc_ava->aa_value;
338
339 #ifdef ENABLE_REWRITE
340                         rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
341 #else /* ! ENABLE_REWRITE */
342                         rc = 1;
343                         rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
344 #endif /* ! ENABLE_REWRITE */
345
346                         if ( rc != LDAP_SUCCESS ) {
347                                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
348                                 send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
349                                 return -1;
350                         }
351
352                         op->orc_ava->aa_value = mapped_vals[0];
353                 }
354                 op->orc_ava->aa_desc = ad;
355         }
356
357         return SLAP_CB_CONTINUE;
358 }
359
360 static int
361 rwm_op_delete( Operation *op, SlapReply *rs )
362 {
363         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
364         int                     rc;
365
366 #ifdef ENABLE_REWRITE
367         rc = rwm_op_dn_massage( op, rs, "deleteDN" );
368 #else /* ! ENABLE_REWRITE */
369         rc = 1;
370         rc = rwm_op_dn_massage( op, rs, &rc );
371 #endif /* ! ENABLE_REWRITE */
372         if ( rc != LDAP_SUCCESS ) {
373                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
374                 send_ldap_error( op, rs, rc, "deleteDN massage error" );
375                 return -1;
376         }
377
378         return SLAP_CB_CONTINUE;
379 }
380
381 static int
382 rwm_op_modify( Operation *op, SlapReply *rs )
383 {
384         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
385         struct ldaprwmap        *rwmap = 
386                         (struct ldaprwmap *)on->on_bi.bi_private;
387
388         int                     isupdate;
389         Modifications           **mlp;
390         int                     rc;
391
392 #ifdef ENABLE_REWRITE
393         rc = rwm_op_dn_massage( op, rs, "modifyDN" );
394 #else /* ! ENABLE_REWRITE */
395         rc = 1;
396         rc = rwm_op_dn_massage( op, rs, &rc );
397 #endif /* ! ENABLE_REWRITE */
398         if ( rc != LDAP_SUCCESS ) {
399                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
400                 send_ldap_error( op, rs, rc, "modifyDN massage error" );
401                 return -1;
402         }
403
404         isupdate = be_shadow_update( op );
405         for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
406                 int                     is_oc = 0;
407                 Modifications           *ml;
408                 struct ldapmapping      *mapping = NULL;
409
410                 if ( (*mlp)->sml_desc == slap_schema.si_ad_objectClass 
411                                 || (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass )
412                 {
413                         is_oc = 1;
414
415                 } else if ( !isupdate && (*mlp)->sml_desc->ad_type->sat_no_user_mod  ) {
416                         goto next_mod;
417
418                 } else {
419                         int                     drop_missing;
420
421                         drop_missing = rwm_mapping( &rwmap->rwm_at,
422                                         &(*mlp)->sml_desc->ad_cname,
423                                         &mapping, RWM_MAP );
424                         if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
425                         {
426                                 goto cleanup_mod;
427                         }
428                 }
429
430                 if ( (*mlp)->sml_values != NULL ) {
431                         if ( is_oc ) {
432                                 int     last, j;
433
434                                 for ( last = 0; !BER_BVISNULL( &(*mlp)->sml_values[ last ] ); last++ )
435                                         /* count values */ ;
436                                 last--;
437
438                                 for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[ j ] ); j++ ) {
439                                         struct ldapmapping      *mapping = NULL;
440
441                                         ( void )rwm_mapping( &rwmap->rwm_oc, &(*mlp)->sml_values[ j ],
442                                                         &mapping, RWM_MAP );
443                                         if ( mapping == NULL ) {
444                                                 if ( rwmap->rwm_at.drop_missing ) {
445                                                         /* FIXME: we allow to remove objectClasses as well;
446                                                          * if the resulting entry is inconsistent, that's
447                                                          * the relayed database's business...
448                                                          */
449                                                         ch_free( (*mlp)->sml_values[ j ].bv_val );
450                                                         if ( last > j ) {
451                                                                 (*mlp)->sml_values[ j ] = (*mlp)->sml_values[ last ];
452                                                         }
453                                                         BER_BVZERO( &(*mlp)->sml_values[ last ] );
454                                                         last--;
455                                                         j--;
456                                                 }
457         
458                                         } else {
459                                                 ch_free( (*mlp)->sml_values[ j ].bv_val );
460                                                 ber_dupbv( &(*mlp)->sml_values[ j ], &mapping->m_dst );
461                                         }
462                                 }
463
464                         } else {
465                                 if ( (*mlp)->sml_desc->ad_type->sat_syntax ==
466                                                 slap_schema.si_syn_distinguishedName )
467                                 {
468 #ifdef ENABLE_REWRITE
469                                         rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
470                                                         (*mlp)->sml_values,
471                                                         (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
472 #else /* ! ENABLE_REWRITE */
473                                         rc = 1;
474                                         rc = rwm_dnattr_rewrite( op, rs, &rc, 
475                                                         (*mlp)->sml_values,
476                                                         (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
477 #endif /* ! ENABLE_REWRITE */
478
479                                 } else if ( (*mlp)->sml_desc == slap_schema.si_ad_ref ) {
480 #ifdef ENABLE_REWRITE
481                                         rc = rwm_referral_rewrite( op, rs,
482                                                         "referralAttrDN",
483                                                         (*mlp)->sml_values,
484                                                         (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
485 #else /* ! ENABLE_REWRITE */
486                                         rc = 1;
487                                         rc = rwm_referral_rewrite( op, rs, &rc,
488                                                         (*mlp)->sml_values,
489                                                         (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
490 #endif /* ! ENABLE_REWRITE */
491                                         if ( rc != LDAP_SUCCESS ) {
492                                                 goto cleanup_mod;
493                                         }
494                                 }
495
496                                 if ( rc != LDAP_SUCCESS ) {
497                                         goto cleanup_mod;
498                                 }
499                         }
500                 }
501
502 next_mod:;
503                 if ( mapping != NULL ) {
504                         /* use new attribute description */
505                         assert( mapping->m_dst_ad );
506                         (*mlp)->sml_desc = mapping->m_dst_ad;
507                 }
508
509                 mlp = &(*mlp)->sml_next;
510                 continue;
511
512 cleanup_mod:;
513                 ml = *mlp;
514                 *mlp = (*mlp)->sml_next;
515                 slap_mod_free( &ml->sml_mod, 0 );
516                 free( ml );
517         }
518
519         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
520         return SLAP_CB_CONTINUE;
521 }
522
523 static int
524 rwm_op_modrdn( Operation *op, SlapReply *rs )
525 {
526         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
527         struct ldaprwmap        *rwmap = 
528                         (struct ldaprwmap *)on->on_bi.bi_private;
529         
530         int                     rc;
531
532         if ( op->orr_newSup ) {
533                 dncookie        dc;
534                 struct berval   nnewSup = BER_BVNULL;
535                 struct berval   newSup = BER_BVNULL;
536
537                 /*
538                  * Rewrite the new superior, if defined and required
539                  */
540                 dc.rwmap = rwmap;
541 #ifdef ENABLE_REWRITE
542                 dc.conn = op->o_conn;
543                 dc.rs = rs;
544                 dc.ctx = "newSuperiorDN";
545 #else /* ! ENABLE_REWRITE */
546                 dc.tofrom = 0;
547                 dc.normalized = 0;
548 #endif /* ! ENABLE_REWRITE */
549                 newSup = *op->orr_newSup;
550                 nnewSup = *op->orr_nnewSup;
551                 rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
552                 if ( rc != LDAP_SUCCESS ) {
553                         op->o_bd->bd_info = (BackendInfo *)on->on_info;
554                         send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
555                         return -1;
556                 }
557
558                 if ( op->orr_newSup->bv_val != newSup.bv_val ) {
559                         op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
560                         op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
561                         *op->orr_newSup = newSup;
562                         *op->orr_nnewSup = nnewSup;
563                 }
564         }
565
566         /*
567          * Rewrite the dn, if needed
568          */
569 #ifdef ENABLE_REWRITE
570         rc = rwm_op_dn_massage( op, rs, "renameDN" );
571 #else /* ! ENABLE_REWRITE */
572         rc = 1;
573         rc = rwm_op_dn_massage( op, rs, &rc );
574 #endif /* ! ENABLE_REWRITE */
575         if ( rc != LDAP_SUCCESS ) {
576                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
577                 send_ldap_error( op, rs, rc, "renameDN massage error" );
578                 return -1;
579         }
580
581         /* TODO: rewrite newRDN, attribute types, 
582          * values of DN-valued attributes ... */
583         return SLAP_CB_CONTINUE;
584 }
585
586 static int
587 rwm_swap_attrs( Operation *op, SlapReply *rs )
588 {
589         slap_callback   *cb = op->o_callback;
590         AttributeName   *an = (AttributeName *)cb->sc_private;
591
592         rs->sr_attrs = an;
593         
594         return SLAP_CB_CONTINUE;
595 }
596
597 static int rwm_freeself( Operation *op, SlapReply *rs )
598 {
599         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_RESULT ) {
600                 assert( op->o_callback );
601
602                 op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
603                 op->o_callback = NULL;
604         }
605
606         return SLAP_CB_CONTINUE;
607 }
608
609 static int
610 rwm_op_search( Operation *op, SlapReply *rs )
611 {
612         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
613         struct ldaprwmap        *rwmap = 
614                         (struct ldaprwmap *)on->on_bi.bi_private;
615
616         int                     rc;
617         dncookie                dc;
618
619         struct berval           fstr = BER_BVNULL;
620         Filter                  *f = NULL;
621
622         slap_callback           *cb;
623         AttributeName           *an = NULL;
624
625         char                    *text = NULL;
626
627 #ifdef ENABLE_REWRITE
628         rc = rwm_op_dn_massage( op, rs, "searchDN" );
629 #else /* ! ENABLE_REWRITE */
630         rc = 1;
631         rc = rwm_op_dn_massage( op, rs, &rc );
632 #endif /* ! ENABLE_REWRITE */
633         if ( rc != LDAP_SUCCESS ) {
634                 text = "searchDN massage error";
635                 goto error_return;
636         }
637
638         /*
639          * Rewrite the dn if needed
640          */
641         dc.rwmap = rwmap;
642 #ifdef ENABLE_REWRITE
643         dc.conn = op->o_conn;
644         dc.rs = rs;
645         dc.ctx = "searchFilterAttrDN";
646 #else /* ! ENABLE_REWRITE */
647         dc.tofrom = 0;
648         dc.normalized = 0;
649 #endif /* ! ENABLE_REWRITE */
650
651         rc = rwm_filter_map_rewrite( &dc, op->ors_filter, &fstr );
652         if ( rc != LDAP_SUCCESS ) {
653                 text = "searchFilter/searchFilterAttrDN massage error";
654                 goto error_return;
655         }
656
657         f = str2filter_x( op, fstr.bv_val );
658
659         if ( f == NULL ) {
660                 text = "massaged filter parse error";
661                 goto error_return;
662         }
663
664         if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
665                 ch_free( op->ors_filterstr.bv_val );
666         }
667
668         if( op->ors_filter ) {
669                 filter_free_x( op, op->ors_filter );
670         }
671
672         op->ors_filter = f;
673         op->ors_filterstr = fstr;
674
675         rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
676                         op->ors_attrs, &an, RWM_MAP );
677         if ( rc != LDAP_SUCCESS ) {
678                 text = "attribute list mapping error";
679                 goto error_return;
680         }
681
682         cb = (slap_callback *) op->o_tmpcalloc( sizeof( slap_callback ),
683                         1, op->o_tmpmemctx );
684         if ( cb == NULL ) {
685                 rc = LDAP_NO_MEMORY;
686                 goto error_return;
687         }
688
689         cb->sc_response = rwm_swap_attrs;
690         cb->sc_cleanup = rwm_freeself;
691         cb->sc_private = (void *)op->ors_attrs;
692         cb->sc_next = op->o_callback;
693
694         op->o_callback = cb;
695         op->ors_attrs = an;
696
697         return SLAP_CB_CONTINUE;
698
699 error_return:;
700         if ( an != NULL ) {
701                 ch_free( an );
702         }
703
704         if ( f != NULL ) {
705                 filter_free_x( op, f );
706         }
707
708         if ( !BER_BVISNULL( &fstr ) ) {
709                 ch_free( fstr.bv_val );
710         }
711
712         op->o_bd->bd_info = (BackendInfo *)on->on_info;
713         send_ldap_error( op, rs, rc, text );
714
715         return -1;
716
717 }
718
719 static int
720 rwm_extended( Operation *op, SlapReply *rs )
721 {
722         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
723         int                     rc;
724
725 #ifdef ENABLE_REWRITE
726         rc = rwm_op_dn_massage( op, rs, "extendedDN" );
727 #else /* ! ENABLE_REWRITE */
728         rc = 1;
729         rc = rwm_op_dn_massage( op, rs, &rc );
730 #endif /* ! ENABLE_REWRITE */
731         if ( rc != LDAP_SUCCESS ) {
732                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
733                 send_ldap_error( op, rs, rc, "extendedDN massage error" );
734                 return -1;
735         }
736
737         /* TODO: rewrite/map extended data ? ... */
738         return SLAP_CB_CONTINUE;
739 }
740
741 static int
742 rwm_matched( Operation *op, SlapReply *rs )
743 {
744         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
745         struct ldaprwmap        *rwmap = 
746                         (struct ldaprwmap *)on->on_bi.bi_private;
747
748         struct berval           dn, mdn;
749         dncookie                dc;
750         int                     rc;
751
752         if ( rs->sr_matched == NULL ) {
753                 return SLAP_CB_CONTINUE;
754         }
755
756         dc.rwmap = rwmap;
757 #ifdef ENABLE_REWRITE
758         dc.conn = op->o_conn;
759         dc.rs = rs;
760         dc.ctx = "matchedDN";
761 #else /* ! ENABLE_REWRITE */
762         dc.tofrom = 0;
763         dc.normalized = 0;
764 #endif /* ! ENABLE_REWRITE */
765         ber_str2bv( rs->sr_matched, 0, 0, &dn );
766         mdn = dn;
767         rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
768         if ( rc != LDAP_SUCCESS ) {
769                 rs->sr_err = rc;
770                 rs->sr_text = "Rewrite error";
771                 return 1;
772         }
773
774         if ( mdn.bv_val != dn.bv_val ) {
775                 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
776                         ch_free( (void *)rs->sr_matched );
777
778                 } else {
779                         rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
780                 }
781                 rs->sr_matched = mdn.bv_val;
782         }
783         
784         return SLAP_CB_CONTINUE;
785 }
786
787 static int
788 rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
789 {
790         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
791         struct ldaprwmap        *rwmap = 
792                         (struct ldaprwmap *)on->on_bi.bi_private;
793
794         dncookie                dc;
795         int                     rc;
796         Attribute               **ap;
797         int                     isupdate;
798
799         /*
800          * Rewrite the dn attrs, if needed
801          */
802         dc.rwmap = rwmap;
803 #ifdef ENABLE_REWRITE
804         dc.conn = op->o_conn;
805         dc.rs = NULL; 
806 #else /* ! ENABLE_REWRITE */
807         dc.tofrom = 0;
808         dc.normalized = 0;
809 #endif /* ! ENABLE_REWRITE */
810
811         /* FIXME: the entries are in the remote mapping form;
812          * so we need to select those attributes we are willing
813          * to return, and remap them accordingly */
814
815         /* FIXME: in principle, one could map an attribute
816          * on top of another, which already exists.
817          * As such, in the end there might exist more than
818          * one instance of an attribute.
819          * We should at least check if this occurs, and issue
820          * an error (because multiple instances of attrs in 
821          * response are not valid), or merge the values (what
822          * about duplicate values?) */
823         isupdate = be_shadow_update( op );
824         for ( ap = a_first; *ap; ) {
825                 struct ldapmapping      *mapping;
826                 int                     drop_missing;
827                 int                     last;
828                 Attribute               *a;
829
830                 if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
831                 {
832                         /* go on */ ;
833                         
834                 } else {
835                         drop_missing = rwm_mapping( &rwmap->rwm_at,
836                                         &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
837                         if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
838                         {
839                                 goto cleanup_attr;
840                         }
841
842                         if ( mapping != NULL ) {
843                                 (*ap)->a_desc = mapping->m_dst_ad;
844                         }
845
846                         if ( op->ors_attrs != NULL && 
847                                         !SLAP_USERATTRS( rs->sr_attr_flags ) &&
848                                         !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
849                         {
850                                 goto cleanup_attr;
851                         }
852                 }
853
854                 if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
855                         /* will be generated by frontend */
856                         goto cleanup_attr;
857                 }
858
859                 if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod 
860                         && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
861                 {
862                         goto next_attr;
863                 }
864
865                 for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
866                         /* just count */ ;
867
868                 if ( last == 0 ) {
869                         /* empty? for now, we leave it in place */
870                         goto next_attr;
871                 }
872                 last--;
873
874                 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
875                                 || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
876                 {
877                         struct berval   *bv;
878                         
879                         for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
880                                 struct berval   mapped;
881
882                                 rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
883                                 if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
884                                         ch_free( bv[0].bv_val );
885                                         BER_BVZERO( &bv[0] );
886                                         if ( &(*ap)->a_vals[last] > &bv[0] ) {
887                                                 bv[0] = (*ap)->a_vals[last];
888                                                 BER_BVZERO( &(*ap)->a_vals[last] );
889                                         }
890                                         last--;
891                                         bv--;
892
893                                 } else if ( mapped.bv_val != bv[0].bv_val ) {
894                                         /*
895                                          * FIXME: after LBER_FREEing
896                                          * the value is replaced by
897                                          * ch_alloc'ed memory
898                                          */
899                                         ch_free( bv[0].bv_val );
900                                         ber_dupbv( &bv[0], &mapped );
901                                 }
902                         }
903
904                 /*
905                  * It is necessary to try to rewrite attributes with
906                  * dn syntax because they might be used in ACLs as
907                  * members of groups; since ACLs are applied to the
908                  * rewritten stuff, no dn-based subject clause could
909                  * be used at the ldap backend side (see
910                  * http://www.OpenLDAP.org/faq/data/cache/452.html)
911                  * The problem can be overcome by moving the dn-based
912                  * ACLs to the target directory server, and letting
913                  * everything pass thru the ldap backend. */
914                 /* FIXME: handle distinguishedName-like syntaxes, like
915                  * nameAndOptionalUID */
916                 } else if ( (*ap)->a_desc->ad_type->sat_syntax ==
917                                 slap_schema.si_syn_distinguishedName )
918                 {
919 #ifdef ENABLE_REWRITE
920                         dc.ctx = "searchAttrDN";
921 #endif /* ENABLE_REWRITE */
922                         rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
923                         if ( rc != LDAP_SUCCESS ) {
924                                 goto cleanup_attr;
925                         }
926
927                 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
928 #ifdef ENABLE_REWRITE
929                         dc.ctx = "searchAttrDN";
930 #endif /* ENABLE_REWRITE */
931                         rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
932                         if ( rc != LDAP_SUCCESS ) {
933                                 goto cleanup_attr;
934                         }
935                 }
936
937                 if ( mapping != NULL ) {
938                         /* rewrite the attribute description */
939                         assert( mapping->m_dst_ad );
940                         (*ap)->a_desc = mapping->m_dst_ad;
941                 }
942
943 next_attr:;
944                 ap = &(*ap)->a_next;
945                 continue;
946
947 cleanup_attr:;
948                 a = *ap;
949                 *ap = (*ap)->a_next;
950
951                 attr_free( a );
952         }
953
954         return 0;
955 }
956
957 static int
958 rwm_send_entry( Operation *op, SlapReply *rs )
959 {
960         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
961         struct ldaprwmap        *rwmap = 
962                         (struct ldaprwmap *)on->on_bi.bi_private;
963
964         Entry                   *e = NULL;
965         int                     flags;
966         struct berval           dn = BER_BVNULL,
967                                 ndn = BER_BVNULL;
968         dncookie                dc;
969         int                     rc;
970
971         assert( rs->sr_entry );
972
973         /*
974          * Rewrite the dn of the result, if needed
975          */
976         dc.rwmap = rwmap;
977 #ifdef ENABLE_REWRITE
978         dc.conn = op->o_conn;
979         dc.rs = NULL; 
980         dc.ctx = "searchEntryDN";
981 #else /* ! ENABLE_REWRITE */
982         dc.tofrom = 0;
983         dc.normalized = 0;
984 #endif /* ! ENABLE_REWRITE */
985
986         e = rs->sr_entry;
987         flags = rs->sr_flags;
988         if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
989                 /* FIXME: all we need to duplicate are:
990                  * - dn
991                  * - ndn
992                  * - attributes that are requested
993                  * - no values if attrsonly is set
994                  */
995
996                 e = entry_dup( e );
997                 if ( e == NULL ) {
998                         rc = LDAP_NO_MEMORY;
999                         goto fail;
1000                 }
1001
1002                 flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
1003         }
1004
1005         /*
1006          * Note: this may fail if the target host(s) schema differs
1007          * from the one known to the meta, and a DN with unknown
1008          * attributes is returned.
1009          */
1010         dn = e->e_name;
1011         ndn = e->e_nname;
1012         rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1013         if ( rc != LDAP_SUCCESS ) {
1014                 rc = 1;
1015                 goto fail;
1016         }
1017
1018         if ( e->e_name.bv_val != dn.bv_val ) {
1019                 ch_free( e->e_name.bv_val );
1020                 ch_free( e->e_nname.bv_val );
1021
1022                 e->e_name = dn;
1023                 e->e_nname = ndn;
1024         }
1025
1026         /* TODO: map entry attribute types, objectclasses 
1027          * and dn-valued attribute values */
1028
1029         /* FIXME: the entries are in the remote mapping form;
1030          * so we need to select those attributes we are willing
1031          * to return, and remap them accordingly */
1032         (void)rwm_attrs( op, rs, &e->e_attrs );
1033
1034         rs->sr_entry = e;
1035         rs->sr_flags = flags;
1036
1037         return SLAP_CB_CONTINUE;
1038
1039 fail:;
1040         if ( !BER_BVISNULL( &dn ) ) {
1041                 ch_free( dn.bv_val );
1042         }
1043
1044         if ( !BER_BVISNULL( &ndn ) ) {
1045                 ch_free( ndn.bv_val );
1046         }
1047
1048         if ( e != NULL && e != rs->sr_entry ) {
1049                 entry_free( e );
1050         }
1051
1052         return rc;
1053 }
1054
1055 static int
1056 rwm_operational( Operation *op, SlapReply *rs )
1057 {
1058         /* FIXME: the entries are in the remote mapping form;
1059          * so we need to select those attributes we are willing
1060          * to return, and remap them accordingly */
1061         if ( rs->sr_operational_attrs ) {
1062                 rwm_attrs( op, rs, &rs->sr_operational_attrs );
1063         }
1064
1065         return SLAP_CB_CONTINUE;
1066 }
1067
1068 #if 0
1069 /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1070  * rewritten for subsequent operations; fine for plain suffixmassage,
1071  * but destroys everything else */
1072 static int
1073 rwm_chk_referrals( Operation *op, SlapReply *rs )
1074 {
1075         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
1076         int                     rc;
1077
1078 #ifdef ENABLE_REWRITE
1079         rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1080 #else /* ! ENABLE_REWRITE */
1081         rc = 1;
1082         rc = rwm_op_dn_massage( op, rs, &rc );
1083 #endif /* ! ENABLE_REWRITE */
1084         if ( rc != LDAP_SUCCESS ) {
1085                 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1086                 send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1087                 return -1;
1088         }
1089
1090         return SLAP_CB_CONTINUE;
1091 }
1092 #endif
1093
1094 static int
1095 rwm_rw_config(
1096     BackendDB   *be,
1097     const char  *fname,
1098     int         lineno,
1099     int         argc,
1100     char        **argv
1101 )
1102 {
1103 #ifdef ENABLE_REWRITE
1104         slap_overinst           *on = (slap_overinst *) be->bd_info;
1105         struct ldaprwmap        *rwmap = 
1106                         (struct ldaprwmap *)on->on_bi.bi_private;
1107
1108         return rewrite_parse( rwmap->rwm_rw,
1109                                 fname, lineno, argc, argv );
1110
1111 #else /* !ENABLE_REWRITE */
1112         fprintf( stderr, "%s: line %d: rewrite capabilities "
1113                         "are not enabled\n", fname, lineno );
1114 #endif /* !ENABLE_REWRITE */
1115                 
1116         return 0;
1117 }
1118
1119 static int
1120 rwm_suffixmassage_config(
1121     BackendDB   *be,
1122     const char  *fname,
1123     int         lineno,
1124     int         argc,
1125     char        **argv
1126 )
1127 {
1128         slap_overinst           *on = (slap_overinst *) be->bd_info;
1129         struct ldaprwmap        *rwmap = 
1130                         (struct ldaprwmap *)on->on_bi.bi_private;
1131
1132         struct berval           bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1133         int                     massaged;
1134 #ifdef ENABLE_REWRITE
1135         int                     rc;
1136 #endif /* ENABLE_REWRITE */
1137                 
1138         /*
1139          * syntax:
1140          * 
1141          *      suffixmassage [<suffix>] <massaged suffix>
1142          *
1143          * the [<suffix>] field must be defined as a valid suffix
1144          * for the current database;
1145          * the <massaged suffix> shouldn't have already been
1146          * defined as a valid suffix for the current server
1147          */
1148         if ( argc == 2 ) {
1149                 if ( be->be_suffix == NULL ) {
1150                         fprintf( stderr, "%s: line %d: "
1151                                        " \"suffixMassage [<suffix>]"
1152                                        " <massaged suffix>\" without "
1153                                        "<suffix> part requires database "
1154                                        "suffix be defined first.\n",
1155                                 fname, lineno );
1156                         return 1;
1157                 }
1158                 bvnc = be->be_suffix[ 0 ];
1159                 massaged = 1;
1160
1161         } else if ( argc == 3 ) {
1162                 ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1163                 massaged = 2;
1164
1165         } else  {
1166                 fprintf( stderr, "%s: line %d: syntax is"
1167                                " \"suffixMassage [<suffix>]"
1168                                " <massaged suffix>\"\n",
1169                         fname, lineno );
1170                 return 1;
1171         }
1172
1173         if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1174                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1175                         fname, lineno, bvnc.bv_val );
1176                 return 1;
1177         }
1178
1179         ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1180         if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1181                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1182                                 fname, lineno, brnc.bv_val );
1183                 free( nvnc.bv_val );
1184                 free( pvnc.bv_val );
1185                 return 1;
1186         }
1187
1188 #ifdef ENABLE_REWRITE
1189         /*
1190          * The suffix massaging is emulated 
1191          * by means of the rewrite capabilities
1192          */
1193         rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1194                         &pvnc, &nvnc, &prnc, &nrnc );
1195         free( nvnc.bv_val );
1196         free( pvnc.bv_val );
1197         free( nrnc.bv_val );
1198         free( prnc.bv_val );
1199
1200         return( rc );
1201
1202 #else /* !ENABLE_REWRITE */
1203         ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
1204         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
1205                 
1206         ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
1207         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
1208 #endif /* !ENABLE_REWRITE */
1209
1210         return 0;
1211 }
1212
1213 static int
1214 rwm_m_config(
1215     BackendDB   *be,
1216     const char  *fname,
1217     int         lineno,
1218     int         argc,
1219     char        **argv
1220 )
1221 {
1222         slap_overinst           *on = (slap_overinst *) be->bd_info;
1223         struct ldaprwmap        *rwmap = 
1224                         (struct ldaprwmap *)on->on_bi.bi_private;
1225
1226         /* objectclass/attribute mapping */
1227         return rwm_map_config( &rwmap->rwm_oc,
1228                         &rwmap->rwm_at,
1229                         fname, lineno, argc, argv );
1230 }
1231
1232 static int
1233 rwm_response( Operation *op, SlapReply *rs )
1234 {
1235         slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
1236         struct ldaprwmap        *rwmap = 
1237                         (struct ldaprwmap *)on->on_bi.bi_private;
1238
1239         int             rc;
1240
1241         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1242                 return rwm_send_entry( op, rs );
1243         }
1244
1245         switch( op->o_tag ) {
1246         case LDAP_REQ_SEARCH:
1247                 /* Note: the operation attrs are remapped */
1248                 if ( op->ors_attrs != NULL && op->ors_attrs != rs->sr_attrs )
1249                 {
1250                         ch_free( op->ors_attrs );
1251                         op->ors_attrs = rs->sr_attrs;
1252                 }
1253                 /* fall thru */
1254
1255         case LDAP_REQ_BIND:
1256         case LDAP_REQ_ADD:
1257         case LDAP_REQ_DELETE:
1258         case LDAP_REQ_MODRDN:
1259         case LDAP_REQ_MODIFY:
1260         case LDAP_REQ_COMPARE:
1261         case LDAP_REQ_EXTENDED:
1262                 if ( rs->sr_ref ) {
1263                         dncookie                dc;
1264
1265                         /*
1266                          * Rewrite the dn of the referrals, if needed
1267                          */
1268                         dc.rwmap = rwmap;
1269 #ifdef ENABLE_REWRITE
1270                         dc.conn = op->o_conn;
1271                         dc.rs = NULL; 
1272                         dc.ctx = "referralDN";
1273 #else /* ! ENABLE_REWRITE */
1274                         dc.tofrom = 0;
1275                         dc.normalized = 0;
1276 #endif /* ! ENABLE_REWRITE */
1277                         rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1278                         if ( rc != LDAP_SUCCESS ) {
1279                                 rc = 1;
1280                                 break;
1281                         }
1282                 }
1283                 rc = rwm_matched( op, rs );
1284                 break;
1285
1286         default:
1287                 rc = SLAP_CB_CONTINUE;
1288                 break;
1289         }
1290
1291         return rc;
1292 }
1293
1294 static int
1295 rwm_db_config(
1296     BackendDB   *be,
1297     const char  *fname,
1298     int         lineno,
1299     int         argc,
1300     char        **argv
1301 )
1302 {
1303         int             rc = 0;
1304         char            *argv0 = NULL;
1305
1306         if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1307                 argv0 = argv[ 0 ];
1308                 argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1309         }
1310
1311         if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1312                 rc = rwm_rw_config( be, fname, lineno, argc, argv );
1313
1314         } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1315                 rc = rwm_m_config( be, fname, lineno, argc, argv );
1316
1317         } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1318                 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1319
1320         } else {
1321                 rc = SLAP_CONF_UNKNOWN;
1322         }
1323
1324         if ( argv0 ) {
1325                 argv[ 0 ] = argv0;
1326         }
1327
1328         return rc;
1329 }
1330
1331 static int
1332 rwm_db_init(
1333         BackendDB *be
1334 )
1335 {
1336         slap_overinst           *on = (slap_overinst *) be->bd_info;
1337         struct ldapmapping      *mapping = NULL;
1338         struct ldaprwmap        *rwmap;
1339
1340         rwmap = (struct ldaprwmap *)ch_malloc(sizeof(struct ldaprwmap));
1341         memset(rwmap, 0, sizeof(struct ldaprwmap));
1342
1343 #ifdef ENABLE_REWRITE
1344         rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
1345         if ( rwmap->rwm_rw == NULL ) {
1346                 ch_free( rwmap );
1347                 return -1;
1348         }
1349
1350         {
1351                 char    *rargv[3];
1352
1353                 /* this rewriteContext by default must be null;
1354                  * rules can be added if required */
1355                 rargv[ 0 ] = "rewriteContext";
1356                 rargv[ 1 ] = "searchFilter";
1357                 rargv[ 2 ] = NULL;
1358                 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
1359
1360                 rargv[ 0 ] = "rewriteContext";
1361                 rargv[ 1 ] = "default";
1362                 rargv[ 2 ] = NULL;
1363                 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
1364         }
1365         
1366 #endif /* ENABLE_REWRITE */
1367
1368         if ( rwm_map_init( &rwmap->rwm_oc, &mapping ) != LDAP_SUCCESS ||
1369                         rwm_map_init( &rwmap->rwm_at, &mapping ) != LDAP_SUCCESS )
1370         {
1371                 return 1;
1372         }
1373
1374         on->on_bi.bi_private = (void *)rwmap;
1375
1376         return 0;
1377 }
1378
1379 static int
1380 rwm_db_destroy(
1381         BackendDB *be
1382 )
1383 {
1384         slap_overinst   *on = (slap_overinst *) be->bd_info;
1385         int             rc = 0;
1386
1387         if ( on->on_bi.bi_private ) {
1388                 struct ldaprwmap        *rwmap = 
1389                         (struct ldaprwmap *)on->on_bi.bi_private;
1390
1391 #ifdef ENABLE_REWRITE
1392                 if (rwmap->rwm_rw) {
1393                         rewrite_info_delete( &rwmap->rwm_rw );
1394                 }
1395 #else /* !ENABLE_REWRITE */
1396                 if ( rwmap->rwm_suffix_massage ) {
1397                         ber_bvarray_free( rwmap->rwm_suffix_massage );
1398                 }
1399 #endif /* !ENABLE_REWRITE */
1400
1401                 avl_free( rwmap->rwm_oc.remap, NULL );
1402                 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
1403                 avl_free( rwmap->rwm_at.remap, NULL );
1404                 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
1405         }
1406
1407         return rc;
1408 }
1409
1410 static slap_overinst rwm = { { NULL } };
1411
1412 int
1413 rwm_init(void)
1414 {
1415         memset( &rwm, 0, sizeof( slap_overinst ) );
1416
1417         rwm.on_bi.bi_type = "rwm";
1418
1419         rwm.on_bi.bi_db_init = rwm_db_init;
1420         rwm.on_bi.bi_db_config = rwm_db_config;
1421         rwm.on_bi.bi_db_destroy = rwm_db_destroy;
1422
1423         rwm.on_bi.bi_op_bind = rwm_op_bind;
1424         rwm.on_bi.bi_op_search = rwm_op_search;
1425         rwm.on_bi.bi_op_compare = rwm_op_compare;
1426         rwm.on_bi.bi_op_modify = rwm_op_modify;
1427         rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
1428         rwm.on_bi.bi_op_add = rwm_op_add;
1429         rwm.on_bi.bi_op_delete = rwm_op_delete;
1430         rwm.on_bi.bi_op_unbind = rwm_op_unbind;
1431         rwm.on_bi.bi_extended = rwm_extended;
1432
1433         rwm.on_bi.bi_operational = rwm_operational;
1434         rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
1435
1436         rwm.on_response = rwm_response;
1437
1438         return overlay_register( &rwm );
1439 }
1440
1441 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
1442 int
1443 init_module( int argc, char *argv[] )
1444 {
1445         return rwm_init();
1446 }
1447 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
1448
1449 #endif /* SLAPD_OVER_RWM */