xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/mra.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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