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