1 /* $NetBSD: mra.c,v 1.3 2021/08/14 16:14:58 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-2021 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.3 2021/08/14 16:14:58 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
mra_free(Operation * op,MatchingRuleAssertion * mra,int freeit)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
get_mra(Operation * op,BerElement * ber,Filter * f,const char ** text)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" );
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" );
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" );
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" );
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" );
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" );
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" );
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" );
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