1/* map.c - ldap backend mapping routines */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* ACKNOWLEDGEMENTS: 17 * This work was initially developed by the Howard Chu for inclusion 18 * in OpenLDAP Software and subsequently enhanced by Pierangelo 19 * Masarati. 20 */ 21/* This is an altered version */ 22/* 23 * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com> 24 * 25 * Permission is granted to anyone to use this software for any purpose 26 * on any computer system, and to alter it and redistribute it, subject 27 * to the following restrictions: 28 * 29 * 1. The author is not responsible for the consequences of use of this 30 * software, no matter how awful, even if they arise from flaws in it. 31 * 32 * 2. The origin of this software must not be misrepresented, either by 33 * explicit claim or by omission. Since few users ever read sources, 34 * credits should appear in the documentation. 35 * 36 * 3. Altered versions must be plainly marked as such, and must not be 37 * misrepresented as being the original software. Since few users 38 * ever read sources, credits should appear in the documentation. 39 * 40 * 4. This notice may not be removed or altered. 41 * 42 * 43 * 44 * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it> 45 * 46 * This software is being modified by Pierangelo Masarati. 47 * The previously reported conditions apply to the modified code as well. 48 * Changes in the original code are highlighted where required. 49 * Credits for the original code go to the author, Howard Chu. 50 */ 51 52#include "portable.h" 53 54#include <stdio.h> 55 56#include <ac/string.h> 57#include <ac/socket.h> 58 59#include "slap.h" 60#include "lutil.h" 61#include "../back-ldap/back-ldap.h" 62#include "back-meta.h" 63 64int 65mapping_cmp ( const void *c1, const void *c2 ) 66{ 67 struct ldapmapping *map1 = (struct ldapmapping *)c1; 68 struct ldapmapping *map2 = (struct ldapmapping *)c2; 69 int rc = map1->src.bv_len - map2->src.bv_len; 70 if (rc) return rc; 71 return ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) ); 72} 73 74int 75mapping_dup ( void *c1, void *c2 ) 76{ 77 struct ldapmapping *map1 = (struct ldapmapping *)c1; 78 struct ldapmapping *map2 = (struct ldapmapping *)c2; 79 80 return ( ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) == 0 ) ? -1 : 0 ); 81} 82 83void 84ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m ) 85{ 86 struct ldapmapping *mapping; 87 88 assert( m != NULL ); 89 90 *m = NULL; 91 92 mapping = (struct ldapmapping *)ch_calloc( 2, 93 sizeof( struct ldapmapping ) ); 94 if ( mapping == NULL ) { 95 return; 96 } 97 98 ber_str2bv( "objectclass", STRLENOF("objectclass"), 1, &mapping[0].src); 99 ber_dupbv( &mapping[0].dst, &mapping[0].src ); 100 mapping[1].src = mapping[0].src; 101 mapping[1].dst = mapping[0].dst; 102 103 avl_insert( &lm->map, (caddr_t)&mapping[0], 104 mapping_cmp, mapping_dup ); 105 avl_insert( &lm->remap, (caddr_t)&mapping[1], 106 mapping_cmp, mapping_dup ); 107 *m = mapping; 108} 109 110int 111ldap_back_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **m, 112 int remap ) 113{ 114 Avlnode *tree; 115 struct ldapmapping fmapping; 116 117 assert( m != NULL ); 118 119 /* let special attrnames slip through (ITS#5760) */ 120 if ( bvmatch( s, slap_bv_no_attrs ) 121 || bvmatch( s, slap_bv_all_user_attrs ) 122 || bvmatch( s, slap_bv_all_operational_attrs ) ) 123 { 124 *m = NULL; 125 return 0; 126 } 127 128 if ( remap == BACKLDAP_REMAP ) { 129 tree = map->remap; 130 131 } else { 132 tree = map->map; 133 } 134 135 fmapping.src = *s; 136 *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp ); 137 if ( *m == NULL ) { 138 return map->drop_missing; 139 } 140 141 return 0; 142} 143 144void 145ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, 146 int remap ) 147{ 148 struct ldapmapping *mapping; 149 int drop_missing; 150 151 /* map->map may be NULL when mapping is configured, 152 * but map->remap can't */ 153 if ( map->remap == NULL ) { 154 *bv = *s; 155 return; 156 } 157 158 BER_BVZERO( bv ); 159 drop_missing = ldap_back_mapping( map, s, &mapping, remap ); 160 if ( mapping != NULL ) { 161 if ( !BER_BVISNULL( &mapping->dst ) ) { 162 *bv = mapping->dst; 163 } 164 return; 165 } 166 167 if ( !drop_missing ) { 168 *bv = *s; 169 } 170} 171 172int 173ldap_back_map_attrs( 174 Operation *op, 175 struct ldapmap *at_map, 176 AttributeName *an, 177 int remap, 178 char ***mapped_attrs ) 179{ 180 int i, x, j; 181 char **na; 182 struct berval mapped; 183 184 if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) { 185 *mapped_attrs = NULL; 186 return LDAP_SUCCESS; 187 } 188 189 i = 0; 190 if ( an != NULL ) { 191 for ( ; !BER_BVISNULL( &an[i].an_name ); i++ ) 192 /* */ ; 193 } 194 195 x = 0; 196 if ( op->o_bd->be_extra_anlist != NULL ) { 197 for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) 198 /* */ ; 199 } 200 201 assert( i > 0 || x > 0 ); 202 203 na = (char **)ber_memcalloc_x( i + x + 1, sizeof(char *), op->o_tmpmemctx ); 204 if ( na == NULL ) { 205 *mapped_attrs = NULL; 206 return LDAP_NO_MEMORY; 207 } 208 209 j = 0; 210 if ( i > 0 ) { 211 for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { 212 ldap_back_map( at_map, &an[i].an_name, &mapped, remap ); 213 if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { 214 na[j++] = mapped.bv_val; 215 } 216 } 217 } 218 219 if ( x > 0 ) { 220 for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) { 221 if ( op->o_bd->be_extra_anlist[x].an_desc && 222 ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, an ) ) 223 { 224 continue; 225 } 226 227 ldap_back_map( at_map, &op->o_bd->be_extra_anlist[x].an_name, &mapped, remap ); 228 if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { 229 na[j++] = mapped.bv_val; 230 } 231 } 232 } 233 234 if ( j == 0 && ( i > 0 || x > 0 ) ) { 235 na[j++] = LDAP_NO_ATTRS; 236 } 237 na[j] = NULL; 238 239 *mapped_attrs = na; 240 241 return LDAP_SUCCESS; 242} 243 244static int 245map_attr_value( 246 dncookie *dc, 247 AttributeDescription *ad, 248 struct berval *mapped_attr, 249 struct berval *value, 250 struct berval *mapped_value, 251 int remap, 252 void *memctx ) 253{ 254 struct berval vtmp; 255 int freeval = 0; 256 257 ldap_back_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap ); 258 if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { 259#if 0 260 /* 261 * FIXME: are we sure we need to search oc_map if at_map fails? 262 */ 263 ldap_back_map( &dc->target->mt_rwmap.rwm_oc, &ad->ad_cname, mapped_attr, remap ); 264 if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { 265 *mapped_attr = ad->ad_cname; 266 } 267#endif 268 if ( dc->target->mt_rwmap.rwm_at.drop_missing ) { 269 return -1; 270 } 271 272 *mapped_attr = ad->ad_cname; 273 } 274 275 if ( value == NULL ) { 276 return 0; 277 } 278 279 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) 280 { 281 dncookie fdc = *dc; 282 283#ifdef ENABLE_REWRITE 284 fdc.ctx = "searchFilterAttrDN"; 285#endif 286 287 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) { 288 case LDAP_SUCCESS: 289 if ( vtmp.bv_val != value->bv_val ) { 290 freeval = 1; 291 } 292 break; 293 294 case LDAP_UNWILLING_TO_PERFORM: 295 return -1; 296 297 case LDAP_OTHER: 298 return -1; 299 } 300 301 } else if ( ad->ad_type->sat_equality && 302 ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) 303 { 304 if ( ad->ad_type->sat_equality->smr_normalize( 305 (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX), 306 NULL, NULL, value, &vtmp, memctx ) ) 307 { 308 return -1; 309 } 310 freeval = 2; 311 312 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) { 313 ldap_back_map( &dc->target->mt_rwmap.rwm_oc, value, &vtmp, remap ); 314 if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { 315 vtmp = *value; 316 } 317 318 } else { 319 vtmp = *value; 320 } 321 322 filter_escape_value_x( &vtmp, mapped_value, memctx ); 323 324 switch ( freeval ) { 325 case 1: 326 ber_memfree( vtmp.bv_val ); 327 break; 328 case 2: 329 ber_memfree_x( vtmp.bv_val, memctx ); 330 break; 331 } 332 333 return 0; 334} 335 336static int 337ldap_back_int_filter_map_rewrite( 338 dncookie *dc, 339 Filter *f, 340 struct berval *fstr, 341 int remap, 342 void *memctx ) 343{ 344 int i; 345 Filter *p; 346 struct berval atmp, 347 vtmp, 348 *tmp; 349 static struct berval 350 /* better than nothing... */ 351 ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), 352 ber_bvtf_false = BER_BVC( "(|)" ), 353 /* better than nothing... */ 354 ber_bvtrue = BER_BVC( "(objectClass=*)" ), 355 ber_bvtf_true = BER_BVC( "(&)" ), 356#if 0 357 /* no longer needed; preserved for completeness */ 358 ber_bvundefined = BER_BVC( "(?=undefined)" ), 359#endif 360 ber_bverror = BER_BVC( "(?=error)" ), 361 ber_bvunknown = BER_BVC( "(?=unknown)" ), 362 ber_bvnone = BER_BVC( "(?=none)" ); 363 ber_len_t len; 364 365 assert( fstr != NULL ); 366 BER_BVZERO( fstr ); 367 368 if ( f == NULL ) { 369 ber_dupbv_x( fstr, &ber_bvnone, memctx ); 370 return LDAP_OTHER; 371 } 372 373 switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) { 374 case LDAP_FILTER_EQUALITY: 375 if ( map_attr_value( dc, f->f_av_desc, &atmp, 376 &f->f_av_value, &vtmp, remap, memctx ) ) 377 { 378 goto computed; 379 } 380 381 fstr->bv_len = atmp.bv_len + vtmp.bv_len 382 + ( sizeof("(=)") - 1 ); 383 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 384 385 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)", 386 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 387 388 ber_memfree_x( vtmp.bv_val, memctx ); 389 break; 390 391 case LDAP_FILTER_GE: 392 if ( map_attr_value( dc, f->f_av_desc, &atmp, 393 &f->f_av_value, &vtmp, remap, memctx ) ) 394 { 395 goto computed; 396 } 397 398 fstr->bv_len = atmp.bv_len + vtmp.bv_len 399 + ( sizeof("(>=)") - 1 ); 400 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 401 402 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)", 403 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 404 405 ber_memfree_x( vtmp.bv_val, memctx ); 406 break; 407 408 case LDAP_FILTER_LE: 409 if ( map_attr_value( dc, f->f_av_desc, &atmp, 410 &f->f_av_value, &vtmp, remap, memctx ) ) 411 { 412 goto computed; 413 } 414 415 fstr->bv_len = atmp.bv_len + vtmp.bv_len 416 + ( sizeof("(<=)") - 1 ); 417 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 418 419 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)", 420 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 421 422 ber_memfree_x( vtmp.bv_val, memctx ); 423 break; 424 425 case LDAP_FILTER_APPROX: 426 if ( map_attr_value( dc, f->f_av_desc, &atmp, 427 &f->f_av_value, &vtmp, remap, memctx ) ) 428 { 429 goto computed; 430 } 431 432 fstr->bv_len = atmp.bv_len + vtmp.bv_len 433 + ( sizeof("(~=)") - 1 ); 434 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 435 436 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)", 437 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 438 439 ber_memfree_x( vtmp.bv_val, memctx ); 440 break; 441 442 case LDAP_FILTER_SUBSTRINGS: 443 if ( map_attr_value( dc, f->f_sub_desc, &atmp, 444 NULL, NULL, remap, memctx ) ) 445 { 446 goto computed; 447 } 448 449 /* cannot be a DN ... */ 450 451 fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); 452 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */ 453 454 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 455 atmp.bv_val ); 456 457 if ( !BER_BVISNULL( &f->f_sub_initial ) ) { 458 len = fstr->bv_len; 459 460 filter_escape_value_x( &f->f_sub_initial, &vtmp, memctx ); 461 462 fstr->bv_len += vtmp.bv_len; 463 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 464 465 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3, 466 /* "(attr=" */ "%s*)", 467 vtmp.bv_len ? vtmp.bv_val : "" ); 468 469 ber_memfree_x( vtmp.bv_val, memctx ); 470 } 471 472 if ( f->f_sub_any != NULL ) { 473 for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) { 474 len = fstr->bv_len; 475 filter_escape_value_x( &f->f_sub_any[i], &vtmp, memctx ); 476 477 fstr->bv_len += vtmp.bv_len + 1; 478 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 479 480 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 481 /* "(attr=[init]*[any*]" */ "%s*)", 482 vtmp.bv_len ? vtmp.bv_val : "" ); 483 ber_memfree_x( vtmp.bv_val, memctx ); 484 } 485 } 486 487 if ( !BER_BVISNULL( &f->f_sub_final ) ) { 488 len = fstr->bv_len; 489 490 filter_escape_value_x( &f->f_sub_final, &vtmp, memctx ); 491 492 fstr->bv_len += vtmp.bv_len; 493 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 494 495 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 496 /* "(attr=[init*][any*]" */ "%s)", 497 vtmp.bv_len ? vtmp.bv_val : "" ); 498 499 ber_memfree_x( vtmp.bv_val, memctx ); 500 } 501 502 break; 503 504 case LDAP_FILTER_PRESENT: 505 if ( map_attr_value( dc, f->f_desc, &atmp, 506 NULL, NULL, remap, memctx ) ) 507 { 508 goto computed; 509 } 510 511 fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); 512 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 513 514 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 515 atmp.bv_val ); 516 break; 517 518 case LDAP_FILTER_AND: 519 case LDAP_FILTER_OR: 520 case LDAP_FILTER_NOT: 521 fstr->bv_len = STRLENOF( "(%)" ); 522 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128? */ 523 524 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)", 525 f->f_choice == LDAP_FILTER_AND ? '&' : 526 f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); 527 528 for ( p = f->f_list; p != NULL; p = p->f_next ) { 529 int rc; 530 531 len = fstr->bv_len; 532 533 rc = ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap, memctx ); 534 if ( rc != LDAP_SUCCESS ) { 535 return rc; 536 } 537 538 fstr->bv_len += vtmp.bv_len; 539 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 540 541 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 542 /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" ); 543 544 ber_memfree_x( vtmp.bv_val, memctx ); 545 } 546 547 break; 548 549 case LDAP_FILTER_EXT: 550 if ( f->f_mr_desc ) { 551 if ( map_attr_value( dc, f->f_mr_desc, &atmp, 552 &f->f_mr_value, &vtmp, remap, memctx ) ) 553 { 554 goto computed; 555 } 556 557 } else { 558 BER_BVSTR( &atmp, "" ); 559 filter_escape_value_x( &f->f_mr_value, &vtmp, memctx ); 560 } 561 562 /* FIXME: cleanup (less ?: operators...) */ 563 fstr->bv_len = atmp.bv_len + 564 ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) + 565 ( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) + 566 vtmp.bv_len + ( STRLENOF( "(:=)" ) ); 567 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 568 569 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)", 570 atmp.bv_val, 571 f->f_mr_dnattrs ? ":dn" : "", 572 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "", 573 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "", 574 vtmp.bv_len ? vtmp.bv_val : "" ); 575 ber_memfree_x( vtmp.bv_val, memctx ); 576 break; 577 578 case SLAPD_FILTER_COMPUTED: 579 switch ( f->f_result ) { 580 /* FIXME: treat UNDEFINED as FALSE */ 581 case SLAPD_COMPARE_UNDEFINED: 582computed:; 583 if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) { 584 return LDAP_COMPARE_FALSE; 585 } 586 /* fallthru */ 587 588 case LDAP_COMPARE_FALSE: 589 if ( META_BACK_TGT_T_F( dc->target ) ) { 590 tmp = &ber_bvtf_false; 591 break; 592 } 593 tmp = &ber_bvfalse; 594 break; 595 596 case LDAP_COMPARE_TRUE: 597 if ( META_BACK_TGT_T_F( dc->target ) ) { 598 tmp = &ber_bvtf_true; 599 break; 600 } 601 602 tmp = &ber_bvtrue; 603 break; 604 605 default: 606 tmp = &ber_bverror; 607 break; 608 } 609 610 ber_dupbv_x( fstr, tmp, memctx ); 611 break; 612 613 default: 614 ber_dupbv_x( fstr, &ber_bvunknown, memctx ); 615 break; 616 } 617 618 return 0; 619} 620 621int 622ldap_back_filter_map_rewrite( 623 dncookie *dc, 624 Filter *f, 625 struct berval *fstr, 626 int remap, 627 void *memctx ) 628{ 629 int rc; 630 dncookie fdc; 631 struct berval ftmp; 632 static char *dmy = ""; 633 634 rc = ldap_back_int_filter_map_rewrite( dc, f, fstr, remap, memctx ); 635 636#ifdef ENABLE_REWRITE 637 if ( rc != LDAP_SUCCESS ) { 638 return rc; 639 } 640 641 fdc = *dc; 642 ftmp = *fstr; 643 644 fdc.ctx = "searchFilter"; 645 646 switch ( rewrite_session( fdc.target->mt_rwmap.rwm_rw, fdc.ctx, 647 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : dmy ), 648 fdc.conn, &fstr->bv_val ) ) 649 { 650 case REWRITE_REGEXEC_OK: 651 if ( !BER_BVISNULL( fstr ) ) { 652 fstr->bv_len = strlen( fstr->bv_val ); 653 654 } else { 655 *fstr = ftmp; 656 } 657 Debug( LDAP_DEBUG_ARGS, 658 "[rw] %s: \"%s\" -> \"%s\"\n", 659 fdc.ctx, BER_BVISNULL( &ftmp ) ? "" : ftmp.bv_val, 660 BER_BVISNULL( fstr ) ? "" : fstr->bv_val ); 661 rc = LDAP_SUCCESS; 662 break; 663 664 case REWRITE_REGEXEC_UNWILLING: 665 if ( fdc.rs ) { 666 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 667 fdc.rs->sr_text = "Operation not allowed"; 668 } 669 rc = LDAP_UNWILLING_TO_PERFORM; 670 break; 671 672 case REWRITE_REGEXEC_ERR: 673 if ( fdc.rs ) { 674 fdc.rs->sr_err = LDAP_OTHER; 675 fdc.rs->sr_text = "Rewrite error"; 676 } 677 rc = LDAP_OTHER; 678 break; 679 } 680 681 if ( fstr->bv_val == dmy ) { 682 BER_BVZERO( fstr ); 683 684 } else if ( fstr->bv_val != ftmp.bv_val ) { 685 /* NOTE: need to realloc mapped filter on slab 686 * and free the original one, until librewrite 687 * becomes slab-aware 688 */ 689 ber_dupbv_x( &ftmp, fstr, memctx ); 690 ch_free( fstr->bv_val ); 691 *fstr = ftmp; 692 } 693#endif /* ENABLE_REWRITE */ 694 695 return rc; 696} 697 698int 699ldap_back_referral_result_rewrite( 700 dncookie *dc, 701 BerVarray a_vals, 702 void *memctx 703) 704{ 705 int i, last; 706 707 assert( dc != NULL ); 708 assert( a_vals != NULL ); 709 710 for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ ) 711 ; 712 last--; 713 714 for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) { 715 struct berval dn, 716 olddn = BER_BVNULL; 717 int rc; 718 LDAPURLDesc *ludp; 719 720 rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp ); 721 if ( rc != LDAP_URL_SUCCESS ) { 722 /* leave attr untouched if massage failed */ 723 continue; 724 } 725 726 /* FIXME: URLs like "ldap:///dc=suffix" if passed 727 * thru ldap_url_parse() and ldap_url_desc2str() 728 * get rewritten as "ldap:///dc=suffix??base"; 729 * we don't want this to occur... */ 730 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { 731 ludp->lud_scope = LDAP_SCOPE_DEFAULT; 732 } 733 734 ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); 735 736 rc = ldap_back_dn_massage( dc, &olddn, &dn ); 737 switch ( rc ) { 738 case LDAP_UNWILLING_TO_PERFORM: 739 /* 740 * FIXME: need to check if it may be considered 741 * legal to trim values when adding/modifying; 742 * it should be when searching (e.g. ACLs). 743 */ 744 ber_memfree( a_vals[ i ].bv_val ); 745 if ( last > i ) { 746 a_vals[ i ] = a_vals[ last ]; 747 } 748 BER_BVZERO( &a_vals[ last ] ); 749 last--; 750 i--; 751 break; 752 753 default: 754 /* leave attr untouched if massage failed */ 755 if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) 756 { 757 char *newurl; 758 759 ludp->lud_dn = dn.bv_val; 760 newurl = ldap_url_desc2str( ludp ); 761 free( dn.bv_val ); 762 if ( newurl == NULL ) { 763 /* FIXME: leave attr untouched 764 * even if ldap_url_desc2str failed... 765 */ 766 break; 767 } 768 769 ber_memfree_x( a_vals[ i ].bv_val, memctx ); 770 ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx ); 771 ber_memfree( newurl ); 772 ludp->lud_dn = olddn.bv_val; 773 } 774 break; 775 } 776 777 ldap_free_urldesc( ludp ); 778 } 779 780 return 0; 781} 782 783/* 784 * I don't like this much, but we need two different 785 * functions because different heap managers may be 786 * in use in back-ldap/meta to reduce the amount of 787 * calls to malloc routines, and some of the free() 788 * routines may be macros with args 789 */ 790int 791ldap_dnattr_rewrite( 792 dncookie *dc, 793 BerVarray a_vals 794) 795{ 796 struct berval bv; 797 int i, last; 798 799 assert( a_vals != NULL ); 800 801 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ) 802 ; 803 last--; 804 805 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 806 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) { 807 case LDAP_UNWILLING_TO_PERFORM: 808 /* 809 * FIXME: need to check if it may be considered 810 * legal to trim values when adding/modifying; 811 * it should be when searching (e.g. ACLs). 812 */ 813 ch_free( a_vals[i].bv_val ); 814 if ( last > i ) { 815 a_vals[i] = a_vals[last]; 816 } 817 BER_BVZERO( &a_vals[last] ); 818 last--; 819 break; 820 821 default: 822 /* leave attr untouched if massage failed */ 823 if ( !BER_BVISNULL( &bv ) && bv.bv_val != a_vals[i].bv_val ) { 824 ch_free( a_vals[i].bv_val ); 825 a_vals[i] = bv; 826 } 827 break; 828 } 829 } 830 831 return 0; 832} 833 834int 835ldap_dnattr_result_rewrite( 836 dncookie *dc, 837 BerVarray a_vals 838) 839{ 840 struct berval bv; 841 int i, last; 842 843 assert( a_vals != NULL ); 844 845 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ) 846 ; 847 last--; 848 849 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 850 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) { 851 case LDAP_UNWILLING_TO_PERFORM: 852 /* 853 * FIXME: need to check if it may be considered 854 * legal to trim values when adding/modifying; 855 * it should be when searching (e.g. ACLs). 856 */ 857 ber_memfree( a_vals[i].bv_val ); 858 if ( last > i ) { 859 a_vals[i] = a_vals[last]; 860 } 861 BER_BVZERO( &a_vals[last] ); 862 last--; 863 break; 864 865 default: 866 /* leave attr untouched if massage failed */ 867 if ( !BER_BVISNULL( &bv ) && a_vals[i].bv_val != bv.bv_val ) { 868 ber_memfree( a_vals[i].bv_val ); 869 a_vals[i] = bv; 870 } 871 break; 872 } 873 } 874 875 return 0; 876} 877 878