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