]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
aad1a41a08438da0a94d6f64d867378c879b823b
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/string.h>
14
15 #include "slap.h"
16
17 static int      get_filter_list(
18         Connection *conn,
19         BerElement *ber,
20         Filter **f,
21         struct berval *fstr,
22         const char **text );
23
24 static int      get_substring_filter(
25         Connection *conn,
26         BerElement *ber,
27         Filter *f,
28         struct berval *fstr,
29         const char **text );
30
31 static int filter_escape_value(
32         struct berval *in,
33         struct berval *out );
34
35 int
36 get_filter(
37         Connection *conn,
38         BerElement *ber,
39         Filter **filt,
40         struct berval *fstr,
41         const char **text )
42 {
43         ber_tag_t       tag;
44         ber_len_t       len;
45         int             err;
46         Filter          *f;
47         struct berval   ftmp = { 0, NULL };
48         struct berval escaped;
49
50 #ifdef NEW_LOGGING
51         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY, "get_filter: conn %d\n",
52                    conn->c_connid ));
53 #else
54         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
55 #endif
56         /*
57          * A filter looks like this coming in:
58          *      Filter ::= CHOICE {
59          *              and             [0]     SET OF Filter,
60          *              or              [1]     SET OF Filter,
61          *              not             [2]     Filter,
62          *              equalityMatch   [3]     AttributeValueAssertion,
63          *              substrings      [4]     SubstringFilter,
64          *              greaterOrEqual  [5]     AttributeValueAssertion,
65          *              lessOrEqual     [6]     AttributeValueAssertion,
66          *              present         [7]     AttributeType,,
67          *              approxMatch     [8]     AttributeValueAssertion
68          *              extensibleMatch [9] MatchingRuleAssertion
69          *      }
70          *
71          *      SubstringFilter ::= SEQUENCE {
72          *              type               AttributeType,
73          *              SEQUENCE OF CHOICE {
74          *                      initial          [0] IA5String,
75          *                      any              [1] IA5String,
76          *                      final            [2] IA5String
77          *              }
78          *      }
79          *
80      *  MatchingRuleAssertion ::= SEQUENCE {
81      *          matchingRule    [1] MatchingRuleId OPTIONAL,
82      *          type            [2] AttributeDescription OPTIONAL,
83      *          matchValue      [3] AssertionValue,
84      *          dnAttributes    [4] BOOLEAN DEFAULT FALSE
85          *      }
86          *
87          */
88
89         tag = ber_peek_tag( ber, &len );
90
91         if( tag == LBER_ERROR ) {
92                 *text = "error decoding filter";
93                 return SLAPD_DISCONNECT;
94         }
95
96         f = (Filter *) ch_malloc( sizeof(Filter) );
97         f->f_next = NULL;
98
99         err = LDAP_SUCCESS;
100         *fstr = ftmp;
101         f->f_choice = tag; 
102
103         switch ( f->f_choice ) {
104         case LDAP_FILTER_EQUALITY:
105 #ifdef NEW_LOGGING
106                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL2,
107                            "get_filter: conn %d  EQUALITY\n", conn->c_connid ));
108 #else
109                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
110 #endif
111                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY, text );
112                 if ( err != LDAP_SUCCESS ) {
113                         break;
114                 }
115
116                 assert( f->f_ava != NULL );
117
118                 filter_escape_value( &f->f_av_value, &escaped );
119
120                 fstr->bv_len = sizeof("(=)")-1
121                         + f->f_av_desc->ad_cname.bv_len
122                         + escaped.bv_len;
123
124                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
125
126                 sprintf( fstr->bv_val, "(%s=%s)",
127                         f->f_av_desc->ad_cname.bv_val,
128                     escaped.bv_val );
129
130                 ber_memfree( escaped.bv_val );
131                 break;
132
133         case LDAP_FILTER_SUBSTRINGS:
134 #ifdef NEW_LOGGING
135                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
136                            "get_filter: conn %d  SUBSTRINGS\n", conn->c_connid ));
137 #else
138                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
139 #endif
140                 err = get_substring_filter( conn, ber, f, fstr, text );
141                 break;
142
143         case LDAP_FILTER_GE:
144 #ifdef NEW_LOGGING
145                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
146                            "get_filter: conn %d  GE\n", conn->c_connid ));
147 #else
148                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
149 #endif
150                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
151                 if ( err != LDAP_SUCCESS ) {
152                         break;
153                 }
154
155                 filter_escape_value( &f->f_av_value, &escaped );
156
157                 fstr->bv_len = sizeof("(>=)")-1
158                         + f->f_av_desc->ad_cname.bv_len
159                         + escaped.bv_len;
160
161                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
162
163                 sprintf( fstr->bv_val, "(%s>=%s)",
164                         f->f_av_desc->ad_cname.bv_val,
165                     escaped.bv_val );
166
167                 ber_memfree( escaped.bv_val );
168                 break;
169
170         case LDAP_FILTER_LE:
171 #ifdef NEW_LOGGING
172                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
173                            "get_filter: conn %d  LE\n", conn->c_connid ));
174 #else
175                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
176 #endif
177                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
178                 if ( err != LDAP_SUCCESS ) {
179                         break;
180                 }
181
182
183                 filter_escape_value( &f->f_av_value, &escaped );
184
185                 fstr->bv_len = sizeof("(<=)")-1
186                         + f->f_av_desc->ad_cname.bv_len
187                         + escaped.bv_len;
188
189                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
190
191                 sprintf( fstr->bv_val, "(%s<=%s)",
192                         f->f_av_desc->ad_cname.bv_val,
193                     escaped.bv_val );
194
195                 ber_memfree( escaped.bv_val );
196                 break;
197
198         case LDAP_FILTER_PRESENT: {
199                 struct berval type;
200
201 #ifdef NEW_LOGGING
202                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
203                            "get_filter: conn %d PRESENT\n", conn->c_connid ));
204 #else
205                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
206 #endif
207                 if ( ber_scanf( ber, "o", &type ) == LBER_ERROR ) {
208                         err = SLAPD_DISCONNECT;
209                         *text = "error decoding filter";
210                         break;
211                 }
212
213                 f->f_desc = NULL;
214                 err = slap_bv2ad( &type, &f->f_desc, text );
215
216                 if( err != LDAP_SUCCESS ) {
217                         /* unrecognized attribute description or other error */
218                         f->f_choice = SLAPD_FILTER_COMPUTED;
219                         f->f_result = LDAP_COMPARE_FALSE;
220                         ber_str2bv("(unrecognized=*)",
221                                 sizeof("(unrecognized=*)")-1, 1, fstr);
222                         ch_free( type.bv_val );
223                         err = LDAP_SUCCESS;
224                         break;
225                 }
226
227                 ch_free( type.bv_val );
228
229                 fstr->bv_len = sizeof("(=*)") - 1 
230                         + f->f_desc->ad_cname.bv_len;
231                 fstr->bv_val = ch_malloc( fstr->bv_len + 1);
232                 sprintf( fstr->bv_val, "(%s=*)",
233                         f->f_desc->ad_cname.bv_val );
234
235                 } break;
236
237         case LDAP_FILTER_APPROX:
238 #ifdef NEW_LOGGING
239                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
240                            "get_filter: conn %d  APPROX\n", conn->c_connid ));
241 #else
242                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
243 #endif
244                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY_APPROX, text );
245                 if ( err != LDAP_SUCCESS ) {
246                         break;
247                 }
248
249                 filter_escape_value( &f->f_av_value, &escaped );
250
251                 fstr->bv_len = sizeof("(~=)") - 1
252                         + f->f_av_desc->ad_cname.bv_len
253                         + escaped.bv_len;
254                 fstr->bv_val = ch_malloc( fstr->bv_len + 1);
255
256                 sprintf( fstr->bv_val, "(%s~=%s)",
257                         f->f_av_desc->ad_cname.bv_val,
258                     escaped.bv_val );
259
260                 ber_memfree( escaped.bv_val );
261                 break;
262
263         case LDAP_FILTER_AND:
264 #ifdef NEW_LOGGING
265                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
266                            "get_filter: conn %d  AND\n", conn->c_connid ));
267 #else
268                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
269 #endif
270                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
271                 if ( err != LDAP_SUCCESS ) {
272                         break;
273                 }
274                 fstr->bv_len = sizeof("(&)") - 1 + ftmp.bv_len;
275                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
276                 sprintf( fstr->bv_val, "(&%s)",
277                         ftmp.bv_len ? ftmp.bv_val : "" );
278                 break;
279
280         case LDAP_FILTER_OR:
281 #ifdef NEW_LOGGING
282                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
283                            "get_filter: conn %d  OR\n", conn->c_connid  ));
284 #else
285                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
286 #endif
287                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
288                 if ( err != LDAP_SUCCESS ) {
289                         break;
290                 }
291                 fstr->bv_len = sizeof("(|)") - 1 + ftmp.bv_len;
292                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
293                 sprintf( fstr->bv_val, "(|%s)",
294                         ftmp.bv_len ? ftmp.bv_val : "" );
295                 break;
296
297         case LDAP_FILTER_NOT:
298 #ifdef NEW_LOGGING
299                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
300                            "get_filter: conn %d  NOT\n", conn->c_connid ));
301 #else
302                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
303 #endif
304                 (void) ber_skip_tag( ber, &len );
305                 err = get_filter( conn, ber, &f->f_not, &ftmp, text );
306                 if ( err != LDAP_SUCCESS ) {
307                         break;
308                 }
309                 fstr->bv_len = sizeof("(!)") - 1 + ftmp.bv_len;
310                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
311                 sprintf( fstr->bv_val, "(!%s)",
312                         ftmp.bv_len ? ftmp.bv_val : "" );
313                 break;
314
315         case LDAP_FILTER_EXT:
316 #ifdef NEW_LOGGING
317                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
318                            "get_filter: conn %d  EXTENSIBLE\n", conn->c_connid ));
319 #else
320                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
321 #endif
322
323                 err = get_mra( ber, &f->f_mra, text );
324                 if ( err != LDAP_SUCCESS ) {
325                         break;
326                 }
327
328                 assert( f->f_mra != NULL );
329
330                 filter_escape_value( &f->f_mr_value, &escaped );
331
332                 fstr->bv_len = sizeof("(:dn::=)") - 1
333                         + (f->f_mr_desc ? f->f_mr_desc->ad_cname.bv_len : 0)
334                         + f->f_mr_rule_text.bv_len
335                         + escaped.bv_len;
336
337                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
338                 sprintf( fstr->bv_val, "(%s%s%s%s:=%s)",
339                          (f->f_mr_desc ? f->f_mr_desc->ad_cname.bv_val : ""),
340                          (f->f_mr_dnattrs ? ":dn" : ""),
341                          (f->f_mr_rule_text.bv_len ? ":" : ""),
342                          (f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : ""),
343                          escaped.bv_val );
344
345                 ber_memfree( escaped.bv_val );
346                 break;
347
348         default:
349                 (void) ber_scanf( ber, "x" ); /* skip the element */
350 #ifdef NEW_LOGGING
351                 LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
352                            "get_filter: conn %d unknown filter type=%lu\n",
353                            conn->c_connid, f->f_choice ));
354 #else
355                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
356                        f->f_choice, 0, 0 );
357 #endif
358                 f->f_choice = SLAPD_FILTER_COMPUTED;
359                 f->f_result = SLAPD_COMPARE_UNDEFINED;
360                 ber_str2bv( "(undefined)", sizeof("(undefined)") - 1,
361                         1, fstr );
362                 break;
363         }
364
365         free( ftmp.bv_val );
366
367         if ( err != LDAP_SUCCESS ) {
368                 if ( fstr->bv_val != NULL ) {
369                         free( fstr->bv_val );
370                 }
371
372                 if( err != SLAPD_DISCONNECT ) {
373                         /* ignore error */
374                         f->f_choice = SLAPD_FILTER_COMPUTED;
375                         f->f_result = SLAPD_COMPARE_UNDEFINED;
376                         ber_str2bv( "(badfilter)", sizeof("(badfilter)") - 1,
377                                 1, fstr );
378                         err = LDAP_SUCCESS;
379                         *filt = f;
380
381                 } else {
382                         free(f);
383                 }
384         } else {
385                 *filt = f;
386         }
387
388 #ifdef NEW_LOGGING
389         LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL2,
390                 "get_filter: conn %d exit\n", conn->c_connid ));
391 #else
392         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
393 #endif
394         return( err );
395 }
396
397 static int
398 get_filter_list( Connection *conn, BerElement *ber,
399         Filter **f, struct berval *fstr,
400         const char **text )
401 {
402         Filter          **new;
403         int             err;
404         ber_tag_t       tag;
405         ber_len_t       len;
406         char            *last;
407         struct berval   ftmp;
408
409 #ifdef NEW_LOGGING
410         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
411                    "get_filter_list: conn %d start\n", conn->c_connid ));
412 #else
413         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
414 #endif
415         new = f;
416         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
417             tag = ber_next_element( ber, &len, last ) )
418         {
419                 err = get_filter( conn, ber, new, &ftmp, text );
420                 if ( err != LDAP_SUCCESS )
421                         return( err );
422
423                 if ( !fstr->bv_len ) {
424                         *fstr = ftmp;
425                 } else {
426                         int i = fstr->bv_len;
427                         fstr->bv_len += ftmp.bv_len;
428                         fstr->bv_val = ch_realloc( fstr->bv_val,
429                                 fstr->bv_len + 1 );
430                         strcpy( fstr->bv_val+i, ftmp.bv_val );
431                         free( ftmp.bv_val );
432                 }
433                 new = &(*new)->f_next;
434         }
435         *new = NULL;
436
437 #ifdef NEW_LOGGING
438         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
439                    "get_filter_list: conn %d exit\n", conn->c_connid ));
440 #else
441         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
442 #endif
443         return( LDAP_SUCCESS );
444 }
445
446 static int
447 get_substring_filter(
448     Connection  *conn,
449     BerElement  *ber,
450     Filter      *f,
451     struct berval       *fstr,
452         const char      **text
453 )
454 {
455         ber_tag_t       tag;
456         ber_len_t       len;
457         ber_tag_t       rc;
458         struct berval value;
459         struct berval escaped;
460         char            *last;
461         struct berval bv;
462         *text = "error decoding filter";
463
464 #ifdef NEW_LOGGING
465         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
466                    "get_substring_filter: conn %d  begin\n", conn->c_connid ));
467 #else
468         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
469 #endif
470         if ( ber_scanf( ber, "{o" /*}*/, &bv ) == LBER_ERROR ) {
471                 return SLAPD_DISCONNECT;
472         }
473
474         f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
475         f->f_sub_desc = NULL;
476         rc = slap_bv2ad( &bv, &f->f_sub_desc, text );
477
478         ch_free( bv.bv_val );
479
480         if( rc != LDAP_SUCCESS ) {
481                 text = NULL;
482                 ch_free( f->f_sub );
483                 f->f_choice = SLAPD_FILTER_COMPUTED;
484                 f->f_result = SLAPD_COMPARE_UNDEFINED;
485                 ber_str2bv( "(undefined)", sizeof("(undefined)")-1, 1, fstr );
486                 return LDAP_SUCCESS;
487         }
488
489         f->f_sub_initial.bv_val = NULL;
490         f->f_sub_any = NULL;
491         f->f_sub_final.bv_val = NULL;
492
493         fstr->bv_len = sizeof("(=" /*)*/) - 1 +
494                 f->f_sub_desc->ad_cname.bv_len;
495         fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
496         sprintf( fstr->bv_val, "(%s=" /*)*/, f->f_sub_desc->ad_cname.bv_val );
497
498         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
499             tag = ber_next_element( ber, &len, last ) )
500         {
501                 unsigned usage;
502
503                 rc = ber_scanf( ber, "o", &value );
504                 if ( rc == LBER_ERROR ) {
505                         rc = SLAPD_DISCONNECT;
506                         goto return_error;
507                 }
508
509                 if ( value.bv_val == NULL || value.bv_len == 0 ) {
510                         rc = LDAP_INVALID_SYNTAX;
511                         goto return_error;
512                 } 
513
514                 switch ( tag ) {
515                 case LDAP_SUBSTRING_INITIAL:
516                         usage = SLAP_MR_SUBSTR_INITIAL;
517                         break;
518
519                 case LDAP_SUBSTRING_ANY:
520                         usage = SLAP_MR_SUBSTR_ANY;
521                         break;
522
523                 case LDAP_SUBSTRING_FINAL:
524                         usage = SLAP_MR_SUBSTR_FINAL;
525                         break;
526
527                 default:
528                         rc = LDAP_PROTOCOL_ERROR;
529
530 #ifdef NEW_LOGGING
531                         LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
532                                    "get_filter_substring: conn %d  unknown substring choice=%ld\n",
533                                    conn->c_connid, (long)tag ));
534 #else
535                         Debug( LDAP_DEBUG_FILTER,
536                                 "  unknown substring choice=%ld\n",
537                                 (long) tag, 0, 0 );
538 #endif
539                         free( value.bv_val );
540                         goto return_error;
541                 }
542
543                 rc = value_normalize( f->f_sub_desc, usage, &value, &bv, text );
544                 free( value.bv_val );
545
546                 if( rc != LDAP_SUCCESS ) {
547                         goto return_error;
548                 }
549
550                 value = bv;
551
552                 rc = LDAP_PROTOCOL_ERROR;
553
554                 switch ( tag ) {
555                 case LDAP_SUBSTRING_INITIAL:
556 #ifdef NEW_LOGGING
557                         LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
558                                    "get_substring_filter: conn %d  INITIAL\n",
559                                    conn->c_connid ));
560 #else
561                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
562 #endif
563
564                         if ( f->f_sub_initial.bv_val != NULL
565                                 || f->f_sub_any != NULL 
566                                 || f->f_sub_final.bv_val != NULL )
567                         {
568                                 free( value.bv_val );
569                                 goto return_error;
570                         }
571
572                         f->f_sub_initial = value;
573
574                         if( fstr->bv_val ) {
575                                 int i = fstr->bv_len;
576                                 filter_escape_value( &value, &escaped );
577                                 fstr->bv_len += escaped.bv_len;
578                                 fstr->bv_val = ch_realloc( fstr->bv_val,
579                                         fstr->bv_len + 1 );
580                                 strcpy( fstr->bv_val+i, escaped.bv_val );
581                                 ber_memfree( escaped.bv_val );
582                         }
583                         break;
584
585                 case LDAP_SUBSTRING_ANY:
586 #ifdef NEW_LOGGING
587                         LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
588                                    "get_substring_filter: conn %d  ANY\n",
589                                    conn->c_connid ));
590 #else
591                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
592 #endif
593
594                         if ( f->f_sub_final.bv_val != NULL ) {
595                                 free( value.bv_val );
596                                 goto return_error;
597                         }
598
599                         bvarray_add( &f->f_sub_any, &value );
600
601                         if( fstr->bv_val ) {
602                                 int i = fstr->bv_len;
603                                 filter_escape_value( &value, &escaped );
604                                 fstr->bv_len += escaped.bv_len + 2;
605                                 fstr->bv_val = ch_realloc( fstr->bv_val,
606                                         fstr->bv_len + 1 );
607                                 strcpy( fstr->bv_val+i, "*" );
608                                 strcpy( fstr->bv_val+i+1, escaped.bv_val );
609                                 ber_memfree( escaped.bv_val );
610                         }
611                         break;
612
613                 case LDAP_SUBSTRING_FINAL:
614 #ifdef NEW_LOGGING
615                         LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
616                                    "get_substring_filter: conn %d  FINAL\n",
617                                    conn->c_connid ));
618 #else
619                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
620 #endif
621
622                         if ( f->f_sub_final.bv_val != NULL ) {
623                                 free( value.bv_val );
624                                 goto return_error;
625                         }
626
627                         f->f_sub_final = value;
628
629                         if( fstr->bv_val ) {
630                                 int i = fstr->bv_len;
631                                 filter_escape_value( &value, &escaped );
632                                 fstr->bv_len += escaped.bv_len + 2;
633                                 fstr->bv_val = ch_realloc( fstr->bv_val,
634                                         fstr->bv_len + 1 );
635                                 strcpy( fstr->bv_val+i, "*" );
636                                 strcpy( fstr->bv_val+i+1, escaped.bv_val );
637                                 ber_memfree( escaped.bv_val );
638                         }
639                         break;
640
641                 default:
642 #ifdef NEW_LOGGING
643                         LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
644                                    "get_substring_filter: conn %d  unknown substring type %ld\n",
645                                    conn->c_connid, (long)tag ));
646 #else
647                         Debug( LDAP_DEBUG_FILTER,
648                                 "  unknown substring type=%ld\n",
649                                 (long) tag, 0, 0 );
650 #endif
651
652                         free( value.bv_val );
653
654 return_error:
655 #ifdef NEW_LOGGING
656                         LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
657                                    "get_substring_filter: conn %d  error %ld\n",
658                                    conn->c_connid, (long)rc ));
659 #else
660                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
661                                 (long) rc, 0, 0 );
662 #endif
663                         if( fstr->bv_val ) {
664                                 free( fstr->bv_val );
665                                 fstr->bv_val = NULL;
666                                 fstr->bv_len = 0;
667                         }
668
669                         free( f->f_sub_initial.bv_val );
670                         bvarray_free( f->f_sub_any );
671                         free( f->f_sub_final.bv_val );
672                         ch_free( f->f_sub );
673                         return rc;
674                 }
675         }
676
677         if( fstr->bv_val ) {
678                 int i = fstr->bv_len;
679                 fstr->bv_len += 3;
680                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 3 );
681                 if ( f->f_sub_final.bv_val == NULL ) {
682                         strcpy( fstr->bv_val+i, "*" );
683                         i++;
684                 }
685                 strcpy( fstr->bv_val+i, /*(*/ ")" );
686         }
687
688 #ifdef NEW_LOGGING
689         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
690                    "get_substring_filter: conn %d exit\n", conn->c_connid ));
691 #else
692         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
693 #endif
694         return( LDAP_SUCCESS );
695 }
696
697 void
698 filter_free( Filter *f )
699 {
700         Filter  *p, *next;
701
702         if ( f == NULL ) {
703                 return;
704         }
705
706         switch ( f->f_choice ) {
707         case LDAP_FILTER_PRESENT:
708                 break;
709
710         case LDAP_FILTER_EQUALITY:
711         case LDAP_FILTER_GE:
712         case LDAP_FILTER_LE:
713         case LDAP_FILTER_APPROX:
714                 ava_free( f->f_ava, 1 );
715                 break;
716
717         case LDAP_FILTER_SUBSTRINGS:
718                 if ( f->f_sub_initial.bv_val != NULL ) {
719                         free( f->f_sub_initial.bv_val );
720                 }
721                 bvarray_free( f->f_sub_any );
722                 if ( f->f_sub_final.bv_val != NULL ) {
723                         free( f->f_sub_final.bv_val );
724                 }
725                 ch_free( f->f_sub );
726                 break;
727
728         case LDAP_FILTER_AND:
729         case LDAP_FILTER_OR:
730         case LDAP_FILTER_NOT:
731                 for ( p = f->f_list; p != NULL; p = next ) {
732                         next = p->f_next;
733                         filter_free( p );
734                 }
735                 break;
736
737         case SLAPD_FILTER_COMPUTED:
738                 break;
739
740         default:
741 #ifdef NEW_LOGGING
742                 LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
743                            "filter_free: unknown filter type %lu\n", f->f_choice ));
744 #else
745                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
746                        f->f_choice, 0, 0 );
747 #endif
748                 break;
749         }
750
751         free( f );
752 }
753
754 #ifdef LDAP_DEBUG
755 void
756 filter_print( Filter *f )
757 {
758         int     i;
759         Filter  *p;
760         struct berval escaped;
761
762         if ( f == NULL ) {
763                 fprintf( stderr, "No filter!" );
764         }
765
766         switch ( f->f_choice ) {
767         case LDAP_FILTER_EQUALITY:
768                 filter_escape_value( &f->f_av_value, &escaped );
769                 fprintf( stderr, "(%s=%s)",
770                         f->f_av_desc->ad_cname.bv_val,
771                     escaped.bv_val );
772                 ber_memfree( escaped.bv_val );
773                 break;
774
775         case LDAP_FILTER_GE:
776                 filter_escape_value( &f->f_av_value, &escaped );
777                 fprintf( stderr, "(%s>=%s)",
778                         f->f_av_desc->ad_cname.bv_val,
779                     escaped.bv_val );
780                 ber_memfree( escaped.bv_val );
781                 break;
782
783         case LDAP_FILTER_LE:
784                 filter_escape_value( &f->f_av_value, &escaped );
785                 fprintf( stderr, "(%s<=%s)",
786                         f->f_ava->aa_desc->ad_cname.bv_val,
787                     escaped.bv_val );
788                 ber_memfree( escaped.bv_val );
789                 break;
790
791         case LDAP_FILTER_APPROX:
792                 filter_escape_value( &f->f_av_value, &escaped );
793                 fprintf( stderr, "(%s~=%s)",
794                         f->f_ava->aa_desc->ad_cname.bv_val,
795                     escaped.bv_val );
796                 ber_memfree( escaped.bv_val );
797                 break;
798
799         case LDAP_FILTER_SUBSTRINGS:
800                 fprintf( stderr, "(%s=" /*)*/,
801                         f->f_sub_desc->ad_cname.bv_val );
802                 if ( f->f_sub_initial.bv_val != NULL ) {
803                         filter_escape_value( &f->f_sub_initial, &escaped );
804                         fprintf( stderr, "%s",
805                                 escaped.bv_val );
806                         ber_memfree( escaped.bv_val );
807                 }
808                 if ( f->f_sub_any != NULL ) {
809                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
810                                 filter_escape_value( &f->f_sub_any[i], &escaped );
811                                 fprintf( stderr, "*%s",
812                                         escaped.bv_val );
813                                 ber_memfree( escaped.bv_val );
814                         }
815                 }
816                 if ( f->f_sub_final.bv_val != NULL ) {
817                         filter_escape_value( &f->f_sub_final, &escaped );
818                         fprintf( stderr,
819                                 "*%s", escaped.bv_val );
820                         ber_memfree( escaped.bv_val );
821                 }
822                 fprintf( stderr, /*(*/ ")" );
823                 break;
824
825         case LDAP_FILTER_PRESENT:
826                 fprintf( stderr, "(%s=*)",
827                         f->f_desc->ad_cname.bv_val );
828                 break;
829
830         case LDAP_FILTER_AND:
831         case LDAP_FILTER_OR:
832         case LDAP_FILTER_NOT:
833                 fprintf( stderr, "(%c" /*)*/,
834                         f->f_choice == LDAP_FILTER_AND ? '&' :
835                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
836                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
837                         filter_print( p );
838                 }
839                 fprintf( stderr, /*(*/ ")" );
840                 break;
841
842         case SLAPD_FILTER_COMPUTED:
843                 fprintf( stderr, "(?=%s)",
844                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
845                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
846                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
847                         "error" );
848                 break;
849
850         default:
851                 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
852                 break;
853         }
854 }
855
856 #endif /* ldap_debug */
857
858 static int filter_escape_value(
859         struct berval *in,
860         struct berval *out )
861 {
862         ber_len_t i;
863         assert( in );
864         assert( out );
865
866         out->bv_val = (char *) ch_malloc( ( in->bv_len * 3 ) + 1 );
867         out->bv_len = 0;
868
869         for( i=0; i < in->bv_len ; i++ ) {
870                 if( FILTER_ESCAPE(in->bv_val[i]) ) {
871                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_CHAR;
872                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_HI( in->bv_val[i] );
873                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_LO( in->bv_val[i] );
874                 } else {
875                         out->bv_val[out->bv_len++] = in->bv_val[i];
876                 }
877         }
878
879         out->bv_val[out->bv_len] = '\0';
880         return LDAP_SUCCESS;
881 }