1/* filterentry.c - apply a filter to an entry */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 27#include "portable.h" 28 29#include <stdio.h> 30 31#include <ac/socket.h> 32#include <ac/string.h> 33 34#include "slap.h" 35 36#ifdef LDAP_COMP_MATCH 37#include "component.h" 38#endif 39 40static int test_filter_and( Operation *op, Entry *e, Filter *flist ); 41static int test_filter_or( Operation *op, Entry *e, Filter *flist ); 42static int test_substrings_filter( Operation *op, Entry *e, Filter *f); 43static int test_ava_filter( Operation *op, 44 Entry *e, AttributeAssertion *ava, int type ); 45static int test_mra_filter( Operation *op, 46 Entry *e, MatchingRuleAssertion *mra ); 47static int test_presence_filter( Operation *op, 48 Entry *e, AttributeDescription *desc ); 49 50 51/* 52 * test_filter - test a filter against a single entry. 53 * returns: 54 * LDAP_COMPARE_TRUE filter matched 55 * LDAP_COMPARE_FALSE filter did not match 56 * SLAPD_COMPARE_UNDEFINED filter is undefined 57 * or an ldap result code indicating error 58 */ 59 60int 61test_filter( 62 Operation *op, 63 Entry *e, 64 Filter *f ) 65{ 66 int rc; 67 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 ); 68 69 if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) { 70 Debug( LDAP_DEBUG_FILTER, " UNDEFINED\n", 0, 0, 0 ); 71 rc = SLAPD_COMPARE_UNDEFINED; 72 goto out; 73 } 74 75 switch ( f->f_choice ) { 76 case SLAPD_FILTER_COMPUTED: 77 Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n", 78 f->f_result == LDAP_COMPARE_FALSE ? "false" : 79 f->f_result == LDAP_COMPARE_TRUE ? "true" : 80 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error", 81 f->f_result, 0 ); 82 83 rc = f->f_result; 84 break; 85 86 case LDAP_FILTER_EQUALITY: 87 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 ); 88 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_EQUALITY ); 89 break; 90 91 case LDAP_FILTER_SUBSTRINGS: 92 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 ); 93 rc = test_substrings_filter( op, e, f ); 94 break; 95 96 case LDAP_FILTER_GE: 97 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 ); 98 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_GE ); 99 break; 100 101 case LDAP_FILTER_LE: 102 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 ); 103 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_LE ); 104 break; 105 106 case LDAP_FILTER_PRESENT: 107 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 ); 108 rc = test_presence_filter( op, e, f->f_desc ); 109 break; 110 111 case LDAP_FILTER_APPROX: 112 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 ); 113 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_APPROX ); 114 break; 115 116 case LDAP_FILTER_AND: 117 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 ); 118 rc = test_filter_and( op, e, f->f_and ); 119 break; 120 121 case LDAP_FILTER_OR: 122 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 ); 123 rc = test_filter_or( op, e, f->f_or ); 124 break; 125 126 case LDAP_FILTER_NOT: 127 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 ); 128 rc = test_filter( op, e, f->f_not ); 129 130 /* Flip true to false and false to true 131 * but leave Undefined alone. 132 */ 133 switch( rc ) { 134 case LDAP_COMPARE_TRUE: 135 rc = LDAP_COMPARE_FALSE; 136 break; 137 case LDAP_COMPARE_FALSE: 138 rc = LDAP_COMPARE_TRUE; 139 break; 140 } 141 break; 142 143 case LDAP_FILTER_EXT: 144 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 ); 145 rc = test_mra_filter( op, e, f->f_mra ); 146 break; 147 148 default: 149 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n", 150 f->f_choice, 0, 0 ); 151 rc = LDAP_PROTOCOL_ERROR; 152 } 153out: 154 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 ); 155 return( rc ); 156} 157 158static int test_mra_filter( 159 Operation *op, 160 Entry *e, 161 MatchingRuleAssertion *mra ) 162{ 163 Attribute *a; 164 void *memctx; 165 BER_MEMFREE_FN *memfree; 166#ifdef LDAP_COMP_MATCH 167 int i, num_attr_vals = 0; 168#endif 169 170 if ( op == NULL ) { 171 memctx = NULL; 172 memfree = slap_sl_mfuncs.bmf_free; 173 } else { 174 memctx = op->o_tmpmemctx; 175 memfree = op->o_tmpfree; 176 } 177 178 if ( mra->ma_desc ) { 179 /* 180 * if ma_desc is available, then we're filtering for 181 * one attribute, and SEARCH permissions can be checked 182 * directly. 183 */ 184 if ( !access_allowed( op, e, 185 mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) ) 186 { 187 return LDAP_INSUFFICIENT_ACCESS; 188 } 189 190 if ( mra->ma_desc == slap_schema.si_ad_entryDN ) { 191 int ret, rc; 192 const char *text; 193 194 rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule, 195 SLAP_MR_EXT, &e->e_nname, &mra->ma_value, &text ); 196 197 198 if( rc != LDAP_SUCCESS ) return rc; 199 if ( ret == 0 ) return LDAP_COMPARE_TRUE; 200 return LDAP_COMPARE_FALSE; 201 } 202 203 for ( a = attrs_find( e->e_attrs, mra->ma_desc ); 204 a != NULL; 205 a = attrs_find( a->a_next, mra->ma_desc ) ) 206 { 207 struct berval *bv; 208 int normalize_attribute = 0; 209 210#ifdef LDAP_COMP_MATCH 211 /* Component Matching */ 212 if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) { 213 num_attr_vals = 0; 214 if ( !a->a_comp_data ) { 215 num_attr_vals = a->a_numvals; 216 if ( num_attr_vals <= 0 ) { 217 /* no attribute value */ 218 return LDAP_INAPPROPRIATE_MATCHING; 219 } 220 num_attr_vals++; 221 222 /* following malloced will be freed by comp_tree_free () */ 223 a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) + 224 sizeof( ComponentSyntaxInfo* )*num_attr_vals ); 225 226 if ( !a->a_comp_data ) return LDAP_NO_MEMORY; 227 a->a_comp_data->cd_tree = (ComponentSyntaxInfo**) 228 ((char*)a->a_comp_data + sizeof(ComponentData)); 229 a->a_comp_data->cd_tree[num_attr_vals - 1] = 230 (ComponentSyntaxInfo*) NULL; 231 a->a_comp_data->cd_mem_op = 232 nibble_mem_allocator( 1024*16, 1024 ); 233 } 234 } 235#endif 236 237 /* If ma_rule is not the same as the attribute's 238 * normal rule, then we can't use the a_nvals. 239 */ 240 if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) { 241 bv = a->a_nvals; 242 243 } else { 244 bv = a->a_vals; 245 normalize_attribute = 1; 246 } 247#ifdef LDAP_COMP_MATCH 248 i = 0; 249#endif 250 for ( ; !BER_BVISNULL( bv ); bv++ ) { 251 int ret; 252 int rc; 253 const char *text; 254 255#ifdef LDAP_COMP_MATCH 256 if ( mra->ma_cf && 257 mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) 258 { 259 /* Check if decoded component trees are already linked */ 260 if ( num_attr_vals ) { 261 a->a_comp_data->cd_tree[i] = attr_converter( 262 a, a->a_desc->ad_type->sat_syntax, bv ); 263 } 264 /* decoding error */ 265 if ( !a->a_comp_data->cd_tree[i] ) { 266 return LDAP_OPERATIONS_ERROR; 267 } 268 rc = value_match( &ret, a->a_desc, mra->ma_rule, 269 SLAP_MR_COMPONENT, 270 (struct berval*)a->a_comp_data->cd_tree[i++], 271 (void*)mra, &text ); 272 } else 273#endif 274 { 275 struct berval nbv = BER_BVNULL; 276 277 if ( normalize_attribute && mra->ma_rule->smr_normalize ) { 278 /* 279 280 Document: RFC 4511 281 282 4.5.1. Search Request 283 ... 284 If the type field is present and the matchingRule is present, 285 the matchValue is compared against entry attributes of the 286 specified type. In this case, the matchingRule MUST be one 287 suitable for use with the specified type (see [RFC4517]), 288 otherwise the filter item is Undefined. 289 290 291 In this case, since the matchingRule requires the assertion 292 value to be normalized, we normalize the attribute value 293 according to the syntax of the matchingRule. 294 295 This should likely be done inside value_match(), by passing 296 the appropriate flags, but this is not done at present. 297 See ITS#3406. 298 */ 299 if ( mra->ma_rule->smr_normalize( 300 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 301 mra->ma_rule->smr_syntax, 302 mra->ma_rule, 303 bv, &nbv, memctx ) != LDAP_SUCCESS ) 304 { 305 /* FIXME: stop processing? */ 306 continue; 307 } 308 309 } else { 310 nbv = *bv; 311 } 312 313 rc = value_match( &ret, a->a_desc, mra->ma_rule, 314 SLAP_MR_EXT, &nbv, &mra->ma_value, &text ); 315 316 if ( nbv.bv_val != bv->bv_val ) { 317 memfree( nbv.bv_val, memctx ); 318 } 319 } 320 321 if ( rc != LDAP_SUCCESS ) return rc; 322 if ( ret == 0 ) return LDAP_COMPARE_TRUE; 323 } 324 } 325 326 } else { 327 /* 328 * No attribute description: test all 329 */ 330 for ( a = e->e_attrs; a != NULL; a = a->a_next ) { 331 struct berval *bv, value; 332 const char *text = NULL; 333 int rc; 334 int normalize_attribute = 0; 335 336 /* check if matching is appropriate */ 337 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) { 338 continue; 339 } 340 341 /* normalize for equality */ 342 rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule, 343 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 344 &mra->ma_value, &value, &text, memctx ); 345 if ( rc != LDAP_SUCCESS ) continue; 346 347 /* check search access */ 348 if ( !access_allowed( op, e, 349 a->a_desc, &value, ACL_SEARCH, NULL ) ) 350 { 351 memfree( value.bv_val, memctx ); 352 continue; 353 } 354#ifdef LDAP_COMP_MATCH 355 /* Component Matching */ 356 if ( mra->ma_cf && 357 mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) 358 { 359 int ret; 360 361 rc = value_match( &ret, a->a_desc, mra->ma_rule, 362 SLAP_MR_COMPONENT, 363 (struct berval*)a, (void*)mra, &text ); 364 if ( rc != LDAP_SUCCESS ) break; 365 366 if ( ret == 0 ) { 367 rc = LDAP_COMPARE_TRUE; 368 break; 369 } 370 371 } 372#endif 373 374 /* check match */ 375 if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) { 376 bv = a->a_nvals; 377 378 } else { 379 bv = a->a_vals; 380 normalize_attribute = 1; 381 } 382 383 for ( ; !BER_BVISNULL( bv ); bv++ ) { 384 int ret; 385 struct berval nbv = BER_BVNULL; 386 387 if ( normalize_attribute && mra->ma_rule->smr_normalize ) { 388 /* see comment above */ 389 if ( mra->ma_rule->smr_normalize( 390 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 391 mra->ma_rule->smr_syntax, 392 mra->ma_rule, 393 bv, &nbv, memctx ) != LDAP_SUCCESS ) 394 { 395 /* FIXME: stop processing? */ 396 continue; 397 } 398 399 } else { 400 nbv = *bv; 401 } 402 403 rc = value_match( &ret, a->a_desc, mra->ma_rule, 404 SLAP_MR_EXT, &nbv, &value, &text ); 405 406 if ( nbv.bv_val != bv->bv_val ) { 407 memfree( nbv.bv_val, memctx ); 408 } 409 410 if ( rc != LDAP_SUCCESS ) break; 411 412 if ( ret == 0 ) { 413 rc = LDAP_COMPARE_TRUE; 414 break; 415 } 416 } 417 memfree( value.bv_val, memctx ); 418 if ( rc != LDAP_SUCCESS ) return rc; 419 } 420 } 421 422 /* check attrs in DN AVAs if required */ 423 if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) { 424 LDAPDN dn = NULL; 425 int iRDN, iAVA; 426 int rc; 427 428 /* parse and pretty the dn */ 429 rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx ); 430 if ( rc != LDAP_SUCCESS ) { 431 return LDAP_INVALID_SYNTAX; 432 } 433 434 /* for each AVA of each RDN ... */ 435 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { 436 LDAPRDN rdn = dn[ iRDN ]; 437 438 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 439 LDAPAVA *ava = rdn[ iAVA ]; 440 struct berval *bv = &ava->la_value, 441 value = BER_BVNULL, 442 nbv = BER_BVNULL; 443 AttributeDescription *ad = 444 (AttributeDescription *)ava->la_private; 445 int ret; 446 const char *text; 447 448 assert( ad != NULL ); 449 450 if ( mra->ma_desc ) { 451 /* have a mra type? check for subtype */ 452 if ( !is_ad_subtype( ad, mra->ma_desc ) ) { 453 continue; 454 } 455 value = mra->ma_value; 456 457 } else { 458 const char *text = NULL; 459 460 /* check if matching is appropriate */ 461 if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) { 462 continue; 463 } 464 465 /* normalize for equality */ 466 rc = asserted_value_validate_normalize( ad, 467 mra->ma_rule, 468 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 469 &mra->ma_value, &value, &text, memctx ); 470 if ( rc != LDAP_SUCCESS ) continue; 471 472 /* check search access */ 473 if ( !access_allowed( op, e, 474 ad, &value, ACL_SEARCH, NULL ) ) 475 { 476 memfree( value.bv_val, memctx ); 477 continue; 478 } 479 } 480 481 if ( mra->ma_rule->smr_normalize ) { 482 /* see comment above */ 483 if ( mra->ma_rule->smr_normalize( 484 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 485 mra->ma_rule->smr_syntax, 486 mra->ma_rule, 487 bv, &nbv, memctx ) != LDAP_SUCCESS ) 488 { 489 /* FIXME: stop processing? */ 490 rc = LDAP_SUCCESS; 491 ret = -1; 492 goto cleanup; 493 } 494 495 } else { 496 nbv = *bv; 497 } 498 499 /* check match */ 500 rc = value_match( &ret, ad, mra->ma_rule, SLAP_MR_EXT, 501 &nbv, &value, &text ); 502 503cleanup:; 504 if ( !BER_BVISNULL( &value ) && value.bv_val != mra->ma_value.bv_val ) { 505 memfree( value.bv_val, memctx ); 506 } 507 508 if ( !BER_BVISNULL( &nbv ) && nbv.bv_val != bv->bv_val ) { 509 memfree( nbv.bv_val, memctx ); 510 } 511 512 if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE; 513 514 if ( rc != LDAP_SUCCESS ) { 515 ldap_dnfree_x( dn, memctx ); 516 return rc; 517 } 518 } 519 } 520 ldap_dnfree_x( dn, memctx ); 521 } 522 523 return LDAP_COMPARE_FALSE; 524} 525 526static int 527test_ava_filter( 528 Operation *op, 529 Entry *e, 530 AttributeAssertion *ava, 531 int type ) 532{ 533 int rc; 534 Attribute *a; 535#ifdef LDAP_COMP_MATCH 536 int i, num_attr_vals = 0; 537 AttributeAliasing *a_alias = NULL; 538#endif 539 540 if ( !access_allowed( op, e, 541 ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) ) 542 { 543 return LDAP_INSUFFICIENT_ACCESS; 544 } 545 546 if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates 547 && op && op->o_bd && op->o_bd->be_has_subordinates ) 548 { 549 int hasSubordinates = 0; 550 struct berval hs; 551 552 if( type != LDAP_FILTER_EQUALITY && 553 type != LDAP_FILTER_APPROX ) 554 { 555 /* No other match is allowed */ 556 return LDAP_INAPPROPRIATE_MATCHING; 557 } 558 559 if ( op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) != 560 LDAP_SUCCESS ) 561 { 562 return LDAP_OTHER; 563 } 564 565 if ( hasSubordinates == LDAP_COMPARE_TRUE ) { 566 hs = slap_true_bv; 567 568 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) { 569 hs = slap_false_bv; 570 571 } else { 572 return LDAP_OTHER; 573 } 574 575 if ( bvmatch( &ava->aa_value, &hs ) ) return LDAP_COMPARE_TRUE; 576 return LDAP_COMPARE_FALSE; 577 } 578 579 if ( ava->aa_desc == slap_schema.si_ad_entryDN ) { 580 MatchingRule *mr; 581 int match; 582 const char *text; 583 584 if( type != LDAP_FILTER_EQUALITY && 585 type != LDAP_FILTER_APPROX ) 586 { 587 /* No other match is allowed */ 588 return LDAP_INAPPROPRIATE_MATCHING; 589 } 590 591 mr = slap_schema.si_ad_entryDN->ad_type->sat_equality; 592 assert( mr != NULL ); 593 594 rc = value_match( &match, slap_schema.si_ad_entryDN, mr, 595 SLAP_MR_EXT, &e->e_nname, &ava->aa_value, &text ); 596 597 if( rc != LDAP_SUCCESS ) return rc; 598 if( match == 0 ) return LDAP_COMPARE_TRUE; 599 return LDAP_COMPARE_FALSE; 600 } 601 602 rc = LDAP_COMPARE_FALSE; 603 604#ifdef LDAP_COMP_MATCH 605 if ( is_aliased_attribute && ava->aa_cf ) 606 { 607 a_alias = is_aliased_attribute ( ava->aa_desc ); 608 if ( a_alias ) 609 ava->aa_desc = a_alias->aa_aliased_ad; 610 else 611 ava->aa_cf = NULL; 612 } 613#endif 614 615 for(a = attrs_find( e->e_attrs, ava->aa_desc ); 616 a != NULL; 617 a = attrs_find( a->a_next, ava->aa_desc ) ) 618 { 619 int use; 620 MatchingRule *mr; 621 struct berval *bv; 622 623 if (( ava->aa_desc != a->a_desc ) && !access_allowed( op, 624 e, a->a_desc, &ava->aa_value, ACL_SEARCH, NULL )) 625 { 626 rc = LDAP_INSUFFICIENT_ACCESS; 627 continue; 628 } 629 630 use = SLAP_MR_EQUALITY; 631 632 switch ( type ) { 633 case LDAP_FILTER_APPROX: 634 use = SLAP_MR_EQUALITY_APPROX; 635 mr = a->a_desc->ad_type->sat_approx; 636 if( mr != NULL ) break; 637 638 /* fallthru: use EQUALITY matching rule if no APPROX rule */ 639 640 case LDAP_FILTER_EQUALITY: 641 /* use variable set above so fall thru use is not clobbered */ 642 mr = a->a_desc->ad_type->sat_equality; 643 break; 644 645 case LDAP_FILTER_GE: 646 case LDAP_FILTER_LE: 647 use = SLAP_MR_ORDERING; 648 mr = a->a_desc->ad_type->sat_ordering; 649 break; 650 651 default: 652 mr = NULL; 653 } 654 655 if( mr == NULL ) { 656 rc = LDAP_INAPPROPRIATE_MATCHING; 657 continue; 658 } 659 660 /* We have no Sort optimization for Approx matches */ 661 if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && type != LDAP_FILTER_APPROX ) { 662 unsigned slot; 663 int ret; 664 665 /* For Ordering matches, we just need to do one comparison with 666 * either the first (least) or last (greatest) value. 667 */ 668 if ( use == SLAP_MR_ORDERING ) { 669 const char *text; 670 int match, which; 671 which = (type == LDAP_FILTER_LE) ? 0 : a->a_numvals-1; 672 ret = value_match( &match, a->a_desc, mr, use, 673 &a->a_nvals[which], &ava->aa_value, &text ); 674 if ( ret != LDAP_SUCCESS ) return ret; 675 if (( type == LDAP_FILTER_LE && match <= 0 ) || 676 ( type == LDAP_FILTER_GE && match >= 0 )) 677 return LDAP_COMPARE_TRUE; 678 continue; 679 } 680 /* Only Equality will get here */ 681 ret = attr_valfind( a, use | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH | 682 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, 683 &ava->aa_value, &slot, NULL ); 684 if ( ret == LDAP_SUCCESS ) 685 return LDAP_COMPARE_TRUE; 686 else if ( ret != LDAP_NO_SUCH_ATTRIBUTE ) 687 return ret; 688#if 0 689 /* The following is useful if we want to know which values 690 * matched an ordering test. But here we don't care, we just 691 * want to know if any value did, and that is checked above. 692 */ 693 if ( ret == LDAP_NO_SUCH_ATTRIBUTE ) { 694 /* If insertion point is not the end of the list, there was 695 * at least one value greater than the assertion. 696 */ 697 if ( type == LDAP_FILTER_GE && slot < a->a_numvals ) 698 return LDAP_COMPARE_TRUE; 699 /* Likewise, if insertion point is not the head of the list, 700 * there was at least one value less than the assertion. 701 */ 702 if ( type == LDAP_FILTER_LE && slot > 0 ) 703 return LDAP_COMPARE_TRUE; 704 return LDAP_COMPARE_FALSE; 705 } 706#endif 707 continue; 708 } 709 710#ifdef LDAP_COMP_MATCH 711 if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) { 712 /* Component Matching */ 713 for ( num_attr_vals = 0; a->a_vals[num_attr_vals].bv_val != NULL; num_attr_vals++ ); 714 if ( num_attr_vals <= 0 )/* no attribute value */ 715 return LDAP_INAPPROPRIATE_MATCHING; 716 num_attr_vals++;/* for NULL termination */ 717 718 /* following malloced will be freed by comp_tree_free () */ 719 a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals ); 720 721 if ( !a->a_comp_data ) { 722 return LDAP_NO_MEMORY; 723 } 724 725 a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData)); 726 i = num_attr_vals; 727 for ( ; i ; i-- ) { 728 a->a_comp_data->cd_tree[ i-1 ] = (ComponentSyntaxInfo*)NULL; 729 } 730 731 a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*10*(num_attr_vals-1), 1024 ); 732 if ( a->a_comp_data->cd_mem_op == NULL ) { 733 free ( a->a_comp_data ); 734 a->a_comp_data = NULL; 735 return LDAP_OPERATIONS_ERROR; 736 } 737 } 738 739 i = 0; 740#endif 741 742 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) { 743 int ret, match; 744 const char *text; 745 746#ifdef LDAP_COMP_MATCH 747 if( attr_converter && ava->aa_cf && a->a_comp_data ) { 748 /* Check if decoded component trees are already linked */ 749 struct berval cf_bv = { 20, "componentFilterMatch" }; 750 MatchingRule* cf_mr = mr_bvfind( &cf_bv ); 751 MatchingRuleAssertion mra; 752 mra.ma_cf = ava->aa_cf; 753 754 if ( a->a_comp_data->cd_tree[i] == NULL ) 755 a->a_comp_data->cd_tree[i] = attr_converter (a, a->a_desc->ad_type->sat_syntax, (a->a_vals + i)); 756 /* decoding error */ 757 if ( !a->a_comp_data->cd_tree[i] ) { 758 free_ComponentData ( a ); 759 return LDAP_OPERATIONS_ERROR; 760 } 761 762 ret = value_match( &match, a->a_desc, cf_mr, 763 SLAP_MR_COMPONENT, 764 (struct berval*)a->a_comp_data->cd_tree[i++], 765 (void*)&mra, &text ); 766 if ( ret == LDAP_INAPPROPRIATE_MATCHING ) { 767 /* cached component tree is broken, just remove it */ 768 free_ComponentData ( a ); 769 return ret; 770 } 771 if ( a_alias ) 772 ava->aa_desc = a_alias->aa_aliasing_ad; 773 774 } else 775#endif 776 { 777 ret = ordered_value_match( &match, a->a_desc, mr, use, 778 bv, &ava->aa_value, &text ); 779 } 780 781 if( ret != LDAP_SUCCESS ) { 782 rc = ret; 783 break; 784 } 785 786 switch ( type ) { 787 case LDAP_FILTER_EQUALITY: 788 case LDAP_FILTER_APPROX: 789 if ( match == 0 ) return LDAP_COMPARE_TRUE; 790 break; 791 792 case LDAP_FILTER_GE: 793 if ( match >= 0 ) return LDAP_COMPARE_TRUE; 794 break; 795 796 case LDAP_FILTER_LE: 797 if ( match <= 0 ) return LDAP_COMPARE_TRUE; 798 break; 799 } 800 } 801 } 802 803#ifdef LDAP_COMP_MATCH 804 if ( a_alias ) 805 ava->aa_desc = a_alias->aa_aliasing_ad; 806#endif 807 808 return rc; 809} 810 811 812static int 813test_presence_filter( 814 Operation *op, 815 Entry *e, 816 AttributeDescription *desc ) 817{ 818 Attribute *a; 819 int rc; 820 821 if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) ) { 822 return LDAP_INSUFFICIENT_ACCESS; 823 } 824 825 if ( desc == slap_schema.si_ad_hasSubordinates ) { 826 /* 827 * XXX: fairly optimistic: if the function is defined, 828 * then PRESENCE must succeed, because hasSubordinate 829 * is boolean-valued; I think we may live with this 830 * simplification by now. 831 */ 832 if ( op && op->o_bd && op->o_bd->be_has_subordinates ) { 833 return LDAP_COMPARE_TRUE; 834 } 835 836 return LDAP_COMPARE_FALSE; 837 } 838 839 if ( desc == slap_schema.si_ad_entryDN || 840 desc == slap_schema.si_ad_subschemaSubentry ) 841 { 842 /* entryDN and subschemaSubentry are always present */ 843 return LDAP_COMPARE_TRUE; 844 } 845 846 rc = LDAP_COMPARE_FALSE; 847 848 for(a = attrs_find( e->e_attrs, desc ); 849 a != NULL; 850 a = attrs_find( a->a_next, desc ) ) 851 { 852 if (( desc != a->a_desc ) && !access_allowed( op, 853 e, a->a_desc, NULL, ACL_SEARCH, NULL )) 854 { 855 rc = LDAP_INSUFFICIENT_ACCESS; 856 continue; 857 } 858 859 rc = LDAP_COMPARE_TRUE; 860 break; 861 } 862 863 return rc; 864} 865 866 867static int 868test_filter_and( 869 Operation *op, 870 Entry *e, 871 Filter *flist ) 872{ 873 Filter *f; 874 int rtn = LDAP_COMPARE_TRUE; /* True if empty */ 875 876 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 ); 877 878 for ( f = flist; f != NULL; f = f->f_next ) { 879 int rc = test_filter( op, e, f ); 880 881 if ( rc == LDAP_COMPARE_FALSE ) { 882 /* filter is False */ 883 rtn = rc; 884 break; 885 } 886 887 if ( rc != LDAP_COMPARE_TRUE ) { 888 /* filter is Undefined unless later elements are False */ 889 rtn = rc; 890 } 891 } 892 893 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 ); 894 895 return rtn; 896} 897 898static int 899test_filter_or( 900 Operation *op, 901 Entry *e, 902 Filter *flist ) 903{ 904 Filter *f; 905 int rtn = LDAP_COMPARE_FALSE; /* False if empty */ 906 907 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 ); 908 909 for ( f = flist; f != NULL; f = f->f_next ) { 910 int rc = test_filter( op, e, f ); 911 912 if ( rc == LDAP_COMPARE_TRUE ) { 913 /* filter is True */ 914 rtn = rc; 915 break; 916 } 917 918 if ( rc != LDAP_COMPARE_FALSE ) { 919 /* filter is Undefined unless later elements are True */ 920 rtn = rc; 921 } 922 } 923 924 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 ); 925 return rtn; 926} 927 928 929static int 930test_substrings_filter( 931 Operation *op, 932 Entry *e, 933 Filter *f ) 934{ 935 Attribute *a; 936 int rc; 937 938 Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 ); 939 940 if ( !access_allowed( op, e, 941 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) ) 942 { 943 return LDAP_INSUFFICIENT_ACCESS; 944 } 945 946 rc = LDAP_COMPARE_FALSE; 947 948 for(a = attrs_find( e->e_attrs, f->f_sub_desc ); 949 a != NULL; 950 a = attrs_find( a->a_next, f->f_sub_desc ) ) 951 { 952 MatchingRule *mr; 953 struct berval *bv; 954 955 if (( f->f_sub_desc != a->a_desc ) && !access_allowed( op, 956 e, a->a_desc, NULL, ACL_SEARCH, NULL )) 957 { 958 rc = LDAP_INSUFFICIENT_ACCESS; 959 continue; 960 } 961 962 mr = a->a_desc->ad_type->sat_substr; 963 if( mr == NULL ) { 964 rc = LDAP_INAPPROPRIATE_MATCHING; 965 continue; 966 } 967 968 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) { 969 int ret, match; 970 const char *text; 971 972 ret = value_match( &match, a->a_desc, mr, SLAP_MR_SUBSTR, 973 bv, f->f_sub, &text ); 974 975 if( ret != LDAP_SUCCESS ) { 976 rc = ret; 977 break; 978 } 979 if ( match == 0 ) return LDAP_COMPARE_TRUE; 980 } 981 } 982 983 Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter %d\n", 984 rc, 0, 0 ); 985 return rc; 986} 987