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