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