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