Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / openldap / dist / servers / slapd / component.c
blobcbe9a7eec6537b6c596854ea790afb315194f8ff
1 /* component.c -- Component Filter Match Routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/component.c,v 1.31.2.3 2008/02/11 23:26:43 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2004 by IBM Corporation.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 #include "portable.h"
20 #include <ac/string.h>
21 #include <ac/socket.h>
23 #include "lutil.h"
24 #include <ldap.h>
25 #include "slap.h"
27 #ifdef LDAP_COMP_MATCH
29 #include "component.h"
32 * Following function pointers are initialized
33 * when a component module is loaded
35 alloc_nibble_func* nibble_mem_allocator = NULL;
36 free_nibble_func* nibble_mem_free = NULL;
37 convert_attr_to_comp_func* attr_converter = NULL;
38 convert_assert_to_comp_func* assert_converter = NULL ;
39 free_component_func* component_destructor = NULL ;
40 test_component_func* test_components = NULL;
41 test_membership_func* is_aliased_attribute = NULL;
42 component_encoder_func* component_encoder = NULL;
43 get_component_info_func* get_component_description = NULL;
44 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
45 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
46 #define MAX_LDAP_STR_LEN 128
48 static int
49 peek_componentId_type( ComponentAssertionValue* cav );
51 static int
52 strip_cav_str( ComponentAssertionValue* cav, char* str);
54 static int
55 peek_cav_str( ComponentAssertionValue* cav, char* str );
57 static int
58 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
59 ComponentFilter** filt, const char** text );
61 static void
62 free_comp_filter( ComponentFilter* f );
64 static int
65 test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f );
67 int
68 componentCertificateValidate(
69 Syntax *syntax,
70 struct berval *val )
72 return LDAP_SUCCESS;
75 int
76 componentFilterValidate(
77 Syntax *syntax,
78 struct berval *val )
80 return LDAP_SUCCESS;
83 int
84 allComponentsValidate(
85 Syntax *syntax,
86 struct berval *val )
88 return LDAP_SUCCESS;
91 int
92 componentFilterMatch (
93 int *matchp,
94 slap_mask_t flags,
95 Syntax *syntax,
96 MatchingRule *mr,
97 struct berval *value,
98 void *assertedValue )
100 ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
101 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
102 int rc;
104 if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING;
106 /* Check if the component module is loaded */
107 if ( !attr_converter || !nibble_mem_allocator ) {
108 return LDAP_OTHER;
111 rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
113 if ( rc == LDAP_COMPARE_TRUE ) {
114 *matchp = 0;
115 return LDAP_SUCCESS;
117 else if ( rc == LDAP_COMPARE_FALSE ) {
118 *matchp = 1;
119 return LDAP_SUCCESS;
121 else {
122 return LDAP_INAPPROPRIATE_MATCHING;
127 directoryComponentsMatch(
128 int *matchp,
129 slap_mask_t flags,
130 Syntax *syntax,
131 MatchingRule *mr,
132 struct berval *value,
133 void *assertedValue )
135 /* Only for registration */
136 *matchp = 0;
137 return LDAP_SUCCESS;
141 allComponentsMatch(
142 int *matchp,
143 slap_mask_t flags,
144 Syntax *syntax,
145 MatchingRule *mr,
146 struct berval *value,
147 void *assertedValue )
149 /* Only for registration */
150 *matchp = 0;
151 return LDAP_SUCCESS;
154 static int
155 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
157 cav->cav_ptr = cav->cav_buf = bv->bv_val;
158 cav->cav_end = bv->bv_val + bv->bv_len;
160 return LDAP_SUCCESS;
163 ComponentReference*
164 dup_comp_ref ( Operation* op, ComponentReference* cr )
166 ComponentReference* dup_cr;
167 ComponentId* ci_curr;
168 ComponentId** ci_temp;
170 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
172 dup_cr->cr_len = cr->cr_len;
173 dup_cr->cr_string = cr->cr_string;
175 ci_temp = &dup_cr->cr_list;
176 ci_curr = cr->cr_list;
178 for ( ; ci_curr != NULL ;
179 ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
181 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
182 if ( !*ci_temp ) return NULL;
183 **ci_temp = *ci_curr;
186 dup_cr->cr_curr = dup_cr->cr_list;
188 return dup_cr;
191 static int
192 dup_comp_filter_list (
193 Operation *op,
194 struct berval *bv,
195 ComponentFilter* in_f,
196 ComponentFilter** out_f )
198 ComponentFilter **new, *f;
199 int rc;
201 new = out_f;
202 for ( f = in_f; f != NULL; f = f->cf_next ) {
203 rc = dup_comp_filter( op, bv, f, new );
204 if ( rc != LDAP_SUCCESS ) {
205 return rc;
207 new = &(*new)->cf_next;
209 return LDAP_SUCCESS;
213 get_len_of_next_assert_value ( struct berval* bv, char separator )
215 int i = 0;
216 while (1) {
217 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
218 break;
219 i++;
221 bv->bv_val += (i + 1);
222 bv->bv_len -= (i + 1);
223 return i;
227 dup_comp_filter_item (
228 Operation *op,
229 struct berval* assert_bv,
230 ComponentAssertion* in_ca,
231 ComponentAssertion** out_ca )
233 int len;
235 if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
237 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
238 if ( !(*out_ca) ) return LDAP_NO_MEMORY;
240 (*out_ca)->ca_comp_data.cd_tree = NULL;
241 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
243 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
244 (*out_ca)->ca_use_def = 0;
245 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
247 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
248 len = get_len_of_next_assert_value ( assert_bv, '$' );
249 if ( len <= 0 ) return SLAPD_DISCONNECT;
250 (*out_ca)->ca_ma_value.bv_len = len;
252 return LDAP_SUCCESS;
256 dup_comp_filter (
257 Operation* op,
258 struct berval *bv,
259 ComponentFilter *in_f,
260 ComponentFilter **out_f )
262 int rc;
263 ComponentFilter dup_f = {0};
265 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
267 switch ( in_f->cf_choice ) {
268 case LDAP_COMP_FILTER_AND:
269 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
270 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
271 break;
272 case LDAP_COMP_FILTER_OR:
273 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
274 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
275 break;
276 case LDAP_COMP_FILTER_NOT:
277 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
278 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
279 break;
280 case LDAP_COMP_FILTER_ITEM:
281 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
282 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
283 break;
284 default:
285 rc = LDAP_PROTOCOL_ERROR;
288 if ( rc == LDAP_SUCCESS ) {
289 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
290 **out_f = dup_f;
293 return( rc );
297 get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text )
299 struct berval assert_bv;
301 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
303 if ( !aa->aa_cf )
304 return LDAP_PROTOCOL_ERROR;
306 assert_bv = a_assert->aa_value;
308 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
309 * the component assertion value in assert_bv
310 * Multiple values may be separated with '$'
312 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
316 get_aliased_filter( Operation* op,
317 MatchingRuleAssertion* ma, AttributeAliasing* aa,
318 const char** text )
320 struct berval assert_bv;
322 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
324 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
326 assert_bv = ma->ma_value;
327 /* Attribute Description is replaced with aliased one */
328 ma->ma_desc = aa->aa_aliased_ad;
329 ma->ma_rule = aa->aa_mr;
331 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
332 * the component assertion value in assert_bv
333 * Multiple values may be separated with '$'
335 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
339 get_comp_filter( Operation* op, struct berval* bv,
340 ComponentFilter** filt, const char **text )
342 ComponentAssertionValue cav;
343 int rc;
345 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
346 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
347 return rc;
349 rc = parse_comp_filter( op, &cav, filt, text );
350 bv->bv_val = cav.cav_ptr;
352 return rc;
355 static void
356 eat_whsp( ComponentAssertionValue* cav )
358 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
359 cav->cav_ptr++;
363 static int
364 cav_cur_len( ComponentAssertionValue* cav )
366 return cav->cav_end - cav->cav_ptr;
369 static ber_tag_t
370 comp_first_element( ComponentAssertionValue* cav )
372 eat_whsp( cav );
373 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
374 return LDAP_COMP_FILTER_ITEM;
376 } else if ( cav_cur_len( cav ) >= 7 &&
377 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
379 return LDAP_COMP_FILTER_AND;
381 } else if ( cav_cur_len( cav ) >= 6 &&
382 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
384 return LDAP_COMP_FILTER_OR;
386 } else if ( cav_cur_len( cav ) >= 7 &&
387 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
389 return LDAP_COMP_FILTER_NOT;
391 } else {
392 return LDAP_COMP_FILTER_UNDEFINED;
396 static ber_tag_t
397 comp_next_element( ComponentAssertionValue* cav )
399 eat_whsp( cav );
400 if ( *(cav->cav_ptr) == ',' ) {
401 /* move pointer to the next CA */
402 cav->cav_ptr++;
403 return comp_first_element( cav );
405 else return LDAP_COMP_FILTER_UNDEFINED;
408 static int
409 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
410 ComponentFilter** f, const char** text )
412 ComponentFilter **new;
413 int err;
414 ber_tag_t tag;
416 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
417 new = f;
418 for ( tag = comp_first_element( cav );
419 tag != LDAP_COMP_FILTER_UNDEFINED;
420 tag = comp_next_element( cav ) )
422 err = parse_comp_filter( op, cav, new, text );
423 if ( err != LDAP_SUCCESS ) return ( err );
424 new = &(*new)->cf_next;
426 *new = NULL;
428 return( LDAP_SUCCESS );
431 static int
432 get_componentId( Operation *op, ComponentAssertionValue* cav,
433 ComponentId ** cid, const char** text )
435 ber_tag_t type;
436 ComponentId _cid;
437 int len;
439 type = peek_componentId_type( cav );
441 Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
442 (unsigned long) type, 0, 0 );
443 len = 0;
444 _cid.ci_type = type;
445 _cid.ci_next = NULL;
446 switch ( type ) {
447 case LDAP_COMPREF_IDENTIFIER :
448 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
449 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
450 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
451 _cid.ci_val.ci_identifier.bv_len = len;
452 cav->cav_ptr += len;
453 break;
454 case LDAP_COMPREF_FROM_BEGINNING :
455 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
456 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
457 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
458 cav->cav_ptr += len;
459 break;
460 case LDAP_COMPREF_FROM_END :
461 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
462 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
463 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
464 cav->cav_ptr += len;
465 break;
466 case LDAP_COMPREF_COUNT :
467 _cid.ci_val.ci_count = 0;
468 cav->cav_ptr++;
469 break;
470 case LDAP_COMPREF_CONTENT :
471 _cid.ci_val.ci_content = 1;
472 cav->cav_ptr += strlen("content");
473 break;
474 case LDAP_COMPREF_SELECT :
475 if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
476 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
477 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
478 ; len++ );
479 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
480 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
481 cav->cav_ptr += len + 1;
482 break;
483 case LDAP_COMPREF_ALL :
484 _cid.ci_val.ci_all = '*';
485 cav->cav_ptr++;
486 break;
487 default :
488 return LDAP_COMPREF_UNDEFINED;
491 if ( op ) {
492 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
493 } else {
494 *cid = malloc( sizeof( ComponentId ) );
496 **cid = _cid;
497 return LDAP_SUCCESS;
500 static int
501 peek_componentId_type( ComponentAssertionValue* cav )
503 eat_whsp( cav );
505 if ( cav->cav_ptr[0] == '-' ) {
506 return LDAP_COMPREF_FROM_END;
508 } else if ( cav->cav_ptr[0] == '(' ) {
509 return LDAP_COMPREF_SELECT;
511 } else if ( cav->cav_ptr[0] == '*' ) {
512 return LDAP_COMPREF_ALL;
514 } else if ( cav->cav_ptr[0] == '0' ) {
515 return LDAP_COMPREF_COUNT;
517 } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
518 return LDAP_COMPREF_FROM_BEGINNING;
520 } else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
521 strncmp(cav->cav_ptr,"content",7) == 0 )
523 return LDAP_COMPREF_CONTENT;
524 } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
525 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
527 return LDAP_COMPREF_IDENTIFIER;
530 return LDAP_COMPREF_UNDEFINED;
533 static ber_tag_t
534 comp_next_id( ComponentAssertionValue* cav )
536 if ( *(cav->cav_ptr) == '.' ) {
537 cav->cav_ptr++;
538 return LDAP_COMPREF_DEFINED;
541 return LDAP_COMPREF_UNDEFINED;
546 static int
547 get_component_reference(
548 Operation *op,
549 ComponentAssertionValue* cav,
550 ComponentReference** cr,
551 const char** text )
553 int rc, count = 0;
554 ber_int_t type;
555 ComponentReference* ca_comp_ref;
556 ComponentId** cr_list;
557 char* start, *end;
559 eat_whsp( cav );
561 start = cav->cav_ptr;
562 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
563 if ( op ) {
564 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
565 op->o_tmpmemctx );
566 } else {
567 ca_comp_ref = malloc( sizeof( ComponentReference ) );
570 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
572 cr_list = &ca_comp_ref->cr_list;
574 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
575 ; type = comp_next_id( cav ), count++ )
577 rc = get_componentId( op, cav, cr_list, text );
578 if ( rc == LDAP_SUCCESS ) {
579 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
580 cr_list = &(*cr_list)->ci_next;
582 } else if ( rc == LDAP_COMPREF_UNDEFINED ) {
583 if ( op ) {
584 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
585 } else {
586 free( ca_comp_ref );
588 return rc;
591 ca_comp_ref->cr_len = count;
592 end = cav->cav_ptr;
593 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
594 if ( op ) {
595 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
596 } else {
597 free( ca_comp_ref );
599 return rc;
602 *cr = ca_comp_ref;
603 **cr = *ca_comp_ref;
605 (*cr)->cr_string.bv_val = start;
606 (*cr)->cr_string.bv_len = end - start + 1;
608 return rc;
612 insert_component_reference(
613 ComponentReference *cr,
614 ComponentReference** cr_list)
616 if ( !cr ) return LDAP_PARAM_ERROR;
618 if ( !(*cr_list) ) {
619 *cr_list = cr;
620 cr->cr_next = NULL;
621 } else {
622 cr->cr_next = *cr_list;
623 *cr_list = cr;
625 return LDAP_SUCCESS;
629 * If there is '.' in the name of a given attribute
630 * the first '.'- following characters are considered
631 * as a component reference of the attribute
632 * EX) userCertificate.toBeSigned.serialNumber
633 * attribute : userCertificate
634 * component reference : toBeSigned.serialNumber
637 is_component_reference( char* attr ) {
638 int i;
639 for ( i=0; attr[i] != '\0' ; i++ ) {
640 if ( attr[i] == '.' ) return (1);
642 return (0);
646 extract_component_reference(
647 char* attr,
648 ComponentReference** cr )
650 int i, rc;
651 char* cr_ptr;
652 int cr_len;
653 ComponentAssertionValue cav;
654 char text[1][128];
656 for ( i=0; attr[i] != '\0' ; i++ ) {
657 if ( attr[i] == '.' ) break;
660 if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
661 attr[i] = '\0';
663 cr_ptr = attr + i + 1 ;
664 cr_len = strlen ( cr_ptr );
665 if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
667 /* enclosed between double quotes*/
668 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
669 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
670 cav.cav_buf[0] = '"';
671 cav.cav_buf[cr_len+1] = '"';
672 cav.cav_end = cr_ptr + cr_len + 2;
674 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
675 if ( rc != LDAP_SUCCESS ) return rc;
676 (*cr)->cr_string.bv_val = cav.cav_buf;
677 (*cr)->cr_string.bv_len = cr_len + 2;
679 return LDAP_SUCCESS;
682 static int
683 get_ca_use_default( Operation *op,
684 ComponentAssertionValue* cav,
685 int* ca_use_def, const char** text )
687 strip_cav_str( cav, "useDefaultValues" );
689 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
690 strip_cav_str( cav, "TRUE" );
691 *ca_use_def = 1;
693 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
694 strip_cav_str( cav, "FALSE" );
695 *ca_use_def = 0;
697 } else {
698 return LDAP_INVALID_SYNTAX;
701 return LDAP_SUCCESS;
704 static int
705 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
706 MatchingRule** mr, const char** text )
708 int count = 0;
709 struct berval rule_text = { 0L, NULL };
711 eat_whsp( cav );
713 for ( ; ; count++ ) {
714 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
715 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
716 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
718 break;
722 if ( count == 0 ) {
723 *text = "component matching rule not recognized";
724 return LDAP_INAPPROPRIATE_MATCHING;
727 rule_text.bv_len = count;
728 rule_text.bv_val = cav->cav_ptr;
729 *mr = mr_bvfind( &rule_text );
730 cav->cav_ptr += count;
731 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
732 (*mr)->smr_mrule.mr_oid, 0, 0 );
733 if ( *mr == NULL ) {
734 *text = "component matching rule not recognized";
735 return LDAP_INAPPROPRIATE_MATCHING;
737 return LDAP_SUCCESS;
740 static int
741 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
743 int count, sequent_dquote, unclosed_brace, succeed;
745 eat_whsp( cav );
747 * Four cases of GSER <Values>
748 * 1) "..." :
749 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
750 * 2) '...'B or '...'H :
751 * BitStringVal, OctetStringVal
752 * 3) {...} :
753 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
754 * 4) Between two white spaces
755 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
758 succeed = 0;
759 if ( cav->cav_ptr[0] == '"' ) {
760 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
761 /* In order to find escaped double quote */
762 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
763 else sequent_dquote = 0;
765 if ( cav->cav_ptr[count] == '\0' ||
766 (cav->cav_ptr+count) > cav->cav_end )
768 break;
771 if ( ( cav->cav_ptr[count] == '"' &&
772 cav->cav_ptr[count-1] != '"') ||
773 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
775 succeed = 1;
776 break;
780 if ( !succeed || cav->cav_ptr[count] != '"' ) {
781 return LDAP_FILTER_ERROR;
784 bv->bv_val = cav->cav_ptr + 1;
785 bv->bv_len = count - 1; /* exclude '"' */
787 } else if ( cav->cav_ptr[0] == '\'' ) {
788 for( count = 1 ; ; count++ ) {
789 if ( cav->cav_ptr[count] == '\0' ||
790 (cav->cav_ptr+count) > cav->cav_end )
792 break;
794 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
795 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
797 succeed = 1;
798 break;
802 if ( !succeed ||
803 !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
805 return LDAP_FILTER_ERROR;
808 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
809 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
811 } else if ( cav->cav_ptr[0] == '{' ) {
812 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
813 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
814 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
816 if ( cav->cav_ptr[count] == '\0' ||
817 (cav->cav_ptr+count) > cav->cav_end )
819 break;
821 if ( unclosed_brace == 0 ) {
822 succeed = 1;
823 break;
827 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
829 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
830 bv->bv_len = count - 1;/* exclude "'B" */
832 } else {
833 succeed = 1;
834 /*Find following white space where the value is ended*/
835 for( count = 1 ; ; count++ ) {
836 if ( cav->cav_ptr[count] == '\0' ||
837 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
838 cav->cav_ptr[count] == '{' ||
839 (cav->cav_ptr+count) > cav->cav_end )
841 break;
844 bv->bv_val = cav->cav_ptr;
845 bv->bv_len = count;
848 cav->cav_ptr += bv->bv_len;
849 return LDAP_SUCCESS;
852 static int
853 get_matching_value( Operation *op, ComponentAssertion* ca,
854 ComponentAssertionValue* cav, struct berval* bv,
855 const char** text )
857 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
858 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
859 return LDAP_FILTER_ERROR;
862 } else {
863 /* embeded componentFilterMatch Description */
864 bv->bv_val = cav->cav_ptr;
865 bv->bv_len = cav_cur_len( cav );
868 return LDAP_SUCCESS;
871 /* Don't move the position pointer, just peek given string */
872 static int
873 peek_cav_str( ComponentAssertionValue* cav, char* str )
875 eat_whsp( cav );
876 if ( cav_cur_len( cav ) >= strlen( str ) &&
877 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
879 return LDAP_SUCCESS;
882 return LDAP_INVALID_SYNTAX;
885 static int
886 strip_cav_str( ComponentAssertionValue* cav, char* str)
888 eat_whsp( cav );
889 if ( cav_cur_len( cav ) >= strlen( str ) &&
890 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
892 cav->cav_ptr += strlen( str );
893 return LDAP_SUCCESS;
896 return LDAP_INVALID_SYNTAX;
900 * TAG : "item", "and", "or", "not"
902 static ber_tag_t
903 strip_cav_tag( ComponentAssertionValue* cav )
906 eat_whsp( cav );
907 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
908 strip_cav_str( cav , "item:" );
909 return LDAP_COMP_FILTER_ITEM;
911 } else if ( cav_cur_len( cav ) >= 7 &&
912 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
914 strip_cav_str( cav , "and:" );
915 return LDAP_COMP_FILTER_AND;
917 } else if ( cav_cur_len( cav ) >= 6 &&
918 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
920 strip_cav_str( cav , "or:" );
921 return LDAP_COMP_FILTER_OR;
923 } else if ( cav_cur_len( cav ) >= 7 &&
924 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
926 strip_cav_str( cav , "not:" );
927 return LDAP_COMP_FILTER_NOT;
930 return LBER_ERROR;
934 * when encoding, "item" is denotation of ComponentAssertion
935 * ComponentAssertion :: SEQUENCE {
936 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
937 * useDefaultValues BOOLEAN DEFAULT TRUE,
938 * rule MATCHING-RULE.&id,
939 * value MATCHING-RULE.&AssertionType }
941 static int
942 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
943 const char** text )
945 int rc;
946 ComponentAssertion* _ca;
947 struct berval value;
948 MatchingRule* mr;
950 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
951 if ( op )
952 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
953 else
954 _ca = malloc( sizeof( ComponentAssertion ) );
956 if ( !_ca ) return LDAP_NO_MEMORY;
958 _ca->ca_comp_data.cd_tree = NULL;
959 _ca->ca_comp_data.cd_mem_op = NULL;
961 rc = peek_cav_str( cav, "component" );
962 if ( rc == LDAP_SUCCESS ) {
963 strip_cav_str( cav, "component" );
964 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
965 if ( rc != LDAP_SUCCESS ) {
966 if ( op )
967 op->o_tmpfree( _ca, op->o_tmpmemctx );
968 else
969 free( _ca );
970 return LDAP_INVALID_SYNTAX;
972 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
973 return rc;
974 } else {
975 _ca->ca_comp_ref = NULL;
978 rc = peek_cav_str( cav, "useDefaultValues");
979 if ( rc == LDAP_SUCCESS ) {
980 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
981 if ( rc != LDAP_SUCCESS ) {
982 if ( op )
983 op->o_tmpfree( _ca, op->o_tmpmemctx );
984 else
985 free( _ca );
986 return LDAP_INVALID_SYNTAX;
988 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
989 return rc;
991 else _ca->ca_use_def = 1;
993 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
994 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
995 if ( op )
996 op->o_tmpfree( _ca, op->o_tmpmemctx );
997 else
998 free( _ca );
999 return LDAP_INAPPROPRIATE_MATCHING;
1002 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1003 return rc;
1004 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1005 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1006 if ( op )
1007 op->o_tmpfree( _ca, op->o_tmpmemctx );
1008 else
1009 free( _ca );
1010 return LDAP_INVALID_SYNTAX;
1014 * Normalize the value of this component assertion when the matching
1015 * rule is one of existing matching rules
1017 mr = _ca->ca_ma_rule;
1018 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1020 value.bv_val[value.bv_len] = '\0';
1021 rc = mr->smr_normalize (
1022 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1023 NULL, mr,
1024 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
1025 if ( rc != LDAP_SUCCESS )
1026 return rc;
1028 else
1029 _ca->ca_ma_value = value;
1031 * Validate the value of this component assertion
1033 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1034 return LDAP_INVALID_SYNTAX;
1038 /* componentFilterMatch contains componentFilterMatch in it */
1039 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1040 struct berval bv;
1041 bv.bv_val = cav->cav_ptr;
1042 bv.bv_len = cav_cur_len( cav );
1043 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1044 if ( rc != LDAP_SUCCESS ) {
1045 if ( op )
1046 op->o_tmpfree( _ca, op->o_tmpmemctx );
1047 else
1048 free( _ca );
1049 return rc;
1051 cav->cav_ptr = bv.bv_val;
1052 assert( cav->cav_end >= bv.bv_val );
1055 *ca = _ca;
1056 return LDAP_SUCCESS;
1059 static int
1060 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1061 ComponentFilter** filt, const char** text )
1064 * A component filter looks like this coming in:
1065 * Filter ::= CHOICE {
1066 * item [0] ComponentAssertion,
1067 * and [1] SEQUENCE OF ComponentFilter,
1068 * or [2] SEQUENCE OF ComponentFilter,
1069 * not [3] ComponentFilter,
1073 ber_tag_t tag;
1074 int err;
1075 ComponentFilter f;
1076 /* TAG : item, and, or, not in RFC 4515 */
1077 tag = strip_cav_tag( cav );
1079 if ( tag == LBER_ERROR ) {
1080 *text = "error decoding comp filter";
1081 return LDAP_PROTOCOL_ERROR;
1084 if ( tag != LDAP_COMP_FILTER_NOT )
1085 strip_cav_str( cav, "{");
1087 err = LDAP_SUCCESS;
1089 f.cf_next = NULL;
1090 f.cf_choice = tag;
1092 switch ( f.cf_choice ) {
1093 case LDAP_COMP_FILTER_AND:
1094 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1095 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1096 if ( err != LDAP_SUCCESS ) {
1097 break;
1099 if ( f.cf_and == NULL ) {
1100 f.cf_choice = SLAPD_FILTER_COMPUTED;
1101 f.cf_result = LDAP_COMPARE_TRUE;
1103 break;
1105 case LDAP_COMP_FILTER_OR:
1106 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1107 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1108 if ( err != LDAP_SUCCESS ) {
1109 break;
1111 if ( f.cf_or == NULL ) {
1112 f.cf_choice = SLAPD_FILTER_COMPUTED;
1113 f.cf_result = LDAP_COMPARE_FALSE;
1115 /* no assert - list could be empty */
1116 break;
1118 case LDAP_COMP_FILTER_NOT:
1119 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1120 err = parse_comp_filter( op, cav, &f.cf_not, text );
1121 if ( err != LDAP_SUCCESS ) {
1122 break;
1125 assert( f.cf_not != NULL );
1126 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1127 int fresult = f.cf_not->cf_result;
1128 f.cf_choice = SLAPD_FILTER_COMPUTED;
1129 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1130 f.cf_not = NULL;
1132 switch ( fresult ) {
1133 case LDAP_COMPARE_TRUE:
1134 f.cf_result = LDAP_COMPARE_FALSE;
1135 break;
1136 case LDAP_COMPARE_FALSE:
1137 f.cf_result = LDAP_COMPARE_TRUE;
1138 break;
1139 default: ;
1140 /* (!Undefined) is Undefined */
1143 break;
1145 case LDAP_COMP_FILTER_ITEM:
1146 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1147 err = get_item( op, cav, &f.cf_ca, text );
1148 if ( err != LDAP_SUCCESS ) {
1149 break;
1152 assert( f.cf_ca != NULL );
1153 break;
1155 default:
1156 f.cf_choice = SLAPD_FILTER_COMPUTED;
1157 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1158 break;
1161 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1162 *text = "Component Filter Syntax Error";
1163 return err;
1166 if ( tag != LDAP_COMP_FILTER_NOT )
1167 strip_cav_str( cav, "}");
1169 if ( err == LDAP_SUCCESS ) {
1170 if ( op ) {
1171 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1172 } else {
1173 *filt = malloc( sizeof(f) );
1175 **filt = f;
1178 return( err );
1181 static int
1182 test_comp_filter_and(
1183 Syntax *syn,
1184 ComponentSyntaxInfo *a,
1185 ComponentFilter *flist )
1187 ComponentFilter *f;
1188 int rtn = LDAP_COMPARE_TRUE;
1190 for ( f = flist ; f != NULL; f = f->cf_next ) {
1191 int rc = test_comp_filter( syn, a, f );
1192 if ( rc == LDAP_COMPARE_FALSE ) {
1193 rtn = rc;
1194 break;
1197 if ( rc != LDAP_COMPARE_TRUE ) {
1198 rtn = rc;
1202 return rtn;
1205 static int
1206 test_comp_filter_or(
1207 Syntax *syn,
1208 ComponentSyntaxInfo *a,
1209 ComponentFilter *flist )
1211 ComponentFilter *f;
1212 int rtn = LDAP_COMPARE_TRUE;
1214 for ( f = flist ; f != NULL; f = f->cf_next ) {
1215 int rc = test_comp_filter( syn, a, f );
1216 if ( rc == LDAP_COMPARE_TRUE ) {
1217 rtn = rc;
1218 break;
1221 if ( rc != LDAP_COMPARE_FALSE ) {
1222 rtn = rc;
1226 return rtn;
1230 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1231 struct berval* bv_assert )
1233 int rc;
1234 int match;
1236 assert( mr != NULL );
1237 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1239 if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1241 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1242 mr, bv_attr, bv_assert );
1244 if ( rc != LDAP_SUCCESS ) return rc;
1246 return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1250 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1252 static int
1253 test_comp_filter_item(
1254 Syntax *syn,
1255 ComponentSyntaxInfo *csi_attr,
1256 ComponentAssertion *ca )
1258 int rc;
1259 void *attr_nm, *assert_nm;
1261 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1262 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1263 /* componentFilterMatch inside of componentFilterMatch */
1264 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1265 return rc;
1268 /* Memory for storing will-be-extracted attribute values */
1269 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1270 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1272 /* Memory for storing component assertion values */
1273 if( !ca->ca_comp_data.cd_mem_op ) {
1274 assert_nm = nibble_mem_allocator ( 256, 64 );
1275 if ( !assert_nm ) {
1276 nibble_mem_free ( attr_nm );
1277 return LDAP_PROTOCOL_ERROR;
1279 ca->ca_comp_data.cd_mem_op = assert_nm;
1281 } else {
1282 assert_nm = ca->ca_comp_data.cd_mem_op;
1285 /* component reference initialization */
1286 if ( ca->ca_comp_ref ) {
1287 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1289 rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1291 /* free memory used for storing extracted attribute value */
1292 nibble_mem_free ( attr_nm );
1293 return rc;
1296 static int
1297 test_comp_filter(
1298 Syntax *syn,
1299 ComponentSyntaxInfo *a,
1300 ComponentFilter *f )
1302 int rc;
1304 if ( !f ) return LDAP_PROTOCOL_ERROR;
1306 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1307 switch ( f->cf_choice ) {
1308 case SLAPD_FILTER_COMPUTED:
1309 rc = f->cf_result;
1310 break;
1311 case LDAP_COMP_FILTER_AND:
1312 rc = test_comp_filter_and( syn, a, f->cf_and );
1313 break;
1314 case LDAP_COMP_FILTER_OR:
1315 rc = test_comp_filter_or( syn, a, f->cf_or );
1316 break;
1317 case LDAP_COMP_FILTER_NOT:
1318 rc = test_comp_filter( syn, a, f->cf_not );
1320 switch ( rc ) {
1321 case LDAP_COMPARE_TRUE:
1322 rc = LDAP_COMPARE_FALSE;
1323 break;
1324 case LDAP_COMPARE_FALSE:
1325 rc = LDAP_COMPARE_TRUE;
1326 break;
1328 break;
1329 case LDAP_COMP_FILTER_ITEM:
1330 rc = test_comp_filter_item( syn, a, f->cf_ca );
1331 break;
1332 default:
1333 rc = LDAP_PROTOCOL_ERROR;
1336 return( rc );
1339 static void
1340 free_comp_filter_list( ComponentFilter* f )
1342 ComponentFilter* tmp;
1343 for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1344 free_comp_filter( tmp );
1348 static void
1349 free_comp_filter( ComponentFilter* f )
1351 if ( !f ) {
1352 Debug( LDAP_DEBUG_FILTER,
1353 "free_comp_filter: Invalid filter so failed to release memory\n",
1354 0, 0, 0 );
1355 return;
1357 switch ( f->cf_choice ) {
1358 case LDAP_COMP_FILTER_AND:
1359 case LDAP_COMP_FILTER_OR:
1360 free_comp_filter_list( f->cf_any );
1361 break;
1362 case LDAP_COMP_FILTER_NOT:
1363 free_comp_filter( f->cf_any );
1364 break;
1365 case LDAP_COMP_FILTER_ITEM:
1366 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1367 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1369 break;
1370 default:
1371 break;
1375 void
1376 component_free( ComponentFilter *f ) {
1377 free_comp_filter( f );
1380 void
1381 free_ComponentData( Attribute *a ) {
1382 if ( a->a_comp_data->cd_mem_op )
1383 component_destructor( a->a_comp_data->cd_mem_op );
1384 free ( a->a_comp_data );
1385 a->a_comp_data = NULL;
1387 #endif