rwmmap.c revision 1.1.1.2 1 /* $NetBSD: rwmmap.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */
2
3 /* rwmmap.c - rewrite/mapping routines */
4 /* OpenLDAP: pkg/ldap/servers/slapd/overlays/rwmmap.c,v 1.31.2.12 2009/02/17 19:14:42 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 1999-2009 The OpenLDAP Foundation.
8 * Portions Copyright 1999-2003 Howard Chu.
9 * Portions Copyright 2000-2003 Pierangelo Masarati.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted only as authorized by the OpenLDAP
14 * Public License.
15 *
16 * A copy of this license is available in the file LICENSE in the
17 * top-level directory of the distribution or, alternatively, at
18 * <http://www.OpenLDAP.org/license.html>.
19 */
20 /* ACKNOWLEDGEMENTS:
21 * This work was initially developed by the Howard Chu for inclusion
22 * in OpenLDAP Software and subsequently enhanced by Pierangelo
23 * Masarati.
24 */
25
26 #include "portable.h"
27
28 #ifdef SLAPD_OVER_RWM
29
30 #include <stdio.h>
31
32 #include <ac/string.h>
33 #include <ac/socket.h>
34
35 #include "slap.h"
36 #include "rwm.h"
37
38 #undef ldap_debug /* silence a warning in ldap-int.h */
39 #include "../../../libraries/libldap/ldap-int.h"
40
41 int
42 rwm_mapping_cmp( const void *c1, const void *c2 )
43 {
44 struct ldapmapping *map1 = (struct ldapmapping *)c1;
45 struct ldapmapping *map2 = (struct ldapmapping *)c2;
46 int rc = map1->m_src.bv_len - map2->m_src.bv_len;
47
48 if ( rc ) {
49 return rc;
50 }
51
52 return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
53 }
54
55 int
56 rwm_mapping_dup( void *c1, void *c2 )
57 {
58 struct ldapmapping *map1 = (struct ldapmapping *)c1;
59 struct ldapmapping *map2 = (struct ldapmapping *)c2;
60 int rc = map1->m_src.bv_len - map2->m_src.bv_len;
61
62 if ( rc ) {
63 return 0;
64 }
65
66 return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
67 }
68
69 int
70 rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
71 {
72 struct ldapmapping *mapping;
73 const char *text;
74 int rc;
75
76 assert( m != NULL );
77
78 *m = NULL;
79
80 mapping = (struct ldapmapping *)ch_calloc( 2,
81 sizeof( struct ldapmapping ) );
82 if ( mapping == NULL ) {
83 return LDAP_NO_MEMORY;
84 }
85
86 /* NOTE: this is needed to make sure that
87 * rwm-map attribute *
88 * does not filter out all attributes including objectClass */
89 rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
90 if ( rc != LDAP_SUCCESS ) {
91 ch_free( mapping );
92 return rc;
93 }
94
95 mapping[0].m_dst_ad = mapping[0].m_src_ad;
96 ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
97 ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
98
99 mapping[1].m_src = mapping[0].m_src;
100 mapping[1].m_dst = mapping[0].m_dst;
101 mapping[1].m_src_ad = mapping[0].m_src_ad;
102 mapping[1].m_dst_ad = mapping[1].m_src_ad;
103
104 avl_insert( &lm->map, (caddr_t)&mapping[0],
105 rwm_mapping_cmp, rwm_mapping_dup );
106 avl_insert( &lm->remap, (caddr_t)&mapping[1],
107 rwm_mapping_cmp, rwm_mapping_dup );
108
109 *m = mapping;
110
111 return rc;
112 }
113
114 int
115 rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
116 {
117 Avlnode *tree;
118 struct ldapmapping fmapping;
119
120 if ( map == NULL ) {
121 return 0;
122 }
123
124 assert( m != NULL );
125
126 /* let special attrnames slip through (ITS#5760) */
127 if ( bvmatch( s, slap_bv_no_attrs )
128 || bvmatch( s, slap_bv_all_user_attrs )
129 || bvmatch( s, slap_bv_all_operational_attrs ) )
130 {
131 *m = NULL;
132 return 0;
133 }
134
135 if ( remap == RWM_REMAP ) {
136 tree = map->remap;
137
138 } else {
139 tree = map->map;
140 }
141
142 fmapping.m_src = *s;
143 *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
144 rwm_mapping_cmp );
145
146 if ( *m == NULL ) {
147 return map->drop_missing;
148 }
149
150 return 0;
151 }
152
153 void
154 rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
155 {
156 struct ldapmapping *mapping;
157
158 /* map->map may be NULL when mapping is configured,
159 * but map->remap can't */
160 if ( map->remap == NULL ) {
161 *bv = *s;
162 return;
163 }
164
165 BER_BVZERO( bv );
166 ( void )rwm_mapping( map, s, &mapping, remap );
167 if ( mapping != NULL ) {
168 if ( !BER_BVISNULL( &mapping->m_dst ) ) {
169 *bv = mapping->m_dst;
170 }
171 return;
172 }
173
174 if ( !map->drop_missing ) {
175 *bv = *s;
176 }
177 }
178
179 /*
180 * Map attribute names in place
181 */
182 int
183 rwm_map_attrnames(
184 struct ldapmap *at_map,
185 struct ldapmap *oc_map,
186 AttributeName *an,
187 AttributeName **anp,
188 int remap )
189 {
190 int i, j;
191
192 assert( anp != NULL );
193
194 *anp = NULL;
195
196 if ( an == NULL ) {
197 return LDAP_SUCCESS;
198 }
199
200 for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
201 /* just count */ ;
202 *anp = ch_malloc( ( i + 1 )* sizeof( AttributeName ) );
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 int
335 rwm_map_attrs(
336 struct ldapmap *at_map,
337 AttributeName *an,
338 int remap,
339 char ***mapped_attrs )
340 {
341 int i, j;
342 char **na;
343
344 if ( an == NULL ) {
345 *mapped_attrs = NULL;
346 return LDAP_SUCCESS;
347 }
348
349 for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ )
350 /* count'em */ ;
351
352 na = (char **)ch_calloc( i + 1, sizeof( char * ) );
353 if ( na == NULL ) {
354 *mapped_attrs = NULL;
355 return LDAP_NO_MEMORY;
356 }
357
358 for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
359 struct ldapmapping *mapping;
360
361 if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
362 continue;
363 }
364
365 if ( !mapping ) {
366 na[ j++ ] = an[ i ].an_name.bv_val;
367
368 } else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
369 na[ j++ ] = mapping->m_dst.bv_val;
370 }
371 }
372
373 if ( j == 0 && i != 0 ) {
374 na[ j++ ] = LDAP_NO_ATTRS;
375 }
376
377 na[ j ] = NULL;
378
379 *mapped_attrs = na;
380
381 return LDAP_SUCCESS;
382 }
383
384 static int
385 map_attr_value(
386 dncookie *dc,
387 AttributeDescription **adp,
388 struct berval *mapped_attr,
389 struct berval *value,
390 struct berval *mapped_value,
391 int remap )
392 {
393 struct berval vtmp = BER_BVNULL;
394 int freeval = 0;
395 AttributeDescription *ad = *adp;
396 struct ldapmapping *mapping = NULL;
397
398 rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
399 if ( mapping == NULL ) {
400 if ( dc->rwmap->rwm_at.drop_missing ) {
401 return -1;
402 }
403
404 *mapped_attr = ad->ad_cname;
405
406 } else {
407 *mapped_attr = mapping->m_dst;
408 }
409
410 if ( value != NULL ) {
411 assert( mapped_value != NULL );
412
413 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
414 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
415 {
416 dncookie fdc = *dc;
417 int rc;
418
419 fdc.ctx = "searchFilterAttrDN";
420
421 vtmp = *value;
422 rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
423 switch ( rc ) {
424 case LDAP_SUCCESS:
425 if ( vtmp.bv_val != value->bv_val ) {
426 freeval = 1;
427 }
428 break;
429
430 case LDAP_UNWILLING_TO_PERFORM:
431 case LDAP_OTHER:
432 default:
433 return -1;
434 }
435
436 } else if ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) {
437 if ( ad->ad_type->sat_equality->smr_normalize(
438 (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
439 NULL, NULL, value, &vtmp, NULL ) )
440 {
441 return -1;
442 }
443 freeval = 1;
444
445 } else if ( ad == slap_schema.si_ad_objectClass
446 || ad == slap_schema.si_ad_structuralObjectClass )
447 {
448 rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
449 if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
450 vtmp = *value;
451 }
452
453 } else {
454 vtmp = *value;
455 }
456
457 filter_escape_value( &vtmp, mapped_value );
458
459 if ( freeval ) {
460 ch_free( vtmp.bv_val );
461 }
462 }
463
464 if ( mapping != NULL ) {
465 assert( mapping->m_dst_ad != NULL );
466 *adp = mapping->m_dst_ad;
467 }
468
469 return 0;
470 }
471
472 static int
473 rwm_int_filter_map_rewrite(
474 Operation *op,
475 dncookie *dc,
476 Filter *f,
477 struct berval *fstr )
478 {
479 int i;
480 Filter *p;
481 AttributeDescription *ad;
482 struct berval atmp,
483 vtmp,
484 *tmp;
485 static struct berval
486 /* better than nothing... */
487 ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
488 ber_bvtf_false = BER_BVC( "(|)" ),
489 /* better than nothing... */
490 ber_bvtrue = BER_BVC( "(objectClass=*)" ),
491 ber_bvtf_true = BER_BVC( "(&)" ),
492 #if 0
493 /* no longer needed; preserved for completeness */
494 ber_bvundefined = BER_BVC( "(?=undefined)" ),
495 #endif
496 ber_bverror = BER_BVC( "(?=error)" ),
497 ber_bvunknown = BER_BVC( "(?=unknown)" ),
498 ber_bvnone = BER_BVC( "(?=none)" );
499 ber_len_t len;
500
501 assert( fstr != NULL );
502 BER_BVZERO( fstr );
503
504 if ( f == NULL ) {
505 ber_dupbv( fstr, &ber_bvnone );
506 return LDAP_OTHER;
507 }
508
509 if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
510 goto computed;
511 }
512
513 switch ( f->f_choice & SLAPD_FILTER_MASK ) {
514 case LDAP_FILTER_EQUALITY:
515 ad = f->f_av_desc;
516 if ( map_attr_value( dc, &ad, &atmp,
517 &f->f_av_value, &vtmp, RWM_MAP ) )
518 {
519 goto computed;
520 }
521
522 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
523 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
524
525 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
526 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
527
528 ch_free( vtmp.bv_val );
529 break;
530
531 case LDAP_FILTER_GE:
532 ad = f->f_av_desc;
533 if ( map_attr_value( dc, &ad, &atmp,
534 &f->f_av_value, &vtmp, RWM_MAP ) )
535 {
536 goto computed;
537 }
538
539 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
540 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
541
542 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
543 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
544
545 ch_free( vtmp.bv_val );
546 break;
547
548 case LDAP_FILTER_LE:
549 ad = f->f_av_desc;
550 if ( map_attr_value( dc, &ad, &atmp,
551 &f->f_av_value, &vtmp, RWM_MAP ) )
552 {
553 goto computed;
554 }
555
556 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
557 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
558
559 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
560 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
561
562 ch_free( vtmp.bv_val );
563 break;
564
565 case LDAP_FILTER_APPROX:
566 ad = f->f_av_desc;
567 if ( map_attr_value( dc, &ad, &atmp,
568 &f->f_av_value, &vtmp, RWM_MAP ) )
569 {
570 goto computed;
571 }
572
573 fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
574 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
575
576 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
577 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
578
579 ch_free( vtmp.bv_val );
580 break;
581
582 case LDAP_FILTER_SUBSTRINGS:
583 ad = f->f_sub_desc;
584 if ( map_attr_value( dc, &ad, &atmp,
585 NULL, NULL, RWM_MAP ) )
586 {
587 goto computed;
588 }
589
590 /* cannot be a DN ... */
591
592 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
593 fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
594
595 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
596 atmp.bv_val );
597
598 if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
599 len = fstr->bv_len;
600
601 filter_escape_value( &f->f_sub_initial, &vtmp );
602
603 fstr->bv_len += vtmp.bv_len;
604 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
605
606 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
607 /* "(attr=" */ "%s*)",
608 vtmp.bv_len ? vtmp.bv_val : "" );
609
610 ch_free( vtmp.bv_val );
611 }
612
613 if ( f->f_sub_any != NULL ) {
614 for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
615 len = fstr->bv_len;
616 filter_escape_value( &f->f_sub_any[i], &vtmp );
617
618 fstr->bv_len += vtmp.bv_len + 1;
619 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
620
621 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
622 /* "(attr=[init]*[any*]" */ "%s*)",
623 vtmp.bv_len ? vtmp.bv_val : "" );
624 ch_free( vtmp.bv_val );
625 }
626 }
627
628 if ( !BER_BVISNULL( &f->f_sub_final ) ) {
629 len = fstr->bv_len;
630
631 filter_escape_value( &f->f_sub_final, &vtmp );
632
633 fstr->bv_len += vtmp.bv_len;
634 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
635
636 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
637 /* "(attr=[init*][any*]" */ "%s)",
638 vtmp.bv_len ? vtmp.bv_val : "" );
639
640 ch_free( vtmp.bv_val );
641 }
642
643 break;
644
645 case LDAP_FILTER_PRESENT:
646 ad = f->f_desc;
647 if ( map_attr_value( dc, &ad, &atmp,
648 NULL, NULL, RWM_MAP ) )
649 {
650 goto computed;
651 }
652
653 fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
654 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
655
656 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
657 atmp.bv_val );
658 break;
659
660 case LDAP_FILTER_AND:
661 case LDAP_FILTER_OR:
662 case LDAP_FILTER_NOT:
663 fstr->bv_len = STRLENOF( "(%)" );
664 fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
665
666 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
667 f->f_choice == LDAP_FILTER_AND ? '&' :
668 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
669
670 for ( p = f->f_list; p != NULL; p = p->f_next ) {
671 int rc;
672
673 len = fstr->bv_len;
674
675 rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp );
676 if ( rc != LDAP_SUCCESS ) {
677 return rc;
678 }
679
680 fstr->bv_len += vtmp.bv_len;
681 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
682
683 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
684 /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
685
686 ch_free( vtmp.bv_val );
687 }
688
689 break;
690
691 case LDAP_FILTER_EXT: {
692 if ( f->f_mr_desc ) {
693 ad = f->f_mr_desc;
694 if ( map_attr_value( dc, &ad, &atmp,
695 &f->f_mr_value, &vtmp, RWM_MAP ) )
696 {
697 goto computed;
698 }
699
700 } else {
701 BER_BVSTR( &atmp, "" );
702 filter_escape_value( &f->f_mr_value, &vtmp );
703 }
704
705
706 fstr->bv_len = atmp.bv_len +
707 ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
708 ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
709 vtmp.bv_len + STRLENOF( "(:=)" );
710 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
711
712 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
713 atmp.bv_val,
714 f->f_mr_dnattrs ? ":dn" : "",
715 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
716 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
717 vtmp.bv_len ? vtmp.bv_val : "" );
718 ch_free( vtmp.bv_val );
719 break;
720 }
721
722 case -1:
723 computed:;
724 filter_free_x( op, f, 0 );
725 f->f_choice = SLAPD_FILTER_COMPUTED;
726 f->f_result = SLAPD_COMPARE_UNDEFINED;
727 /* fallthru */
728
729 case SLAPD_FILTER_COMPUTED:
730 switch ( f->f_result ) {
731 case LDAP_COMPARE_FALSE:
732 /* FIXME: treat UNDEFINED as FALSE */
733 case SLAPD_COMPARE_UNDEFINED:
734 if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
735 tmp = &ber_bvtf_false;
736 break;
737 }
738 tmp = &ber_bvfalse;
739 break;
740
741 case LDAP_COMPARE_TRUE:
742 if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
743 tmp = &ber_bvtf_true;
744 break;
745 }
746 tmp = &ber_bvtrue;
747 break;
748
749 default:
750 tmp = &ber_bverror;
751 break;
752 }
753
754 ber_dupbv( fstr, tmp );
755 break;
756
757 default:
758 ber_dupbv( fstr, &ber_bvunknown );
759 break;
760 }
761
762 return LDAP_SUCCESS;
763 }
764
765 int
766 rwm_filter_map_rewrite(
767 Operation *op,
768 dncookie *dc,
769 Filter *f,
770 struct berval *fstr )
771 {
772 int rc;
773 dncookie fdc;
774 struct berval ftmp;
775
776 rc = rwm_int_filter_map_rewrite( op, dc, f, fstr );
777
778 if ( rc != 0 ) {
779 return rc;
780 }
781
782 fdc = *dc;
783 ftmp = *fstr;
784
785 fdc.ctx = "searchFilter";
786
787 switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx,
788 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ),
789 fdc.conn, &fstr->bv_val ) )
790 {
791 case REWRITE_REGEXEC_OK:
792 if ( !BER_BVISNULL( fstr ) ) {
793 fstr->bv_len = strlen( fstr->bv_val );
794 if ( fstr->bv_val != ftmp.bv_val ) {
795 ch_free( ftmp.bv_val );
796 }
797
798 } else {
799 *fstr = ftmp;
800 }
801
802 Debug( LDAP_DEBUG_ARGS,
803 "[rw] %s: \"%s\" -> \"%s\"\n",
804 fdc.ctx, ftmp.bv_val, fstr->bv_val );
805 rc = LDAP_SUCCESS;
806 break;
807
808 case REWRITE_REGEXEC_UNWILLING:
809 if ( fdc.rs ) {
810 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
811 fdc.rs->sr_text = "Operation not allowed";
812 }
813 rc = LDAP_UNWILLING_TO_PERFORM;
814 break;
815
816 case REWRITE_REGEXEC_ERR:
817 if ( fdc.rs ) {
818 fdc.rs->sr_err = LDAP_OTHER;
819 fdc.rs->sr_text = "Rewrite error";
820 }
821 rc = LDAP_OTHER;
822 break;
823 }
824
825 return rc;
826 }
827
828 /*
829 * I don't like this much, but we need two different
830 * functions because different heap managers may be
831 * in use in back-ldap/meta to reduce the amount of
832 * calls to malloc routines, and some of the free()
833 * routines may be macros with args
834 */
835 int
836 rwm_referral_rewrite(
837 Operation *op,
838 SlapReply *rs,
839 void *cookie,
840 BerVarray a_vals,
841 BerVarray *pa_nvals )
842 {
843 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
844 struct ldaprwmap *rwmap =
845 (struct ldaprwmap *)on->on_bi.bi_private;
846
847 int i, last;
848
849 dncookie dc;
850 struct berval dn = BER_BVNULL,
851 ndn = BER_BVNULL;
852
853 assert( a_vals != NULL );
854
855 /*
856 * Rewrite the dn if needed
857 */
858 dc.rwmap = rwmap;
859 dc.conn = op->o_conn;
860 dc.rs = rs;
861 dc.ctx = (char *)cookie;
862
863 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
864 ;
865 last--;
866
867 if ( pa_nvals != NULL ) {
868 if ( *pa_nvals == NULL ) {
869 *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
870 memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
871 }
872 }
873
874 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
875 struct berval olddn = BER_BVNULL,
876 oldval;
877 int rc;
878 LDAPURLDesc *ludp;
879
880 oldval = a_vals[i];
881 rc = ldap_url_parse( oldval.bv_val, &ludp );
882 if ( rc != LDAP_URL_SUCCESS ) {
883 /* leave attr untouched if massage failed */
884 if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
885 ber_dupbv( &(*pa_nvals)[i], &oldval );
886 }
887 continue;
888 }
889
890 /* FIXME: URLs like "ldap:///dc=suffix" if passed
891 * thru ldap_url_parse() and ldap_url_desc2str()
892 * get rewritten as "ldap:///dc=suffix??base";
893 * we don't want this to occur... */
894 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
895 ludp->lud_scope = LDAP_SCOPE_DEFAULT;
896 }
897
898 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
899
900 dn = olddn;
901 if ( pa_nvals ) {
902 ndn = olddn;
903 rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
904 &dn, &ndn );
905 } else {
906 rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
907 }
908
909 switch ( rc ) {
910 case LDAP_UNWILLING_TO_PERFORM:
911 /*
912 * FIXME: need to check if it may be considered
913 * legal to trim values when adding/modifying;
914 * it should be when searching (e.g. ACLs).
915 */
916 ch_free( a_vals[i].bv_val );
917 if (last > i ) {
918 a_vals[i] = a_vals[last];
919 if ( pa_nvals ) {
920 (*pa_nvals)[i] = (*pa_nvals)[last];
921 }
922 }
923 BER_BVZERO( &a_vals[last] );
924 if ( pa_nvals ) {
925 BER_BVZERO( &(*pa_nvals)[last] );
926 }
927 last--;
928 break;
929
930 case LDAP_SUCCESS:
931 if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
932 char *newurl;
933
934 ludp->lud_dn = dn.bv_val;
935 newurl = ldap_url_desc2str( ludp );
936 ludp->lud_dn = olddn.bv_val;
937 ch_free( dn.bv_val );
938 if ( newurl == NULL ) {
939 /* FIXME: leave attr untouched
940 * even if ldap_url_desc2str failed...
941 */
942 break;
943 }
944
945 ber_str2bv( newurl, 0, 1, &a_vals[i] );
946 LDAP_FREE( newurl );
947
948 if ( pa_nvals ) {
949 ludp->lud_dn = ndn.bv_val;
950 newurl = ldap_url_desc2str( ludp );
951 ludp->lud_dn = olddn.bv_val;
952 ch_free( ndn.bv_val );
953 if ( newurl == NULL ) {
954 /* FIXME: leave attr untouched
955 * even if ldap_url_desc2str failed...
956 */
957 ch_free( a_vals[i].bv_val );
958 a_vals[i] = oldval;
959 break;
960 }
961
962 if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
963 ch_free( (*pa_nvals)[i].bv_val );
964 }
965 ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
966 LDAP_FREE( newurl );
967 }
968
969 ch_free( oldval.bv_val );
970 ludp->lud_dn = olddn.bv_val;
971 }
972 break;
973
974 default:
975 /* leave attr untouched if massage failed */
976 if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
977 ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
978 }
979 break;
980 }
981 ldap_free_urldesc( ludp );
982 }
983
984 return 0;
985 }
986
987 /*
988 * I don't like this much, but we need two different
989 * functions because different heap managers may be
990 * in use in back-ldap/meta to reduce the amount of
991 * calls to malloc routines, and some of the free()
992 * routines may be macros with args
993 */
994 int
995 rwm_dnattr_rewrite(
996 Operation *op,
997 SlapReply *rs,
998 void *cookie,
999 BerVarray a_vals,
1000 BerVarray *pa_nvals )
1001 {
1002 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1003 struct ldaprwmap *rwmap =
1004 (struct ldaprwmap *)on->on_bi.bi_private;
1005
1006 int i, last;
1007
1008 dncookie dc;
1009 struct berval dn = BER_BVNULL,
1010 ndn = BER_BVNULL;
1011 BerVarray in;
1012
1013 if ( a_vals ) {
1014 in = a_vals;
1015
1016 } else {
1017 if ( pa_nvals == NULL || *pa_nvals == NULL ) {
1018 return LDAP_OTHER;
1019 }
1020 in = *pa_nvals;
1021 }
1022
1023 /*
1024 * Rewrite the dn if needed
1025 */
1026 dc.rwmap = rwmap;
1027 dc.conn = op->o_conn;
1028 dc.rs = rs;
1029 dc.ctx = (char *)cookie;
1030
1031 for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
1032 last--;
1033 if ( pa_nvals != NULL ) {
1034 if ( *pa_nvals == NULL ) {
1035 *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
1036 memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
1037 }
1038 }
1039
1040 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1041 int rc;
1042
1043 if ( a_vals ) {
1044 dn = in[i];
1045 if ( pa_nvals ) {
1046 ndn = (*pa_nvals)[i];
1047 rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
1048 } else {
1049 rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
1050 }
1051 } else {
1052 ndn = in[i];
1053 rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
1054 }
1055
1056 switch ( rc ) {
1057 case LDAP_UNWILLING_TO_PERFORM:
1058 /*
1059 * FIXME: need to check if it may be considered
1060 * legal to trim values when adding/modifying;
1061 * it should be when searching (e.g. ACLs).
1062 */
1063 ch_free( in[i].bv_val );
1064 if (last > i ) {
1065 in[i] = in[last];
1066 if ( a_vals && pa_nvals ) {
1067 (*pa_nvals)[i] = (*pa_nvals)[last];
1068 }
1069 }
1070 BER_BVZERO( &in[last] );
1071 if ( a_vals && pa_nvals ) {
1072 BER_BVZERO( &(*pa_nvals)[last] );
1073 }
1074 last--;
1075 break;
1076
1077 case LDAP_SUCCESS:
1078 if ( a_vals ) {
1079 if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
1080 ch_free( a_vals[i].bv_val );
1081 a_vals[i] = dn;
1082
1083 if ( pa_nvals ) {
1084 if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1085 ch_free( (*pa_nvals)[i].bv_val );
1086 }
1087 (*pa_nvals)[i] = ndn;
1088 }
1089 }
1090
1091 } else {
1092 if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
1093 ch_free( (*pa_nvals)[i].bv_val );
1094 (*pa_nvals)[i] = ndn;
1095 }
1096 }
1097 break;
1098
1099 default:
1100 /* leave attr untouched if massage failed */
1101 if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
1102 dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
1103 }
1104 break;
1105 }
1106 }
1107
1108 return 0;
1109 }
1110
1111 int
1112 rwm_referral_result_rewrite(
1113 dncookie *dc,
1114 BerVarray a_vals )
1115 {
1116 int i, last;
1117
1118 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1119 last--;
1120
1121 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1122 struct berval dn,
1123 olddn = BER_BVNULL;
1124 int rc;
1125 LDAPURLDesc *ludp;
1126
1127 rc = ldap_url_parse( a_vals[i].bv_val, &ludp );
1128 if ( rc != LDAP_URL_SUCCESS ) {
1129 /* leave attr untouched if massage failed */
1130 continue;
1131 }
1132
1133 /* FIXME: URLs like "ldap:///dc=suffix" if passed
1134 * thru ldap_url_parse() and ldap_url_desc2str()
1135 * get rewritten as "ldap:///dc=suffix??base";
1136 * we don't want this to occur... */
1137 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
1138 ludp->lud_scope = LDAP_SCOPE_DEFAULT;
1139 }
1140
1141 ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
1142
1143 dn = olddn;
1144 rc = rwm_dn_massage_pretty( dc, &olddn, &dn );
1145 switch ( rc ) {
1146 case LDAP_UNWILLING_TO_PERFORM:
1147 /*
1148 * FIXME: need to check if it may be considered
1149 * legal to trim values when adding/modifying;
1150 * it should be when searching (e.g. ACLs).
1151 */
1152 ch_free( a_vals[i].bv_val );
1153 if ( last > i ) {
1154 a_vals[i] = a_vals[last];
1155 }
1156 BER_BVZERO( &a_vals[last] );
1157 last--;
1158 i--;
1159 break;
1160
1161 default:
1162 /* leave attr untouched if massage failed */
1163 if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) {
1164 char *newurl;
1165
1166 ludp->lud_dn = dn.bv_val;
1167 newurl = ldap_url_desc2str( ludp );
1168 if ( newurl == NULL ) {
1169 /* FIXME: leave attr untouched
1170 * even if ldap_url_desc2str failed...
1171 */
1172 break;
1173 }
1174
1175 ch_free( a_vals[i].bv_val );
1176 ber_str2bv( newurl, 0, 1, &a_vals[i] );
1177 LDAP_FREE( newurl );
1178 ludp->lud_dn = olddn.bv_val;
1179 }
1180 break;
1181 }
1182
1183 ldap_free_urldesc( ludp );
1184 }
1185
1186 return 0;
1187 }
1188
1189 int
1190 rwm_dnattr_result_rewrite(
1191 dncookie *dc,
1192 BerVarray a_vals,
1193 BerVarray a_nvals )
1194 {
1195 int i, last;
1196
1197 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
1198 last--;
1199
1200 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
1201 struct berval pdn, ndn = BER_BVNULL;
1202 int rc;
1203
1204 pdn = a_vals[i];
1205 rc = rwm_dn_massage_pretty_normalize( dc, &a_vals[i], &pdn, &ndn );
1206 switch ( rc ) {
1207 case LDAP_UNWILLING_TO_PERFORM:
1208 /*
1209 * FIXME: need to check if it may be considered
1210 * legal to trim values when adding/modifying;
1211 * it should be when searching (e.g. ACLs).
1212 */
1213 assert( a_vals[i].bv_val != a_nvals[i].bv_val );
1214 ch_free( a_vals[i].bv_val );
1215 ch_free( a_nvals[i].bv_val );
1216 if ( last > i ) {
1217 a_vals[i] = a_vals[last];
1218 a_nvals[i] = a_nvals[last];
1219 }
1220 BER_BVZERO( &a_vals[last] );
1221 BER_BVZERO( &a_nvals[last] );
1222 last--;
1223 break;
1224
1225 default:
1226 /* leave attr untouched if massage failed */
1227 if ( !BER_BVISNULL( &pdn ) && a_vals[i].bv_val != pdn.bv_val ) {
1228 ch_free( a_vals[i].bv_val );
1229 a_vals[i] = pdn;
1230 }
1231 if ( !BER_BVISNULL( &ndn ) && a_nvals[i].bv_val != ndn.bv_val ) {
1232 ch_free( a_nvals[i].bv_val );
1233 a_nvals[i] = ndn;
1234 }
1235 break;
1236 }
1237 }
1238
1239 return 0;
1240 }
1241
1242 void
1243 rwm_mapping_dst_free( void *v_mapping )
1244 {
1245 struct ldapmapping *mapping = v_mapping;
1246
1247 if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) {
1248 rwm_mapping_free( &mapping[ -1 ] );
1249 }
1250 }
1251
1252 void
1253 rwm_mapping_free( void *v_mapping )
1254 {
1255 struct ldapmapping *mapping = v_mapping;
1256
1257 if ( !BER_BVISNULL( &mapping[0].m_src ) ) {
1258 ch_free( mapping[0].m_src.bv_val );
1259 }
1260
1261 if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) {
1262 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1263 if ( mapping[0].m_src_oc ) {
1264 ch_free( mapping[0].m_src_oc );
1265 }
1266
1267 } else {
1268 if ( mapping[0].m_src_ad ) {
1269 ch_free( mapping[0].m_src_ad );
1270 }
1271 }
1272 }
1273
1274 if ( !BER_BVISNULL( &mapping[0].m_dst ) ) {
1275 ch_free( mapping[0].m_dst.bv_val );
1276 }
1277
1278 if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) {
1279 if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) {
1280 if ( mapping[0].m_dst_oc ) {
1281 ch_free( mapping[0].m_dst_oc );
1282 }
1283
1284 } else {
1285 if ( mapping[0].m_dst_ad ) {
1286 ch_free( mapping[0].m_dst_ad );
1287 }
1288 }
1289 }
1290
1291 ch_free( mapping );
1292
1293 }
1294
1295 #endif /* SLAPD_OVER_RWM */
1296