]> git.sur5r.net Git - openldap/blob - servers/slapd/filterentry.c
add new ber dump routine (behind NEW_LOGGING)
[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         Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
59
60         switch ( f->f_choice ) {
61         case SLAPD_FILTER_COMPUTED:
62                 Debug( LDAP_DEBUG_FILTER, "    COMPUTED %s (%d)\n",
63                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
64                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
65                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
66                         f->f_result, 0 );
67                 rc = f->f_result;
68                 break;
69
70         case LDAP_FILTER_EQUALITY:
71                 Debug( LDAP_DEBUG_FILTER, "    EQUALITY\n", 0, 0, 0 );
72                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
73                     LDAP_FILTER_EQUALITY );
74                 break;
75
76         case LDAP_FILTER_SUBSTRINGS:
77                 Debug( LDAP_DEBUG_FILTER, "    SUBSTRINGS\n", 0, 0, 0 );
78                 rc = test_substrings_filter( be, conn, op, e, f );
79                 break;
80
81         case LDAP_FILTER_GE:
82                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
83                     LDAP_FILTER_GE );
84                 break;
85
86         case LDAP_FILTER_LE:
87                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
88                     LDAP_FILTER_LE );
89                 break;
90
91         case LDAP_FILTER_PRESENT:
92                 Debug( LDAP_DEBUG_FILTER, "    PRESENT\n", 0, 0, 0 );
93                 rc = test_presence_filter( be, conn, op, e, f->f_desc );
94                 break;
95
96         case LDAP_FILTER_APPROX:
97                 Debug( LDAP_DEBUG_FILTER, "    APPROX\n", 0, 0, 0 );
98                 rc = test_ava_filter( be, conn, op, e, f->f_ava,
99                     LDAP_FILTER_APPROX );
100                 break;
101
102         case LDAP_FILTER_AND:
103                 Debug( LDAP_DEBUG_FILTER, "    AND\n", 0, 0, 0 );
104                 rc = test_filter_and( be, conn, op, e, f->f_and );
105                 break;
106
107         case LDAP_FILTER_OR:
108                 Debug( LDAP_DEBUG_FILTER, "    OR\n", 0, 0, 0 );
109                 rc = test_filter_or( be, conn, op, e, f->f_or );
110                 break;
111
112         case LDAP_FILTER_NOT:
113                 Debug( LDAP_DEBUG_FILTER, "    NOT\n", 0, 0, 0 );
114                 rc = test_filter( be, conn, op, e, f->f_not );
115
116                 switch( rc ) {
117                 case LDAP_COMPARE_TRUE:
118                         rc = LDAP_COMPARE_FALSE;
119                         break;
120                 case LDAP_COMPARE_FALSE:
121                         rc = LDAP_COMPARE_TRUE;
122                         break;
123                 }
124                 break;
125
126 #ifdef SLAPD_EXT_FILTERS
127         case LDAP_FILTER_EXT:
128                 Debug( LDAP_DEBUG_FILTER, "    EXT\n", 0, 0, 0 );
129                 rc = test_mra_filter( be, conn, op, e, f->f_mra );
130                 break;
131 #endif
132
133         default:
134                 Debug( LDAP_DEBUG_ANY, "    unknown filter type %lu\n",
135                     f->f_choice, 0, 0 );
136                 rc = LDAP_PROTOCOL_ERROR;
137         }
138
139         Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
140         return( rc );
141 }
142
143
144 static int
145 test_ava_filter(
146     Backend     *be,
147     Connection  *conn,
148     Operation   *op,
149     Entry       *e,
150         AttributeAssertion *ava,
151     int         type
152 )
153 {
154         int             i;
155         Attribute       *a;
156
157         if ( be != NULL && ! access_allowed( be, conn, op, e,
158                 ava->aa_desc, ava->aa_value, ACL_SEARCH ) )
159         {
160                 return LDAP_INSUFFICIENT_ACCESS;
161         }
162
163         for(a = attrs_find( e->e_attrs, ava->aa_desc );
164                 a != NULL;
165                 a = attrs_find( a->a_next, ava->aa_desc ) )
166         {
167                 MatchingRule *mr;
168
169                 switch ( type ) {
170                 case LDAP_FILTER_APPROX:
171                         mr = a->a_desc->ad_type->sat_approx;
172                         if( mr != NULL ) break;
173
174                         /* use EQUALITY matching rule if no APPROX rule */
175
176                 case LDAP_FILTER_EQUALITY:
177                         mr = a->a_desc->ad_type->sat_equality;
178                         break;
179
180                 case LDAP_FILTER_GE:
181                 case LDAP_FILTER_LE:
182                         mr = a->a_desc->ad_type->sat_ordering;
183                         break;
184
185                 default:
186                         mr = NULL;
187                 }
188
189                 if( mr == NULL ) {
190                         continue;
191                 }
192
193                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
194                         int ret;
195                         int rc;
196                         const char *text;
197
198                         rc = value_match( &ret, a->a_desc, mr, 0,
199                                 a->a_vals[i], ava->aa_value,
200                                 &text );
201
202                         if( rc != LDAP_SUCCESS ) {
203                                 return rc;
204                         }
205
206                         switch ( type ) {
207                         case LDAP_FILTER_EQUALITY:
208                         case LDAP_FILTER_APPROX:
209                                 if ( ret == 0 ) {
210                                         return LDAP_COMPARE_TRUE;
211                                 }
212                                 break;
213
214                         case LDAP_FILTER_GE:
215                                 if ( ret >= 0 ) {
216                                         return LDAP_COMPARE_TRUE;
217                                 }
218                                 break;
219
220                         case LDAP_FILTER_LE:
221                                 if ( ret <= 0 ) {
222                                         return LDAP_COMPARE_TRUE;
223                                 }
224                                 break;
225                         }
226                 }
227         }
228
229         return( LDAP_COMPARE_FALSE );
230 }
231
232
233 static int
234 test_presence_filter(
235     Backend     *be,
236     Connection  *conn,
237     Operation   *op,
238     Entry       *e,
239         AttributeDescription *desc
240 )
241 {
242         if ( be != NULL && ! access_allowed( be, conn, op, e,
243                 desc, NULL, ACL_SEARCH ) )
244         {
245                 return LDAP_INSUFFICIENT_ACCESS;
246         }
247
248         return attrs_find( e->e_attrs, desc ) != NULL
249                 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
250 }
251
252
253 static int
254 test_filter_and(
255     Backend     *be,
256     Connection  *conn,
257     Operation   *op,
258     Entry       *e,
259     Filter      *flist
260 )
261 {
262         Filter  *f;
263         int rtn = LDAP_COMPARE_TRUE;
264
265         Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
266
267         for ( f = flist; f != NULL; f = f->f_next ) {
268                 int rc = test_filter( be, conn, op, e, f );
269
270                 if ( rc == LDAP_COMPARE_FALSE ) {
271                         rtn = LDAP_COMPARE_FALSE;
272                         break;
273                 }
274                 if ( rc != LDAP_COMPARE_TRUE ) {
275                         rtn = rc;
276                 }
277         }
278
279         Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
280         return rtn;
281 }
282
283 static int
284 test_filter_or(
285     Backend     *be,
286     Connection  *conn,
287     Operation   *op,
288     Entry       *e,
289     Filter      *flist
290 )
291 {
292         Filter  *f;
293         int rtn = LDAP_COMPARE_FALSE;
294
295         Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
296
297         for ( f = flist; f != NULL; f = f->f_next ) {
298                 int rc = test_filter( be, conn, op, e, f );
299
300                 if ( rc == LDAP_COMPARE_TRUE ) {
301                         rtn = LDAP_COMPARE_TRUE;
302                         break;
303                 }
304                 if ( rc != LDAP_COMPARE_TRUE ) {
305                         rtn = rc;
306                 }
307         }
308
309         Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
310         return rtn;
311 }
312
313
314 static int
315 test_substrings_filter(
316     Backend     *be,
317     Connection  *conn,
318     Operation   *op,
319     Entry       *e,
320     Filter      *f
321 )
322 {
323         Attribute       *a;
324
325         Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
326
327         if ( be != NULL && ! access_allowed( be, conn, op, e,
328                 f->f_sub_desc, NULL, ACL_SEARCH ) )
329         {
330                 return LDAP_INSUFFICIENT_ACCESS;
331         }
332
333         for(a = attrs_find( e->e_attrs, f->f_sub_desc );
334                 a != NULL;
335                 a = attrs_find( a->a_next, f->f_sub_desc ) )
336         {
337                 int i;
338                 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
339
340                 if( mr == NULL ) {
341                         continue;
342                 }
343
344                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
345                         int ret;
346                         int rc;
347                         const char *text;
348
349                         rc = value_match( &ret, a->a_desc, mr, 0,
350                                 a->a_vals[i], f->f_sub,
351                                 &text );
352
353                         if( rc != LDAP_SUCCESS ) {
354                                 return rc;
355                         }
356
357                         if ( ret == 0 ) {
358                                 return LDAP_COMPARE_TRUE;
359                         }
360                 }
361         }
362
363         Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
364         return LDAP_COMPARE_FALSE;
365 }