1/* $NetBSD: mra.c,v 1.1.1.3 2010/12/12 15:22:34 adam Exp $ */ 2 3/* mra.c - routines for dealing with extensible matching rule assertions */ 4/* OpenLDAP: pkg/ldap/servers/slapd/mra.c,v 1.45.2.5 2010/04/13 20:23:17 kurt Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19#include "portable.h" 20 21#include <stdio.h> 22 23#include <ac/string.h> 24#include <ac/socket.h> 25 26#include "slap.h" 27 28#ifdef LDAP_COMP_MATCH 29#include "component.h" 30#endif 31 32void 33mra_free( 34 Operation *op, 35 MatchingRuleAssertion *mra, 36 int freeit ) 37{ 38#ifdef LDAP_COMP_MATCH 39 /* free component assertion */ 40 if ( mra->ma_rule->smr_usage & SLAP_MR_COMPONENT && mra->ma_cf ) { 41 component_free( mra->ma_cf ); 42 } 43#endif 44 /* op->o_tmpfree( mra->ma_value.bv_val, op->o_tmpmemctx ); */ 45 ch_free( mra->ma_value.bv_val ); 46 if ( mra->ma_desc && mra->ma_desc->ad_flags & SLAP_DESC_TEMPORARY ) 47 op->o_tmpfree( mra->ma_desc, op->o_tmpmemctx ); 48 if ( freeit ) op->o_tmpfree( (char *) mra, op->o_tmpmemctx ); 49} 50 51int 52get_mra( 53 Operation *op, 54 BerElement *ber, 55 Filter *f, 56 const char **text ) 57{ 58 int rc; 59 ber_tag_t tag, rtag; 60 ber_len_t length; 61 struct berval type = BER_BVNULL; 62 struct berval value = BER_BVNULL; 63 struct berval rule_text = BER_BVNULL; 64 MatchingRuleAssertion ma = { 0 }; 65#ifdef LDAP_COMP_MATCH 66 AttributeAliasing* aa = NULL; 67#endif 68 69 rtag = ber_scanf( ber, "{t" /*"}"*/, &tag ); 70 71 if( rtag == LBER_ERROR ) { 72 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 ); 73 74 *text = "Error parsing matching rule assertion"; 75 return SLAPD_DISCONNECT; 76 } 77 78 if ( tag == LDAP_FILTER_EXT_OID ) { 79 rtag = ber_scanf( ber, "m", &rule_text ); 80 if ( rtag == LBER_ERROR ) { 81 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf for mr\n", 0, 0, 0 ); 82 83 *text = "Error parsing matching rule in matching rule assertion"; 84 return SLAPD_DISCONNECT; 85 } 86 87 rtag = ber_scanf( ber, "t", &tag ); 88 if( rtag == LBER_ERROR ) { 89 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 ); 90 91 *text = "Error parsing matching rule assertion"; 92 return SLAPD_DISCONNECT; 93 } 94 } 95 96 if ( tag == LDAP_FILTER_EXT_TYPE ) { 97 rtag = ber_scanf( ber, "m", &type ); 98 if ( rtag == LBER_ERROR ) { 99 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf for ad\n", 0, 0, 0 ); 100 101 *text = "Error parsing attribute description in matching rule assertion"; 102 return SLAPD_DISCONNECT; 103 } 104 105 rtag = ber_scanf( ber, "t", &tag ); 106 if( rtag == LBER_ERROR ) { 107 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 ); 108 109 *text = "Error parsing matching rule assertion"; 110 return SLAPD_DISCONNECT; 111 } 112 } 113 114 if ( tag != LDAP_FILTER_EXT_VALUE ) { 115 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf missing value\n", 0, 0, 0 ); 116 117 *text = "Missing value in matching rule assertion"; 118 return SLAPD_DISCONNECT; 119 } 120 121 rtag = ber_scanf( ber, "m", &value ); 122 123 if( rtag == LBER_ERROR ) { 124 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 ); 125 126 *text = "Error decoding value in matching rule assertion"; 127 return SLAPD_DISCONNECT; 128 } 129 130 tag = ber_peek_tag( ber, &length ); 131 132 if ( tag == LDAP_FILTER_EXT_DNATTRS ) { 133 rtag = ber_scanf( ber, /*"{"*/ "b}", &ma.ma_dnattrs ); 134 } else { 135 rtag = ber_scanf( ber, /*"{"*/ "}" ); 136 } 137 138 if( rtag == LBER_ERROR ) { 139 Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 ); 140 141 *text = "Error decoding dnattrs matching rule assertion"; 142 return SLAPD_DISCONNECT; 143 } 144 145 if( type.bv_val != NULL ) { 146 rc = slap_bv2ad( &type, &ma.ma_desc, text ); 147 if( rc != LDAP_SUCCESS ) { 148 f->f_choice |= SLAPD_FILTER_UNDEFINED; 149 rc = slap_bv2undef_ad( &type, &ma.ma_desc, text, 150 SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); 151 152 if( rc != LDAP_SUCCESS ) { 153 ma.ma_desc = slap_bv2tmp_ad( &type, op->o_tmpmemctx ); 154 rc = LDAP_SUCCESS; 155 } 156 } 157 } 158 159 if( rule_text.bv_val != NULL ) { 160 ma.ma_rule = mr_bvfind( &rule_text ); 161 if( ma.ma_rule == NULL ) { 162 *text = "matching rule not recognized"; 163 return LDAP_INAPPROPRIATE_MATCHING; 164 } 165 } 166 167 if ( ma.ma_rule == NULL ) { 168 /* 169 * Need either type or rule ... 170 */ 171 if ( ma.ma_desc == NULL ) { 172 *text = "no matching rule or type"; 173 return LDAP_INAPPROPRIATE_MATCHING; 174 } 175 176 if ( ma.ma_desc->ad_type->sat_equality != NULL && 177 ma.ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT ) 178 { 179 /* no matching rule was provided, use the attribute's 180 equality rule if it supports extensible matching. */ 181 ma.ma_rule = ma.ma_desc->ad_type->sat_equality; 182 183 } else { 184 *text = "no appropriate rule to use for type"; 185 return LDAP_INAPPROPRIATE_MATCHING; 186 } 187 } 188 189 if ( ma.ma_desc != NULL ) { 190 if( !mr_usable_with_at( ma.ma_rule, ma.ma_desc->ad_type ) ) { 191 *text = "matching rule use with this attribute not appropriate"; 192 return LDAP_INAPPROPRIATE_MATCHING; 193 } 194 195 } 196 197 /* 198 * Normalize per matching rule 199 */ 200 rc = asserted_value_validate_normalize( ma.ma_desc, 201 ma.ma_rule, 202 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 203 &value, &ma.ma_value, text, op->o_tmpmemctx ); 204 205 if( rc != LDAP_SUCCESS ) return rc; 206 207#ifdef LDAP_COMP_MATCH 208 /* Check If this attribute is aliased */ 209 if ( is_aliased_attribute && ma.ma_desc && ( aa = is_aliased_attribute ( ma.ma_desc ) ) ) { 210 rc = get_aliased_filter ( op, &ma, aa, text ); 211 if ( rc != LDAP_SUCCESS ) return rc; 212 } 213 else if ( ma.ma_rule && ma.ma_rule->smr_usage & SLAP_MR_COMPONENT ) { 214 /* Matching Rule for Component Matching */ 215 rc = get_comp_filter( op, &ma.ma_value, &ma.ma_cf, text ); 216 if ( rc != LDAP_SUCCESS ) return rc; 217 } 218#endif 219 220 length = sizeof(ma); 221 /* Append rule_text to end of struct */ 222 if (rule_text.bv_val) length += rule_text.bv_len + 1; 223 f->f_mra = op->o_tmpalloc( length, op->o_tmpmemctx ); 224 *f->f_mra = ma; 225 if (rule_text.bv_val) { 226 f->f_mra->ma_rule_text.bv_len = rule_text.bv_len; 227 f->f_mra->ma_rule_text.bv_val = (char *)(f->f_mra+1); 228 AC_MEMCPY(f->f_mra->ma_rule_text.bv_val, rule_text.bv_val, 229 rule_text.bv_len+1); 230 } 231 232 return LDAP_SUCCESS; 233} 234