]> git.sur5r.net Git - openldap/blob - servers/slapd/value.c
/*
[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_add_one( 
58     BerVarray *vals,
59     struct berval *addval
60 )
61 {
62         int     n;
63         BerVarray v2;
64
65         if ( *vals == NULL ) {
66                 *vals = (BerVarray) ch_malloc( 2 * sizeof(struct berval) );
67                 n = 0;
68         } else {
69                 for ( n = 0; (*vals)[n].bv_val != NULL; n++ ) {
70                         ;       /* Empty */
71                 }
72                 *vals = (BerVarray) ch_realloc( (char *) *vals,
73                     (n + 2) * sizeof(struct berval) );
74         }
75
76         v2 = *vals + n;
77         ber_dupbv(v2, addval);
78
79         v2++;
80         v2->bv_val = NULL;
81         v2->bv_len = 0;
82
83         return LDAP_SUCCESS;
84 }
85
86 int
87 value_validate(
88         MatchingRule *mr,
89         struct berval *in,
90         const char **text )
91 {
92         int rc;
93
94         if( mr == NULL ) {
95                 *text = "inappropriate matching request";
96                 return LDAP_INAPPROPRIATE_MATCHING;
97         }
98
99         if( mr->smr_syntax == NULL ) {
100                 *text = "no assertion syntax";
101                 return LDAP_INVALID_SYNTAX;
102         }
103
104         if( ! mr->smr_syntax->ssyn_validate ) {
105                 *text = "no syntax validator";
106                 return LDAP_INVALID_SYNTAX;
107         }
108
109         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
110
111         if( rc != LDAP_SUCCESS ) {
112                 *text = "value is invalid";
113                 return LDAP_INVALID_SYNTAX;
114         }
115
116         return LDAP_SUCCESS;
117 }
118
119 int
120 value_normalize(
121         AttributeDescription *ad,
122         unsigned usage,
123         struct berval *in,
124         struct berval *out,
125         const char **text )
126 {
127         int rc;
128         MatchingRule *mr;
129
130         switch( usage & SLAP_MR_TYPE_MASK ) {
131         case SLAP_MR_NONE:
132         case SLAP_MR_EQUALITY:
133                 mr = ad->ad_type->sat_equality;
134                 break;
135         case SLAP_MR_ORDERING:
136                 mr = ad->ad_type->sat_ordering;
137                 break;
138         case SLAP_MR_SUBSTR:
139                 mr = ad->ad_type->sat_substr;
140                 break;
141         case SLAP_MR_EXT:
142         default:
143                 assert( 0 );
144                 *text = "internal error";
145                 return LDAP_OTHER;
146         }
147
148         if( mr == NULL ) {
149                 *text = "inappropriate matching request";
150                 return LDAP_INAPPROPRIATE_MATCHING;
151         }
152
153         /* we only support equality matching of binary attributes */
154         /* This is suspect, flexible certificate matching will hit this */
155         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
156                 *text = "inappropriate binary matching";
157                 return LDAP_INAPPROPRIATE_MATCHING;
158         }
159
160         if( mr->smr_normalize ) {
161                 rc = (mr->smr_normalize)( usage,
162                         ad->ad_type->sat_syntax,
163                         mr, in, out );
164
165                 if( rc != LDAP_SUCCESS ) {
166                         *text = "unable to normalize value";
167                         return LDAP_INVALID_SYNTAX;
168                 }
169
170         } else if ( mr->smr_syntax->ssyn_normalize ) {
171                 rc = (mr->smr_syntax->ssyn_normalize)(
172                         ad->ad_type->sat_syntax,
173                         in, out );
174
175                 if( rc != LDAP_SUCCESS ) {
176                         *text = "unable to normalize value";
177                         return LDAP_INVALID_SYNTAX;
178                 }
179
180         } else {
181                 ber_dupbv( out, in );
182         }
183
184         return LDAP_SUCCESS;
185 }
186
187 int
188 value_validate_normalize(
189         AttributeDescription *ad,
190         unsigned usage,
191         struct berval *in,
192         struct berval *out,
193         const char **text )
194 {
195         int rc;
196         MatchingRule *mr;
197
198         switch( usage & SLAP_MR_TYPE_MASK ) {
199         case SLAP_MR_NONE:
200         case SLAP_MR_EQUALITY:
201                 mr = ad->ad_type->sat_equality;
202                 break;
203         case SLAP_MR_ORDERING:
204                 mr = ad->ad_type->sat_ordering;
205                 break;
206         case SLAP_MR_SUBSTR:
207                 mr = ad->ad_type->sat_substr;
208                 break;
209         case SLAP_MR_EXT:
210         default:
211                 assert( 0 );
212                 *text = "internal error";
213                 return LDAP_OTHER;
214         }
215
216         if( mr == NULL ) {
217                 *text = "inappropriate matching request";
218                 return LDAP_INAPPROPRIATE_MATCHING;
219         }
220
221         if( mr->smr_syntax == NULL ) {
222                 *text = "no assertion syntax";
223                 return LDAP_INVALID_SYNTAX;
224         }
225
226         if( ! mr->smr_syntax->ssyn_validate ) {
227                 *text = "no syntax validator";
228                 return LDAP_INVALID_SYNTAX;
229         }
230
231         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
232
233         if( rc != LDAP_SUCCESS ) {
234                 *text = "value is invalid";
235                 return LDAP_INVALID_SYNTAX;
236         }
237
238         /* we only support equality matching of binary attributes */
239         /* This is suspect, flexible certificate matching will hit this */
240         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
241                 *text = "inappropriate binary matching";
242                 return LDAP_INAPPROPRIATE_MATCHING;
243         }
244
245         if( mr->smr_normalize ) {
246                 rc = (mr->smr_normalize)( usage,
247                         ad->ad_type->sat_syntax,
248                         mr, in, out );
249
250                 if( rc != LDAP_SUCCESS ) {
251                         *text = "unable to normalize value";
252                         return LDAP_INVALID_SYNTAX;
253                 }
254
255         } else if ( mr->smr_syntax->ssyn_normalize ) {
256                 rc = (mr->smr_syntax->ssyn_normalize)(
257                         ad->ad_type->sat_syntax,
258                         in, out );
259
260                 if( rc != LDAP_SUCCESS ) {
261                         *text = "unable to normalize value";
262                         return LDAP_INVALID_SYNTAX;
263                 }
264
265         } else {
266                 ber_dupbv( out, in );
267         }
268
269         return LDAP_SUCCESS;
270 }
271
272
273 int
274 value_match(
275         int *match,
276         AttributeDescription *ad,
277         MatchingRule *mr,
278         unsigned flags,
279         struct berval *v1, /* stored value */
280         void *v2, /* assertion */
281         const char ** text )
282 {
283         int rc;
284         struct berval nv1 = { 0, NULL };
285         struct berval nv2 = { 0, NULL };
286
287         if( !mr->smr_match ) {
288                 return LDAP_INAPPROPRIATE_MATCHING;
289         }
290
291         if( ad->ad_type->sat_syntax->ssyn_normalize ) {
292                 rc = ad->ad_type->sat_syntax->ssyn_normalize(
293                         ad->ad_type->sat_syntax, v1, &nv1 );
294
295                 if( rc != LDAP_SUCCESS ) {
296                         return LDAP_INAPPROPRIATE_MATCHING;
297                 }
298         }
299
300         if ( SLAP_IS_MR_VALUE_SYNTAX_NONCONVERTED_MATCH( flags ) &&
301                 mr->smr_convert )
302         {
303                 rc = (mr->smr_convert)( v2, &nv2 );
304                 if ( rc != LDAP_SUCCESS ) {
305                         return LDAP_INVALID_SYNTAX;
306                 }
307
308                 /* let smr_match know we've converted the value */
309                 flags |= SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH;
310         }
311
312         rc = (mr->smr_match)( match, flags,
313                 ad->ad_type->sat_syntax,
314                 mr,
315                 nv1.bv_val != NULL ? &nv1 : v1,
316                 nv2.bv_val != NULL ? &nv2 : v2 );
317         
318         if (nv1.bv_val ) free( nv1.bv_val );
319         if (nv2.bv_val ) free( nv2.bv_val );
320         return rc;
321 }
322
323
324 int value_find_ex(
325         AttributeDescription *ad,
326         unsigned flags,
327         BerVarray vals,
328         struct berval *val )
329 {
330         int     i;
331         int rc;
332         struct berval nval = { 0, NULL };
333         MatchingRule *mr = ad->ad_type->sat_equality;
334
335         if( mr == NULL || !mr->smr_match ) {
336                 return LDAP_INAPPROPRIATE_MATCHING;
337         }
338
339         /* Take care of this here or ssyn_normalize later will hurt */
340         if ( SLAP_IS_MR_VALUE_SYNTAX_NONCONVERTED_MATCH( flags )
341                 && mr->smr_convert )
342         {
343                 rc = (mr->smr_convert)( val, &nval );
344                 if ( rc != LDAP_SUCCESS ) {
345                         return LDAP_INVALID_SYNTAX;
346                 }
347
348                 /* let value_match know we've done the version */
349                 flags |= SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH;
350         }
351
352         if( mr->smr_syntax->ssyn_normalize ) {
353                 struct berval nval_tmp;
354
355                 rc = mr->smr_syntax->ssyn_normalize(
356                         mr->smr_syntax,
357                         nval.bv_val == NULL ? val : &nval, &nval_tmp );
358
359                 free(nval.bv_val);
360                 nval = nval_tmp;
361                 if( rc != LDAP_SUCCESS ) {
362                         free(nval.bv_val);
363                         return LDAP_INAPPROPRIATE_MATCHING;
364                 }
365         }
366
367         for ( i = 0; vals[i].bv_val != NULL; i++ ) {
368                 int match;
369                 const char *text;
370
371                 rc = value_match( &match, ad, mr, flags,
372                         &vals[i], nval.bv_val == NULL ? val : &nval, &text );
373
374                 if( rc == LDAP_SUCCESS && match == 0 ) {
375                         free( nval.bv_val );
376                         return LDAP_SUCCESS;
377                 }
378         }
379
380         free( nval.bv_val );
381         return LDAP_NO_SUCH_ATTRIBUTE;
382 }