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
componentCertificateValidate(Syntax * syntax,struct berval * val)73 componentCertificateValidate(
74           Syntax *syntax,
75           struct berval *val )
76 {
77           return LDAP_SUCCESS;
78 }
79 
80 int
componentFilterValidate(Syntax * syntax,struct berval * val)81 componentFilterValidate(
82           Syntax *syntax,
83           struct berval *val )
84 {
85           return LDAP_SUCCESS;
86 }
87 
88 int
allComponentsValidate(Syntax * syntax,struct berval * val)89 allComponentsValidate(
90           Syntax *syntax,
91           struct berval *val )
92 {
93           return LDAP_SUCCESS;
94 }
95 
96 int
componentFilterMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
directoryComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
allComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
slapd_ber2cav(struct berval * bv,ComponentAssertionValue * cav)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*
dup_comp_ref(Operation * op,ComponentReference * cr)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
dup_comp_filter_list(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)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
get_len_of_next_assert_value(struct berval * bv,char separator)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
dup_comp_filter_item(Operation * op,struct berval * assert_bv,ComponentAssertion * in_ca,ComponentAssertion ** out_ca)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
dup_comp_filter(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)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
get_aliased_filter_aa(Operation * op,AttributeAssertion * a_assert,AttributeAliasing * aa,const char ** text)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
get_aliased_filter(Operation * op,MatchingRuleAssertion * ma,AttributeAliasing * aa,const char ** text)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
get_comp_filter(Operation * op,struct berval * bv,ComponentFilter ** filt,const char ** text)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
eat_whsp(ComponentAssertionValue * cav)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
cav_cur_len(ComponentAssertionValue * cav)369 cav_cur_len( ComponentAssertionValue* cav )
370 {
371           return cav->cav_end - cav->cav_ptr;
372 }
373 
374 static ber_tag_t
comp_first_element(ComponentAssertionValue * cav)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
comp_next_element(ComponentAssertionValue * cav)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
get_comp_filter_list(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** f,const char ** text)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
get_componentId(Operation * op,ComponentAssertionValue * cav,ComponentId ** cid,const char ** text)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
peek_componentId_type(ComponentAssertionValue * cav)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
comp_next_id(ComponentAssertionValue * cav)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
get_component_reference(Operation * op,ComponentAssertionValue * cav,ComponentReference ** cr,const char ** text)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
insert_component_reference(ComponentReference * cr,ComponentReference ** cr_list)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
is_component_reference(char * attr)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
extract_component_reference(char * attr,ComponentReference ** cr)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
get_ca_use_default(Operation * op,ComponentAssertionValue * cav,int * ca_use_def,const char ** text)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
get_matching_rule(Operation * op,ComponentAssertionValue * cav,MatchingRule ** mr,const char ** text)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
get_GSER_value(ComponentAssertionValue * cav,struct berval * bv)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
get_matching_value(Operation * op,ComponentAssertion * ca,ComponentAssertionValue * cav,struct berval * bv,const char ** text)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
peek_cav_str(ComponentAssertionValue * cav,char * str)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
strip_cav_str(ComponentAssertionValue * cav,char * str)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
strip_cav_tag(ComponentAssertionValue * cav)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
get_item(Operation * op,ComponentAssertionValue * cav,ComponentAssertion ** ca,const char ** text)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
parse_comp_filter(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** filt,const char ** text)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
test_comp_filter_and(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)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
test_comp_filter_or(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)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
csi_value_match(MatchingRule * mr,struct berval * bv_attr,struct berval * bv_assert)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
test_comp_filter_item(Syntax * syn,ComponentSyntaxInfo * csi_attr,ComponentAssertion * ca)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
test_comp_filter(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * f)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
free_comp_filter_list(ComponentFilter * f)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
free_comp_filter(ComponentFilter * f)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
component_free(ComponentFilter * f)1387 component_free( ComponentFilter *f ) {
1388           free_comp_filter( f );
1389 }
1390 
1391 void
free_ComponentData(Attribute * a)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