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