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