]> git.sur5r.net Git - openldap/blob - servers/slapd/mra.c
014e9d4367f2ca1f8f3b527e8ca902fe028e1d12
[openldap] / servers / slapd / mra.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* mra.c - routines for dealing with extensible matching rule assertions */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16
17 void
18 mra_free(
19         MatchingRuleAssertion *mra,
20         int     freeit
21 )
22 {
23         ch_free( mra->ma_value.bv_val );
24         if ( freeit ) {
25                 ch_free( (char *) mra );
26         }
27 }
28
29 int
30 get_mra(
31         BerElement      *ber,
32         MatchingRuleAssertion   **mra,
33         const char **text
34 )
35 {
36         int rc;
37         ber_tag_t tag, rtag;
38         ber_len_t length;
39         struct berval type = { 0, NULL };
40         struct berval value = { 0, NULL };
41         MatchingRuleAssertion ma;
42
43         memset( &ma, 0, sizeof ma);
44
45         rtag = ber_scanf( ber, "{t" /*"}"*/, &tag );
46
47         if( rtag == LBER_ERROR ) {
48 #ifdef NEW_LOGGING
49                 LDAP_LOG( OPERATION, ERR, 
50                         "get_mra: ber_scanf (\"{t\") failure\n", 0, 0, 0 );
51 #else
52                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
53 #endif
54
55                 *text = "Error parsing matching rule assertion";
56                 return SLAPD_DISCONNECT;
57         }
58
59         if ( tag == LDAP_FILTER_EXT_OID ) {
60                 rtag = ber_scanf( ber, "m", &ma.ma_rule_text );
61                 if ( rtag == LBER_ERROR ) {
62 #ifdef NEW_LOGGING
63                         LDAP_LOG( OPERATION, ERR,
64                            "get_mra: ber_scanf(\"o\") failure.\n", 0, 0, 0 );
65 #else
66                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for mr\n", 0, 0, 0 );
67 #endif
68
69                         *text = "Error parsing matching rule in matching rule assertion";
70                         return SLAPD_DISCONNECT;
71                 }
72
73                 rtag = ber_scanf( ber, "t", &tag );
74                 if( rtag == LBER_ERROR ) {
75 #ifdef NEW_LOGGING
76                         LDAP_LOG( OPERATION, ERR,
77                            "get_mra: ber_scanf (\"t\") failure\n", 0, 0, 0 );
78 #else
79                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
80 #endif
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 #ifdef NEW_LOGGING
91                         LDAP_LOG( OPERATION, ERR,
92                            "get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
93 #else
94                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf for ad\n", 0, 0, 0 );
95 #endif
96
97                         *text = "Error parsing attribute description in matching rule assertion";
98                         return SLAPD_DISCONNECT;
99                 }
100
101                 rtag = ber_scanf( ber, "t", &tag );
102                 if( rtag == LBER_ERROR ) {
103 #ifdef NEW_LOGGING
104                         LDAP_LOG( OPERATION, ERR,
105                            "get_mra: ber_scanf (\"t\") failure.\n", 0, 0, 0 );
106 #else
107                         Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
108 #endif
109
110                         *text = "Error parsing matching rule assertion";
111                         return SLAPD_DISCONNECT;
112                 }
113         }
114
115         if ( tag != LDAP_FILTER_EXT_VALUE ) {
116 #ifdef NEW_LOGGING
117                 LDAP_LOG( OPERATION, ERR, 
118                         "get_mra: ber_scanf missing value\n", 0, 0, 0 );
119 #else
120                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf missing value\n", 0, 0, 0 );
121 #endif
122
123                 *text = "Missing value in matching rule assertion";
124                 return SLAPD_DISCONNECT;
125         }
126
127         rtag = ber_scanf( ber, "m", &value );
128
129         if( rtag == LBER_ERROR ) {
130 #ifdef NEW_LOGGING
131                 LDAP_LOG( OPERATION, ERR, 
132                         "get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
133 #else
134                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
135 #endif
136
137                 *text = "Error decoding value in matching rule assertion";
138                 return SLAPD_DISCONNECT;
139         }
140
141         tag = ber_peek_tag( ber, &length );
142
143         if ( tag == LDAP_FILTER_EXT_DNATTRS ) {
144                 rtag = ber_scanf( ber, /*"{"*/ "b}", &ma.ma_dnattrs );
145         } else {
146                 rtag = ber_scanf( ber, /*"{"*/ "}" );
147         }
148
149         if( rtag == LBER_ERROR ) {
150 #ifdef NEW_LOGGING
151                 LDAP_LOG( OPERATION, ERR, "get_mra: ber_scanf failure\n", 0, 0, 0);
152 #else
153                 Debug( LDAP_DEBUG_ANY, "  get_mra ber_scanf\n", 0, 0, 0 );
154 #endif
155
156                 *text = "Error decoding dnattrs matching rule assertion";
157                 return SLAPD_DISCONNECT;
158         }
159
160         if( type.bv_val != NULL ) {
161                 rc = slap_bv2ad( &type, &ma.ma_desc, text );
162                 if( rc != LDAP_SUCCESS ) {
163                         return rc;
164                 }
165         }
166
167         if( ma.ma_rule_text.bv_val != NULL ) {
168                 ma.ma_rule = mr_bvfind( &ma.ma_rule_text );
169                 if( ma.ma_rule == NULL ) {
170                         *text = "matching rule not recognized";
171                         return LDAP_INAPPROPRIATE_MATCHING;
172                 }
173         }
174
175         if ( ma.ma_rule == NULL ) {
176                 /*
177                  * Need either type or rule ...
178                  */
179                 if ( ma.ma_desc == NULL ) {
180                         *text = "no matching rule or type";
181                         return LDAP_INAPPROPRIATE_MATCHING;
182                 }
183
184                 if ( ma.ma_desc->ad_type->sat_equality != NULL &&
185                         ma.ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
186                 {
187                         /* no matching rule was provided, use the attribute's
188                            equality rule if it supports extensible matching. */
189                         ma.ma_rule = ma.ma_desc->ad_type->sat_equality;
190
191                 } else {
192                         *text = "no appropriate rule to use for type";
193                         return LDAP_INAPPROPRIATE_MATCHING;
194                 }
195         }
196
197         if ( ma.ma_desc != NULL ) {
198                 if( !mr_usable_with_at( ma.ma_rule, ma.ma_desc->ad_type ) ) {
199                         *text = "matching rule use with this attribute not appropriate";
200                         return LDAP_INAPPROPRIATE_MATCHING;
201                 }
202
203 #ifndef SLAP_NVALUES
204                 /*
205                  * OK, if no matching rule, normalize for equality, otherwise
206                  * normalize for the matching rule.
207                  */
208                 rc = value_validate_normalize( ma.ma_desc, SLAP_MR_EQUALITY,
209                         &value, &ma.ma_value, text );
210         } else {
211                 /*
212                  * Need to normalize, but how?
213                  */
214                 rc = value_validate( ma.ma_rule, &value, text );
215                 if ( rc == LDAP_SUCCESS ) {
216                         ber_dupbv( &ma.ma_value, &value );
217                 }
218 #endif
219         }
220
221 #ifdef SLAP_NVALUES
222         /*
223          * Normalize per matching rule
224          */
225         rc = asserted_value_validate_normalize( ma.ma_desc,
226                 ma.ma_rule,
227                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
228                 &value, &ma.ma_value, text );
229         if ( rc == LDAP_SUCCESS ) {
230                 ma.ma_value = value;
231         } else
232 #else
233         if( rc != LDAP_SUCCESS )
234 #endif
235         {
236                 return rc;
237         }
238
239         *mra = ch_malloc( sizeof ma );
240         **mra = ma;
241
242         return LDAP_SUCCESS;
243 }
244