]> git.sur5r.net Git - openldap/blob - servers/slapd/value.c
83ec803257317ec46768e31110d75641a0699f5c
[openldap] / servers / slapd / value.c
1 /* value.c - routines for dealing with values */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 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) SLAP_MALLOC( (nn + 1)
35                     * sizeof(struct berval) );
36                 if( *vals == NULL ) {
37 #ifdef NEW_LOGGING
38                          LDAP_LOG( OPERATION, ERR,
39                       "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
40 #else
41                         Debug(LDAP_DEBUG_TRACE,
42                       "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
43 #endif
44                         return LBER_ERROR_MEMORY;
45                 }
46                 n = 0;
47         } else {
48                 for ( n = 0; (*vals)[n].bv_val != NULL; n++ ) {
49                         ;       /* Empty */
50                 }
51                 *vals = (BerVarray) SLAP_REALLOC( (char *) *vals,
52                     (n + nn + 1) * sizeof(struct berval) );
53                 if( *vals == NULL ) {
54 #ifdef NEW_LOGGING
55                          LDAP_LOG( OPERATION, ERR,
56                       "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
57 #else
58                         Debug(LDAP_DEBUG_TRACE,
59                       "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
60 #endif
61                         return LBER_ERROR_MEMORY;
62                 }
63         }
64
65         v2 = *vals + n;
66         for ( ; addvals->bv_val; v2++, addvals++ ) {
67                 ber_dupbv(v2, addvals);
68                 if (v2->bv_val == NULL) break;
69         }
70         v2->bv_val = NULL;
71         v2->bv_len = 0;
72
73         return LDAP_SUCCESS;
74 }
75
76 int
77 value_add_one( 
78     BerVarray *vals,
79     struct berval *addval
80 )
81 {
82         int     n;
83         BerVarray v2;
84
85         if ( *vals == NULL ) {
86                 *vals = (BerVarray) SLAP_MALLOC( 2 * sizeof(struct berval) );
87                 if( *vals == NULL ) {
88 #ifdef NEW_LOGGING
89                          LDAP_LOG( OPERATION, ERR,
90                       "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
91 #else
92                         Debug(LDAP_DEBUG_TRACE,
93                       "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
94 #endif
95                         return LBER_ERROR_MEMORY;
96                 }
97                 n = 0;
98         } else {
99                 for ( n = 0; (*vals)[n].bv_val != NULL; n++ ) {
100                         ;       /* Empty */
101                 }
102                 *vals = (BerVarray) SLAP_REALLOC( (char *) *vals,
103                     (n + 2) * sizeof(struct berval) );
104                 if( *vals == NULL ) {
105 #ifdef NEW_LOGGING
106                          LDAP_LOG( OPERATION, ERR,
107                       "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
108 #else
109                         Debug(LDAP_DEBUG_TRACE,
110                       "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
111 #endif
112                         return LBER_ERROR_MEMORY;
113                 }
114         }
115
116         v2 = *vals + n;
117         ber_dupbv(v2, addval);
118
119         v2++;
120         v2->bv_val = NULL;
121         v2->bv_len = 0;
122
123         return LDAP_SUCCESS;
124 }
125
126 #ifdef SLAP_NVALUES
127 int asserted_value_validate_normalize( 
128         AttributeDescription *ad,
129         MatchingRule *mr,
130         unsigned usage,
131         struct berval *in,
132         struct berval *out,
133         const char ** text )
134 {
135         int rc;
136
137         /* we expect the value to be in the assertion syntax */
138         assert( !SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
139
140         if( mr == NULL ) {
141                 *text = "inappropriate matching request";
142                 return LDAP_INAPPROPRIATE_MATCHING;
143         }
144
145         if( !mr->smr_match ) {
146                 *text = "requested matching rule not supported";
147                 return LDAP_INAPPROPRIATE_MATCHING;
148         }
149
150         assert( mr->smr_syntax );
151         assert( mr->smr_syntax->ssyn_validate );
152
153         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
154
155         if( rc != LDAP_SUCCESS ) {
156                 *text = "value does not conform to assertion syntax";
157                 return LDAP_INVALID_SYNTAX;
158         }
159
160         if( mr->smr_normalize ) {
161                 rc = (mr->smr_normalize)( usage,
162                         ad ? ad->ad_type->sat_syntax : NULL,
163                         mr, in, out );
164
165                 if( rc != LDAP_SUCCESS ) {
166                         *text = "unable to normalize value for matching";
167                         return LDAP_INVALID_SYNTAX;
168                 }
169
170         } else {
171                 ber_dupbv( out, in );
172         }
173 }
174
175 #else
176 int
177 value_validate(
178         MatchingRule *mr,
179         struct berval *in,
180         const char **text )
181 {
182         int rc;
183
184         if( mr == NULL ) {
185                 *text = "inappropriate matching request";
186                 return LDAP_INAPPROPRIATE_MATCHING;
187         }
188
189         if( mr->smr_syntax == NULL ) {
190                 *text = "no assertion syntax";
191                 return LDAP_INVALID_SYNTAX;
192         }
193
194         if( ! mr->smr_syntax->ssyn_validate ) {
195                 *text = "no syntax validator";
196                 return LDAP_INVALID_SYNTAX;
197         }
198
199         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
200
201         if( rc != LDAP_SUCCESS ) {
202                 *text = "value is invalid";
203                 return LDAP_INVALID_SYNTAX;
204         }
205
206         return LDAP_SUCCESS;
207 }
208
209 int
210 value_normalize(
211         AttributeDescription *ad,
212         unsigned usage,
213         struct berval *in,
214         struct berval *out,
215         const char **text )
216 {
217         int rc;
218         MatchingRule *mr = ad_mr( ad, usage );
219
220         if( mr == NULL ) {
221                 *text = "inappropriate matching request";
222                 return LDAP_INAPPROPRIATE_MATCHING;
223         }
224
225         /* we only support equality matching of binary attributes */
226         /* This is suspect, flexible certificate matching will hit this */
227         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
228                 *text = "inappropriate binary matching";
229                 return LDAP_INAPPROPRIATE_MATCHING;
230         }
231
232         if( mr->smr_normalize ) {
233                 rc = (mr->smr_normalize)( usage,
234                         ad->ad_type->sat_syntax,
235                         mr, in, out );
236
237                 if( rc != LDAP_SUCCESS ) {
238                         *text = "unable to normalize value";
239                         return LDAP_INVALID_SYNTAX;
240                 }
241
242         } else if ( mr->smr_syntax->ssyn_normalize ) {
243                 rc = (mr->smr_syntax->ssyn_normalize)(
244                         ad->ad_type->sat_syntax,
245                         in, out );
246
247                 if( rc != LDAP_SUCCESS ) {
248                         *text = "unable to normalize value";
249                         return LDAP_INVALID_SYNTAX;
250                 }
251
252         } else {
253                 ber_dupbv( out, in );
254         }
255
256         return LDAP_SUCCESS;
257 }
258
259 int
260 value_validate_normalize(
261         AttributeDescription *ad,
262         unsigned usage,
263         struct berval *in,
264         struct berval *out,
265         const char **text )
266 {
267         int rc;
268         MatchingRule *mr = ad_mr( ad, usage );
269
270         if( mr == NULL ) {
271                 *text = "inappropriate matching request";
272                 return LDAP_INAPPROPRIATE_MATCHING;
273         }
274
275         if( mr->smr_syntax == NULL ) {
276                 *text = "no assertion syntax";
277                 return LDAP_INVALID_SYNTAX;
278         }
279
280         if( ! mr->smr_syntax->ssyn_validate ) {
281                 *text = "no syntax validator";
282                 return LDAP_INVALID_SYNTAX;
283         }
284
285         rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
286
287         if( rc != LDAP_SUCCESS ) {
288                 *text = "value is invalid";
289                 return LDAP_INVALID_SYNTAX;
290         }
291
292         /* we only support equality matching of binary attributes */
293         /* This is suspect, flexible certificate matching will hit this */
294         if( slap_ad_is_binary( ad ) && usage != SLAP_MR_EQUALITY ) {
295                 *text = "inappropriate binary matching";
296                 return LDAP_INAPPROPRIATE_MATCHING;
297         }
298
299         if( mr->smr_normalize ) {
300                 rc = (mr->smr_normalize)( usage,
301                         ad->ad_type->sat_syntax,
302                         mr, in, out );
303
304                 if( rc != LDAP_SUCCESS ) {
305                         *text = "unable to normalize value";
306                         return LDAP_INVALID_SYNTAX;
307                 }
308
309         } else if ( mr->smr_syntax->ssyn_normalize ) {
310                 rc = (mr->smr_syntax->ssyn_normalize)(
311                         ad->ad_type->sat_syntax,
312                         in, out );
313
314                 if( rc != LDAP_SUCCESS ) {
315                         *text = "unable to normalize value";
316                         return LDAP_INVALID_SYNTAX;
317                 }
318
319         } else {
320                 ber_dupbv( out, in );
321         }
322
323         return LDAP_SUCCESS;
324 }
325 #endif
326
327 int
328 value_match(
329         int *match,
330         AttributeDescription *ad,
331         MatchingRule *mr,
332         unsigned flags,
333         struct berval *v1, /* stored value */
334         void *v2, /* assertion */
335         const char ** text )
336 {
337         int rc;
338         struct berval nv1 = { 0, NULL };
339         struct berval nv2 = { 0, NULL };
340
341         assert( mr != NULL );
342
343         if( !mr->smr_match ) {
344                 return LDAP_INAPPROPRIATE_MATCHING;
345         }
346
347 #ifndef SLAP_NVALUES
348         if( ad->ad_type->sat_syntax->ssyn_normalize ) {
349                 rc = ad->ad_type->sat_syntax->ssyn_normalize(
350                         ad->ad_type->sat_syntax, v1, &nv1 );
351
352                 if( rc != LDAP_SUCCESS ) {
353                         return LDAP_INAPPROPRIATE_MATCHING;
354                 }
355         }
356
357         if ( SLAP_IS_MR_ATTRIBUTE_SYNTAX_NONCONVERTED_MATCH( flags ) &&
358                 mr->smr_convert )
359         {
360                 rc = (mr->smr_convert)( v2, &nv2 );
361                 if ( rc != LDAP_SUCCESS ) {
362                         return LDAP_INVALID_SYNTAX;
363                 }
364
365                 /* let smr_match know we've converted the value */
366                 flags |= SLAP_MR_ATTRIBUTE_SYNTAX_CONVERTED_MATCH;
367         }
368 #endif
369
370         rc = (mr->smr_match)( match, flags,
371                 ad->ad_type->sat_syntax,
372                 mr,
373                 nv1.bv_val != NULL ? &nv1 : v1,
374                 nv2.bv_val != NULL ? &nv2 : v2 );
375         
376         if (nv1.bv_val ) free( nv1.bv_val );
377         if (nv2.bv_val ) free( nv2.bv_val );
378         return rc;
379 }
380
381 int value_find_ex(
382         AttributeDescription *ad,
383         unsigned flags,
384         BerVarray vals,
385         struct berval *val )
386 {
387         int     i;
388         int rc;
389         struct berval nval = { 0, NULL };
390         MatchingRule *mr = ad->ad_type->sat_equality;
391
392         if( mr == NULL || !mr->smr_match ) {
393                 return LDAP_INAPPROPRIATE_MATCHING;
394         }
395
396 #ifdef SLAP_NVALUES
397         assert(SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( flags ));
398
399         if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) &&
400                 mr->smr_normalize )
401         {
402                 rc = (mr->smr_normalize)(
403                         flags & SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK,
404                         ad ? ad->ad_type->sat_syntax : NULL,
405                         mr, val, &nval );
406
407                 if( rc != LDAP_SUCCESS ) {
408                         return LDAP_INVALID_SYNTAX;
409                 }
410         }
411 #else
412
413         /* Take care of this here or ssyn_normalize later will hurt */
414         if ( SLAP_IS_MR_ATTRIBUTE_SYNTAX_NONCONVERTED_MATCH( flags )
415                 && mr->smr_convert )
416         {
417                 rc = (mr->smr_convert)( val, &nval );
418                 if ( rc != LDAP_SUCCESS ) {
419                         return LDAP_INVALID_SYNTAX;
420                 }
421
422                 /* let value_match know we've done the version */
423                 flags |= SLAP_MR_ATTRIBUTE_SYNTAX_CONVERTED_MATCH;
424         }
425
426         if( !(flags & SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH) &&
427                 mr->smr_syntax->ssyn_normalize )
428         {
429                 struct berval nval_tmp = { 0, NULL };
430
431                 rc = mr->smr_syntax->ssyn_normalize(
432                         mr->smr_syntax,
433                         nval.bv_val == NULL ? val : &nval, &nval_tmp );
434
435                 free(nval.bv_val);
436                 nval = nval_tmp;
437                 if( rc != LDAP_SUCCESS ) {
438                         free(nval.bv_val);
439                         return LDAP_INAPPROPRIATE_MATCHING;
440                 }
441         }
442 #endif
443
444         for ( i = 0; vals[i].bv_val != NULL; i++ ) {
445                 int match;
446                 const char *text;
447
448                 rc = value_match( &match, ad, mr, flags,
449                         &vals[i], nval.bv_val == NULL ? val : &nval, &text );
450
451                 if( rc == LDAP_SUCCESS && match == 0 ) {
452                         free( nval.bv_val );
453                         return LDAP_SUCCESS;
454                 }
455         }
456
457         free( nval.bv_val );
458         return LDAP_NO_SUCH_ATTRIBUTE;
459 }