]> git.sur5r.net Git - openldap/blob - servers/slapd/filterentry.c
Fix referral handling bug
[openldap] / servers / slapd / filterentry.c
1 /* filterentry.c - apply a filter to an entry */
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
16 #include "slap.h"
17
18 static int      test_filter_and( Backend *be,
19         Connection *conn, Operation *op,
20         Entry *e, Filter *flist );
21 static int      test_filter_or( Backend *be,
22         Connection *conn, Operation *op,
23         Entry *e, Filter *flist );
24 static int      test_substrings_filter( Backend *be,
25         Connection *conn, Operation *op,
26         Entry *e, Filter *f);
27 static int      test_ava_filter( Backend *be,
28         Connection *conn, Operation *op,
29         Entry *e, AttributeAssertion *ava, int type );
30 static int      test_mra_filter( Backend *be,
31         Connection *conn, Operation *op,
32         Entry *e, MatchingRuleAssertion *mra );
33 static int      test_presence_filter( Backend *be,
34         Connection *conn, Operation *op,
35         Entry *e, AttributeDescription *desc );
36
37
38 /*
39  * test_filter - test a filter against a single entry.
40  * returns:
41  *              LDAP_COMPARE_TRUE               filter matched
42  *              LDAP_COMPARE_FALSE              filter did not match
43  *              SLAPD_COMPARE_UNDEFINED filter is undefined
44  *      or an ldap result code indicating error
45  */
46
47 int
48 test_filter(
49     Backend     *be,
50     Connection  *conn,
51     Operation   *op,
52     Entry       *e,
53     Filter      *f
54 )
55 {
56         int     rc;
57
58 #ifdef NEW_LOGGING
59         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
60                    "test_filter: begin\n" ));
61 #else
62         Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
63 #endif
64
65
66         switch ( f->f_choice ) {
67         case SLAPD_FILTER_COMPUTED:
68 #ifdef NEW_LOGGING
69                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
70                            "test_filter:   COMPUTED %s (%d)\n",
71                            f->f_result == LDAP_COMPARE_FALSE ? "false" :
72                            f->f_result == LDAP_COMPARE_TRUE      ? "true"  :
73                            f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
74                            "error",
75                            f->f_result ));
76 #else
77                 Debug( LDAP_DEBUG_FILTER, "    COMPUTED %s (%d)\n",
78                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
79                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
80                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
81                         f->f_result, 0 );
82 #endif
83
84                 rc = f->f_result;
85                 break;
86
87         case LDAP_FILTER_EQUALITY:
88 #ifdef NEW_LOGGING
89                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
90                            "test_filter:   EQUALITY\n" ));
91 #else
92                 Debug( LDAP_DEBUG_FILTER, "    EQUALITY\n", 0, 0, 0 );
93 #endif
94
95                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
96                     LDAP_FILTER_EQUALITY );
97                 break;
98
99         case LDAP_FILTER_SUBSTRINGS:
100 #ifdef NEW_LOGGING
101                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
102                            "test_filter  SUBSTRINGS\n" ));
103 #else
104                 Debug( LDAP_DEBUG_FILTER, "    SUBSTRINGS\n", 0, 0, 0 );
105 #endif
106
107                 rc = test_substrings_filter( be, conn, op, e, f );
108                 break;
109
110         case LDAP_FILTER_GE:
111                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
112                     LDAP_FILTER_GE );
113                 break;
114
115         case LDAP_FILTER_LE:
116                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
117                     LDAP_FILTER_LE );
118                 break;
119
120         case LDAP_FILTER_PRESENT:
121 #ifdef NEW_LOGGING
122                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
123                            "test_filter:        PRESENT\n" ));
124 #else
125                 Debug( LDAP_DEBUG_FILTER, "    PRESENT\n", 0, 0, 0 );
126 #endif
127
128                 rc = test_presence_filter( be, conn, op, e, f->f_desc );
129                 break;
130
131         case LDAP_FILTER_APPROX:
132 #ifdef NEW_LOGGING
133                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
134                            "test_filter: APPROX\n" ));
135 #else
136                 Debug( LDAP_DEBUG_FILTER, "    APPROX\n", 0, 0, 0 );
137 #endif
138                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
139                     LDAP_FILTER_APPROX );
140                 break;
141
142         case LDAP_FILTER_AND:
143 #ifdef NEW_LOGGING
144                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
145                            "test_filter:  AND\n" ));
146 #else
147                 Debug( LDAP_DEBUG_FILTER, "    AND\n", 0, 0, 0 );
148 #endif
149
150                 rc = test_filter_and( be, conn, op, e, f->f_and );
151                 break;
152
153         case LDAP_FILTER_OR:
154 #ifdef NEW_LOGGING
155                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
156                            "test_filter:        OR\n" ));
157 #else
158                 Debug( LDAP_DEBUG_FILTER, "    OR\n", 0, 0, 0 );
159 #endif
160
161                 rc = test_filter_or( be, conn, op, e, f->f_or );
162                 break;
163
164         case LDAP_FILTER_NOT:
165 #ifdef NEW_LOGGING
166                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
167                            "test_filter:        NOT\n" ));
168 #else
169                 Debug( LDAP_DEBUG_FILTER, "    NOT\n", 0, 0, 0 );
170 #endif
171
172                 rc = test_filter( be, conn, op, e, f->f_not );
173
174                 switch( rc ) {
175                 case LDAP_COMPARE_TRUE:
176                         rc = LDAP_COMPARE_FALSE;
177                         break;
178                 case LDAP_COMPARE_FALSE:
179                         rc = LDAP_COMPARE_TRUE;
180                         break;
181                 }
182                 break;
183
184 #ifdef SLAPD_EXT_FILTERS
185         case LDAP_FILTER_EXT:
186 #ifdef NEW_LOGGING
187                 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
188                            "test_filter:        EXT\n" ));
189 #else
190                 Debug( LDAP_DEBUG_FILTER, "    EXT\n", 0, 0, 0 );
191 #endif
192
193                 rc = test_mra_filter( be, conn, op, e, f->f_mra );
194                 break;
195 #endif
196
197         default:
198 #ifdef NEW_LOGGING
199                 LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
200                            "test_filter:  unknown filter type %lu\n", 
201                        f->f_choice ));
202 #else
203                 Debug( LDAP_DEBUG_ANY, "    unknown filter type %lu\n",
204                     f->f_choice, 0, 0 );
205 #endif
206
207                 rc = LDAP_PROTOCOL_ERROR;
208         }
209
210 #ifdef NEW_LOGGING
211         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
212                    "test_filter:  return=%d\n", rc ));
213 #else
214         Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
215 #endif
216
217         return( rc );
218 }
219
220
221 static int
222 test_ava_filter(
223     Backend     *be,
224     Connection  *conn,
225     Operation   *op,
226     Entry       *e,
227         AttributeAssertion *ava,
228     int         type
229 )
230 {
231         int             i;
232         Attribute       *a;
233
234         if ( be != NULL && ! access_allowed( be, conn, op, e,
235                 ava->aa_desc, ava->aa_value, ACL_SEARCH ) )
236         {
237                 return LDAP_INSUFFICIENT_ACCESS;
238         }
239
240         for(a = attrs_find( e->e_attrs, ava->aa_desc );
241                 a != NULL;
242                 a = attrs_find( a->a_next, ava->aa_desc ) )
243         {
244                 MatchingRule *mr;
245
246                 switch ( type ) {
247                 case LDAP_FILTER_APPROX:
248                         mr = a->a_desc->ad_type->sat_approx;
249                         if( mr != NULL ) break;
250
251                         /* use EQUALITY matching rule if no APPROX rule */
252
253                 case LDAP_FILTER_EQUALITY:
254                         mr = a->a_desc->ad_type->sat_equality;
255                         break;
256
257                 case LDAP_FILTER_GE:
258                 case LDAP_FILTER_LE:
259                         mr = a->a_desc->ad_type->sat_ordering;
260                         break;
261
262                 default:
263                         mr = NULL;
264                 }
265
266                 if( mr == NULL ) {
267                         continue;
268                 }
269
270                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
271                         int ret;
272                         int rc;
273                         const char *text;
274
275                         rc = value_match( &ret, a->a_desc, mr, 0,
276                                 a->a_vals[i], ava->aa_value,
277                                 &text );
278
279                         if( rc != LDAP_SUCCESS ) {
280                                 return rc;
281                         }
282
283                         switch ( type ) {
284                         case LDAP_FILTER_EQUALITY:
285                         case LDAP_FILTER_APPROX:
286                                 if ( ret == 0 ) {
287                                         return LDAP_COMPARE_TRUE;
288                                 }
289                                 break;
290
291                         case LDAP_FILTER_GE:
292                                 if ( ret >= 0 ) {
293                                         return LDAP_COMPARE_TRUE;
294                                 }
295                                 break;
296
297                         case LDAP_FILTER_LE:
298                                 if ( ret <= 0 ) {
299                                         return LDAP_COMPARE_TRUE;
300                                 }
301                                 break;
302                         }
303                 }
304         }
305
306         return( LDAP_COMPARE_FALSE );
307 }
308
309
310 static int
311 test_presence_filter(
312     Backend     *be,
313     Connection  *conn,
314     Operation   *op,
315     Entry       *e,
316         AttributeDescription *desc
317 )
318 {
319         if ( be != NULL && ! access_allowed( be, conn, op, e,
320                 desc, NULL, ACL_SEARCH ) )
321         {
322                 return LDAP_INSUFFICIENT_ACCESS;
323         }
324
325         return attrs_find( e->e_attrs, desc ) != NULL
326                 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
327 }
328
329
330 static int
331 test_filter_and(
332     Backend     *be,
333     Connection  *conn,
334     Operation   *op,
335     Entry       *e,
336     Filter      *flist
337 )
338 {
339         Filter  *f;
340         int rtn = LDAP_COMPARE_TRUE;
341
342 #ifdef NEW_LOGGING
343         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
344                    "test_filter_and: begin\n" ));
345 #else
346         Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
347 #endif
348
349
350         for ( f = flist; f != NULL; f = f->f_next ) {
351                 int rc = test_filter( be, conn, op, e, f );
352
353                 if ( rc == LDAP_COMPARE_FALSE ) {
354                         rtn = LDAP_COMPARE_FALSE;
355                         break;
356                 }
357                 if ( rc != LDAP_COMPARE_TRUE ) {
358                         rtn = rc;
359                 }
360         }
361
362 #ifdef NEW_LOGGING
363         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
364                    "test_filter_and:  rc=%d\n", rtn ));
365 #else
366         Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
367 #endif
368
369         return rtn;
370 }
371
372 static int
373 test_filter_or(
374     Backend     *be,
375     Connection  *conn,
376     Operation   *op,
377     Entry       *e,
378     Filter      *flist
379 )
380 {
381         Filter  *f;
382         int rtn = LDAP_COMPARE_FALSE;
383
384 #ifdef NEW_LOGGING
385         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
386                    "test_filter_or: begin\n" ));
387 #else
388         Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
389 #endif
390
391
392         for ( f = flist; f != NULL; f = f->f_next ) {
393                 int rc = test_filter( be, conn, op, e, f );
394
395                 if ( rc == LDAP_COMPARE_TRUE ) {
396                         rtn = LDAP_COMPARE_TRUE;
397                         break;
398                 }
399                 if ( rc != LDAP_COMPARE_TRUE ) {
400                         rtn = rc;
401                 }
402         }
403
404 #ifdef NEW_LOGGING
405         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
406                    "test_filter_or: result=%d\n", rtn ));
407 #else
408         Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
409 #endif
410
411         return rtn;
412 }
413
414
415 static int
416 test_substrings_filter(
417     Backend     *be,
418     Connection  *conn,
419     Operation   *op,
420     Entry       *e,
421     Filter      *f
422 )
423 {
424         Attribute       *a;
425
426 #ifdef NEW_LOGGING
427         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
428                    "test_substrings_filter: begin\n" ));
429 #else
430         Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
431 #endif
432
433
434         if ( be != NULL && ! access_allowed( be, conn, op, e,
435                 f->f_sub_desc, NULL, ACL_SEARCH ) )
436         {
437                 return LDAP_INSUFFICIENT_ACCESS;
438         }
439
440         for(a = attrs_find( e->e_attrs, f->f_sub_desc );
441                 a != NULL;
442                 a = attrs_find( a->a_next, f->f_sub_desc ) )
443         {
444                 int i;
445                 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
446
447                 if( mr == NULL ) {
448                         continue;
449                 }
450
451                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
452                         int ret;
453                         int rc;
454                         const char *text;
455
456                         rc = value_match( &ret, a->a_desc, mr, 0,
457                                 a->a_vals[i], f->f_sub,
458                                 &text );
459
460                         if( rc != LDAP_SUCCESS ) {
461                                 return rc;
462                         }
463
464                         if ( ret == 0 ) {
465                                 return LDAP_COMPARE_TRUE;
466                         }
467                 }
468         }
469
470 #ifdef NEW_LOGGING
471         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
472                    "test_substrings_filter: return FALSE\n" ));
473 #else
474         Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
475 #endif
476
477         return LDAP_COMPARE_FALSE;
478 }