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