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