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