]> git.sur5r.net Git - openldap/blob - servers/slapd/mra.c
Fix ITS#3424
[openldap] / servers / slapd / mra.c
1 /* mra.c - routines for dealing with extensible matching rule assertions */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2004 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 void
27 mra_free(
28         Operation *op,
29         MatchingRuleAssertion *mra,
30         int     freeit )
31 {
32 #ifdef LDAP_COMP_MATCH
33         /* free component assertion */
34         if ( mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
35                 component_free( mra->ma_cf );
36         }
37 #endif
38         /* op->o_tmpfree( mra->ma_value.bv_val, op->o_tmpmemctx ); */
39         ch_free( mra->ma_value.bv_val );
40         if ( freeit ) op->o_tmpfree( (char *) mra, op->o_tmpmemctx );
41 }
42
43 int
44 get_mra(
45         Operation *op,
46         BerElement      *ber,
47         MatchingRuleAssertion   **mra,
48         const char **text )
49 {
50         int rc;
51         ber_tag_t tag, rtag;
52         ber_len_t length;
53         struct berval type = BER_BVNULL;
54         struct berval value = BER_BVNULL;
55         struct berval rule_text = BER_BVNULL;
56         MatchingRuleAssertion ma;
57
58         memset( &ma, 0, sizeof ma);
59
60         rtag = ber_scanf( ber, "{t" /*"}"*/, &tag );
61
62         if( rtag == LBER_ERROR ) {
63                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
64
65                 *text = "Error parsing matching rule assertion";
66                 return SLAPD_DISCONNECT;
67         }
68
69         if ( tag == LDAP_FILTER_EXT_OID ) {
70                 rtag = ber_scanf( ber, "m", &rule_text );
71                 if ( rtag == LBER_ERROR ) {
72                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for mr\n", 0, 0, 0 );
73
74                         *text = "Error parsing matching rule in matching rule assertion";
75                         return SLAPD_DISCONNECT;
76                 }
77
78                 rtag = ber_scanf( ber, "t", &tag );
79                 if( rtag == LBER_ERROR ) {
80                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
81
82                         *text = "Error parsing matching rule assertion";
83                         return SLAPD_DISCONNECT;
84                 }
85         }
86
87         if ( tag == LDAP_FILTER_EXT_TYPE ) {
88                 rtag = ber_scanf( ber, "m", &type );
89                 if ( rtag == LBER_ERROR ) {
90                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for ad\n", 0, 0, 0 );
91
92                         *text = "Error parsing attribute description in matching rule assertion";
93                         return SLAPD_DISCONNECT;
94                 }
95
96                 rtag = ber_scanf( ber, "t", &tag );
97                 if( rtag == LBER_ERROR ) {
98                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
99
100                         *text = "Error parsing matching rule assertion";
101                         return SLAPD_DISCONNECT;
102                 }
103         }
104
105         if ( tag != LDAP_FILTER_EXT_VALUE ) {
106                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf missing value\n", 0, 0, 0 );
107
108                 *text = "Missing value in matching rule assertion";
109                 return SLAPD_DISCONNECT;
110         }
111
112         rtag = ber_scanf( ber, "m", &value );
113
114         if( rtag == LBER_ERROR ) {
115                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
116
117                 *text = "Error decoding value in matching rule assertion";
118                 return SLAPD_DISCONNECT;
119         }
120
121         tag = ber_peek_tag( ber, &length );
122
123         if ( tag == LDAP_FILTER_EXT_DNATTRS ) {
124                 rtag = ber_scanf( ber, /*"{"*/ "b}", &ma.ma_dnattrs );
125         } else {
126                 rtag = ber_scanf( ber, /*"{"*/ "}" );
127         }
128
129         if( rtag == LBER_ERROR ) {
130                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
131
132                 *text = "Error decoding dnattrs matching rule assertion";
133                 return SLAPD_DISCONNECT;
134         }
135
136         if( type.bv_val != NULL ) {
137                 rc = slap_bv2ad( &type, &ma.ma_desc, text );
138                 if( rc != LDAP_SUCCESS ) {
139                         return rc;
140                 }
141         }
142
143         if( rule_text.bv_val != NULL ) {
144                 ma.ma_rule = mr_bvfind( &rule_text );
145                 if( ma.ma_rule == NULL ) {
146                         *text = "matching rule not recognized";
147                         return LDAP_INAPPROPRIATE_MATCHING;
148                 }
149         }
150
151         if ( ma.ma_rule == NULL ) {
152                 /*
153                  * Need either type or rule ...
154                  */
155                 if ( ma.ma_desc == NULL ) {
156                         *text = "no matching rule or type";
157                         return LDAP_INAPPROPRIATE_MATCHING;
158                 }
159
160                 if ( ma.ma_desc->ad_type->sat_equality != NULL &&
161                         ma.ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
162                 {
163                         /* no matching rule was provided, use the attribute's
164                            equality rule if it supports extensible matching. */
165                         ma.ma_rule = ma.ma_desc->ad_type->sat_equality;
166
167                 } else {
168                         *text = "no appropriate rule to use for type";
169                         return LDAP_INAPPROPRIATE_MATCHING;
170                 }
171         }
172
173         if ( ma.ma_desc != NULL ) {
174                 if( !mr_usable_with_at( ma.ma_rule, ma.ma_desc->ad_type ) ) {
175                         *text = "matching rule use with this attribute not appropriate";
176                         return LDAP_INAPPROPRIATE_MATCHING;
177                 }
178
179         }
180
181         /*
182          * Normalize per matching rule
183          */
184         rc = asserted_value_validate_normalize( ma.ma_desc,
185                 ma.ma_rule,
186                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
187                 &value, &ma.ma_value, text, op->o_tmpmemctx );
188
189         if( rc != LDAP_SUCCESS ) return rc;
190
191 #ifdef LDAP_COMP_MATCH
192         /* Matching Rule for Component Matching */
193         Debug( LDAP_DEBUG_FILTER, "matchingrule %s\n",
194                 ma.ma_rule->smr_mrule.mr_oid, 0, 0);
195         if( ma.ma_rule && ma.ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
196                 rc = get_comp_filter( op, &ma.ma_value, &ma.ma_cf, text );
197                 if ( rc != LDAP_SUCCESS ) return rc;
198         }
199 #endif
200
201         length = sizeof(ma);
202         /* Append rule_text to end of struct */
203         if (rule_text.bv_val) length += rule_text.bv_len + 1;
204         *mra = op->o_tmpalloc( length, op->o_tmpmemctx );
205         **mra = ma;
206         if (rule_text.bv_val) {
207                 (*mra)->ma_rule_text.bv_len = rule_text.bv_len;
208                 (*mra)->ma_rule_text.bv_val = (char *)(*mra+1);
209                 AC_MEMCPY((*mra)->ma_rule_text.bv_val, rule_text.bv_val,
210                         rule_text.bv_len+1);
211         }
212
213         return LDAP_SUCCESS;
214 }