]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwmmap.c
check sat_equality before using it (ITS#6943)
[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-2011 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 != NULL );
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         /* NOTE: this is needed to make sure that
85          *      rwm-map attribute *
86          * does not  filter out all attributes including objectClass */
87         rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
88         if ( rc != LDAP_SUCCESS ) {
89                 ch_free( mapping );
90                 return rc;
91         }
92
93         mapping[0].m_dst_ad = mapping[0].m_src_ad;
94         ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
95         ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
96
97         mapping[1].m_src = mapping[0].m_src;
98         mapping[1].m_dst = mapping[0].m_dst;
99         mapping[1].m_src_ad = mapping[0].m_src_ad;
100         mapping[1].m_dst_ad = mapping[1].m_src_ad;
101
102         avl_insert( &lm->map, (caddr_t)&mapping[0], 
103                         rwm_mapping_cmp, rwm_mapping_dup );
104         avl_insert( &lm->remap, (caddr_t)&mapping[1], 
105                         rwm_mapping_cmp, rwm_mapping_dup );
106
107         *m = mapping;
108
109         return rc;
110 }
111
112 int
113 rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
114 {
115         Avlnode *tree;
116         struct ldapmapping fmapping;
117
118         if ( map == NULL ) {
119                 return 0;
120         }
121
122         assert( m != NULL );
123
124         /* let special attrnames slip through (ITS#5760) */
125         if ( bvmatch( s, slap_bv_no_attrs )
126                 || bvmatch( s, slap_bv_all_user_attrs )
127                 || bvmatch( s, slap_bv_all_operational_attrs ) )
128         {
129                 *m = NULL;
130                 return 0;
131         }
132
133         if ( remap == RWM_REMAP ) {
134                 tree = map->remap;
135
136         } else {
137                 tree = map->map;
138         }
139
140         fmapping.m_src = *s;
141         *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
142                         rwm_mapping_cmp );
143
144         if ( *m == NULL ) {
145                 return map->drop_missing;
146         }
147
148         return 0;
149 }
150
151 void
152 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
153 {
154         struct ldapmapping *mapping;
155
156         /* map->map may be NULL when mapping is configured,
157          * but map->remap can't */
158         if ( map->remap == NULL ) {
159                 *bv = *s;
160                 return;
161         }
162
163         BER_BVZERO( bv );
164         ( void )rwm_mapping( map, s, &mapping, remap );
165         if ( mapping != NULL ) {
166                 if ( !BER_BVISNULL( &mapping->m_dst ) ) {
167                         *bv = mapping->m_dst;
168                 }
169                 return;
170         }
171
172         if ( !map->drop_missing ) {
173                 *bv = *s;
174         }
175 }
176
177 /*
178  * Map attribute names in place
179  */
180 int
181 rwm_map_attrnames(
182         Operation       *op,
183         struct ldapmap  *at_map,
184         struct ldapmap  *oc_map,
185         AttributeName   *an,
186         AttributeName   **anp,
187         int             remap )
188 {
189         int             i, j;
190
191         assert( anp != NULL );
192
193         *anp = NULL;
194
195         if ( an == NULL ) {
196                 return LDAP_SUCCESS;
197         }
198
199         for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
200                 /* just count */ ;
201         *anp = op->o_tmpalloc( ( i + 1 )* sizeof( AttributeName ),
202                 op->o_tmpmemctx );
203         if ( *anp == NULL ) {
204                 return LDAP_NO_MEMORY;
205         }
206
207         for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
208                 struct ldapmapping      *m;
209                 int                     at_drop_missing = 0,
210                                         oc_drop_missing = 0;
211
212                 if ( an[i].an_desc ) {
213                         if ( !at_map ) {
214                                 /* FIXME: better leave as is? */
215                                 continue;
216                         }
217                                 
218                         at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
219                         if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
220                                 continue;
221                         }
222
223                         if ( !m ) {
224                                 (*anp)[j] = an[i];
225                                 j++;
226                                 continue;
227                         }
228
229                         (*anp)[j] = an[i];
230                         if ( remap == RWM_MAP ) {
231                                 (*anp)[j].an_name = m->m_dst;
232                                 (*anp)[j].an_desc = m->m_dst_ad;
233                         } else {
234                                 (*anp)[j].an_name = m->m_src;
235                                 (*anp)[j].an_desc = m->m_src_ad;
236
237                         }
238
239                         j++;
240                         continue;
241
242                 } else if ( an[i].an_oc ) {
243                         if ( !oc_map ) {
244                                 /* FIXME: better leave as is? */
245                                 continue;
246                         }
247
248                         oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
249
250                         if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
251                                 continue;
252                         }
253
254                         if ( !m ) {
255                                 (*anp)[j] = an[i];
256                                 j++;
257                                 continue;
258                         }
259
260                         (*anp)[j] = an[i];
261                         if ( remap == RWM_MAP ) {
262                                 (*anp)[j].an_name = m->m_dst;
263                                 (*anp)[j].an_oc = m->m_dst_oc;
264                         } else {
265                                 (*anp)[j].an_name = m->m_src;
266                                 (*anp)[j].an_oc = m->m_src_oc;
267                         }
268
269                 } else {
270                         at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
271                 
272                         if ( at_drop_missing || !m ) {
273                                 oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
274
275                                 /* if both at_map and oc_map required to drop missing,
276                                  * then do it */
277                                 if ( oc_drop_missing && at_drop_missing ) {
278                                         continue;
279                                 }
280
281                                 /* if no oc_map mapping was found and at_map required
282                                  * to drop missing, then do it; otherwise, at_map wins
283                                  * and an is considered an attr and is left unchanged */
284                                 if ( !m ) {
285                                         if ( at_drop_missing ) {
286                                                 continue;
287                                         }
288                                         (*anp)[j] = an[i];
289                                         j++;
290                                         continue;
291                                 }
292         
293                                 if ( BER_BVISNULL( &m->m_dst ) ) {
294                                         continue;
295                                 }
296
297                                 (*anp)[j] = an[i];
298                                 if ( remap == RWM_MAP ) {
299                                         (*anp)[j].an_name = m->m_dst;
300                                         (*anp)[j].an_oc = m->m_dst_oc;
301                                 } else {
302                                         (*anp)[j].an_name = m->m_src;
303                                         (*anp)[j].an_oc = m->m_src_oc;
304                                 }
305                                 j++;
306                                 continue;
307                         }
308
309                         if ( !BER_BVISNULL( &m->m_dst ) ) {
310                                 (*anp)[j] = an[i];
311                                 if ( remap == RWM_MAP ) {
312                                         (*anp)[j].an_name = m->m_dst;
313                                         (*anp)[j].an_desc = m->m_dst_ad;
314                                 } else {
315                                         (*anp)[j].an_name = m->m_src;
316                                         (*anp)[j].an_desc = m->m_src_ad;
317                                 }
318                                 j++;
319                                 continue;
320                         }
321                 }
322         }
323
324         if ( j == 0 && i != 0 ) {
325                 memset( &(*anp)[0], 0, sizeof( AttributeName ) );
326                 (*anp)[0].an_name = *slap_bv_no_attrs;
327                 j = 1;
328         }
329         memset( &(*anp)[j], 0, sizeof( AttributeName ) );
330
331         return LDAP_SUCCESS;
332 }
333
334 #if 0 /* unused! */
335 int
336 rwm_map_attrs(
337         struct ldapmap  *at_map,
338         AttributeName   *an,
339         int             remap,
340         char            ***mapped_attrs )
341 {
342         int i, j;
343         char **na;
344
345         if ( an == NULL ) {
346                 *mapped_attrs = NULL;
347                 return LDAP_SUCCESS;
348         }
349
350         for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ )
351                 /* count'em */ ;
352
353         na = (char **)ch_calloc( i + 1, sizeof( char * ) );
354         if ( na == NULL ) {
355                 *mapped_attrs = NULL;
356                 return LDAP_NO_MEMORY;
357         }
358
359         for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
360                 struct ldapmapping      *mapping;
361                 
362                 if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
363                         continue;
364                 }
365
366                 if ( !mapping ) {
367                         na[ j++ ] = an[ i ].an_name.bv_val;
368                         
369                 } else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
370                         na[ j++ ] = mapping->m_dst.bv_val;
371                 }
372         }
373
374         if ( j == 0 && i != 0 ) {
375                 na[ j++ ] = LDAP_NO_ATTRS;
376         }
377
378         na[ j ] = NULL;
379
380         *mapped_attrs = na;
381
382         return LDAP_SUCCESS;
383 }
384 #endif
385
386 static int
387 map_attr_value(
388         dncookie                *dc,
389         AttributeDescription    **adp,
390         struct berval           *mapped_attr,
391         struct berval           *value,
392         struct berval           *mapped_value,
393         int                     remap,
394         void                    *memctx )
395 {
396         struct berval           vtmp = BER_BVNULL;
397         int                     freeval = 0;
398         AttributeDescription    *ad = *adp;
399         struct ldapmapping      *mapping = NULL;
400
401         rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
402         if ( mapping == NULL ) {
403                 if ( dc->rwmap->rwm_at.drop_missing ) {
404                         return -1;
405                 }
406
407                 *mapped_attr = ad->ad_cname;
408
409         } else {
410                 *mapped_attr = mapping->m_dst;
411         }
412
413         if ( value != NULL ) {
414                 assert( mapped_value != NULL );
415
416                 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
417                                 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
418                 {
419                         dncookie        fdc = *dc;
420                         int             rc;
421
422                         fdc.ctx = "searchFilterAttrDN";
423
424                         vtmp = *value;
425                         rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
426                         switch ( rc ) {
427                         case LDAP_SUCCESS:
428                                 if ( vtmp.bv_val != value->bv_val ) {
429                                         freeval = 1;
430                                 }
431                                 break;
432                 
433                         case LDAP_UNWILLING_TO_PERFORM:
434                         case LDAP_OTHER:
435                         default:
436                                 return -1;
437                         }
438
439                 } else if ( ad->ad_type->sat_equality &&
440                         ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) )
441                 {
442                         if ( ad->ad_type->sat_equality->smr_normalize(
443                                 (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
444                                 NULL, NULL, value, &vtmp, memctx ) )
445                         {
446                                 return -1;
447                         }
448                         freeval = 2;
449
450                 } else if ( ad == slap_schema.si_ad_objectClass
451                                 || ad == slap_schema.si_ad_structuralObjectClass )
452                 {
453                         rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
454                         if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
455                                 vtmp = *value;
456                         }
457                 
458                 } else {
459                         vtmp = *value;
460                 }
461
462                 filter_escape_value_x( &vtmp, mapped_value, memctx );
463
464                 switch ( freeval ) {
465                 case 1:
466                         ch_free( vtmp.bv_val );
467                         break;
468
469                 case 2:
470                         ber_memfree_x( vtmp.bv_val, memctx );
471                         break;
472                 }
473         }
474         
475         if ( mapping != NULL ) {
476                 assert( mapping->m_dst_ad != NULL );
477                 *adp = mapping->m_dst_ad;
478         }
479
480         return 0;
481 }
482
483 static int
484 rwm_int_filter_map_rewrite(
485         Operation               *op,
486         dncookie                *dc,
487         Filter                  *f,
488         struct berval           *fstr )
489 {
490         int             i;
491         Filter          *p;
492         AttributeDescription *ad;
493         struct berval   atmp,
494                         vtmp,
495                         *tmp;
496         static struct berval
497                         /* better than nothing... */
498                         ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
499                         ber_bvtf_false = BER_BVC( "(|)" ),
500                         /* better than nothing... */
501                         ber_bvtrue = BER_BVC( "(objectClass=*)" ),
502                         ber_bvtf_true = BER_BVC( "(&)" ),
503 #if 0
504                         /* no longer needed; preserved for completeness */
505                         ber_bvundefined = BER_BVC( "(?=undefined)" ),
506 #endif
507                         ber_bverror = BER_BVC( "(?=error)" ),
508                         ber_bvunknown = BER_BVC( "(?=unknown)" ),
509                         ber_bvnone = BER_BVC( "(?=none)" );
510         ber_len_t       len;
511
512         assert( fstr != NULL );
513         BER_BVZERO( fstr );
514
515         if ( f == NULL ) {
516                 ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx );
517                 return LDAP_OTHER;
518         }
519
520 #if 0
521         /* ITS#6814: give the caller a chance to use undefined filters */
522         if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
523                 goto computed;
524         }
525 #endif
526
527         switch ( f->f_choice & SLAPD_FILTER_MASK ) {
528         case LDAP_FILTER_EQUALITY:
529                 ad = f->f_av_desc;
530                 if ( map_attr_value( dc, &ad, &atmp,
531                         &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
532                 {
533                         goto computed;
534                 }
535
536                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
537                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
538
539                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
540                         atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
541
542                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
543                 break;
544
545         case LDAP_FILTER_GE:
546                 ad = f->f_av_desc;
547                 if ( map_attr_value( dc, &ad, &atmp,
548                         &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
549                 {
550                         goto computed;
551                 }
552
553                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
554                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
555
556                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
557                         atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
558
559                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
560                 break;
561
562         case LDAP_FILTER_LE:
563                 ad = f->f_av_desc;
564                 if ( map_attr_value( dc, &ad, &atmp,
565                         &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
566                 {
567                         goto computed;
568                 }
569
570                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
571                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
572
573                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
574                         atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
575
576                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
577                 break;
578
579         case LDAP_FILTER_APPROX:
580                 ad = f->f_av_desc;
581                 if ( map_attr_value( dc, &ad, &atmp,
582                         &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
583                 {
584                         goto computed;
585                 }
586
587                 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
588                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
589
590                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
591                         atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
592
593                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
594                 break;
595
596         case LDAP_FILTER_SUBSTRINGS:
597                 ad = f->f_sub_desc;
598                 if ( map_attr_value( dc, &ad, &atmp,
599                         NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
600                 {
601                         goto computed;
602                 }
603
604                 /* cannot be a DN ... */
605
606                 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
607                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
608
609                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
610                         atmp.bv_val );
611
612                 if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
613                         len = fstr->bv_len;
614
615                         filter_escape_value_x( &f->f_sub_initial, &vtmp, op->o_tmpmemctx );
616
617                         fstr->bv_len += vtmp.bv_len;
618                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
619                                 op->o_tmpmemctx );
620
621                         snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
622                                 /* "(attr=" */ "%s*)",
623                                 vtmp.bv_len ? vtmp.bv_val : "" );
624
625                         op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
626                 }
627
628                 if ( f->f_sub_any != NULL ) {
629                         for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
630                                 len = fstr->bv_len;
631                                 filter_escape_value_x( &f->f_sub_any[i], &vtmp,
632                                         op->o_tmpmemctx );
633
634                                 fstr->bv_len += vtmp.bv_len + 1;
635                                 fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
636                                         op->o_tmpmemctx );
637
638                                 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
639                                         /* "(attr=[init]*[any*]" */ "%s*)",
640                                         vtmp.bv_len ? vtmp.bv_val : "" );
641                                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
642                         }
643                 }
644
645                 if ( !BER_BVISNULL( &f->f_sub_final ) ) {
646                         len = fstr->bv_len;
647
648                         filter_escape_value_x( &f->f_sub_final, &vtmp, op->o_tmpmemctx );
649
650                         fstr->bv_len += vtmp.bv_len;
651                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
652                                 op->o_tmpmemctx );
653
654                         snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
655                                 /* "(attr=[init*][any*]" */ "%s)",
656                                 vtmp.bv_len ? vtmp.bv_val : "" );
657
658                         op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
659                 }
660
661                 break;
662
663         case LDAP_FILTER_PRESENT:
664                 ad = f->f_desc;
665                 if ( map_attr_value( dc, &ad, &atmp,
666                         NULL, NULL, RWM_MAP, op->o_tmpmemctx ) )
667                 {
668                         goto computed;
669                 }
670
671                 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
672                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
673
674                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
675                         atmp.bv_val );
676                 break;
677
678         case LDAP_FILTER_AND:
679         case LDAP_FILTER_OR:
680         case LDAP_FILTER_NOT:
681                 fstr->bv_len = STRLENOF( "(%)" );
682                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
683
684                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
685                         f->f_choice == LDAP_FILTER_AND ? '&' :
686                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
687
688                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
689                         int     rc;
690
691                         len = fstr->bv_len;
692
693                         rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp );
694                         if ( rc != LDAP_SUCCESS ) {
695                                 return rc;
696                         }
697                         
698                         fstr->bv_len += vtmp.bv_len;
699                         fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
700                                 op->o_tmpmemctx );
701
702                         snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
703                                 /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
704
705                         op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
706                 }
707
708                 break;
709
710         case LDAP_FILTER_EXT: {
711                 if ( f->f_mr_desc ) {
712                         ad = f->f_mr_desc;
713                         if ( map_attr_value( dc, &ad, &atmp,
714                                 &f->f_mr_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) )
715                         {
716                                 goto computed;
717                         }
718
719                 } else {
720                         BER_BVSTR( &atmp, "" );
721                         filter_escape_value_x( &f->f_mr_value, &vtmp, op->o_tmpmemctx );
722                 }
723                         
724
725                 fstr->bv_len = atmp.bv_len +
726                         ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
727                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
728                         vtmp.bv_len + STRLENOF( "(:=)" );
729                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
730
731                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
732                         atmp.bv_val,
733                         f->f_mr_dnattrs ? ":dn" : "",
734                         !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
735                         !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
736                         vtmp.bv_len ? vtmp.bv_val : "" );
737                 op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx );
738                 break;
739         }
740
741         case -1:
742 computed:;
743                 filter_free_x( op, f, 0 );
744                 f->f_choice = SLAPD_FILTER_COMPUTED;
745                 f->f_result = SLAPD_COMPARE_UNDEFINED;
746                 /* fallthru */
747
748         case SLAPD_FILTER_COMPUTED:
749                 switch ( f->f_result ) {
750                 case LDAP_COMPARE_FALSE:
751                 /* FIXME: treat UNDEFINED as FALSE */
752                 case SLAPD_COMPARE_UNDEFINED:
753                         if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
754                                 tmp = &ber_bvtf_false;
755                                 break;
756                         }
757                         tmp = &ber_bvfalse;
758                         break;
759
760                 case LDAP_COMPARE_TRUE:
761                         if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
762                                 tmp = &ber_bvtf_true;
763                                 break;
764                         }
765                         tmp = &ber_bvtrue;
766                         break;
767                         
768                 default:
769                         tmp = &ber_bverror;
770                         break;
771                 }
772
773                 ber_dupbv_x( fstr, tmp, op->o_tmpmemctx );
774                 break;
775                 
776         default:
777                 ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx );
778                 break;
779         }
780
781         return LDAP_SUCCESS;
782 }
783
784 int
785 rwm_filter_map_rewrite(
786         Operation               *op,
787         dncookie                *dc,
788         Filter                  *f,
789         struct berval           *fstr )
790 {
791         int             rc;
792         dncookie        fdc;
793         struct berval   ftmp;
794
795         rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
796
797         if ( rc != 0 ) {
798                 return rc;
799         }
800
801         fdc = *dc;
802         ftmp = *fstr;
803
804         fdc.ctx = "searchFilter";
805
806         switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 
807                                 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 
808                                 fdc.conn, &fstr->bv_val ) )
809         {
810         case REWRITE_REGEXEC_OK:
811                 if ( !BER_BVISNULL( fstr ) ) {
812                         fstr->bv_len = strlen( fstr->bv_val );
813
814                 } else {
815                         *fstr = ftmp;
816                 }
817
818                 Debug( LDAP_DEBUG_ARGS,
819                         "[rw] %s: \"%s\" -> \"%s\"\n",
820                         fdc.ctx, ftmp.bv_val, fstr->bv_val );           
821                 if ( fstr->bv_val != ftmp.bv_val ) {
822                         ber_bvreplace_x( &ftmp, fstr, op->o_tmpmemctx );
823                         ch_free( fstr->bv_val );
824                         *fstr = ftmp;
825                 }
826                 rc = LDAP_SUCCESS;
827                 break;
828                 
829         case REWRITE_REGEXEC_UNWILLING:
830                 if ( fdc.rs ) {
831                         fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
832                         fdc.rs->sr_text = "Operation not allowed";
833                 }
834                 op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
835                 rc = LDAP_UNWILLING_TO_PERFORM;
836                 break;
837                 
838         case REWRITE_REGEXEC_ERR:
839                 if ( fdc.rs ) {
840                         fdc.rs->sr_err = LDAP_OTHER;
841                         fdc.rs->sr_text = "Rewrite error";
842                 }
843                 op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx );
844                 rc = LDAP_OTHER;
845                 break;
846         }
847
848         return rc;
849 }
850
851 /*
852  * I don't like this much, but we need two different
853  * functions because different heap managers may be
854  * in use in back-ldap/meta to reduce the amount of
855  * calls to malloc routines, and some of the free()
856  * routines may be macros with args
857  */
858 int
859 rwm_referral_rewrite(
860         Operation               *op,
861         SlapReply               *rs,
862         void                    *cookie,
863         BerVarray               a_vals,
864         BerVarray               *pa_nvals )
865 {
866         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
867         struct ldaprwmap        *rwmap = 
868                         (struct ldaprwmap *)on->on_bi.bi_private;
869
870         int                     i, last;
871
872         dncookie                dc;
873         struct berval           dn = BER_BVNULL,
874                                 ndn = BER_BVNULL;
875
876         assert( a_vals != NULL );
877
878         /*
879          * Rewrite the dn if needed
880          */
881         dc.rwmap = rwmap;
882         dc.conn = op->o_conn;
883         dc.rs = rs;
884         dc.ctx = (char *)cookie;
885
886         for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
887                 ;
888         last--;
889         
890         if ( pa_nvals != NULL ) {
891                 if ( *pa_nvals == NULL ) {
892                         *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
893                         memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
894                 }
895         }
896
897         for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
898                 struct berval   olddn = BER_BVNULL,
899                                 oldval;
900                 int             rc;
901                 LDAPURLDesc     *ludp;
902
903                 oldval = a_vals[i];
904                 rc = ldap_url_parse( oldval.bv_val, &ludp );
905                 if ( rc != LDAP_URL_SUCCESS ) {
906                         /* leave attr untouched if massage failed */
907                         if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
908                                 ber_dupbv( &(*pa_nvals)[i], &oldval );
909                         }
910                         continue;
911                 }
912
913                 /* FIXME: URLs like "ldap:///dc=suffix" if passed
914                  * thru ldap_url_parse() and ldap_url_desc2str() 
915                  * get rewritten as "ldap:///dc=suffix??base";
916                  * we don't want this to occur... */
917                 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
918                         ludp->lud_scope = LDAP_SCOPE_DEFAULT;
919                 }
920
921                 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
922
923                 dn = olddn;
924                 if ( pa_nvals ) {
925                         ndn = olddn;
926                         rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
927                                         &dn, &ndn );
928                 } else {
929                         rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
930                 }
931
932                 switch ( rc ) {
933                 case LDAP_UNWILLING_TO_PERFORM:
934                         /*
935                          * FIXME: need to check if it may be considered 
936                          * legal to trim values when adding/modifying;
937                          * it should be when searching (e.g. ACLs).
938                          */
939                         ch_free( a_vals[i].bv_val );
940                         if (last > i ) {
941                                 a_vals[i] = a_vals[last];
942                                 if ( pa_nvals ) {
943                                         (*pa_nvals)[i] = (*pa_nvals)[last];
944                                 }
945                         }
946                         BER_BVZERO( &a_vals[last] );
947                         if ( pa_nvals ) {
948                                 BER_BVZERO( &(*pa_nvals)[last] );
949                         }
950                         last--;
951                         break;
952                 
953                 case LDAP_SUCCESS:
954                         if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
955                                 char    *newurl;
956
957                                 ludp->lud_dn = dn.bv_val;
958                                 newurl = ldap_url_desc2str( ludp );
959                                 ludp->lud_dn = olddn.bv_val;
960                                 ch_free( dn.bv_val );
961                                 if ( newurl == NULL ) {
962                                         /* FIXME: leave attr untouched
963                                          * even if ldap_url_desc2str failed...
964                                          */
965                                         break;
966                                 }
967
968                                 ber_str2bv( newurl, 0, 1, &a_vals[i] );
969                                 ber_memfree( newurl );
970
971                                 if ( pa_nvals ) {
972                                         ludp->lud_dn = ndn.bv_val;
973                                         newurl = ldap_url_desc2str( ludp );
974                                         ludp->lud_dn = olddn.bv_val;
975                                         ch_free( ndn.bv_val );
976                                         if ( newurl == NULL ) {
977                                                 /* FIXME: leave attr untouched
978                                                  * even if ldap_url_desc2str failed...
979                                                  */
980                                                 ch_free( a_vals[i].bv_val );
981                                                 a_vals[i] = oldval;
982                                                 break;
983                                         }
984
985                                         if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
986                                                 ch_free( (*pa_nvals)[i].bv_val );
987                                         }
988                                         ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
989                                         ber_memfree( newurl );
990                                 }
991
992                                 ch_free( oldval.bv_val );
993                                 ludp->lud_dn = olddn.bv_val;
994                         }
995                         break;
996
997                 default:
998                         /* leave attr untouched if massage failed */
999                         if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1000                                 ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
1001                         }
1002                         break;
1003                 }
1004                 ldap_free_urldesc( ludp );
1005         }
1006         
1007         return 0;
1008 }
1009
1010 /*
1011  * I don't like this much, but we need two different
1012  * functions because different heap managers may be
1013  * in use in back-ldap/meta to reduce the amount of
1014  * calls to malloc routines, and some of the free()
1015  * routines may be macros with args
1016  */
1017 int
1018 rwm_dnattr_rewrite(
1019         Operation               *op,
1020         SlapReply               *rs,
1021         void                    *cookie,
1022         BerVarray               a_vals,
1023         BerVarray               *pa_nvals )
1024 {
1025         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
1026         struct ldaprwmap        *rwmap = 
1027                         (struct ldaprwmap *)on->on_bi.bi_private;
1028
1029         int                     i, last;
1030
1031         dncookie                dc;
1032         struct berval           dn = BER_BVNULL,
1033                                 ndn = BER_BVNULL;
1034         BerVarray               in;
1035
1036         if ( a_vals ) {
1037                 in = a_vals;
1038
1039         } else {
1040                 if ( pa_nvals == NULL || *pa_nvals == NULL ) {
1041                         return LDAP_OTHER;
1042                 }
1043                 in = *pa_nvals;
1044         }
1045
1046         /*
1047          * Rewrite the dn if needed
1048          */
1049         dc.rwmap = rwmap;
1050         dc.conn = op->o_conn;
1051         dc.rs = rs;
1052         dc.ctx = (char *)cookie;
1053
1054         for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
1055         last--;
1056         if ( pa_nvals != NULL ) {
1057                 if ( *pa_nvals == NULL ) {
1058                         *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
1059                         memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
1060                 }
1061         }
1062
1063         for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1064                 int             rc;
1065
1066                 if ( a_vals ) {
1067                         dn = in[i];
1068                         if ( pa_nvals ) {
1069                                 ndn = (*pa_nvals)[i];
1070                                 rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
1071                         } else {
1072                                 rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
1073                         }
1074                 } else {
1075                         ndn = in[i];
1076                         rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
1077                 }
1078
1079                 switch ( rc ) {
1080                 case LDAP_UNWILLING_TO_PERFORM:
1081                         /*
1082                          * FIXME: need to check if it may be considered 
1083                          * legal to trim values when adding/modifying;
1084                          * it should be when searching (e.g. ACLs).
1085                          */
1086                         ch_free( in[i].bv_val );
1087                         if (last > i ) {
1088                                 in[i] = in[last];
1089                                 if ( a_vals && pa_nvals ) {
1090                                         (*pa_nvals)[i] = (*pa_nvals)[last];
1091                                 }
1092                         }
1093                         BER_BVZERO( &in[last] );
1094                         if ( a_vals && pa_nvals ) {
1095                                 BER_BVZERO( &(*pa_nvals)[last] );
1096                         }
1097                         last--;
1098                         break;
1099                 
1100                 case LDAP_SUCCESS:
1101                         if ( a_vals ) {
1102                                 if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
1103                                         ch_free( a_vals[i].bv_val );
1104                                         a_vals[i] = dn;
1105
1106                                         if ( pa_nvals ) {
1107                                                 if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1108                                                         ch_free( (*pa_nvals)[i].bv_val );
1109                                                 }
1110                                                 (*pa_nvals)[i] = ndn;
1111                                         }
1112                                 }
1113                                 
1114                         } else {
1115                                 if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
1116                                         ch_free( (*pa_nvals)[i].bv_val );
1117                                         (*pa_nvals)[i] = ndn;
1118                                 }
1119                         }
1120                         break;
1121
1122                 default:
1123                         /* leave attr untouched if massage failed */
1124                         if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1125                                 dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
1126                         }
1127                         break;
1128                 }
1129         }
1130         
1131         return 0;
1132 }
1133
1134 int
1135 rwm_referral_result_rewrite(
1136         dncookie                *dc,
1137         BerVarray               a_vals )
1138 {
1139         int             i, last;
1140
1141         for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1142         last--;
1143
1144         for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1145                 struct berval   dn,
1146                                 olddn = BER_BVNULL;
1147                 int             rc;
1148                 LDAPURLDesc     *ludp;
1149
1150                 rc = ldap_url_parse( a_vals[i].bv_val, &ludp );
1151                 if ( rc != LDAP_URL_SUCCESS ) {
1152                         /* leave attr untouched if massage failed */
1153                         continue;
1154                 }
1155
1156                 /* FIXME: URLs like "ldap:///dc=suffix" if passed
1157                  * thru ldap_url_parse() and ldap_url_desc2str()
1158                  * get rewritten as "ldap:///dc=suffix??base";
1159                  * we don't want this to occur... */
1160                 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
1161                         ludp->lud_scope = LDAP_SCOPE_DEFAULT;
1162                 }
1163
1164                 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
1165
1166                 dn = olddn;
1167                 rc = rwm_dn_massage_pretty( dc, &olddn, &dn );
1168                 switch ( rc ) {
1169                 case LDAP_UNWILLING_TO_PERFORM:
1170                         /*
1171                          * FIXME: need to check if it may be considered 
1172                          * legal to trim values when adding/modifying;
1173                          * it should be when searching (e.g. ACLs).
1174                          */
1175                         ch_free( a_vals[i].bv_val );
1176                         if ( last > i ) {
1177                                 a_vals[i] = a_vals[last];
1178                         }
1179                         BER_BVZERO( &a_vals[last] );
1180                         last--;
1181                         i--;
1182                         break;
1183
1184                 default:
1185                         /* leave attr untouched if massage failed */
1186                         if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) {
1187                                 char    *newurl;
1188
1189                                 ludp->lud_dn = dn.bv_val;
1190                                 newurl = ldap_url_desc2str( ludp );
1191                                 if ( newurl == NULL ) {
1192                                         /* FIXME: leave attr untouched
1193                                          * even if ldap_url_desc2str failed...
1194                                          */
1195                                         break;
1196                                 }
1197
1198                                 ch_free( a_vals[i].bv_val );
1199                                 ber_str2bv( newurl, 0, 1, &a_vals[i] );
1200                                 ber_memfree( newurl );
1201                                 ludp->lud_dn = olddn.bv_val;
1202                         }
1203                         break;
1204                 }
1205
1206                 ldap_free_urldesc( ludp );
1207         }
1208
1209         return 0;
1210 }
1211
1212 int
1213 rwm_dnattr_result_rewrite(
1214         dncookie                *dc,
1215         BerVarray               a_vals,
1216         BerVarray               a_nvals )
1217 {
1218         int             i, last;
1219
1220         for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1221         last--;
1222
1223         for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1224                 struct berval   pdn, ndn = BER_BVNULL;
1225                 int             rc;
1226                 
1227                 pdn = a_vals[i];
1228                 rc = rwm_dn_massage_pretty_normalize( dc, &a_vals[i], &pdn, &ndn );
1229                 switch ( rc ) {
1230                 case LDAP_UNWILLING_TO_PERFORM:
1231                         /*
1232                          * FIXME: need to check if it may be considered 
1233                          * legal to trim values when adding/modifying;
1234                          * it should be when searching (e.g. ACLs).
1235                          */
1236                         assert( a_vals[i].bv_val != a_nvals[i].bv_val );
1237                         ch_free( a_vals[i].bv_val );
1238                         ch_free( a_nvals[i].bv_val );
1239                         if ( last > i ) {
1240                                 a_vals[i] = a_vals[last];
1241                                 a_nvals[i] = a_nvals[last];
1242                         }
1243                         BER_BVZERO( &a_vals[last] );
1244                         BER_BVZERO( &a_nvals[last] );
1245                         last--;
1246                         break;
1247
1248                 default:
1249                         /* leave attr untouched if massage failed */
1250                         if ( !BER_BVISNULL( &pdn ) && a_vals[i].bv_val != pdn.bv_val ) {
1251                                 ch_free( a_vals[i].bv_val );
1252                                 a_vals[i] = pdn;
1253                         }
1254                         if ( !BER_BVISNULL( &ndn ) && a_nvals[i].bv_val != ndn.bv_val ) {
1255                                 ch_free( a_nvals[i].bv_val );
1256                                 a_nvals[i] = ndn;
1257                         }
1258                         break;
1259                 }
1260         }
1261
1262         return 0;
1263 }
1264
1265 void
1266 rwm_mapping_dst_free( void *v_mapping )
1267 {
1268         struct ldapmapping *mapping = v_mapping;
1269
1270         if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) {
1271                 rwm_mapping_free( &mapping[ -1 ] );
1272         }
1273 }
1274
1275 void
1276 rwm_mapping_free( void *v_mapping )
1277 {
1278         struct ldapmapping *mapping = v_mapping;
1279
1280         if ( !BER_BVISNULL( &mapping[0].m_src ) ) {
1281                 ch_free( mapping[0].m_src.bv_val );
1282         }
1283
1284         if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
1285                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1286                         if ( mapping[0].m_src_oc ) {
1287                                 ch_free( mapping[0].m_src_oc );
1288                         }
1289
1290                 } else {
1291                         if ( mapping[0].m_src_ad ) {
1292                                 ch_free( mapping[0].m_src_ad );
1293                         }
1294                 }
1295         }
1296
1297         if ( !BER_BVISNULL( &mapping[0].m_dst ) ) {
1298                 ch_free( mapping[0].m_dst.bv_val );
1299         }
1300
1301         if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
1302                 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1303                         if ( mapping[0].m_dst_oc ) {
1304                                 ch_free( mapping[0].m_dst_oc );
1305                         }
1306
1307                 } else {
1308                         if ( mapping[0].m_dst_ad ) {
1309                                 ch_free( mapping[0].m_dst_ad );
1310                         }
1311                 }
1312         }
1313
1314         ch_free( mapping );
1315
1316 }
1317
1318 #endif /* SLAPD_OVER_RWM */