1 /*	$NetBSD: matchedValues.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/servers/slapd/matchedValues.c,v 1.28.2.4 2009/01/22 00:01:01 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2009 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 
27 static int
28 test_mra_vrFilter(
29 	Operation	*op,
30 	Attribute	*a,
31 	MatchingRuleAssertion *mra,
32 	char 		***e_flags
33 );
34 
35 static int
36 test_substrings_vrFilter(
37 	Operation	*op,
38 	Attribute	*a,
39 	ValuesReturnFilter *f,
40 	char		***e_flags
41 );
42 
43 static int
44 test_presence_vrFilter(
45 	Operation	*op,
46 	Attribute	*a,
47 	AttributeDescription *desc,
48 	char 		***e_flags
49 );
50 
51 static int
52 test_ava_vrFilter(
53 	Operation	*op,
54 	Attribute	*a,
55 	AttributeAssertion *ava,
56 	int		type,
57 	char 		***e_flags
58 );
59 
60 
61 int
62 filter_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 
136 static int
137 test_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 
209 static int
210 test_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 
230 static int
231 test_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 
268 static int
269 test_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