1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1999-2011 The OpenLDAP Foundation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
10 *
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
14 */
15
16#include "portable.h"
17
18#include <stdio.h>
19
20#include <ac/string.h>
21#include <ac/socket.h>
22
23#include "slap.h"
24
25static int
26test_mra_vrFilter(
27	Operation	*op,
28	Attribute	*a,
29	MatchingRuleAssertion *mra,
30	char 		***e_flags
31);
32
33static int
34test_substrings_vrFilter(
35	Operation	*op,
36	Attribute	*a,
37	ValuesReturnFilter *f,
38	char		***e_flags
39);
40
41static int
42test_presence_vrFilter(
43	Operation	*op,
44	Attribute	*a,
45	AttributeDescription *desc,
46	char 		***e_flags
47);
48
49static int
50test_ava_vrFilter(
51	Operation	*op,
52	Attribute	*a,
53	AttributeAssertion *ava,
54	int		type,
55	char 		***e_flags
56);
57
58
59int
60filter_matched_values(
61	Operation	*op,
62	Attribute	*a,
63	char		***e_flags )
64{
65	ValuesReturnFilter *vrf;
66	int		rc = LDAP_SUCCESS;
67
68	Debug( LDAP_DEBUG_FILTER, "=> filter_matched_values\n", 0, 0, 0 );
69
70	for ( vrf = op->o_vrFilter; vrf != NULL; vrf = vrf->vrf_next ) {
71		switch ( vrf->vrf_choice ) {
72		case SLAPD_FILTER_COMPUTED:
73			Debug( LDAP_DEBUG_FILTER, "	COMPUTED %s (%d)\n",
74				vrf->vrf_result == LDAP_COMPARE_FALSE ? "false"
75				: vrf->vrf_result == LDAP_COMPARE_TRUE ? "true"
76				: vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "undefined"
77				: "error",
78				vrf->vrf_result, 0 );
79			/*This type of filter does not affect the result */
80			rc = LDAP_SUCCESS;
81		break;
82
83		case LDAP_FILTER_EQUALITY:
84			Debug( LDAP_DEBUG_FILTER, "	EQUALITY\n", 0, 0, 0 );
85			rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
86				LDAP_FILTER_EQUALITY, e_flags );
87			if( rc == -1 ) return rc;
88			break;
89
90		case LDAP_FILTER_SUBSTRINGS:
91			Debug( LDAP_DEBUG_FILTER, "	SUBSTRINGS\n", 0, 0, 0 );
92			rc = test_substrings_vrFilter( op, a,
93				vrf, e_flags );
94			if( rc == -1 ) return rc;
95			break;
96
97		case LDAP_FILTER_PRESENT:
98			Debug( LDAP_DEBUG_FILTER, "	PRESENT\n", 0, 0, 0 );
99			rc = test_presence_vrFilter( op, a,
100				vrf->vrf_desc, e_flags );
101			if( rc == -1 ) return rc;
102			break;
103
104		case LDAP_FILTER_GE:
105			rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
106				LDAP_FILTER_GE, e_flags );
107			if( rc == -1 ) return rc;
108			break;
109
110		case LDAP_FILTER_LE:
111			rc = test_ava_vrFilter( op, a, vrf->vrf_ava,
112				LDAP_FILTER_LE, e_flags );
113			if( rc == -1 ) return rc;
114			break;
115
116		case LDAP_FILTER_EXT:
117			Debug( LDAP_DEBUG_FILTER, "	EXT\n", 0, 0, 0 );
118			rc = test_mra_vrFilter( op, a,
119				vrf->vrf_mra, e_flags );
120			if( rc == -1 ) return rc;
121			break;
122
123		default:
124			Debug( LDAP_DEBUG_ANY, "	unknown filter type %lu\n",
125				vrf->vrf_choice, 0, 0 );
126			rc = LDAP_PROTOCOL_ERROR;
127		}
128	}
129
130	Debug( LDAP_DEBUG_FILTER, "<= filter_matched_values %d\n", rc, 0, 0 );
131	return( rc );
132}
133
134static int
135test_ava_vrFilter(
136	Operation	*op,
137	Attribute	*a,
138	AttributeAssertion *ava,
139	int		type,
140	char 		***e_flags )
141{
142	int 		i, j;
143
144	for ( i=0; a != NULL; a = a->a_next, i++ ) {
145		MatchingRule *mr;
146		struct berval *bv;
147
148		if ( !is_ad_subtype( a->a_desc, ava->aa_desc ) ) {
149			continue;
150		}
151
152		switch ( type ) {
153		case LDAP_FILTER_APPROX:
154			mr = a->a_desc->ad_type->sat_approx;
155			if( mr != NULL ) break;
156			/* use EQUALITY matching rule if no APPROX rule */
157
158		case LDAP_FILTER_EQUALITY:
159			mr = a->a_desc->ad_type->sat_equality;
160			break;
161
162		case LDAP_FILTER_GE:
163		case LDAP_FILTER_LE:
164			mr = a->a_desc->ad_type->sat_ordering;
165			break;
166
167		default:
168			mr = NULL;
169		}
170
171		if( mr == NULL ) continue;
172
173		bv = a->a_nvals;
174		for ( j=0; !BER_BVISNULL( bv ); bv++, j++ ) {
175			int rc, match;
176			const char *text;
177
178			rc = value_match( &match, a->a_desc, mr, 0,
179				bv, &ava->aa_value, &text );
180			if( rc != LDAP_SUCCESS ) return rc;
181
182			switch ( type ) {
183			case LDAP_FILTER_EQUALITY:
184			case LDAP_FILTER_APPROX:
185				if ( match == 0 ) {
186					(*e_flags)[i][j] = 1;
187				}
188				break;
189
190			case LDAP_FILTER_GE:
191				if ( match >= 0 ) {
192					(*e_flags)[i][j] = 1;
193				}
194				break;
195
196			case LDAP_FILTER_LE:
197				if ( match <= 0 ) {
198					(*e_flags)[i][j] = 1;
199				}
200				break;
201			}
202		}
203	}
204	return LDAP_SUCCESS;
205}
206
207static int
208test_presence_vrFilter(
209	Operation	*op,
210	Attribute	*a,
211	AttributeDescription *desc,
212	char 		***e_flags )
213{
214	int i, j;
215
216	for ( i=0; a != NULL; a = a->a_next, i++ ) {
217		struct berval *bv;
218
219		if ( !is_ad_subtype( a->a_desc, desc ) ) continue;
220
221		for ( bv = a->a_vals, j = 0; !BER_BVISNULL( bv ); bv++, j++ );
222		memset( (*e_flags)[i], 1, j);
223	}
224
225	return( LDAP_SUCCESS );
226}
227
228static int
229test_substrings_vrFilter(
230	Operation	*op,
231	Attribute	*a,
232	ValuesReturnFilter *vrf,
233	char		***e_flags )
234{
235	int i, j;
236
237	for ( i=0; a != NULL; a = a->a_next, i++ ) {
238		MatchingRule *mr = a->a_desc->ad_type->sat_substr;
239		struct berval *bv;
240
241		if ( !is_ad_subtype( a->a_desc, vrf->vrf_sub_desc ) ) {
242			continue;
243		}
244
245		if( mr == NULL ) continue;
246
247		bv = a->a_nvals;
248		for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
249			int rc, match;
250			const char *text;
251
252			rc = value_match( &match, a->a_desc, mr, 0,
253				bv, vrf->vrf_sub, &text );
254
255			if( rc != LDAP_SUCCESS ) return rc;
256
257			if ( match == 0 ) {
258				(*e_flags)[i][j] = 1;
259			}
260		}
261	}
262
263	return LDAP_SUCCESS;
264}
265
266static int
267test_mra_vrFilter(
268	Operation	*op,
269	Attribute	*a,
270	MatchingRuleAssertion *mra,
271	char 		***e_flags )
272{
273	int	i, j;
274
275	for ( i = 0; a != NULL; a = a->a_next, i++ ) {
276		struct berval	*bv, assertedValue;
277		int		normalize_attribute = 0;
278
279		if ( mra->ma_desc ) {
280			if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
281				continue;
282			}
283			assertedValue = mra->ma_value;
284
285		} else {
286			int rc;
287			const char	*text = NULL;
288
289			/* check if matching is appropriate */
290			if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
291				continue;
292			}
293
294			rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
295				SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
296				&mra->ma_value, &assertedValue, &text, op->o_tmpmemctx );
297
298			if ( rc != LDAP_SUCCESS ) continue;
299		}
300
301		/* check match */
302		if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
303			bv = a->a_nvals;
304
305		} else {
306			bv = a->a_vals;
307			normalize_attribute = 1;
308		}
309
310		for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
311			int		rc, match;
312			const char	*text;
313			struct berval	nbv = BER_BVNULL;
314
315			if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
316				/* see comment in filterentry.c */
317				if ( mra->ma_rule->smr_normalize(
318						SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
319						mra->ma_rule->smr_syntax,
320						mra->ma_rule,
321						bv, &nbv, op->o_tmpmemctx ) != LDAP_SUCCESS )
322				{
323					/* FIXME: stop processing? */
324					continue;
325				}
326
327			} else {
328				nbv = *bv;
329			}
330
331			rc = value_match( &match, a->a_desc, mra->ma_rule, 0,
332				&nbv, &assertedValue, &text );
333
334			if ( nbv.bv_val != bv->bv_val ) {
335				op->o_tmpfree( nbv.bv_val, op->o_tmpmemctx );
336			}
337
338			if ( rc != LDAP_SUCCESS ) return rc;
339
340			if ( match == 0 ) {
341				(*e_flags)[i][j] = 1;
342			}
343		}
344	}
345
346	return LDAP_SUCCESS;
347}
348
349