]> git.sur5r.net Git - openldap/blob - servers/slapd/filterentry.c
s/SUBSTRINGS/SUBSTR/
[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                 case LDAP_FILTER_EQUALITY:
175                         mr = a->a_desc->ad_type->sat_equality;
176                         break;
177
178                 case LDAP_FILTER_GE:
179                 case LDAP_FILTER_LE:
180                         mr = a->a_desc->ad_type->sat_ordering;
181                         break;
182
183                 default:
184                         mr = NULL;
185                 }
186
187                 if( mr == NULL ) {
188                         continue;
189                 }
190
191                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
192                         int ret;
193                         int rc;
194                         const char *text;
195
196                         rc = value_match( &ret, a->a_desc, mr, 0,
197                                 a->a_vals[i], ava->aa_value,
198                                 &text );
199
200                         if( rc != LDAP_SUCCESS ) {
201                                 return rc;
202                         }
203
204                         switch ( type ) {
205                         case LDAP_FILTER_EQUALITY:
206                         case LDAP_FILTER_APPROX:
207                                 if ( ret == 0 ) {
208                                         return LDAP_COMPARE_TRUE;
209                                 }
210                                 break;
211
212                         case LDAP_FILTER_GE:
213                                 if ( ret >= 0 ) {
214                                         return LDAP_COMPARE_TRUE;
215                                 }
216                                 break;
217
218                         case LDAP_FILTER_LE:
219                                 if ( ret <= 0 ) {
220                                         return LDAP_COMPARE_TRUE;
221                                 }
222                                 break;
223                         }
224                 }
225         }
226
227         return( LDAP_COMPARE_FALSE );
228 }
229
230
231 static int
232 test_presence_filter(
233     Backend     *be,
234     Connection  *conn,
235     Operation   *op,
236     Entry       *e,
237         AttributeDescription *desc
238 )
239 {
240         if ( be != NULL && ! access_allowed( be, conn, op, e,
241                 desc, NULL, ACL_SEARCH ) )
242         {
243                 return LDAP_INSUFFICIENT_ACCESS;
244         }
245
246         return attrs_find( e->e_attrs, desc ) != NULL
247                 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
248 }
249
250
251 static int
252 test_filter_and(
253     Backend     *be,
254     Connection  *conn,
255     Operation   *op,
256     Entry       *e,
257     Filter      *flist
258 )
259 {
260         Filter  *f;
261         int rtn = LDAP_COMPARE_TRUE;
262
263         Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
264
265         for ( f = flist; f != NULL; f = f->f_next ) {
266                 int rc = test_filter( be, conn, op, e, f );
267
268                 if ( rc == LDAP_COMPARE_FALSE ) {
269                         rtn = LDAP_COMPARE_FALSE;
270                         break;
271                 }
272                 if ( rc != LDAP_COMPARE_TRUE ) {
273                         rtn = rc;
274                 }
275         }
276
277         Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
278         return rtn;
279 }
280
281 static int
282 test_filter_or(
283     Backend     *be,
284     Connection  *conn,
285     Operation   *op,
286     Entry       *e,
287     Filter      *flist
288 )
289 {
290         Filter  *f;
291         int rtn = LDAP_COMPARE_FALSE;
292
293         Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
294
295         for ( f = flist; f != NULL; f = f->f_next ) {
296                 int rc = test_filter( be, conn, op, e, f );
297
298                 if ( rc == LDAP_COMPARE_TRUE ) {
299                         rtn = LDAP_COMPARE_TRUE;
300                         break;
301                 }
302                 if ( rc != LDAP_COMPARE_TRUE ) {
303                         rtn = rc;
304                 }
305         }
306
307         Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
308         return rtn;
309 }
310
311
312 static int
313 test_substrings_filter(
314     Backend     *be,
315     Connection  *conn,
316     Operation   *op,
317     Entry       *e,
318     Filter      *f
319 )
320 {
321         Attribute       *a;
322
323         Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
324
325         if ( be != NULL && ! access_allowed( be, conn, op, e,
326                 f->f_sub_desc, NULL, ACL_SEARCH ) )
327         {
328                 return LDAP_INSUFFICIENT_ACCESS;
329         }
330
331         for(a = attrs_find( e->e_attrs, f->f_sub_desc );
332                 a != NULL;
333                 a = attrs_find( a->a_next, f->f_sub_desc ) )
334         {
335                 int i;
336                 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
337
338                 if( mr == NULL ) {
339                         continue;
340                 }
341
342                 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
343                         int ret;
344                         int rc;
345                         const char *text;
346
347                         rc = value_match( &ret, a->a_desc, mr, 0,
348                                 a->a_vals[i], f->f_sub,
349                                 &text );
350
351                         if( rc != LDAP_SUCCESS ) {
352                                 return rc;
353                         }
354
355                         if ( ret == 0 ) {
356                                 return LDAP_COMPARE_TRUE;
357                         }
358                 }
359         }
360
361         Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
362         return LDAP_COMPARE_FALSE;
363 }