1 /* $NetBSD: component.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */ 2 3 /* component.c -- Component Filter Match Routines */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2003-2021 The OpenLDAP Foundation. 8 * Portions Copyright 2004 by IBM Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 20 #include <sys/cdefs.h> 21 __RCSID("$NetBSD: component.c,v 1.3 2021/08/14 16:14:58 christos Exp $"); 22 23 #include "portable.h" 24 25 #include <ac/string.h> 26 #include <ac/socket.h> 27 28 #include "lutil.h" 29 #include <ldap.h> 30 #include "slap.h" 31 32 #ifdef LDAP_COMP_MATCH 33 34 #include "component.h" 35 36 /* 37 * Following function pointers are initialized 38 * when a component module is loaded 39 */ 40 alloc_nibble_func* nibble_mem_allocator = NULL; 41 free_nibble_func* nibble_mem_free = NULL; 42 convert_attr_to_comp_func* attr_converter = NULL; 43 convert_assert_to_comp_func* assert_converter = NULL ; 44 free_component_func* component_destructor = NULL ; 45 test_component_func* test_components = NULL; 46 test_membership_func* is_aliased_attribute = NULL; 47 component_encoder_func* component_encoder = NULL; 48 get_component_info_func* get_component_description = NULL; 49 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6" 50 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2" 51 #define MAX_LDAP_STR_LEN 128 52 53 static int 54 peek_componentId_type( ComponentAssertionValue* cav ); 55 56 static int 57 strip_cav_str( ComponentAssertionValue* cav, char* str); 58 59 static int 60 peek_cav_str( ComponentAssertionValue* cav, char* str ); 61 62 static int 63 parse_comp_filter( Operation* op, ComponentAssertionValue* cav, 64 ComponentFilter** filt, const char** text ); 65 66 static void 67 free_comp_filter( ComponentFilter* f ); 68 69 static int 70 test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f ); 71 72 int 73 componentCertificateValidate( 74 Syntax *syntax, 75 struct berval *val ) 76 { 77 return LDAP_SUCCESS; 78 } 79 80 int 81 componentFilterValidate( 82 Syntax *syntax, 83 struct berval *val ) 84 { 85 return LDAP_SUCCESS; 86 } 87 88 int 89 allComponentsValidate( 90 Syntax *syntax, 91 struct berval *val ) 92 { 93 return LDAP_SUCCESS; 94 } 95 96 int 97 componentFilterMatch ( 98 int *matchp, 99 slap_mask_t flags, 100 Syntax *syntax, 101 MatchingRule *mr, 102 struct berval *value, 103 void *assertedValue ) 104 { 105 ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value; 106 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue; 107 int rc; 108 109 if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING; 110 111 /* Check if the component module is loaded */ 112 if ( !attr_converter || !nibble_mem_allocator ) { 113 return LDAP_OTHER; 114 } 115 116 rc = test_comp_filter( syntax, csi_attr, ma->ma_cf ); 117 118 if ( rc == LDAP_COMPARE_TRUE ) { 119 *matchp = 0; 120 return LDAP_SUCCESS; 121 } 122 else if ( rc == LDAP_COMPARE_FALSE ) { 123 *matchp = 1; 124 return LDAP_SUCCESS; 125 } 126 else { 127 return LDAP_INAPPROPRIATE_MATCHING; 128 } 129 } 130 131 int 132 directoryComponentsMatch( 133 int *matchp, 134 slap_mask_t flags, 135 Syntax *syntax, 136 MatchingRule *mr, 137 struct berval *value, 138 void *assertedValue ) 139 { 140 /* Only for registration */ 141 *matchp = 0; 142 return LDAP_SUCCESS; 143 } 144 145 int 146 allComponentsMatch( 147 int *matchp, 148 slap_mask_t flags, 149 Syntax *syntax, 150 MatchingRule *mr, 151 struct berval *value, 152 void *assertedValue ) 153 { 154 /* Only for registration */ 155 *matchp = 0; 156 return LDAP_SUCCESS; 157 } 158 159 static int 160 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav ) 161 { 162 cav->cav_ptr = cav->cav_buf = bv->bv_val; 163 cav->cav_end = bv->bv_val + bv->bv_len; 164 165 return LDAP_SUCCESS; 166 } 167 168 ComponentReference* 169 dup_comp_ref ( Operation* op, ComponentReference* cr ) 170 { 171 ComponentReference* dup_cr; 172 ComponentId* ci_curr; 173 ComponentId** ci_temp; 174 175 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx ); 176 177 dup_cr->cr_len = cr->cr_len; 178 dup_cr->cr_string = cr->cr_string; 179 180 ci_temp = &dup_cr->cr_list; 181 ci_curr = cr->cr_list; 182 183 for ( ; ci_curr != NULL ; 184 ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next ) 185 { 186 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx ); 187 if ( !*ci_temp ) return NULL; 188 **ci_temp = *ci_curr; 189 } 190 191 dup_cr->cr_curr = dup_cr->cr_list; 192 193 return dup_cr; 194 } 195 196 static int 197 dup_comp_filter_list ( 198 Operation *op, 199 struct berval *bv, 200 ComponentFilter* in_f, 201 ComponentFilter** out_f ) 202 { 203 ComponentFilter **new, *f; 204 int rc; 205 206 new = out_f; 207 for ( f = in_f; f != NULL; f = f->cf_next ) { 208 rc = dup_comp_filter( op, bv, f, new ); 209 if ( rc != LDAP_SUCCESS ) { 210 return rc; 211 } 212 new = &(*new)->cf_next; 213 } 214 return LDAP_SUCCESS; 215 } 216 217 int 218 get_len_of_next_assert_value ( struct berval* bv, char separator ) 219 { 220 ber_len_t i = 0; 221 while (1) { 222 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) ) 223 break; 224 i++; 225 } 226 bv->bv_val += (i + 1); 227 bv->bv_len -= (i + 1); 228 return i; 229 } 230 231 int 232 dup_comp_filter_item ( 233 Operation *op, 234 struct berval* assert_bv, 235 ComponentAssertion* in_ca, 236 ComponentAssertion** out_ca ) 237 { 238 int len; 239 240 if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT; 241 242 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx ); 243 if ( !(*out_ca) ) return LDAP_NO_MEMORY; 244 245 (*out_ca)->ca_comp_data.cd_tree = NULL; 246 (*out_ca)->ca_comp_data.cd_mem_op = NULL; 247 248 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref ); 249 (*out_ca)->ca_use_def = 0; 250 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule; 251 252 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val; 253 len = get_len_of_next_assert_value ( assert_bv, '$' ); 254 if ( len <= 0 ) return SLAPD_DISCONNECT; 255 (*out_ca)->ca_ma_value.bv_len = len; 256 257 return LDAP_SUCCESS; 258 } 259 260 int 261 dup_comp_filter ( 262 Operation* op, 263 struct berval *bv, 264 ComponentFilter *in_f, 265 ComponentFilter **out_f ) 266 { 267 int rc; 268 ComponentFilter dup_f = {0}; 269 270 if ( !in_f ) return LDAP_PROTOCOL_ERROR; 271 272 switch ( in_f->cf_choice ) { 273 case LDAP_COMP_FILTER_AND: 274 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and); 275 dup_f.cf_choice = LDAP_COMP_FILTER_AND; 276 break; 277 case LDAP_COMP_FILTER_OR: 278 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or); 279 dup_f.cf_choice = LDAP_COMP_FILTER_OR; 280 break; 281 case LDAP_COMP_FILTER_NOT: 282 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not); 283 dup_f.cf_choice = LDAP_COMP_FILTER_NOT; 284 break; 285 case LDAP_COMP_FILTER_ITEM: 286 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca ); 287 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM; 288 break; 289 default: 290 rc = LDAP_PROTOCOL_ERROR; 291 } 292 293 if ( rc == LDAP_SUCCESS ) { 294 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx ); 295 **out_f = dup_f; 296 } 297 298 return( rc ); 299 } 300 301 int 302 get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text ) 303 { 304 struct berval assert_bv; 305 306 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n" ); 307 308 if ( !aa->aa_cf ) 309 return LDAP_PROTOCOL_ERROR; 310 311 assert_bv = a_assert->aa_value; 312 /* 313 * Duplicate aa->aa_cf to ma->ma_cf by replacing the 314 * the component assertion value in assert_bv 315 * Multiple values may be separated with '$' 316 */ 317 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf ); 318 } 319 320 int 321 get_aliased_filter( Operation* op, 322 MatchingRuleAssertion* ma, AttributeAliasing* aa, 323 const char** text ) 324 { 325 struct berval assert_bv; 326 327 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n" ); 328 329 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR; 330 331 assert_bv = ma->ma_value; 332 /* Attribute Description is replaced with aliased one */ 333 ma->ma_desc = aa->aa_aliased_ad; 334 ma->ma_rule = aa->aa_mr; 335 /* 336 * Duplicate aa->aa_cf to ma->ma_cf by replacing the 337 * the component assertion value in assert_bv 338 * Multiple values may be separated with '$' 339 */ 340 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf ); 341 } 342 343 int 344 get_comp_filter( Operation* op, struct berval* bv, 345 ComponentFilter** filt, const char **text ) 346 { 347 ComponentAssertionValue cav; 348 int rc; 349 350 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n" ); 351 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) { 352 return rc; 353 } 354 rc = parse_comp_filter( op, &cav, filt, text ); 355 /* bv->bv_val = cav.cav_ptr; */ 356 357 return rc; 358 } 359 360 static void 361 eat_whsp( ComponentAssertionValue* cav ) 362 { 363 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) { 364 cav->cav_ptr++; 365 } 366 } 367 368 static int 369 cav_cur_len( ComponentAssertionValue* cav ) 370 { 371 return cav->cav_end - cav->cav_ptr; 372 } 373 374 static ber_tag_t 375 comp_first_element( ComponentAssertionValue* cav ) 376 { 377 eat_whsp( cav ); 378 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) { 379 return LDAP_COMP_FILTER_ITEM; 380 381 } else if ( cav_cur_len( cav ) >= 7 && 382 strncmp( cav->cav_ptr, "and", 3 ) == 0 ) 383 { 384 return LDAP_COMP_FILTER_AND; 385 386 } else if ( cav_cur_len( cav ) >= 6 && 387 strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) 388 { 389 return LDAP_COMP_FILTER_OR; 390 391 } else if ( cav_cur_len( cav ) >= 7 && 392 strncmp( cav->cav_ptr, "not", 3 ) == 0 ) 393 { 394 return LDAP_COMP_FILTER_NOT; 395 396 } else { 397 return LDAP_COMP_FILTER_UNDEFINED; 398 } 399 } 400 401 static ber_tag_t 402 comp_next_element( ComponentAssertionValue* cav ) 403 { 404 eat_whsp( cav ); 405 if ( *(cav->cav_ptr) == ',' ) { 406 /* move pointer to the next CA */ 407 cav->cav_ptr++; 408 return comp_first_element( cav ); 409 } 410 else return LDAP_COMP_FILTER_UNDEFINED; 411 } 412 413 static int 414 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav, 415 ComponentFilter** f, const char** text ) 416 { 417 ComponentFilter **new; 418 int err; 419 ber_tag_t tag; 420 421 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n" ); 422 new = f; 423 for ( tag = comp_first_element( cav ); 424 tag != LDAP_COMP_FILTER_UNDEFINED; 425 tag = comp_next_element( cav ) ) 426 { 427 err = parse_comp_filter( op, cav, new, text ); 428 if ( err != LDAP_SUCCESS ) return ( err ); 429 new = &(*new)->cf_next; 430 } 431 *new = NULL; 432 433 return( LDAP_SUCCESS ); 434 } 435 436 static int 437 get_componentId( Operation *op, ComponentAssertionValue* cav, 438 ComponentId ** cid, const char** text ) 439 { 440 ber_tag_t type; 441 ComponentId _cid; 442 int len; 443 444 type = peek_componentId_type( cav ); 445 446 Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n", 447 (unsigned long) type ); 448 len = 0; 449 _cid.ci_type = type; 450 _cid.ci_next = NULL; 451 switch ( type ) { 452 case LDAP_COMPREF_IDENTIFIER : 453 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr; 454 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' && 455 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ ); 456 _cid.ci_val.ci_identifier.bv_len = len; 457 cav->cav_ptr += len; 458 break; 459 case LDAP_COMPREF_FROM_BEGINNING : 460 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' && 461 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ ); 462 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 ); 463 cav->cav_ptr += len; 464 break; 465 case LDAP_COMPREF_FROM_END : 466 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' && 467 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ ); 468 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 ); 469 cav->cav_ptr += len; 470 break; 471 case LDAP_COMPREF_COUNT : 472 _cid.ci_val.ci_count = 0; 473 cav->cav_ptr++; 474 break; 475 case LDAP_COMPREF_CONTENT : 476 _cid.ci_val.ci_content = 1; 477 cav->cav_ptr += strlen("content"); 478 break; 479 case LDAP_COMPREF_SELECT : 480 if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED; 481 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' && 482 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')' 483 ; len++ ); 484 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1; 485 _cid.ci_val.ci_select_value.bv_len = len - 1 ; 486 cav->cav_ptr += len + 1; 487 break; 488 case LDAP_COMPREF_ALL : 489 _cid.ci_val.ci_all = '*'; 490 cav->cav_ptr++; 491 break; 492 default : 493 return LDAP_COMPREF_UNDEFINED; 494 } 495 496 if ( op ) { 497 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx ); 498 } else { 499 *cid = SLAP_MALLOC( sizeof( ComponentId ) ); 500 } 501 if (*cid == NULL) { 502 return LDAP_NO_MEMORY; 503 } 504 **cid = _cid; 505 return LDAP_SUCCESS; 506 } 507 508 static int 509 peek_componentId_type( ComponentAssertionValue* cav ) 510 { 511 eat_whsp( cav ); 512 513 if ( cav->cav_ptr[0] == '-' ) { 514 return LDAP_COMPREF_FROM_END; 515 516 } else if ( cav->cav_ptr[0] == '(' ) { 517 return LDAP_COMPREF_SELECT; 518 519 } else if ( cav->cav_ptr[0] == '*' ) { 520 return LDAP_COMPREF_ALL; 521 522 } else if ( cav->cav_ptr[0] == '0' ) { 523 return LDAP_COMPREF_COUNT; 524 525 } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) { 526 return LDAP_COMPREF_FROM_BEGINNING; 527 528 } else if ( (cav->cav_end - cav->cav_ptr) >= 7 && 529 strncmp(cav->cav_ptr,"content",7) == 0 ) 530 { 531 return LDAP_COMPREF_CONTENT; 532 } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') || 533 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') ) 534 { 535 return LDAP_COMPREF_IDENTIFIER; 536 } 537 538 return LDAP_COMPREF_UNDEFINED; 539 } 540 541 static ber_tag_t 542 comp_next_id( ComponentAssertionValue* cav ) 543 { 544 if ( *(cav->cav_ptr) == '.' ) { 545 cav->cav_ptr++; 546 return LDAP_COMPREF_DEFINED; 547 } 548 549 return LDAP_COMPREF_UNDEFINED; 550 } 551 552 553 554 static int 555 get_component_reference( 556 Operation *op, 557 ComponentAssertionValue* cav, 558 ComponentReference** cr, 559 const char** text ) 560 { 561 int rc, count = 0; 562 ber_int_t type; 563 ComponentReference* ca_comp_ref; 564 ComponentId** cr_list; 565 char* start, *end; 566 567 eat_whsp( cav ); 568 569 start = cav->cav_ptr; 570 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc; 571 if ( op ) { 572 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), 573 op->o_tmpmemctx ); 574 } else { 575 ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) ); 576 } 577 578 if ( !ca_comp_ref ) return LDAP_NO_MEMORY; 579 580 cr_list = &ca_comp_ref->cr_list; 581 582 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED 583 ; type = comp_next_id( cav ), count++ ) 584 { 585 rc = get_componentId( op, cav, cr_list, text ); 586 if ( rc == LDAP_SUCCESS ) { 587 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list; 588 cr_list = &(*cr_list)->ci_next; 589 590 } else if ( rc == LDAP_COMPREF_UNDEFINED ) { 591 if ( op ) { 592 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx ); 593 } else { 594 free( ca_comp_ref ); 595 } 596 return rc; 597 } 598 } 599 ca_comp_ref->cr_len = count; 600 end = cav->cav_ptr; 601 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) { 602 if ( op ) { 603 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx ); 604 } else { 605 free( ca_comp_ref ); 606 } 607 return rc; 608 } 609 610 *cr = ca_comp_ref; 611 **cr = *ca_comp_ref; 612 613 (*cr)->cr_string.bv_val = start; 614 (*cr)->cr_string.bv_len = end - start + 1; 615 616 return rc; 617 } 618 619 int 620 insert_component_reference( 621 ComponentReference *cr, 622 ComponentReference** cr_list) 623 { 624 if ( !cr ) return LDAP_PARAM_ERROR; 625 626 if ( !(*cr_list) ) { 627 *cr_list = cr; 628 cr->cr_next = NULL; 629 } else { 630 cr->cr_next = *cr_list; 631 *cr_list = cr; 632 } 633 return LDAP_SUCCESS; 634 } 635 636 /* 637 * If there is '.' in the name of a given attribute 638 * the first '.'- following characters are considered 639 * as a component reference of the attribute 640 * EX) userCertificate.toBeSigned.serialNumber 641 * attribute : userCertificate 642 * component reference : toBeSigned.serialNumber 643 */ 644 int 645 is_component_reference( char* attr ) { 646 int i; 647 for ( i=0; attr[i] != '\0' ; i++ ) { 648 if ( attr[i] == '.' ) return (1); 649 } 650 return (0); 651 } 652 653 int 654 extract_component_reference( 655 char* attr, 656 ComponentReference** cr ) 657 { 658 int i, rc; 659 char* cr_ptr; 660 int cr_len; 661 ComponentAssertionValue cav; 662 char text[1][128]; 663 664 for ( i=0; attr[i] != '\0' ; i++ ) { 665 if ( attr[i] == '.' ) break; 666 } 667 668 if (attr[i] != '.' ) return LDAP_PARAM_ERROR; 669 attr[i] = '\0'; 670 671 cr_ptr = attr + i + 1 ; 672 cr_len = strlen ( cr_ptr ); 673 if ( cr_len <= 0 ) return LDAP_PARAM_ERROR; 674 675 /* enclosed between double quotes*/ 676 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2); 677 memcpy( cav.cav_buf+1, cr_ptr, cr_len ); 678 cav.cav_buf[0] = '"'; 679 cav.cav_buf[cr_len+1] = '"'; 680 cav.cav_end = cr_ptr + cr_len + 2; 681 682 rc = get_component_reference ( NULL, &cav, cr, (const char**)text ); 683 if ( rc != LDAP_SUCCESS ) return rc; 684 (*cr)->cr_string.bv_val = cav.cav_buf; 685 (*cr)->cr_string.bv_len = cr_len + 2; 686 687 return LDAP_SUCCESS; 688 } 689 690 static int 691 get_ca_use_default( Operation *op, 692 ComponentAssertionValue* cav, 693 int* ca_use_def, const char** text ) 694 { 695 strip_cav_str( cav, "useDefaultValues" ); 696 697 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) { 698 strip_cav_str( cav, "TRUE" ); 699 *ca_use_def = 1; 700 701 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) { 702 strip_cav_str( cav, "FALSE" ); 703 *ca_use_def = 0; 704 705 } else { 706 return LDAP_INVALID_SYNTAX; 707 } 708 709 return LDAP_SUCCESS; 710 } 711 712 static int 713 get_matching_rule( Operation *op, ComponentAssertionValue* cav, 714 MatchingRule** mr, const char** text ) 715 { 716 int count = 0; 717 struct berval rule_text = { 0L, NULL }; 718 719 eat_whsp( cav ); 720 721 for ( ; ; count++ ) { 722 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' || 723 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' || 724 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' ) 725 { 726 break; 727 } 728 } 729 730 if ( count == 0 ) { 731 *text = "component matching rule not recognized"; 732 return LDAP_INAPPROPRIATE_MATCHING; 733 } 734 735 rule_text.bv_len = count; 736 rule_text.bv_val = cav->cav_ptr; 737 *mr = mr_bvfind( &rule_text ); 738 cav->cav_ptr += count; 739 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", 740 (*mr)->smr_mrule.mr_oid ); 741 if ( *mr == NULL ) { 742 *text = "component matching rule not recognized"; 743 return LDAP_INAPPROPRIATE_MATCHING; 744 } 745 return LDAP_SUCCESS; 746 } 747 748 static int 749 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv ) 750 { 751 int count, sequent_dquote, unclosed_brace, succeed; 752 753 eat_whsp( cav ); 754 /* 755 * Four cases of GSER <Values> 756 * 1) "..." : 757 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal 758 * 2) '...'B or '...'H : 759 * BitStringVal, OctetStringVal 760 * 3) {...} : 761 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE 762 * 4) Between two white spaces 763 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc 764 */ 765 766 succeed = 0; 767 if ( cav->cav_ptr[0] == '"' ) { 768 for( count = 1, sequent_dquote = 0 ; ; count++ ) { 769 /* In order to find escaped double quote */ 770 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++; 771 else sequent_dquote = 0; 772 773 if ( cav->cav_ptr[count] == '\0' || 774 (cav->cav_ptr+count) > cav->cav_end ) 775 { 776 break; 777 } 778 779 if ( ( cav->cav_ptr[count] == '"' && 780 cav->cav_ptr[count-1] != '"') || 781 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) 782 { 783 succeed = 1; 784 break; 785 } 786 } 787 788 if ( !succeed || cav->cav_ptr[count] != '"' ) { 789 return LDAP_FILTER_ERROR; 790 } 791 792 bv->bv_val = cav->cav_ptr + 1; 793 bv->bv_len = count - 1; /* exclude '"' */ 794 795 } else if ( cav->cav_ptr[0] == '\'' ) { 796 for( count = 1 ; ; count++ ) { 797 if ( cav->cav_ptr[count] == '\0' || 798 (cav->cav_ptr+count) > cav->cav_end ) 799 { 800 break; 801 } 802 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') || 803 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) 804 { 805 succeed = 1; 806 break; 807 } 808 } 809 810 if ( !succeed || 811 !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') ) 812 { 813 return LDAP_FILTER_ERROR; 814 } 815 816 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */ 817 bv->bv_len = count - 2;/* exclude "'H" or "'B" */ 818 819 } else if ( cav->cav_ptr[0] == '{' ) { 820 for( count = 1, unclosed_brace = 1 ; ; count++ ) { 821 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++; 822 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--; 823 824 if ( cav->cav_ptr[count] == '\0' || 825 (cav->cav_ptr+count) > cav->cav_end ) 826 { 827 break; 828 } 829 if ( unclosed_brace == 0 ) { 830 succeed = 1; 831 break; 832 } 833 } 834 835 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR; 836 837 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */ 838 bv->bv_len = count - 1;/* exclude "'B" */ 839 840 } else { 841 succeed = 1; 842 /*Find following white space where the value is ended*/ 843 for( count = 1 ; ; count++ ) { 844 if ( cav->cav_ptr[count] == '\0' || 845 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' || 846 cav->cav_ptr[count] == '{' || 847 (cav->cav_ptr+count) > cav->cav_end ) 848 { 849 break; 850 } 851 } 852 bv->bv_val = cav->cav_ptr; 853 bv->bv_len = count; 854 } 855 856 cav->cav_ptr += bv->bv_len; 857 return LDAP_SUCCESS; 858 } 859 860 static int 861 get_matching_value( Operation *op, ComponentAssertion* ca, 862 ComponentAssertionValue* cav, struct berval* bv, 863 const char** text ) 864 { 865 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) { 866 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) { 867 return LDAP_FILTER_ERROR; 868 } 869 870 } else { 871 /* embedded componentFilterMatch Description */ 872 bv->bv_val = cav->cav_ptr; 873 bv->bv_len = cav_cur_len( cav ); 874 } 875 876 return LDAP_SUCCESS; 877 } 878 879 /* Don't move the position pointer, just peek given string */ 880 static int 881 peek_cav_str( ComponentAssertionValue* cav, char* str ) 882 { 883 eat_whsp( cav ); 884 if ( cav_cur_len( cav ) >= strlen( str ) && 885 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) 886 { 887 return LDAP_SUCCESS; 888 } 889 890 return LDAP_INVALID_SYNTAX; 891 } 892 893 static int 894 strip_cav_str( ComponentAssertionValue* cav, char* str) 895 { 896 eat_whsp( cav ); 897 if ( cav_cur_len( cav ) >= strlen( str ) && 898 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) 899 { 900 cav->cav_ptr += strlen( str ); 901 return LDAP_SUCCESS; 902 } 903 904 return LDAP_INVALID_SYNTAX; 905 } 906 907 /* 908 * TAG : "item", "and", "or", "not" 909 */ 910 static ber_tag_t 911 strip_cav_tag( ComponentAssertionValue* cav ) 912 { 913 int rc; 914 915 eat_whsp( cav ); 916 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) { 917 if ( strip_cav_str( cav , "item:" )) 918 goto fail; 919 return LDAP_COMP_FILTER_ITEM; 920 921 } else if ( cav_cur_len( cav ) >= 7 && 922 strncmp( cav->cav_ptr, "and", 3 ) == 0 ) 923 { 924 if ( strip_cav_str( cav , "and:" )) 925 goto fail; 926 return LDAP_COMP_FILTER_AND; 927 928 } else if ( cav_cur_len( cav ) >= 6 && 929 strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) 930 { 931 if ( strip_cav_str( cav , "or:" )) 932 goto fail; 933 return LDAP_COMP_FILTER_OR; 934 935 } else if ( cav_cur_len( cav ) >= 7 && 936 strncmp( cav->cav_ptr, "not", 3 ) == 0 ) 937 { 938 if ( strip_cav_str( cav , "not:" )) 939 goto fail; 940 return LDAP_COMP_FILTER_NOT; 941 } 942 943 fail: 944 return LBER_ERROR; 945 } 946 947 /* 948 * when encoding, "item" is denotation of ComponentAssertion 949 * ComponentAssertion :: SEQUENCE { 950 * component ComponentReference (SIZE(1..MAX)) OPTIONAL, 951 * useDefaultValues BOOLEAN DEFAULT TRUE, 952 * rule MATCHING-RULE.&id, 953 * value MATCHING-RULE.&AssertionType } 954 */ 955 static int 956 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca, 957 const char** text ) 958 { 959 int rc, freeval = 0; 960 ComponentAssertion* _ca; 961 struct berval value; 962 MatchingRule* mr; 963 964 Debug( LDAP_DEBUG_FILTER, "get_item \n" ); 965 if ( op ) 966 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx ); 967 else 968 _ca = SLAP_MALLOC( sizeof( ComponentAssertion ) ); 969 970 if ( !_ca ) return LDAP_NO_MEMORY; 971 972 _ca->ca_comp_data.cd_tree = NULL; 973 _ca->ca_comp_data.cd_mem_op = NULL; 974 BER_BVZERO( &_ca->ca_ma_value ); 975 976 rc = peek_cav_str( cav, "component" ); 977 if ( rc == LDAP_SUCCESS ) { 978 strip_cav_str( cav, "component" ); 979 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text ); 980 if ( rc != LDAP_SUCCESS ) { 981 rc = LDAP_INVALID_SYNTAX; 982 fail: 983 if ( freeval ) 984 op->o_tmpfree( _ca->ca_ma_value.bv_val, op->o_tmpmemctx ); 985 if ( op ) 986 op->o_tmpfree( _ca, op->o_tmpmemctx ); 987 else 988 free( _ca ); 989 return rc; 990 } 991 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS ) 992 goto fail; 993 } else { 994 _ca->ca_comp_ref = NULL; 995 } 996 997 rc = peek_cav_str( cav, "useDefaultValues"); 998 if ( rc == LDAP_SUCCESS ) { 999 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text ); 1000 if ( rc != LDAP_SUCCESS ) { 1001 rc = LDAP_INVALID_SYNTAX; 1002 goto fail; 1003 } 1004 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS ) 1005 goto fail; 1006 } 1007 else _ca->ca_use_def = 1; 1008 1009 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS && 1010 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) { 1011 rc = LDAP_INAPPROPRIATE_MATCHING; 1012 goto fail; 1013 } 1014 1015 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS ) 1016 goto fail; 1017 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS && 1018 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) { 1019 rc = LDAP_INVALID_SYNTAX; 1020 goto fail; 1021 } 1022 1023 /* 1024 * Normalize the value of this component assertion when the matching 1025 * rule is one of existing matching rules 1026 */ 1027 mr = _ca->ca_ma_rule; 1028 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) { 1029 1030 value.bv_val[value.bv_len] = '\0'; 1031 rc = mr->smr_normalize ( 1032 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 1033 NULL, mr, 1034 &value, &_ca->ca_ma_value, op->o_tmpmemctx ); 1035 if ( rc != LDAP_SUCCESS ) 1036 goto fail; 1037 freeval = 1; 1038 } 1039 else 1040 _ca->ca_ma_value = value; 1041 /* 1042 * Validate the value of this component assertion 1043 */ 1044 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) { 1045 rc = LDAP_INVALID_SYNTAX; 1046 goto fail; 1047 } 1048 1049 1050 /* componentFilterMatch contains componentFilterMatch in it */ 1051 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) { 1052 struct berval bv; 1053 bv.bv_val = cav->cav_ptr; 1054 bv.bv_len = cav_cur_len( cav ); 1055 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text ); 1056 if ( rc != LDAP_SUCCESS ) 1057 goto fail; 1058 cav->cav_ptr = bv.bv_val; 1059 assert( cav->cav_end >= bv.bv_val ); 1060 } 1061 1062 *ca = _ca; 1063 return LDAP_SUCCESS; 1064 } 1065 1066 static int 1067 parse_comp_filter( Operation* op, ComponentAssertionValue* cav, 1068 ComponentFilter** filt, const char** text ) 1069 { 1070 /* 1071 * A component filter looks like this coming in: 1072 * Filter ::= CHOICE { 1073 * item [0] ComponentAssertion, 1074 * and [1] SEQUENCE OF ComponentFilter, 1075 * or [2] SEQUENCE OF ComponentFilter, 1076 * not [3] ComponentFilter, 1077 * } 1078 */ 1079 1080 ber_tag_t tag; 1081 int err = LDAP_SUCCESS; 1082 ComponentFilter f; 1083 /* TAG : item, and, or, not in RFC 4515 */ 1084 tag = strip_cav_tag( cav ); 1085 1086 if ( tag == LBER_ERROR ) { 1087 *text = "error decoding comp filter"; 1088 return LDAP_PROTOCOL_ERROR; 1089 } 1090 1091 if ( tag != LDAP_COMP_FILTER_NOT ) { 1092 err = strip_cav_str( cav, "{"); 1093 if ( err ) 1094 goto invalid; 1095 } 1096 1097 f.cf_next = NULL; 1098 f.cf_choice = tag; 1099 1100 switch ( f.cf_choice ) { 1101 case LDAP_COMP_FILTER_AND: 1102 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n" ); 1103 err = get_comp_filter_list( op, cav, &f.cf_and, text ); 1104 if ( err != LDAP_SUCCESS ) { 1105 break; 1106 } 1107 if ( f.cf_and == NULL ) { 1108 f.cf_choice = SLAPD_FILTER_COMPUTED; 1109 f.cf_result = LDAP_COMPARE_TRUE; 1110 } 1111 break; 1112 1113 case LDAP_COMP_FILTER_OR: 1114 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n" ); 1115 err = get_comp_filter_list( op, cav, &f.cf_or, text ); 1116 if ( err != LDAP_SUCCESS ) { 1117 break; 1118 } 1119 if ( f.cf_or == NULL ) { 1120 f.cf_choice = SLAPD_FILTER_COMPUTED; 1121 f.cf_result = LDAP_COMPARE_FALSE; 1122 } 1123 /* no assert - list could be empty */ 1124 break; 1125 1126 case LDAP_COMP_FILTER_NOT: 1127 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n" ); 1128 err = parse_comp_filter( op, cav, &f.cf_not, text ); 1129 if ( err != LDAP_SUCCESS ) { 1130 break; 1131 } 1132 1133 assert( f.cf_not != NULL ); 1134 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) { 1135 int fresult = f.cf_not->cf_result; 1136 f.cf_choice = SLAPD_FILTER_COMPUTED; 1137 op->o_tmpfree( f.cf_not, op->o_tmpmemctx ); 1138 f.cf_not = NULL; 1139 1140 switch ( fresult ) { 1141 case LDAP_COMPARE_TRUE: 1142 f.cf_result = LDAP_COMPARE_FALSE; 1143 break; 1144 case LDAP_COMPARE_FALSE: 1145 f.cf_result = LDAP_COMPARE_TRUE; 1146 break; 1147 default: ; 1148 /* (!Undefined) is Undefined */ 1149 } 1150 } 1151 break; 1152 1153 case LDAP_COMP_FILTER_ITEM: 1154 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n" ); 1155 err = get_item( op, cav, &f.cf_ca, text ); 1156 if ( err != LDAP_SUCCESS ) { 1157 break; 1158 } 1159 1160 assert( f.cf_ca != NULL ); 1161 break; 1162 1163 default: 1164 f.cf_choice = SLAPD_FILTER_COMPUTED; 1165 f.cf_result = SLAPD_COMPARE_UNDEFINED; 1166 break; 1167 } 1168 1169 invalid: 1170 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) { 1171 *text = "Component Filter Syntax Error"; 1172 return err; 1173 } 1174 1175 if ( tag != LDAP_COMP_FILTER_NOT ) 1176 err = strip_cav_str( cav, "}"); 1177 1178 if ( err == LDAP_SUCCESS ) { 1179 if ( op ) { 1180 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx ); 1181 } else { 1182 *filt = SLAP_MALLOC( sizeof(f) ); 1183 } 1184 if ( *filt == NULL ) { 1185 return LDAP_NO_MEMORY; 1186 } 1187 **filt = f; 1188 } 1189 1190 return( err ); 1191 } 1192 1193 static int 1194 test_comp_filter_and( 1195 Syntax *syn, 1196 ComponentSyntaxInfo *a, 1197 ComponentFilter *flist ) 1198 { 1199 ComponentFilter *f; 1200 int rtn = LDAP_COMPARE_TRUE; 1201 1202 for ( f = flist ; f != NULL; f = f->cf_next ) { 1203 int rc = test_comp_filter( syn, a, f ); 1204 if ( rc == LDAP_COMPARE_FALSE ) { 1205 rtn = rc; 1206 break; 1207 } 1208 1209 if ( rc != LDAP_COMPARE_TRUE ) { 1210 rtn = rc; 1211 } 1212 } 1213 1214 return rtn; 1215 } 1216 1217 static int 1218 test_comp_filter_or( 1219 Syntax *syn, 1220 ComponentSyntaxInfo *a, 1221 ComponentFilter *flist ) 1222 { 1223 ComponentFilter *f; 1224 int rtn = LDAP_COMPARE_TRUE; 1225 1226 for ( f = flist ; f != NULL; f = f->cf_next ) { 1227 int rc = test_comp_filter( syn, a, f ); 1228 if ( rc == LDAP_COMPARE_TRUE ) { 1229 rtn = rc; 1230 break; 1231 } 1232 1233 if ( rc != LDAP_COMPARE_FALSE ) { 1234 rtn = rc; 1235 } 1236 } 1237 1238 return rtn; 1239 } 1240 1241 int 1242 csi_value_match( MatchingRule *mr, struct berval* bv_attr, 1243 struct berval* bv_assert ) 1244 { 1245 int rc; 1246 int match; 1247 1248 assert( mr != NULL ); 1249 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) ); 1250 1251 if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING; 1252 1253 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/, 1254 mr, bv_attr, bv_assert ); 1255 1256 if ( rc != LDAP_SUCCESS ) return rc; 1257 1258 return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE; 1259 } 1260 1261 /* 1262 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE 1263 */ 1264 static int 1265 test_comp_filter_item( 1266 Syntax *syn, 1267 ComponentSyntaxInfo *csi_attr, 1268 ComponentAssertion *ca ) 1269 { 1270 int rc; 1271 void *attr_nm, *assert_nm; 1272 1273 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid, 1274 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) { 1275 /* componentFilterMatch inside of componentFilterMatch */ 1276 rc = test_comp_filter( syn, csi_attr, ca->ca_cf ); 1277 return rc; 1278 } 1279 1280 /* Memory for storing will-be-extracted attribute values */ 1281 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 ); 1282 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR; 1283 1284 /* Memory for storing component assertion values */ 1285 if( !ca->ca_comp_data.cd_mem_op ) { 1286 assert_nm = nibble_mem_allocator ( 256, 64 ); 1287 if ( !assert_nm ) { 1288 nibble_mem_free ( attr_nm ); 1289 return LDAP_PROTOCOL_ERROR; 1290 } 1291 ca->ca_comp_data.cd_mem_op = assert_nm; 1292 1293 } else { 1294 assert_nm = ca->ca_comp_data.cd_mem_op; 1295 } 1296 1297 /* component reference initialization */ 1298 if ( ca->ca_comp_ref ) { 1299 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list; 1300 } 1301 rc = test_components( attr_nm, assert_nm, csi_attr, ca ); 1302 1303 /* free memory used for storing extracted attribute value */ 1304 nibble_mem_free ( attr_nm ); 1305 return rc; 1306 } 1307 1308 static int 1309 test_comp_filter( 1310 Syntax *syn, 1311 ComponentSyntaxInfo *a, 1312 ComponentFilter *f ) 1313 { 1314 int rc; 1315 1316 if ( !f ) return LDAP_PROTOCOL_ERROR; 1317 1318 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n" ); 1319 switch ( f->cf_choice ) { 1320 case SLAPD_FILTER_COMPUTED: 1321 rc = f->cf_result; 1322 break; 1323 case LDAP_COMP_FILTER_AND: 1324 rc = test_comp_filter_and( syn, a, f->cf_and ); 1325 break; 1326 case LDAP_COMP_FILTER_OR: 1327 rc = test_comp_filter_or( syn, a, f->cf_or ); 1328 break; 1329 case LDAP_COMP_FILTER_NOT: 1330 rc = test_comp_filter( syn, a, f->cf_not ); 1331 1332 switch ( rc ) { 1333 case LDAP_COMPARE_TRUE: 1334 rc = LDAP_COMPARE_FALSE; 1335 break; 1336 case LDAP_COMPARE_FALSE: 1337 rc = LDAP_COMPARE_TRUE; 1338 break; 1339 } 1340 break; 1341 case LDAP_COMP_FILTER_ITEM: 1342 rc = test_comp_filter_item( syn, a, f->cf_ca ); 1343 break; 1344 default: 1345 rc = LDAP_PROTOCOL_ERROR; 1346 } 1347 1348 return( rc ); 1349 } 1350 1351 static void 1352 free_comp_filter_list( ComponentFilter* f ) 1353 { 1354 ComponentFilter* tmp; 1355 for ( tmp = f; tmp; tmp = tmp->cf_next ) { 1356 free_comp_filter( tmp ); 1357 } 1358 } 1359 1360 static void 1361 free_comp_filter( ComponentFilter* f ) 1362 { 1363 if ( !f ) { 1364 Debug( LDAP_DEBUG_FILTER, 1365 "free_comp_filter: Invalid filter so failed to release memory\n" ); 1366 return; 1367 } 1368 switch ( f->cf_choice ) { 1369 case LDAP_COMP_FILTER_AND: 1370 case LDAP_COMP_FILTER_OR: 1371 free_comp_filter_list( f->cf_any ); 1372 break; 1373 case LDAP_COMP_FILTER_NOT: 1374 free_comp_filter( f->cf_any ); 1375 break; 1376 case LDAP_COMP_FILTER_ITEM: 1377 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) { 1378 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op ); 1379 } 1380 break; 1381 default: 1382 break; 1383 } 1384 } 1385 1386 void 1387 component_free( ComponentFilter *f ) { 1388 free_comp_filter( f ); 1389 } 1390 1391 void 1392 free_ComponentData( Attribute *a ) { 1393 if ( a->a_comp_data->cd_mem_op ) 1394 component_destructor( a->a_comp_data->cd_mem_op ); 1395 free ( a->a_comp_data ); 1396 a->a_comp_data = NULL; 1397 } 1398 #endif 1399