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