1 /* $NetBSD: map.c,v 1.1.1.3 2010/12/12 15:23:11 adam Exp $ */ 2 3 /* map.c - ldap backend mapping routines */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/back-meta/map.c,v 1.15.2.14 2010/04/15 22:22:28 quanah Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 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 void *memctx ) 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 **)ber_memcalloc_x( i + 1, sizeof(char *), memctx ); 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 static 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 void *memctx ) 227 { 228 struct berval vtmp; 229 int freeval = 0; 230 231 ldap_back_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap ); 232 if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { 233 #if 0 234 /* 235 * FIXME: are we sure we need to search oc_map if at_map fails? 236 */ 237 ldap_back_map( &dc->target->mt_rwmap.rwm_oc, &ad->ad_cname, mapped_attr, remap ); 238 if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { 239 *mapped_attr = ad->ad_cname; 240 } 241 #endif 242 if ( dc->target->mt_rwmap.rwm_at.drop_missing ) { 243 return -1; 244 } 245 246 *mapped_attr = ad->ad_cname; 247 } 248 249 if ( value == NULL ) { 250 return 0; 251 } 252 253 if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) 254 { 255 dncookie fdc = *dc; 256 257 #ifdef ENABLE_REWRITE 258 fdc.ctx = "searchFilterAttrDN"; 259 #endif 260 261 switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) { 262 case LDAP_SUCCESS: 263 if ( vtmp.bv_val != value->bv_val ) { 264 freeval = 1; 265 } 266 break; 267 268 case LDAP_UNWILLING_TO_PERFORM: 269 return -1; 270 271 case LDAP_OTHER: 272 return -1; 273 } 274 275 } else if ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) { 276 if ( ad->ad_type->sat_equality->smr_normalize( 277 (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX), 278 NULL, NULL, value, &vtmp, memctx ) ) 279 { 280 return -1; 281 } 282 freeval = 2; 283 284 } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) { 285 ldap_back_map( &dc->target->mt_rwmap.rwm_oc, value, &vtmp, remap ); 286 if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { 287 vtmp = *value; 288 } 289 290 } else { 291 vtmp = *value; 292 } 293 294 filter_escape_value_x( &vtmp, mapped_value, memctx ); 295 296 switch ( freeval ) { 297 case 1: 298 ber_memfree( vtmp.bv_val ); 299 break; 300 case 2: 301 ber_memfree_x( vtmp.bv_val, memctx ); 302 break; 303 } 304 305 return 0; 306 } 307 308 static int 309 ldap_back_int_filter_map_rewrite( 310 dncookie *dc, 311 Filter *f, 312 struct berval *fstr, 313 int remap, 314 void *memctx ) 315 { 316 int i; 317 Filter *p; 318 struct berval atmp, 319 vtmp, 320 *tmp; 321 static struct berval 322 /* better than nothing... */ 323 ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), 324 ber_bvtf_false = BER_BVC( "(|)" ), 325 /* better than nothing... */ 326 ber_bvtrue = BER_BVC( "(objectClass=*)" ), 327 ber_bvtf_true = BER_BVC( "(&)" ), 328 #if 0 329 /* no longer needed; preserved for completeness */ 330 ber_bvundefined = BER_BVC( "(?=undefined)" ), 331 #endif 332 ber_bverror = BER_BVC( "(?=error)" ), 333 ber_bvunknown = BER_BVC( "(?=unknown)" ), 334 ber_bvnone = BER_BVC( "(?=none)" ); 335 ber_len_t len; 336 337 assert( fstr != NULL ); 338 BER_BVZERO( fstr ); 339 340 if ( f == NULL ) { 341 ber_dupbv_x( fstr, &ber_bvnone, memctx ); 342 return LDAP_OTHER; 343 } 344 345 switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) { 346 case LDAP_FILTER_EQUALITY: 347 if ( map_attr_value( dc, f->f_av_desc, &atmp, 348 &f->f_av_value, &vtmp, remap, memctx ) ) 349 { 350 goto computed; 351 } 352 353 fstr->bv_len = atmp.bv_len + vtmp.bv_len 354 + ( sizeof("(=)") - 1 ); 355 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 356 357 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)", 358 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 359 360 ber_memfree_x( vtmp.bv_val, memctx ); 361 break; 362 363 case LDAP_FILTER_GE: 364 if ( map_attr_value( dc, f->f_av_desc, &atmp, 365 &f->f_av_value, &vtmp, remap, memctx ) ) 366 { 367 goto computed; 368 } 369 370 fstr->bv_len = atmp.bv_len + vtmp.bv_len 371 + ( sizeof("(>=)") - 1 ); 372 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 373 374 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)", 375 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 376 377 ber_memfree_x( vtmp.bv_val, memctx ); 378 break; 379 380 case LDAP_FILTER_LE: 381 if ( map_attr_value( dc, f->f_av_desc, &atmp, 382 &f->f_av_value, &vtmp, remap, memctx ) ) 383 { 384 goto computed; 385 } 386 387 fstr->bv_len = atmp.bv_len + vtmp.bv_len 388 + ( sizeof("(<=)") - 1 ); 389 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 390 391 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)", 392 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 393 394 ber_memfree_x( vtmp.bv_val, memctx ); 395 break; 396 397 case LDAP_FILTER_APPROX: 398 if ( map_attr_value( dc, f->f_av_desc, &atmp, 399 &f->f_av_value, &vtmp, remap, memctx ) ) 400 { 401 goto computed; 402 } 403 404 fstr->bv_len = atmp.bv_len + vtmp.bv_len 405 + ( sizeof("(~=)") - 1 ); 406 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 407 408 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)", 409 atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 410 411 ber_memfree_x( vtmp.bv_val, memctx ); 412 break; 413 414 case LDAP_FILTER_SUBSTRINGS: 415 if ( map_attr_value( dc, f->f_sub_desc, &atmp, 416 NULL, NULL, remap, memctx ) ) 417 { 418 goto computed; 419 } 420 421 /* cannot be a DN ... */ 422 423 fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); 424 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */ 425 426 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 427 atmp.bv_val ); 428 429 if ( !BER_BVISNULL( &f->f_sub_initial ) ) { 430 len = fstr->bv_len; 431 432 filter_escape_value_x( &f->f_sub_initial, &vtmp, memctx ); 433 434 fstr->bv_len += vtmp.bv_len; 435 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 436 437 snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3, 438 /* "(attr=" */ "%s*)", 439 vtmp.bv_len ? vtmp.bv_val : "" ); 440 441 ber_memfree_x( vtmp.bv_val, memctx ); 442 } 443 444 if ( f->f_sub_any != NULL ) { 445 for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) { 446 len = fstr->bv_len; 447 filter_escape_value_x( &f->f_sub_any[i], &vtmp, memctx ); 448 449 fstr->bv_len += vtmp.bv_len + 1; 450 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 451 452 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 453 /* "(attr=[init]*[any*]" */ "%s*)", 454 vtmp.bv_len ? vtmp.bv_val : "" ); 455 ber_memfree_x( vtmp.bv_val, memctx ); 456 } 457 } 458 459 if ( !BER_BVISNULL( &f->f_sub_final ) ) { 460 len = fstr->bv_len; 461 462 filter_escape_value_x( &f->f_sub_final, &vtmp, memctx ); 463 464 fstr->bv_len += vtmp.bv_len; 465 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 466 467 snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 468 /* "(attr=[init*][any*]" */ "%s)", 469 vtmp.bv_len ? vtmp.bv_val : "" ); 470 471 ber_memfree_x( vtmp.bv_val, memctx ); 472 } 473 474 break; 475 476 case LDAP_FILTER_PRESENT: 477 if ( map_attr_value( dc, f->f_desc, &atmp, 478 NULL, NULL, remap, memctx ) ) 479 { 480 goto computed; 481 } 482 483 fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) ); 484 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 485 486 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 487 atmp.bv_val ); 488 break; 489 490 case LDAP_FILTER_AND: 491 case LDAP_FILTER_OR: 492 case LDAP_FILTER_NOT: 493 fstr->bv_len = STRLENOF( "(%)" ); 494 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128? */ 495 496 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)", 497 f->f_choice == LDAP_FILTER_AND ? '&' : 498 f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); 499 500 for ( p = f->f_list; p != NULL; p = p->f_next ) { 501 int rc; 502 503 len = fstr->bv_len; 504 505 rc = ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap, memctx ); 506 if ( rc != LDAP_SUCCESS ) { 507 return rc; 508 } 509 510 fstr->bv_len += vtmp.bv_len; 511 fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx ); 512 513 snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 514 /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" ); 515 516 ber_memfree_x( vtmp.bv_val, memctx ); 517 } 518 519 break; 520 521 case LDAP_FILTER_EXT: 522 if ( f->f_mr_desc ) { 523 if ( map_attr_value( dc, f->f_mr_desc, &atmp, 524 &f->f_mr_value, &vtmp, remap, memctx ) ) 525 { 526 goto computed; 527 } 528 529 } else { 530 BER_BVSTR( &atmp, "" ); 531 filter_escape_value_x( &f->f_mr_value, &vtmp, memctx ); 532 } 533 534 /* FIXME: cleanup (less ?: operators...) */ 535 fstr->bv_len = atmp.bv_len + 536 ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) + 537 ( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) + 538 vtmp.bv_len + ( STRLENOF( "(:=)" ) ); 539 fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx ); 540 541 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)", 542 atmp.bv_val, 543 f->f_mr_dnattrs ? ":dn" : "", 544 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "", 545 !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "", 546 vtmp.bv_len ? vtmp.bv_val : "" ); 547 ber_memfree_x( vtmp.bv_val, memctx ); 548 break; 549 550 case SLAPD_FILTER_COMPUTED: 551 switch ( f->f_result ) { 552 /* FIXME: treat UNDEFINED as FALSE */ 553 case SLAPD_COMPARE_UNDEFINED: 554 computed:; 555 if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) { 556 return LDAP_COMPARE_FALSE; 557 } 558 /* fallthru */ 559 560 case LDAP_COMPARE_FALSE: 561 if ( META_BACK_TGT_T_F( dc->target ) ) { 562 tmp = &ber_bvtf_false; 563 break; 564 } 565 tmp = &ber_bvfalse; 566 break; 567 568 case LDAP_COMPARE_TRUE: 569 if ( META_BACK_TGT_T_F( dc->target ) ) { 570 tmp = &ber_bvtf_true; 571 break; 572 } 573 574 tmp = &ber_bvtrue; 575 break; 576 577 default: 578 tmp = &ber_bverror; 579 break; 580 } 581 582 ber_dupbv_x( fstr, tmp, memctx ); 583 break; 584 585 default: 586 ber_dupbv_x( fstr, &ber_bvunknown, memctx ); 587 break; 588 } 589 590 return 0; 591 } 592 593 int 594 ldap_back_filter_map_rewrite( 595 dncookie *dc, 596 Filter *f, 597 struct berval *fstr, 598 int remap, 599 void *memctx ) 600 { 601 int rc; 602 dncookie fdc; 603 struct berval ftmp; 604 static char *dmy = ""; 605 606 rc = ldap_back_int_filter_map_rewrite( dc, f, fstr, remap, memctx ); 607 608 #ifdef ENABLE_REWRITE 609 if ( rc != LDAP_SUCCESS ) { 610 return rc; 611 } 612 613 fdc = *dc; 614 ftmp = *fstr; 615 616 fdc.ctx = "searchFilter"; 617 618 switch ( rewrite_session( fdc.target->mt_rwmap.rwm_rw, fdc.ctx, 619 ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : dmy ), 620 fdc.conn, &fstr->bv_val ) ) 621 { 622 case REWRITE_REGEXEC_OK: 623 if ( !BER_BVISNULL( fstr ) ) { 624 fstr->bv_len = strlen( fstr->bv_val ); 625 626 } else { 627 *fstr = ftmp; 628 } 629 Debug( LDAP_DEBUG_ARGS, 630 "[rw] %s: \"%s\" -> \"%s\"\n", 631 fdc.ctx, BER_BVISNULL( &ftmp ) ? "" : ftmp.bv_val, 632 BER_BVISNULL( fstr ) ? "" : fstr->bv_val ); 633 rc = LDAP_SUCCESS; 634 break; 635 636 case REWRITE_REGEXEC_UNWILLING: 637 if ( fdc.rs ) { 638 fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 639 fdc.rs->sr_text = "Operation not allowed"; 640 } 641 rc = LDAP_UNWILLING_TO_PERFORM; 642 break; 643 644 case REWRITE_REGEXEC_ERR: 645 if ( fdc.rs ) { 646 fdc.rs->sr_err = LDAP_OTHER; 647 fdc.rs->sr_text = "Rewrite error"; 648 } 649 rc = LDAP_OTHER; 650 break; 651 } 652 653 if ( fstr->bv_val == dmy ) { 654 BER_BVZERO( fstr ); 655 656 } else if ( fstr->bv_val != ftmp.bv_val ) { 657 /* NOTE: need to realloc mapped filter on slab 658 * and free the original one, until librewrite 659 * becomes slab-aware 660 */ 661 ber_dupbv_x( &ftmp, fstr, memctx ); 662 ch_free( fstr->bv_val ); 663 *fstr = ftmp; 664 } 665 #endif /* ENABLE_REWRITE */ 666 667 return rc; 668 } 669 670 int 671 ldap_back_referral_result_rewrite( 672 dncookie *dc, 673 BerVarray a_vals, 674 void *memctx 675 ) 676 { 677 int i, last; 678 679 assert( dc != NULL ); 680 assert( a_vals != NULL ); 681 682 for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ ) 683 ; 684 last--; 685 686 for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) { 687 struct berval dn, 688 olddn = BER_BVNULL; 689 int rc; 690 LDAPURLDesc *ludp; 691 692 rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp ); 693 if ( rc != LDAP_URL_SUCCESS ) { 694 /* leave attr untouched if massage failed */ 695 continue; 696 } 697 698 /* FIXME: URLs like "ldap:///dc=suffix" if passed 699 * thru ldap_url_parse() and ldap_url_desc2str() 700 * get rewritten as "ldap:///dc=suffix??base"; 701 * we don't want this to occur... */ 702 if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { 703 ludp->lud_scope = LDAP_SCOPE_DEFAULT; 704 } 705 706 ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); 707 708 rc = ldap_back_dn_massage( dc, &olddn, &dn ); 709 switch ( rc ) { 710 case LDAP_UNWILLING_TO_PERFORM: 711 /* 712 * FIXME: need to check if it may be considered 713 * legal to trim values when adding/modifying; 714 * it should be when searching (e.g. ACLs). 715 */ 716 LBER_FREE( a_vals[ i ].bv_val ); 717 if ( last > i ) { 718 a_vals[ i ] = a_vals[ last ]; 719 } 720 BER_BVZERO( &a_vals[ last ] ); 721 last--; 722 i--; 723 break; 724 725 default: 726 /* leave attr untouched if massage failed */ 727 if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) 728 { 729 char *newurl; 730 731 ludp->lud_dn = dn.bv_val; 732 newurl = ldap_url_desc2str( ludp ); 733 free( dn.bv_val ); 734 if ( newurl == NULL ) { 735 /* FIXME: leave attr untouched 736 * even if ldap_url_desc2str failed... 737 */ 738 break; 739 } 740 741 ber_memfree_x( a_vals[ i ].bv_val, memctx ); 742 ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx ); 743 LDAP_FREE( newurl ); 744 ludp->lud_dn = olddn.bv_val; 745 } 746 break; 747 } 748 749 ldap_free_urldesc( ludp ); 750 } 751 752 return 0; 753 } 754 755 /* 756 * I don't like this much, but we need two different 757 * functions because different heap managers may be 758 * in use in back-ldap/meta to reduce the amount of 759 * calls to malloc routines, and some of the free() 760 * routines may be macros with args 761 */ 762 int 763 ldap_dnattr_rewrite( 764 dncookie *dc, 765 BerVarray a_vals 766 ) 767 { 768 struct berval bv; 769 int i, last; 770 771 assert( a_vals != NULL ); 772 773 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ) 774 ; 775 last--; 776 777 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 778 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) { 779 case LDAP_UNWILLING_TO_PERFORM: 780 /* 781 * FIXME: need to check if it may be considered 782 * legal to trim values when adding/modifying; 783 * it should be when searching (e.g. ACLs). 784 */ 785 ch_free( a_vals[i].bv_val ); 786 if ( last > i ) { 787 a_vals[i] = a_vals[last]; 788 } 789 BER_BVZERO( &a_vals[last] ); 790 last--; 791 break; 792 793 default: 794 /* leave attr untouched if massage failed */ 795 if ( !BER_BVISNULL( &bv ) && bv.bv_val != a_vals[i].bv_val ) { 796 ch_free( a_vals[i].bv_val ); 797 a_vals[i] = bv; 798 } 799 break; 800 } 801 } 802 803 return 0; 804 } 805 806 int 807 ldap_dnattr_result_rewrite( 808 dncookie *dc, 809 BerVarray a_vals 810 ) 811 { 812 struct berval bv; 813 int i, last; 814 815 assert( a_vals != NULL ); 816 817 for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ) 818 ; 819 last--; 820 821 for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 822 switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) { 823 case LDAP_UNWILLING_TO_PERFORM: 824 /* 825 * FIXME: need to check if it may be considered 826 * legal to trim values when adding/modifying; 827 * it should be when searching (e.g. ACLs). 828 */ 829 LBER_FREE( a_vals[i].bv_val ); 830 if ( last > i ) { 831 a_vals[i] = a_vals[last]; 832 } 833 BER_BVZERO( &a_vals[last] ); 834 last--; 835 break; 836 837 default: 838 /* leave attr untouched if massage failed */ 839 if ( !BER_BVISNULL( &bv ) && a_vals[i].bv_val != bv.bv_val ) { 840 LBER_FREE( a_vals[i].bv_val ); 841 a_vals[i] = bv; 842 } 843 break; 844 } 845 } 846 847 return 0; 848 } 849 850