]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwmmap.c
cleanup
[openldap] / servers / slapd / overlays / rwmmap.c
1 /* rwmmap.c - rewrite/mapping routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1999-2004 The OpenLDAP Foundation.
6  * Portions Copyright 1999-2003 Howard Chu.
7  * Portions Copyright 2000-2003 Pierangelo Masarati.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by the Howard Chu for inclusion
20  * in OpenLDAP Software and subsequently enhanced by Pierangelo
21  * Masarati.
22  */
23
24 #include "portable.h"
25
26 #ifdef SLAPD_OVER_RWM
27
28 #include <stdio.h>
29
30 #include <ac/string.h>
31 #include <ac/socket.h>
32
33 #include "slap.h"
34 #include "rwm.h"
35
36 #undef ldap_debug       /* silence a warning in ldap-int.h */
37 #include "../../../libraries/libldap/ldap-int.h"
38
39 int
40 rwm_mapping_cmp( const void *c1, const void *c2 )
41 {
42         struct ldapmapping *map1 = (struct ldapmapping *)c1;
43         struct ldapmapping *map2 = (struct ldapmapping *)c2;
44         int rc = map1->m_src.bv_len - map2->m_src.bv_len;
45         
46         if ( rc ) {
47                 return rc;
48         }
49
50         return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
51 }
52
53 int
54 rwm_mapping_dup( void *c1, void *c2 )
55 {
56         struct ldapmapping *map1 = (struct ldapmapping *)c1;
57         struct ldapmapping *map2 = (struct ldapmapping *)c2;
58         int rc = map1->m_src.bv_len - map2->m_src.bv_len;
59
60         if ( rc ) {
61                 return 0;
62         }
63
64         return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
65 }
66
67 int
68 rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
69 {
70         struct ldapmapping      *mapping;
71         const char              *text;
72         int                     rc;
73
74         assert( m );
75
76         *m = NULL;
77         
78         mapping = (struct ldapmapping *)ch_calloc( 2, 
79                         sizeof( struct ldapmapping ) );
80         if ( mapping == NULL ) {
81                 return LDAP_NO_MEMORY;
82         }
83
84         /* FIXME: I don't think this is needed any more... */
85         rc = slap_str2ad( "objectClass", &mapping->m_src_ad, &text );
86         if ( rc != LDAP_SUCCESS ) {
87                 return rc;
88         }
89
90         mapping->m_dst_ad = mapping->m_src_ad;
91         ber_dupbv( &mapping->m_dst, &mapping->m_src_ad->ad_cname );
92         ber_dupbv( &mapping->m_dst, &mapping->m_src );
93
94         mapping[1].m_src = mapping->m_src;
95         mapping[1].m_dst = mapping->m_dst;
96
97         avl_insert( &lm->map, (caddr_t)mapping, 
98                         rwm_mapping_cmp, rwm_mapping_dup );
99         avl_insert( &lm->remap, (caddr_t)&mapping[1], 
100                         rwm_mapping_cmp, rwm_mapping_dup );
101
102         *m = mapping;
103
104         return rc;
105 }
106
107 int
108 rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
109 {
110         Avlnode *tree;
111         struct ldapmapping fmapping;
112
113         assert( m );
114
115         if ( remap == RWM_REMAP ) {
116                 tree = map->remap;
117
118         } else {
119                 tree = map->map;
120         }
121
122         fmapping.m_src = *s;
123         *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
124                         rwm_mapping_cmp );
125
126         if ( *m == NULL ) {
127                 return map->drop_missing;
128         }
129
130         return 0;
131 }
132
133 void
134 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
135 {
136         struct ldapmapping *mapping;
137
138         BER_BVZERO( bv );
139         rwm_mapping( map, s, &mapping, remap );
140         if ( mapping != NULL ) {
141                 if ( !BER_BVISNULL( &mapping->m_dst ) ) {
142                         *bv = mapping->m_dst;
143                 }
144                 return;
145         }
146
147         if ( !map->drop_missing ) {
148                 *bv = *s;
149         }
150 }
151
152 /*
153  * Map attribute names in place
154  */
155 int
156 rwm_map_attrnames(
157                 struct ldapmap *at_map,
158                 struct ldapmap *oc_map,
159                 AttributeName *an,
160                 AttributeName **anp,
161                 int remap
162 )
163 {
164         int             i, j;
165
166         if ( an == NULL ) {
167                 return LDAP_SUCCESS;
168         }
169
170         for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
171                 /* just count */ ;
172         *anp = ch_malloc( ( i + 1 )* sizeof( AttributeName ) );
173         if ( *anp == NULL ) {
174                 return LDAP_NO_MEMORY;
175         }
176
177         for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
178                 struct ldapmapping      *m;
179                 int                     at_drop_missing = 0,
180                                         oc_drop_missing = 0;
181
182                 if ( an[i].an_desc ) {
183                         if ( !at_map ) {
184                                 /* FIXME: better leave as is? */
185                                 continue;
186                         }
187                                 
188                         at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
189                         if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
190                                 continue;
191                         }
192
193                         if ( !m ) {
194                                 (*anp)[j] = an[i];
195                                 j++;
196                                 continue;
197                         }
198
199                         (*anp)[j] = an[i];
200                         if ( remap == RWM_MAP ) {
201                                 (*anp)[j].an_name = m->m_dst;
202                                 (*anp)[j].an_desc = m->m_dst_ad;
203                         } else {
204                                 (*anp)[j].an_name = m->m_src;
205                                 (*anp)[j].an_desc = m->m_src_ad;
206
207                         }
208
209                         j++;
210                         continue;
211
212                 } else if ( an[i].an_oc ) {
213                         if ( !oc_map ) {
214                                 /* FIXME: better leave as is? */
215                                 continue;
216                         }
217
218                         oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
219
220                         if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
221                                 continue;
222                         }
223
224                         if ( !m ) {
225                                 (*anp)[j] = an[i];
226                                 j++;
227                                 continue;
228                         }
229
230                         (*anp)[j] = an[i];
231                         if ( remap == RWM_MAP ) {
232                                 (*anp)[j].an_name = m->m_dst;
233                                 (*anp)[j].an_oc = m->m_dst_oc;
234                         } else {
235                                 (*anp)[j].an_name = m->m_src;
236                                 (*anp)[j].an_oc = m->m_src_oc;
237                         }
238
239                 } else {
240                         at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
241                 
242                         if ( at_drop_missing || !m ) {
243
244                                 oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
245
246                                 /* if both at_map and oc_map required to drop missing,
247                                  * then do it */
248                                 if ( oc_drop_missing && at_drop_missing ) {
249                                         continue;
250                                 }
251
252                                 /* if no oc_map mapping was found and at_map required
253                                  * to drop missing, then do it; otherwise, at_map wins
254                                  * and an is considered an attr and is left unchanged */
255                                 if ( !m ) {
256                                         if ( at_drop_missing ) {
257                                                 continue;
258                                         }
259                                         (*anp)[j] = an[i];
260                                         j++;
261                                         continue;
262                                 }
263         
264                                 if ( BER_BVISNULL( &m->m_dst ) ) {
265                                         continue;
266                                 }
267
268                                 (*anp)[j] = an[i];
269                                 if ( remap == RWM_MAP ) {
270                                         (*anp)[j].an_name = m->m_dst;
271                                         (*anp)[j].an_oc = m->m_dst_oc;
272                                 } else {
273                                         (*anp)[j].an_name = m->m_src;
274                                         (*anp)[j].an_oc = m->m_src_oc;
275                                 }
276                                 j++;
277                                 continue;
278                         }
279
280                         if ( !BER_BVISNULL( &m->m_dst ) ) {
281                                 (*anp)[j] = an[i];
282                                 if ( remap == RWM_MAP ) {
283                                         (*anp)[j].an_name = m->m_dst;
284                                         (*anp)[j].an_desc = m->m_dst_ad;
285                                 } else {
286                                         (*anp)[j].an_name = m->m_src;
287                                         (*anp)[j].an_desc = m->m_src_ad;
288                                 }
289                                 j++;
290                                 continue;
291                         }
292                 }
293         }
294
295         if ( j == 0 && i != 0 ) {
296                 memset( &(*anp)[0], 0, sizeof( AttributeName ) );
297                 BER_BVSTR( &(*anp)[0].an_name, LDAP_NO_ATTRS );
298         }
299         memset( &(*anp)[j], 0, sizeof( AttributeName ) );
300
301         return LDAP_SUCCESS;
302 }
303
304 int
305 rwm_map_attrs(
306                 struct ldapmap *at_map,
307                 AttributeName *an,
308                 int remap,
309                 char ***mapped_attrs
310 )
311 {
312         int i, j;
313         char **na;
314
315         if ( an == NULL ) {
316                 *mapped_attrs = NULL;
317                 return LDAP_SUCCESS;
318         }
319
320         for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
321                 /*  */
322         }
323
324         na = (char **)ch_calloc( i + 1, sizeof( char * ) );
325         if (na == NULL) {
326                 *mapped_attrs = NULL;
327                 return LDAP_NO_MEMORY;
328         }
329
330         for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
331                 struct ldapmapping      *m;
332                 
333                 if ( rwm_mapping( at_map, &an[i].an_name, &m, remap ) ) {
334                         continue;
335                 }
336
337                 if ( !m || ( m && !BER_BVISNULL( &m->m_dst ) ) ) {
338                         na[j++] = m->m_dst.bv_val;
339                 }
340         }
341         if ( j == 0 && i != 0 ) {
342                 na[j++] = LDAP_NO_ATTRS;
343         }
344         na[j] = NULL;
345
346         *mapped_attrs = na;
347         return LDAP_SUCCESS;
348 }
349
350 static int
351 map_attr_value(
352                 dncookie                *dc,
353                 AttributeDescription    *ad,
354                 struct berval           *mapped_attr,
355                 struct berval           *value,
356                 struct berval           *mapped_value,
357                 int                     remap )
358 {
359         struct berval           vtmp;
360         int                     freeval = 0;
361
362         rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
363         if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
364                 /*
365                  * FIXME: are we sure we need to search oc_map if at_map fails?
366                  */
367                 rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap );
368                 if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) )
369                 {
370                         *mapped_attr = ad->ad_cname;
371                 }
372         }
373
374         if ( value == NULL ) {
375                 return 0;
376         }
377
378         if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
379         {
380                 dncookie        fdc = *dc;
381                 int             rc;
382
383 #ifdef ENABLE_REWRITE
384                 fdc.ctx = "searchFilterAttrDN";
385 #endif
386
387                 rc = rwm_dn_massage( &fdc, value, &vtmp, NULL );
388                 switch ( rc ) {
389                 case LDAP_SUCCESS:
390                         if ( vtmp.bv_val != value->bv_val ) {
391                                 freeval = 1;
392                         }
393                         break;
394                 
395                 case LDAP_UNWILLING_TO_PERFORM:
396                 case LDAP_OTHER:
397                 default:
398                         return -1;
399                 }
400
401         } else if ( ad == slap_schema.si_ad_objectClass
402                         || ad == slap_schema.si_ad_structuralObjectClass )
403         {
404                 rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
405                 if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
406                         vtmp = *value;
407                 }
408                 
409         } else {
410                 vtmp = *value;
411         }
412
413         filter_escape_value( &vtmp, mapped_value );
414
415         if ( freeval ) {
416                 ber_memfree( vtmp.bv_val );
417         }
418         
419         return 0;
420 }
421
422 static int
423 rwm_int_filter_map_rewrite(
424                 dncookie                *dc,
425                 Filter                  *f,
426                 struct berval           *fstr )
427 {
428         int             i;
429         Filter          *p;
430         struct berval   atmp,
431                         vtmp,
432                         tmp;
433         static struct berval
434                         ber_bvfalse = BER_BVC( "(?=false)" ),
435                         ber_bvtrue = BER_BVC( "(?=true)" ),
436                         ber_bvundefined = BER_BVC( "(?=undefined)" ),
437                         ber_bverror = BER_BVC( "(?=error)" ),
438                         ber_bvunknown = BER_BVC( "(?=unknown)" ),
439                         ber_bvnone = BER_BVC( "(?=none)" );
440         ber_len_t       len;
441
442         if ( f == NULL ) {
443                 ber_dupbv( fstr, &ber_bvnone );
444                 return -1;
445         }
446
447         switch ( f->f_choice ) {
448         case LDAP_FILTER_EQUALITY:
449                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
450                                         &f->f_av_value, &vtmp, RWM_MAP ) )
451                 {
452                         return -1;
453                 }
454
455                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
456                 fstr->bv_val = malloc( fstr->bv_len + 1 );
457
458                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
459                         atmp.bv_val, vtmp.bv_val );
460
461                 ber_memfree( vtmp.bv_val );
462                 break;
463
464         case LDAP_FILTER_GE:
465                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
466                                         &f->f_av_value, &vtmp, RWM_MAP ) )
467                 {
468                         return -1;
469                 }
470
471                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
472                 fstr->bv_val = malloc( fstr->bv_len + 1 );
473
474                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
475                         atmp.bv_val, vtmp.bv_val );
476
477                 ber_memfree( vtmp.bv_val );
478                 break;
479
480         case LDAP_FILTER_LE:
481                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
482                                         &f->f_av_value, &vtmp, RWM_MAP ) )
483                 {
484                         return -1;
485                 }
486
487                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
488                 fstr->bv_val = malloc( fstr->bv_len + 1 );
489
490                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
491                         atmp.bv_val, vtmp.bv_val );
492
493                 ber_memfree( vtmp.bv_val );
494                 break;
495
496         case LDAP_FILTER_APPROX:
497                 if ( map_attr_value( dc, f->f_av_desc, &atmp,
498                                         &f->f_av_value, &vtmp, RWM_MAP ) )
499                 {
500                         return -1;
501                 }
502
503                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
504                 fstr->bv_val = malloc( fstr->bv_len + 1 );
505
506                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
507                         atmp.bv_val, vtmp.bv_val );
508
509                 ber_memfree( vtmp.bv_val );
510                 break;
511
512         case LDAP_FILTER_SUBSTRINGS:
513                 if ( map_attr_value( dc, f->f_sub_desc, &atmp,
514                                         NULL, NULL, RWM_MAP ) )
515                 {
516                         return -1;
517                 }
518
519                 /* cannot be a DN ... */
520
521                 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
522                 fstr->bv_val = malloc( fstr->bv_len + 128 );
523
524                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
525                         atmp.bv_val );
526
527                 if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
528                         len = fstr->bv_len;
529
530                         filter_escape_value( &f->f_sub_initial, &vtmp );
531
532                         fstr->bv_len += vtmp.bv_len;
533                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
534
535                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
536                                 /* "(attr=" */ "%s*)",
537                                 vtmp.bv_val );
538
539                         ber_memfree( vtmp.bv_val );
540                 }
541
542                 if ( f->f_sub_any != NULL ) {
543                         for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
544                                 len = fstr->bv_len;
545                                 filter_escape_value( &f->f_sub_any[i], &vtmp );
546
547                                 fstr->bv_len += vtmp.bv_len + 1;
548                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
549
550                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
551                                         /* "(attr=[init]*[any*]" */ "%s*)",
552                                         vtmp.bv_val );
553                                 ber_memfree( vtmp.bv_val );
554                         }
555                 }
556
557                 if ( !BER_BVISNULL( &f->f_sub_final ) ) {
558                         len = fstr->bv_len;
559
560                         filter_escape_value( &f->f_sub_final, &vtmp );
561
562                         fstr->bv_len += vtmp.bv_len;
563                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
564
565                         snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
566                                 /* "(attr=[init*][any*]" */ "%s)",
567                                 vtmp.bv_val );
568
569                         ber_memfree( vtmp.bv_val );
570                 }
571
572                 break;
573
574         case LDAP_FILTER_PRESENT:
575                 if ( map_attr_value( dc, f->f_desc, &atmp,
576                                         NULL, NULL, RWM_MAP ) )
577                 {
578                         return -1;
579                 }
580
581                 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
582                 fstr->bv_val = malloc( fstr->bv_len + 1 );
583
584                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
585                         atmp.bv_val );
586                 break;
587
588         case LDAP_FILTER_AND:
589         case LDAP_FILTER_OR:
590         case LDAP_FILTER_NOT:
591                 fstr->bv_len = STRLENOF( "(%)" );
592                 fstr->bv_val = malloc( fstr->bv_len + 128 );
593
594                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
595                         f->f_choice == LDAP_FILTER_AND ? '&' :
596                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
597
598                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
599                         len = fstr->bv_len;
600
601                         if ( rwm_int_filter_map_rewrite( dc, p, &vtmp ) )
602                         {
603                                 return -1;
604                         }
605                         
606                         fstr->bv_len += vtmp.bv_len;
607                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
608
609                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
610                                 /*"("*/ "%s)", vtmp.bv_val );
611
612                         ch_free( vtmp.bv_val );
613                 }
614
615                 break;
616
617         case LDAP_FILTER_EXT: {
618                 if ( f->f_mr_desc ) {
619                         if ( map_attr_value( dc, f->f_mr_desc, &atmp,
620                                                 &f->f_mr_value, &vtmp, RWM_MAP ) )
621                         {
622                                 return -1;
623                         }
624
625                 } else {
626                         BER_BVSTR( &atmp, "" );
627                         filter_escape_value( &f->f_mr_value, &vtmp );
628                 }
629                         
630
631                 fstr->bv_len = atmp.bv_len +
632                         ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
633                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
634                         vtmp.bv_len + STRLENOF( "(:=)" );
635                 fstr->bv_val = malloc( fstr->bv_len + 1 );
636
637                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
638                         atmp.bv_val,
639                         f->f_mr_dnattrs ? ":dn" : "",
640                         !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
641                         !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
642                         vtmp.bv_val );
643                 ber_memfree( vtmp.bv_val );
644                 } break;
645
646         case SLAPD_FILTER_COMPUTED:
647                 switch ( f->f_result ) {
648                 case LDAP_COMPARE_FALSE:
649                         tmp = ber_bvfalse;
650                         break;
651
652                 case LDAP_COMPARE_TRUE:
653                         tmp = ber_bvtrue;
654                         break;
655                         
656                 case SLAPD_COMPARE_UNDEFINED:
657                         tmp = ber_bvundefined;
658                         break;
659                         
660                 default:
661                         tmp = ber_bverror;
662                         break;
663                 }
664
665                 ber_dupbv( fstr, &tmp );
666                 break;
667                 
668         default:
669                 ber_dupbv( fstr, &ber_bvunknown );
670                 break;
671         }
672
673         return 0;
674 }
675
676 int
677 rwm_filter_map_rewrite(
678                 dncookie                *dc,
679                 Filter                  *f,
680                 struct berval           *fstr )
681 {
682         int             rc;
683         dncookie        fdc;
684         struct berval   ftmp;
685
686         rc = rwm_int_filter_map_rewrite( dc, f, fstr );
687
688 #ifdef ENABLE_REWRITE
689         if ( rc != LDAP_SUCCESS ) {
690                 return rc;
691         }
692
693         fdc = *dc;
694         ftmp = *fstr;
695
696         fdc.ctx = "searchFilter";
697
698         switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
699                                 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 
700                                 fdc.conn, &fstr->bv_val )) {
701         case REWRITE_REGEXEC_OK:
702                 if ( !BER_BVISNULL( fstr ) ) {
703                         fstr->bv_len = strlen( fstr->bv_val );
704                         free( ftmp.bv_val );
705
706                 } else {
707                         *fstr = ftmp;
708                 }
709
710 #ifdef NEW_LOGGING
711                 LDAP_LOG( BACK_LDAP, DETAIL1, 
712                         "[rw] %s: \"%s\" -> \"%s\"\n",
713                         dc->ctx, ftmp.bv_val, fstr->bv_val );           
714 #else /* !NEW_LOGGING */
715                 Debug( LDAP_DEBUG_ARGS,
716                         "[rw] %s: \"%s\" -> \"%s\"\n",
717                         dc->ctx, ftmp.bv_val, fstr->bv_val );           
718 #endif /* !NEW_LOGGING */
719                 rc = LDAP_SUCCESS;
720                 break;
721                 
722         case REWRITE_REGEXEC_UNWILLING:
723                 if ( fdc.rs ) {
724                         fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
725                         fdc.rs->sr_text = "Operation not allowed";
726                 }
727                 rc = LDAP_UNWILLING_TO_PERFORM;
728                 break;
729                 
730         case REWRITE_REGEXEC_ERR:
731                 if ( fdc.rs ) {
732                         fdc.rs->sr_err = LDAP_OTHER;
733                         fdc.rs->sr_text = "Rewrite error";
734                 }
735                 rc = LDAP_OTHER;
736                 break;
737         }
738
739 #endif /* ENABLE_REWRITE */
740         return rc;
741 }
742
743 /*
744  * I don't like this much, but we need two different
745  * functions because different heap managers may be
746  * in use in back-ldap/meta to reduce the amount of
747  * calls to malloc routines, and some of the free()
748  * routines may be macros with args
749  */
750 int
751 rwm_dnattr_rewrite(
752         Operation               *op,
753         SlapReply               *rs,
754         void                    *cookie,
755         BerVarray               a_vals,
756         BerVarray               *pa_nvals )
757 {
758         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
759         struct ldaprwmap        *rwmap = 
760                         (struct ldaprwmap *)on->on_bi.bi_private;
761
762         int                     i, last;
763
764         dncookie                dc;
765         struct berval           dn, ndn, *pndn = NULL;
766
767         assert( a_vals );
768
769         /*
770          * Rewrite the bind dn if needed
771          */
772         dc.rwmap = rwmap;
773 #ifdef ENABLE_REWRITE
774         dc.conn = op->o_conn;
775         dc.rs = rs;
776         dc.ctx = (char *)cookie;
777 #else
778         dc.tofrom = ((int *)cookie)[0];
779         dc.normalized = 0;
780 #endif
781
782         for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
783         if ( pa_nvals != NULL ) {
784                 pndn = &ndn;
785
786                 if ( *pa_nvals == NULL ) {
787                         *pa_nvals = ch_malloc( last * sizeof(struct berval) );
788                         memset( *pa_nvals, 0, last * sizeof(struct berval) );
789                 }
790         }
791         last--;
792
793         for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
794                 int             rc;
795
796                 rc = rwm_dn_massage( &dc, &a_vals[i], &dn, pndn );
797                 switch ( rc ) {
798                 case LDAP_UNWILLING_TO_PERFORM:
799                         /*
800                          * FIXME: need to check if it may be considered 
801                          * legal to trim values when adding/modifying;
802                          * it should be when searching (e.g. ACLs).
803                          */
804                         ch_free( a_vals[i].bv_val );
805                         if (last > i ) {
806                                 a_vals[i] = a_vals[last];
807                                 if ( pa_nvals ) {
808                                         (*pa_nvals)[i] = (*pa_nvals)[last];
809                                 }
810                         }
811                         BER_BVZERO( &a_vals[last] );
812                         if ( pa_nvals ) {
813                                 BER_BVZERO( &(*pa_nvals)[last] );
814                         }
815                         last--;
816                         break;
817                 
818                 case LDAP_SUCCESS:
819                         if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
820                                 ch_free( a_vals[i].bv_val );
821                                 a_vals[i] = dn;
822                                 if ( pa_nvals ) {
823                                         if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
824                                                 ch_free( (*pa_nvals)[i].bv_val );
825                                         }
826                                         (*pa_nvals)[i] = *pndn;
827                                 }
828                         }
829                         break;
830
831                 default:
832                         /* leave attr untouched if massage failed */
833                         if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
834                                 dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
835                         }
836                         break;
837                 }
838         }
839         
840         return 0;
841 }
842
843 int
844 rwm_dnattr_result_rewrite(
845         dncookie                *dc,
846         BerVarray               a_vals
847 )
848 {
849         int             i, last;
850
851         for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
852         last--;
853
854         for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
855                 struct berval   dn;
856                 int             rc;
857                 
858                 rc = rwm_dn_massage( dc, &a_vals[i], &dn, NULL );
859                 switch ( rc ) {
860                 case LDAP_UNWILLING_TO_PERFORM:
861                         /*
862                          * FIXME: need to check if it may be considered 
863                          * legal to trim values when adding/modifying;
864                          * it should be when searching (e.g. ACLs).
865                          */
866                         LBER_FREE( &a_vals[i].bv_val );
867                         if ( last > i ) {
868                                 a_vals[i] = a_vals[last];
869                         }
870                         BER_BVZERO( &a_vals[last] );
871                         last--;
872                         break;
873
874                 default:
875                         /* leave attr untouched if massage failed */
876                         if ( !BER_BVISNULL( &dn ) && a_vals[i].bv_val != dn.bv_val ) {
877                                 LBER_FREE( a_vals[i].bv_val );
878                                 a_vals[i] = dn;
879                         }
880                         break;
881                 }
882         }
883
884         return 0;
885 }
886
887 void
888 rwm_mapping_free( void *v_mapping )
889 {
890         struct ldapmapping *mapping = v_mapping;
891
892         if ( !BER_BVISNULL( &mapping[0].m_src ) ) {
893                 ch_free( mapping[0].m_src.bv_val );
894         }
895
896         if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
897                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
898                         if ( mapping[0].m_src_oc ) {
899                                 ch_free( mapping[0].m_src_oc );
900                         }
901
902                 } else {
903                         if ( mapping[0].m_src_ad ) {
904                                 ch_free( mapping[0].m_src_ad );
905                         }
906                 }
907         }
908
909         if ( !BER_BVISNULL( &mapping[0].m_dst ) ) {
910                 ch_free( mapping[0].m_dst.bv_val );
911         }
912
913         if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
914                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
915                         if ( mapping[0].m_dst_oc ) {
916                                 ch_free( mapping[0].m_dst_oc );
917                         }
918
919                 } else {
920                         if ( mapping[0].m_dst_ad ) {
921                                 ch_free( mapping[0].m_dst_ad );
922                         }
923                 }
924         }
925
926         ch_free( mapping );
927
928 }
929
930 #endif /* SLAPD_OVER_RWM */