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