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