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