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