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