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