]> git.sur5r.net Git - openldap/blob - servers/slapd/filterentry.c
83edbc6bb42172d2d161f4290db27bfb23de3f9c
[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 = rc;
355                         break;
356                 }
357
358                 if ( rc != LDAP_COMPARE_TRUE ) {
359                         rtn = rc;
360                 }
361         }
362
363 #ifdef NEW_LOGGING
364         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
365                    "test_filter_and:  rc=%d\n", rtn ));
366 #else
367         Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
368 #endif
369
370         return rtn;
371 }
372
373 static int
374 test_filter_or(
375     Backend     *be,
376     Connection  *conn,
377     Operation   *op,
378     Entry       *e,
379     Filter      *flist
380 )
381 {
382         Filter  *f;
383         int rtn = LDAP_COMPARE_FALSE;
384
385 #ifdef NEW_LOGGING
386         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
387                    "test_filter_or: begin\n" ));
388 #else
389         Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
390 #endif
391
392
393         for ( f = flist; f != NULL; f = f->f_next ) {
394                 int rc = test_filter( be, conn, op, e, f );
395
396                 if ( rc == LDAP_COMPARE_TRUE ) {
397                         rtn = rc;
398                         break;
399                 }
400
401                 if ( rc != LDAP_COMPARE_FALSE ) {
402                         rtn = rc;
403                 }
404         }
405
406 #ifdef NEW_LOGGING
407         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
408                    "test_filter_or: result=%d\n", rtn ));
409 #else
410         Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
411 #endif
412
413         return rtn;
414 }
415
416
417 static int
418 test_substrings_filter(
419     Backend     *be,
420     Connection  *conn,
421     Operation   *op,
422     Entry       *e,
423     Filter      *f
424 )
425 {
426         Attribute       *a;
427
428 #ifdef NEW_LOGGING
429         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
430                    "test_substrings_filter: begin\n" ));
431 #else
432         Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
433 #endif
434
435
436         if ( be != NULL && ! access_allowed( be, conn, op, e,
437                 f->f_sub_desc, NULL, ACL_SEARCH ) )
438         {
439                 return LDAP_INSUFFICIENT_ACCESS;
440         }
441
442         for(a = attrs_find( e->e_attrs, f->f_sub_desc );
443                 a != NULL;
444                 a = attrs_find( a->a_next, f->f_sub_desc ) )
445         {
446                 int i;
447                 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
448
449                 if( mr == NULL ) {
450                         continue;
451                 }
452
453                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
454                         int ret;
455                         int rc;
456                         const char *text;
457
458                         rc = value_match( &ret, a->a_desc, mr, 0,
459                                 a->a_vals[i], f->f_sub,
460                                 &text );
461
462                         if( rc != LDAP_SUCCESS ) {
463                                 return rc;
464                         }
465
466                         if ( ret == 0 ) {
467                                 return LDAP_COMPARE_TRUE;
468                         }
469                 }
470         }
471
472 #ifdef NEW_LOGGING
473         LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
474                    "test_substrings_filter: return FALSE\n" ));
475 #else
476         Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
477 #endif
478
479         return LDAP_COMPARE_FALSE;
480 }