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