xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/mra.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: mra.c,v 1.1.1.4 2014/05/28 09:58:47 tron 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-2014 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 
32 void
33 mra_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 
51 int
52 get_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