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