]> git.sur5r.net Git - openldap/blob - servers/slapd/mra.c
ce2af55cba940a4a88b612efcbaed1a49c27d2d3
[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 {
33         /* op->o_tmpfree( mra->ma_value.bv_val, op->o_tmpmemctx ); */
34         ch_free( mra->ma_value.bv_val );
35         if ( freeit ) {
36                 op->o_tmpfree( (char *) mra, op->o_tmpmemctx );
37         }
38 }
39
40 int
41 get_mra(
42         Operation *op,
43         BerElement      *ber,
44         MatchingRuleAssertion   **mra,
45         const char **text
46 )
47 {
48         int rc;
49         ber_tag_t tag, rtag;
50         ber_len_t length;
51         struct berval type = { 0, NULL };
52         struct berval value = { 0, NULL };
53         struct berval rule_text = { 0, NULL };
54         MatchingRuleAssertion ma;
55
56         memset( &ma, 0, sizeof ma);
57
58         rtag = ber_scanf( ber, "{t" /*"}"*/, &tag );
59
60         if( rtag == LBER_ERROR ) {
61 #ifdef NEW_LOGGING
62                 LDAP_LOG( OPERATION, ERR, 
63                         "get_mra: ber_scanf (\"{t\") failure\n", 0, 0, 0 );
64 #else
65                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
66 #endif
67
68                 *text = "Error parsing matching rule assertion";
69                 return SLAPD_DISCONNECT;
70         }
71
72         if ( tag == LDAP_FILTER_EXT_OID ) {
73                 rtag = ber_scanf( ber, "m", &rule_text );
74                 if ( rtag == LBER_ERROR ) {
75 #ifdef NEW_LOGGING
76                         LDAP_LOG( OPERATION, ERR,
77                            "get_mra: ber_scanf(\"o\") failure.\n", 0, 0, 0 );
78 #else
79                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for mr\n", 0, 0, 0 );
80 #endif
81
82                         *text = "Error parsing matching rule in matching rule assertion";
83                         return SLAPD_DISCONNECT;
84                 }
85
86                 rtag = ber_scanf( ber, "t", &tag );
87                 if( rtag == LBER_ERROR ) {
88 #ifdef NEW_LOGGING
89                         LDAP_LOG( OPERATION, ERR,
90                            "get_mra: ber_scanf (\"t\") failure\n", 0, 0, 0 );
91 #else
92                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
93 #endif
94
95                         *text = "Error parsing matching rule assertion";
96                         return SLAPD_DISCONNECT;
97                 }
98         }
99
100         if ( tag == LDAP_FILTER_EXT_TYPE ) {
101                 rtag = ber_scanf( ber, "m", &type );
102                 if ( rtag == LBER_ERROR ) {
103 #ifdef NEW_LOGGING
104                         LDAP_LOG( OPERATION, ERR,
105                            "get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
106 #else
107                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for ad\n", 0, 0, 0 );
108 #endif
109
110                         *text = "Error parsing attribute description in matching rule assertion";
111                         return SLAPD_DISCONNECT;
112                 }
113
114                 rtag = ber_scanf( ber, "t", &tag );
115                 if( rtag == LBER_ERROR ) {
116 #ifdef NEW_LOGGING
117                         LDAP_LOG( OPERATION, ERR,
118                            "get_mra: ber_scanf (\"t\") failure.\n", 0, 0, 0 );
119 #else
120                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
121 #endif
122
123                         *text = "Error parsing matching rule assertion";
124                         return SLAPD_DISCONNECT;
125                 }
126         }
127
128         if ( tag != LDAP_FILTER_EXT_VALUE ) {
129 #ifdef NEW_LOGGING
130                 LDAP_LOG( OPERATION, ERR, 
131                         "get_mra: ber_scanf missing value\n", 0, 0, 0 );
132 #else
133                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf missing value\n", 0, 0, 0 );
134 #endif
135
136                 *text = "Missing value in matching rule assertion";
137                 return SLAPD_DISCONNECT;
138         }
139
140         rtag = ber_scanf( ber, "m", &value );
141
142         if( rtag == LBER_ERROR ) {
143 #ifdef NEW_LOGGING
144                 LDAP_LOG( OPERATION, ERR, 
145                         "get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
146 #else
147                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
148 #endif
149
150                 *text = "Error decoding value in matching rule assertion";
151                 return SLAPD_DISCONNECT;
152         }
153
154         tag = ber_peek_tag( ber, &length );
155
156         if ( tag == LDAP_FILTER_EXT_DNATTRS ) {
157                 rtag = ber_scanf( ber, /*"{"*/ "b}", &ma.ma_dnattrs );
158         } else {
159                 rtag = ber_scanf( ber, /*"{"*/ "}" );
160         }
161
162         if( rtag == LBER_ERROR ) {
163 #ifdef NEW_LOGGING
164                 LDAP_LOG( OPERATION, ERR, "get_mra: ber_scanf failure\n", 0, 0, 0);
165 #else
166                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
167 #endif
168
169                 *text = "Error decoding dnattrs matching rule assertion";
170                 return SLAPD_DISCONNECT;
171         }
172
173         if( type.bv_val != NULL ) {
174                 rc = slap_bv2ad( &type, &ma.ma_desc, text );
175                 if( rc != LDAP_SUCCESS ) {
176                         return rc;
177                 }
178         }
179
180         if( rule_text.bv_val != NULL ) {
181                 ma.ma_rule = mr_bvfind( &rule_text );
182                 if( ma.ma_rule == NULL ) {
183                         *text = "matching rule not recognized";
184                         return LDAP_INAPPROPRIATE_MATCHING;
185                 }
186         }
187
188         if ( ma.ma_rule == NULL ) {
189                 /*
190                  * Need either type or rule ...
191                  */
192                 if ( ma.ma_desc == NULL ) {
193                         *text = "no matching rule or type";
194                         return LDAP_INAPPROPRIATE_MATCHING;
195                 }
196
197                 if ( ma.ma_desc->ad_type->sat_equality != NULL &&
198                         ma.ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
199                 {
200                         /* no matching rule was provided, use the attribute's
201                            equality rule if it supports extensible matching. */
202                         ma.ma_rule = ma.ma_desc->ad_type->sat_equality;
203
204                 } else {
205                         *text = "no appropriate rule to use for type";
206                         return LDAP_INAPPROPRIATE_MATCHING;
207                 }
208         }
209
210         if ( ma.ma_desc != NULL ) {
211                 if( !mr_usable_with_at( ma.ma_rule, ma.ma_desc->ad_type ) ) {
212                         *text = "matching rule use with this attribute not appropriate";
213                         return LDAP_INAPPROPRIATE_MATCHING;
214                 }
215
216         }
217
218         /*
219          * Normalize per matching rule
220          */
221         rc = asserted_value_validate_normalize( ma.ma_desc,
222                 ma.ma_rule,
223                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
224                 &value, &ma.ma_value, text, op->o_tmpmemctx );
225
226         if( rc != LDAP_SUCCESS ) {
227                 return rc;
228         }
229
230         length = sizeof(ma);
231         /* Append rule_text to end of struct */
232         if (rule_text.bv_val) length += rule_text.bv_len + 1;
233         *mra = op->o_tmpalloc( length, op->o_tmpmemctx );
234         **mra = ma;
235         if (rule_text.bv_val) {
236                 (*mra)->ma_rule_text.bv_len = rule_text.bv_len;
237                 (*mra)->ma_rule_text.bv_val = (char *)(*mra+1);
238                 AC_MEMCPY((*mra)->ma_rule_text.bv_val, rule_text.bv_val,
239                         rule_text.bv_len+1);
240         }
241
242         return LDAP_SUCCESS;
243 }