]> git.sur5r.net Git - openldap/blob - servers/slapd/value.c
syntax and mr plugins
[openldap] / servers / slapd / value.c
1 /* value.c - routines for dealing with values */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include <sys/stat.h>
18
19 #include "slap.h"
20
21 int
22 value_add( 
23     BerVarray *vals,
24     BerVarray addvals
25 )
26 {
27         int     n, nn;
28         BerVarray v2;
29
30         for ( nn = 0; addvals != NULL && addvals[nn].bv_val != NULL; nn++ )
31                 ;       /* NULL */
32
33         if ( *vals == NULL ) {
34                 *vals = (BerVarray) ch_malloc( (nn + 1)
35                     * sizeof(struct berval) );
36                 n = 0;
37         } else {
38                 for ( n = 0; (*vals)[n].bv_val != NULL; n++ ) {
39                         ;       /* Empty */
40                 }
41                 *vals = (BerVarray) ch_realloc( (char *) *vals,
42                     (n + nn + 1) * sizeof(struct berval) );
43         }
44
45         v2 = *vals + n;
46         for ( ; addvals->bv_val; v2++, addvals++ ) {
47                 ber_dupbv(v2, addvals);
48                 if (v2->bv_val == NULL) break;
49         }
50         v2->bv_val = NULL;
51         v2->bv_len = 0;
52
53         return LDAP_SUCCESS;
54 }
55
56 int
57 value_validate(
58         MatchingRule *mr,
59         struct berval *in,
60         const char **text )
61 {
62         int rc;
63
64         if( mr == NULL ) {
65                 *text = "inappropriate matching request";
66                 return LDAP_INAPPROPRIATE_MATCHING;
67         }
68
69         if( mr->smr_syntax == NULL ) {
70                 *text = "no assertion syntax";
71                 return LDAP_INVALID_SYNTAX;
72         }
73
74         if( ! mr->smr_syntax->ssyn_validate ) {
75                 *text = "no syntax validator";
76                 return LDAP_INVALID_SYNTAX;
77         }
78
79         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
80
81         if( rc != LDAP_SUCCESS ) {
82                 *text = "value is invalid";
83                 return LDAP_INVALID_SYNTAX;
84         }
85
86         return LDAP_SUCCESS;
87 }
88
89 int
90 value_normalize(
91         AttributeDescription *ad,
92         unsigned usage,
93         struct berval *in,
94         struct berval *out,
95         const char **text )
96 {
97         int rc;
98         MatchingRule *mr;
99
100         switch( usage & SLAP_MR_TYPE_MASK ) {
101         case SLAP_MR_NONE:
102         case SLAP_MR_EQUALITY:
103                 mr = ad->ad_type->sat_equality;
104                 break;
105         case SLAP_MR_ORDERING:
106                 mr = ad->ad_type->sat_ordering;
107                 break;
108         case SLAP_MR_SUBSTR:
109                 mr = ad->ad_type->sat_substr;
110                 break;
111         case SLAP_MR_EXT:
112         default:
113                 assert( 0 );
114                 *text = "internal error";
115                 return LDAP_OTHER;
116         }
117
118         if( mr == NULL ) {
119                 *text = "inappropriate matching request";
120                 return LDAP_INAPPROPRIATE_MATCHING;
121         }
122
123         /* we only support equality matching of binary attributes */
124         /* This is suspect, flexible certificate matching will hit this */
125         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
126                 *text = "inappropriate binary matching";
127                 return LDAP_INAPPROPRIATE_MATCHING;
128         }
129
130         if( mr->smr_normalize ) {
131                 rc = (mr->smr_normalize)( usage,
132                         ad->ad_type->sat_syntax,
133                         mr, in, out );
134
135                 if( rc != LDAP_SUCCESS ) {
136                         *text = "unable to normalize value";
137                         return LDAP_INVALID_SYNTAX;
138                 }
139
140         } else if ( mr->smr_syntax->ssyn_normalize ) {
141                 rc = (mr->smr_syntax->ssyn_normalize)(
142                         ad->ad_type->sat_syntax,
143                         in, out );
144
145                 if( rc != LDAP_SUCCESS ) {
146                         *text = "unable to normalize value";
147                         return LDAP_INVALID_SYNTAX;
148                 }
149
150         } else {
151                 ber_dupbv( out, in );
152         }
153
154         return LDAP_SUCCESS;
155 }
156
157 int
158 value_validate_normalize(
159         AttributeDescription *ad,
160         unsigned usage,
161         struct berval *in,
162         struct berval *out,
163         const char **text )
164 {
165         int rc;
166         MatchingRule *mr;
167
168         switch( usage & SLAP_MR_TYPE_MASK ) {
169         case SLAP_MR_NONE:
170         case SLAP_MR_EQUALITY:
171                 mr = ad->ad_type->sat_equality;
172                 break;
173         case SLAP_MR_ORDERING:
174                 mr = ad->ad_type->sat_ordering;
175                 break;
176         case SLAP_MR_SUBSTR:
177                 mr = ad->ad_type->sat_substr;
178                 break;
179         case SLAP_MR_EXT:
180         default:
181                 assert( 0 );
182                 *text = "internal error";
183                 return LDAP_OTHER;
184         }
185
186         if( mr == NULL ) {
187                 *text = "inappropriate matching request";
188                 return LDAP_INAPPROPRIATE_MATCHING;
189         }
190
191         if( mr->smr_syntax == NULL ) {
192                 *text = "no assertion syntax";
193                 return LDAP_INVALID_SYNTAX;
194         }
195
196         if( ! mr->smr_syntax->ssyn_validate ) {
197                 *text = "no syntax validator";
198                 return LDAP_INVALID_SYNTAX;
199         }
200
201         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
202
203         if( rc != LDAP_SUCCESS ) {
204                 *text = "value is invalid";
205                 return LDAP_INVALID_SYNTAX;
206         }
207
208         /* we only support equality matching of binary attributes */
209         /* This is suspect, flexible certificate matching will hit this */
210         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
211                 *text = "inappropriate binary matching";
212                 return LDAP_INAPPROPRIATE_MATCHING;
213         }
214
215         if( mr->smr_normalize ) {
216                 rc = (mr->smr_normalize)( usage,
217                         ad->ad_type->sat_syntax,
218                         mr, in, out );
219
220                 if( rc != LDAP_SUCCESS ) {
221                         *text = "unable to normalize value";
222                         return LDAP_INVALID_SYNTAX;
223                 }
224
225         } else if ( mr->smr_syntax->ssyn_normalize ) {
226                 rc = (mr->smr_syntax->ssyn_normalize)(
227                         ad->ad_type->sat_syntax,
228                         in, out );
229
230                 if( rc != LDAP_SUCCESS ) {
231                         *text = "unable to normalize value";
232                         return LDAP_INVALID_SYNTAX;
233                 }
234
235         } else {
236                 ber_dupbv( out, in );
237         }
238
239         return LDAP_SUCCESS;
240 }
241
242
243 int
244 value_match(
245         int *match,
246         AttributeDescription *ad,
247         MatchingRule *mr,
248         unsigned flags,
249         struct berval *v1, /* stored value */
250         void *v2, /* assertion */
251         const char ** text )
252 {
253         int rc;
254         struct berval nv1 = { 0, NULL };
255         struct berval nv2 = { 0, NULL };
256
257         if( !mr->smr_match ) {
258                 return LDAP_INAPPROPRIATE_MATCHING;
259         }
260
261         if( ad->ad_type->sat_syntax->ssyn_normalize ) {
262                 rc = ad->ad_type->sat_syntax->ssyn_normalize(
263                         ad->ad_type->sat_syntax, v1, &nv1 );
264
265                 if( rc != LDAP_SUCCESS ) {
266                         return LDAP_INAPPROPRIATE_MATCHING;
267                 }
268         }
269
270         if ( SLAP_IS_MR_VALUE_SYNTAX_NONCONVERTED_MATCH( flags ) &&
271                 mr->smr_convert )
272         {
273                 rc = (mr->smr_convert)( v2, &nv2 );
274                 if ( rc != LDAP_SUCCESS ) {
275                         return LDAP_INVALID_SYNTAX;
276                 }
277
278                 /* let smr_match know we've converted the value */
279                 flags |= SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH;
280         }
281
282         rc = (mr->smr_match)( match, flags,
283                 ad->ad_type->sat_syntax,
284                 mr,
285                 nv1.bv_val != NULL ? &nv1 : v1,
286                 nv2.bv_val != NULL ? &nv2 : v2 );
287         
288         if (nv1.bv_val ) free( nv1.bv_val );
289         if (nv2.bv_val ) free( nv2.bv_val );
290         return rc;
291 }
292
293
294 int value_find_ex(
295         AttributeDescription *ad,
296         unsigned flags,
297         BerVarray vals,
298         struct berval *val )
299 {
300         int     i;
301         int rc;
302         struct berval nval = { 0, NULL };
303         struct berval nval_tmp;
304         MatchingRule *mr = ad->ad_type->sat_equality;
305
306         if( mr == NULL || !mr->smr_match ) {
307                 return LDAP_INAPPROPRIATE_MATCHING;
308         }
309
310         /* Take care of this here or ssyn_normalize later will hurt */
311         if ( SLAP_IS_MR_VALUE_SYNTAX_NONCONVERTED_MATCH( flags )
312                 && mr->smr_convert )
313         {
314                 rc = (mr->smr_convert)( val, &nval );
315                 if ( rc != LDAP_SUCCESS ) {
316                         return LDAP_INVALID_SYNTAX;
317                 }
318
319                 /* let value_match know we've done the version */
320                 flags |= SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH;
321         }
322
323         if( mr->smr_syntax->ssyn_normalize ) {
324                 rc = mr->smr_syntax->ssyn_normalize(
325                         mr->smr_syntax, nval.bv_val == NULL ? val : &nval, &nval_tmp );
326
327                 free(nval.bv_val);
328                 nval = nval_tmp;
329                 if( rc != LDAP_SUCCESS ) {
330                         free(nval.bv_val);
331                         return LDAP_INAPPROPRIATE_MATCHING;
332                 }
333         }
334
335         for ( i = 0; vals[i].bv_val != NULL; i++ ) {
336                 int match;
337                 const char *text;
338
339                 rc = value_match( &match, ad, mr, flags,
340                         &vals[i], nval.bv_val == NULL ? val : &nval, &text );
341
342                 if( rc == LDAP_SUCCESS && match == 0 ) {
343                         free( nval.bv_val );
344                         return LDAP_SUCCESS;
345                 }
346         }
347
348         free( nval.bv_val );
349         return LDAP_NO_SUCH_ATTRIBUTE;
350 }