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