1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT );
69 ldap_pvt_thread_mutex_t ad_undef_mutex;
70 ldap_pvt_thread_mutex_t oc_undef_mutex;
73 generalizedTimeValidate(
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 /* X.509 related stuff */
116 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
119 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
120 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
121 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
122 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
126 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
129 /* X.509 certificate validation */
130 static int certificateValidate( Syntax *syntax, struct berval *in )
132 BerElementBuffer berbuf;
133 BerElement *ber = (BerElement *)&berbuf;
136 ber_int_t version = SLAP_X509_V1;
138 ber_init2( ber, in, LBER_USE_DER );
139 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 tag = ber_skip_tag( ber, &len ); /* Sequence */
142 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
143 tag = ber_peek_tag( ber, &len );
144 /* Optional version */
145 if ( tag == SLAP_X509_OPT_C_VERSION ) {
146 tag = ber_skip_tag( ber, &len );
147 tag = ber_get_int( ber, &version );
148 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
150 /* NOTE: don't try to parse Serial, because it might be longer
151 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
152 tag = ber_skip_tag( ber, &len ); /* Serial */
153 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len ); /* Validity */
162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len ); /* Subject DN */
165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
166 ber_skip_data( ber, len );
167 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
168 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
169 ber_skip_data( ber, len );
170 tag = ber_skip_tag( ber, &len );
171 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
172 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
173 ber_skip_data( ber, len );
174 tag = ber_skip_tag( ber, &len );
176 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
177 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
178 ber_skip_data( ber, len );
179 tag = ber_skip_tag( ber, &len );
181 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
182 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
183 tag = ber_skip_tag( ber, &len );
184 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
185 ber_skip_data( ber, len );
186 tag = ber_skip_tag( ber, &len );
188 /* signatureAlgorithm */
189 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
190 ber_skip_data( ber, len );
191 tag = ber_skip_tag( ber, &len );
193 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
194 ber_skip_data( ber, len );
195 tag = ber_skip_tag( ber, &len );
196 /* Must be at end now */
197 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
201 /* X.509 certificate list validation */
202 static int certificateListValidate( Syntax *syntax, struct berval *in )
204 BerElementBuffer berbuf;
205 BerElement *ber = (BerElement *)&berbuf;
208 ber_int_t version = SLAP_X509_V1;
210 ber_init2( ber, in, LBER_USE_DER );
211 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_skip_tag( ber, &len ); /* Sequence */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_peek_tag( ber, &len );
216 /* Optional version */
217 if ( tag == LBER_INTEGER ) {
218 tag = ber_get_int( ber, &version );
219 assert( tag == LBER_INTEGER );
220 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
222 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
223 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
224 ber_skip_data( ber, len );
225 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
226 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
227 ber_skip_data( ber, len );
228 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
229 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
230 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 /* Optional nextUpdate */
233 tag = ber_skip_tag( ber, &len );
234 if ( tag == 0x17U || tag == 0x18U ) {
235 ber_skip_data( ber, len );
236 tag = ber_skip_tag( ber, &len );
238 /* revokedCertificates - Sequence of Sequence, Optional */
239 if ( tag == LBER_SEQUENCE ) {
241 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
242 /* Should NOT be empty */
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
247 /* Optional Extensions */
248 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
249 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
250 tag = ber_skip_tag( ber, &len );
251 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 /* signatureAlgorithm */
256 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
257 ber_skip_data( ber, len );
258 tag = ber_skip_tag( ber, &len );
260 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
261 ber_skip_data( ber, len );
262 tag = ber_skip_tag( ber, &len );
263 /* Must be at end now */
264 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
274 struct berval *value,
275 void *assertedValue )
277 struct berval *asserted = (struct berval *) assertedValue;
278 int match = value->bv_len - asserted->bv_len;
281 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
289 octetStringOrderingMatch(
294 struct berval *value,
295 void *assertedValue )
297 struct berval *asserted = (struct berval *) assertedValue;
298 ber_len_t v_len = value->bv_len;
299 ber_len_t av_len = asserted->bv_len;
301 int match = memcmp( value->bv_val, asserted->bv_val,
302 (v_len < av_len ? v_len : av_len) );
304 if( match == 0 ) match = v_len - av_len;
312 HASH_CONTEXT *HASHcontext,
313 struct berval *prefix,
318 HASH_Init(HASHcontext);
319 if(prefix && prefix->bv_len > 0) {
320 HASH_Update(HASHcontext,
321 (unsigned char *)prefix->bv_val, prefix->bv_len);
323 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
324 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
325 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
331 HASH_CONTEXT *HASHcontext,
332 unsigned char *HASHdigest,
333 unsigned char *value,
336 HASH_CONTEXT ctx = *HASHcontext;
337 HASH_Update( &ctx, value, len );
338 HASH_Final( HASHdigest, &ctx );
341 /* Index generation function */
342 int octetStringIndexer(
347 struct berval *prefix,
355 HASH_CONTEXT HASHcontext;
356 unsigned char HASHdigest[HASH_BYTES];
357 struct berval digest;
358 digest.bv_val = (char *)HASHdigest;
359 digest.bv_len = sizeof(HASHdigest);
361 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
362 /* just count them */
365 /* we should have at least one value at this point */
368 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
370 slen = syntax->ssyn_oidlen;
371 mlen = mr->smr_oidlen;
373 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
374 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
375 hashIter( &HASHcontext, HASHdigest,
376 (unsigned char *)values[i].bv_val, values[i].bv_len );
377 ber_dupbv_x( &keys[i], &digest, ctx );
380 BER_BVZERO( &keys[i] );
387 /* Index generation function */
388 int octetStringFilter(
393 struct berval *prefix,
394 void * assertedValue,
400 HASH_CONTEXT HASHcontext;
401 unsigned char HASHdigest[HASH_BYTES];
402 struct berval *value = (struct berval *) assertedValue;
403 struct berval digest;
404 digest.bv_val = (char *)HASHdigest;
405 digest.bv_len = sizeof(HASHdigest);
407 slen = syntax->ssyn_oidlen;
408 mlen = mr->smr_oidlen;
410 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
412 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
413 hashIter( &HASHcontext, HASHdigest,
414 (unsigned char *)value->bv_val, value->bv_len );
416 ber_dupbv_x( keys, &digest, ctx );
417 BER_BVZERO( &keys[1] );
425 octetStringSubstringsMatch(
430 struct berval *value,
431 void *assertedValue )
434 SubstringsAssertion *sub = assertedValue;
435 struct berval left = *value;
439 /* Add up asserted input length */
440 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
441 inlen += sub->sa_initial.bv_len;
444 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
445 inlen += sub->sa_any[i].bv_len;
448 if ( !BER_BVISNULL( &sub->sa_final ) ) {
449 inlen += sub->sa_final.bv_len;
452 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
453 if ( inlen > left.bv_len ) {
458 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
459 sub->sa_initial.bv_len );
465 left.bv_val += sub->sa_initial.bv_len;
466 left.bv_len -= sub->sa_initial.bv_len;
467 inlen -= sub->sa_initial.bv_len;
470 if ( !BER_BVISNULL( &sub->sa_final ) ) {
471 if ( inlen > left.bv_len ) {
476 match = memcmp( sub->sa_final.bv_val,
477 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
478 sub->sa_final.bv_len );
484 left.bv_len -= sub->sa_final.bv_len;
485 inlen -= sub->sa_final.bv_len;
489 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
494 if ( inlen > left.bv_len ) {
495 /* not enough length */
500 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
504 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
511 idx = p - left.bv_val;
513 if ( idx >= left.bv_len ) {
514 /* this shouldn't happen */
521 if ( sub->sa_any[i].bv_len > left.bv_len ) {
522 /* not enough left */
527 match = memcmp( left.bv_val,
528 sub->sa_any[i].bv_val,
529 sub->sa_any[i].bv_len );
537 left.bv_val += sub->sa_any[i].bv_len;
538 left.bv_len -= sub->sa_any[i].bv_len;
539 inlen -= sub->sa_any[i].bv_len;
548 /* Substrings Index generation function */
550 octetStringSubstringsIndexer(
555 struct berval *prefix,
564 HASH_CONTEXT HCany, HCini, HCfin;
565 unsigned char HASHdigest[HASH_BYTES];
566 struct berval digest;
567 digest.bv_val = (char *)HASHdigest;
568 digest.bv_len = sizeof(HASHdigest);
572 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
573 /* count number of indices to generate */
574 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
575 if( values[i].bv_len >= index_substr_if_maxlen ) {
576 nkeys += index_substr_if_maxlen -
577 (index_substr_if_minlen - 1);
578 } else if( values[i].bv_len >= index_substr_if_minlen ) {
579 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
583 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
584 if( values[i].bv_len >= index_substr_any_len ) {
585 nkeys += values[i].bv_len - (index_substr_any_len - 1);
589 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
590 if( values[i].bv_len >= index_substr_if_maxlen ) {
591 nkeys += index_substr_if_maxlen -
592 (index_substr_if_minlen - 1);
593 } else if( values[i].bv_len >= index_substr_if_minlen ) {
594 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
600 /* no keys to generate */
605 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
607 slen = syntax->ssyn_oidlen;
608 mlen = mr->smr_oidlen;
610 if ( flags & SLAP_INDEX_SUBSTR_ANY )
611 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
612 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
613 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
614 if( flags & SLAP_INDEX_SUBSTR_FINAL )
615 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
618 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
621 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
622 ( values[i].bv_len >= index_substr_any_len ) )
624 max = values[i].bv_len - (index_substr_any_len - 1);
626 for( j=0; j<max; j++ ) {
627 hashIter( &HCany, HASHdigest,
628 (unsigned char *)&values[i].bv_val[j],
629 index_substr_any_len );
630 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 /* skip if too short */
635 if( values[i].bv_len < index_substr_if_minlen ) continue;
637 max = index_substr_if_maxlen < values[i].bv_len
638 ? index_substr_if_maxlen : values[i].bv_len;
640 for( j=index_substr_if_minlen; j<=max; j++ ) {
642 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
643 hashIter( &HCini, HASHdigest,
644 (unsigned char *)values[i].bv_val, j );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
649 hashIter( &HCfin, HASHdigest,
650 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 BER_BVZERO( &keys[nkeys] );
669 octetStringSubstringsFilter (
674 struct berval *prefix,
675 void * assertedValue,
679 SubstringsAssertion *sa;
682 size_t slen, mlen, klen;
684 HASH_CONTEXT HASHcontext;
685 unsigned char HASHdigest[HASH_BYTES];
686 struct berval *value;
687 struct berval digest;
689 sa = (SubstringsAssertion *) assertedValue;
691 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
692 !BER_BVISNULL( &sa->sa_initial ) &&
693 sa->sa_initial.bv_len >= index_substr_if_minlen )
696 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
697 ( flags & SLAP_INDEX_SUBSTR_ANY ))
699 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
703 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
705 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
706 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
707 /* don't bother accounting with stepping */
708 nkeys += sa->sa_any[i].bv_len -
709 ( index_substr_any_len - 1 );
714 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
715 !BER_BVISNULL( &sa->sa_final ) &&
716 sa->sa_final.bv_len >= index_substr_if_minlen )
719 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
720 ( flags & SLAP_INDEX_SUBSTR_ANY ))
722 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
731 digest.bv_val = (char *)HASHdigest;
732 digest.bv_len = sizeof(HASHdigest);
734 slen = syntax->ssyn_oidlen;
735 mlen = mr->smr_oidlen;
737 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
740 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
741 !BER_BVISNULL( &sa->sa_initial ) &&
742 sa->sa_initial.bv_len >= index_substr_if_minlen )
744 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
745 value = &sa->sa_initial;
747 klen = index_substr_if_maxlen < value->bv_len
748 ? index_substr_if_maxlen : value->bv_len;
750 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
751 hashIter( &HASHcontext, HASHdigest,
752 (unsigned char *)value->bv_val, klen );
753 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
755 /* If initial is too long and we have subany indexed, use it
756 * to match the excess...
758 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
761 pre = SLAP_INDEX_SUBSTR_PREFIX;
762 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
763 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
765 hashIter( &HASHcontext, HASHdigest,
766 (unsigned char *)&value->bv_val[j], index_substr_any_len );
767 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
772 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
774 pre = SLAP_INDEX_SUBSTR_PREFIX;
775 klen = index_substr_any_len;
777 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
778 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
782 value = &sa->sa_any[i];
784 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
786 j <= value->bv_len - index_substr_any_len;
787 j += index_substr_any_step )
789 hashIter( &HASHcontext, HASHdigest,
790 (unsigned char *)&value->bv_val[j], klen );
791 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
796 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
797 !BER_BVISNULL( &sa->sa_final ) &&
798 sa->sa_final.bv_len >= index_substr_if_minlen )
800 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
801 value = &sa->sa_final;
803 klen = index_substr_if_maxlen < value->bv_len
804 ? index_substr_if_maxlen : value->bv_len;
806 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
807 hashIter( &HASHcontext, HASHdigest,
808 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
809 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
811 /* If final is too long and we have subany indexed, use it
812 * to match the excess...
814 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
817 pre = SLAP_INDEX_SUBSTR_PREFIX;
818 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
819 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
821 hashIter( &HASHcontext, HASHdigest,
822 (unsigned char *)&value->bv_val[j], index_substr_any_len );
823 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
829 BER_BVZERO( &keys[nkeys] );
846 /* very unforgiving validation, requires no normalization
847 * before simplistic matching
849 if( in->bv_len < 3 ) {
850 return LDAP_INVALID_SYNTAX;
853 /* RFC 4517 Section 3.3.2 Bit String:
854 * BitString = SQUOTE *binary-digit SQUOTE "B"
855 * binary-digit = "0" / "1"
857 * where SQUOTE [RFC4512] is
858 * SQUOTE = %x27 ; single quote ("'")
860 * Example: '0101111101'B
863 if( in->bv_val[0] != '\'' ||
864 in->bv_val[in->bv_len - 2] != '\'' ||
865 in->bv_val[in->bv_len - 1] != 'B' )
867 return LDAP_INVALID_SYNTAX;
870 for( i = in->bv_len - 3; i > 0; i-- ) {
871 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
872 return LDAP_INVALID_SYNTAX;
880 * Syntaxes from RFC 4517
885 A value of the Bit String syntax is a sequence of binary digits. The
886 LDAP-specific encoding of a value of this syntax is defined by the
889 BitString = SQUOTE *binary-digit SQUOTE "B"
891 binary-digit = "0" / "1"
893 The <SQUOTE> rule is defined in [MODELS].
898 The LDAP definition for the Bit String syntax is:
900 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
902 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
906 3.3.21. Name and Optional UID
908 A value of the Name and Optional UID syntax is the distinguished name
909 [MODELS] of an entity optionally accompanied by a unique identifier
910 that serves to differentiate the entity from others with an identical
913 The LDAP-specific encoding of a value of this syntax is defined by
916 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
918 The <BitString> rule is defined in Section 3.3.2. The
919 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
922 Note that although the '#' character may occur in the string
923 representation of a distinguished name, no additional escaping of
924 this character is performed when a <distinguishedName> is encoded in
925 a <NameAndOptionalUID>.
928 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
930 The LDAP definition for the Name and Optional UID syntax is:
932 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
934 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
941 1.4. Common ABNF Productions
944 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
946 SQUOTE = %x27 ; single quote ("'")
950 * Note: normalization strips any leading "0"s, unless the
951 * bit string is exactly "'0'B", so the normalized example,
952 * in slapd, would result in
954 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
956 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
957 * be escaped except when at the beginning of a value, the
958 * definition of Name and Optional UID appears to be flawed,
959 * because there is no clear means to determine whether the
960 * UID part is present or not.
964 * cn=Someone,dc=example,dc=com#'1'B
966 * could be either a NameAndOptionalUID with trailing UID, i.e.
968 * DN = "cn=Someone,dc=example,dc=com"
971 * or a NameAndOptionalUID with no trailing UID, and the AVA
972 * in the last RDN made of
975 * attributeValue = com#'1'B
977 * in fact "com#'1'B" is a valid IA5 string.
979 * As a consequence, current slapd code assumes that the
980 * presence of portions of a BitString at the end of the string
981 * representation of a NameAndOptionalUID means a BitString
982 * is expected, and cause an error otherwise. This is quite
983 * arbitrary, and might change in the future.
993 struct berval dn, uid;
995 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
997 ber_dupbv( &dn, in );
998 if( !dn.bv_val ) return LDAP_OTHER;
1000 /* if there's a "#", try bitStringValidate()... */
1001 uid.bv_val = strrchr( dn.bv_val, '#' );
1002 if ( !BER_BVISNULL( &uid ) ) {
1004 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1006 rc = bitStringValidate( NULL, &uid );
1007 if ( rc == LDAP_SUCCESS ) {
1008 /* in case of success, trim the UID,
1009 * otherwise treat it as part of the DN */
1010 dn.bv_len -= uid.bv_len + 1;
1011 uid.bv_val[-1] = '\0';
1015 rc = dnValidate( NULL, &dn );
1017 ber_memfree( dn.bv_val );
1028 assert( val != NULL );
1029 assert( out != NULL );
1032 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1034 if( BER_BVISEMPTY( val ) ) {
1035 ber_dupbv_x( out, val, ctx );
1037 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1038 return LDAP_INVALID_SYNTAX;
1042 struct berval dnval = *val;
1043 struct berval uidval = BER_BVNULL;
1045 uidval.bv_val = strrchr( val->bv_val, '#' );
1046 if ( !BER_BVISNULL( &uidval ) ) {
1048 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1050 rc = bitStringValidate( NULL, &uidval );
1052 if ( rc == LDAP_SUCCESS ) {
1053 ber_dupbv_x( &dnval, val, ctx );
1054 dnval.bv_len -= uidval.bv_len + 1;
1055 dnval.bv_val[dnval.bv_len] = '\0';
1058 BER_BVZERO( &uidval );
1062 rc = dnPretty( syntax, &dnval, out, ctx );
1063 if ( dnval.bv_val != val->bv_val ) {
1064 slap_sl_free( dnval.bv_val, ctx );
1066 if( rc != LDAP_SUCCESS ) {
1070 if( !BER_BVISNULL( &uidval ) ) {
1074 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1075 + STRLENOF( "#" ) + uidval.bv_len + 1,
1078 ber_memfree_x( out->bv_val, ctx );
1082 out->bv_val[out->bv_len++] = '#';
1083 out->bv_val[out->bv_len++] = '\'';
1085 got1 = uidval.bv_len < sizeof("'0'B");
1086 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1087 c = uidval.bv_val[i];
1090 if( got1 ) out->bv_val[out->bv_len++] = c;
1094 out->bv_val[out->bv_len++] = c;
1099 out->bv_val[out->bv_len++] = '\'';
1100 out->bv_val[out->bv_len++] = 'B';
1101 out->bv_val[out->bv_len] = '\0';
1105 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1107 return LDAP_SUCCESS;
1111 uniqueMemberNormalize(
1116 struct berval *normalized,
1122 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1124 ber_dupbv_x( &out, val, ctx );
1125 if ( BER_BVISEMPTY( &out ) ) {
1129 struct berval uid = BER_BVNULL;
1131 uid.bv_val = strrchr( out.bv_val, '#' );
1132 if ( !BER_BVISNULL( &uid ) ) {
1134 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1136 rc = bitStringValidate( NULL, &uid );
1137 if ( rc == LDAP_SUCCESS ) {
1138 uid.bv_val[-1] = '\0';
1139 out.bv_len -= uid.bv_len + 1;
1145 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1147 if( rc != LDAP_SUCCESS ) {
1148 slap_sl_free( out.bv_val, ctx );
1149 return LDAP_INVALID_SYNTAX;
1152 if( !BER_BVISNULL( &uid ) ) {
1155 tmp = ch_realloc( normalized->bv_val,
1156 normalized->bv_len + uid.bv_len
1157 + STRLENOF("#") + 1 );
1158 if ( tmp == NULL ) {
1159 ber_memfree_x( normalized->bv_val, ctx );
1163 normalized->bv_val = tmp;
1165 /* insert the separator */
1166 normalized->bv_val[normalized->bv_len++] = '#';
1168 /* append the UID */
1169 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1170 uid.bv_val, uid.bv_len );
1171 normalized->bv_len += uid.bv_len;
1174 normalized->bv_val[normalized->bv_len] = '\0';
1177 slap_sl_free( out.bv_val, ctx );
1180 return LDAP_SUCCESS;
1189 struct berval *value,
1190 void *assertedValue )
1193 struct berval *asserted = (struct berval *) assertedValue;
1194 struct berval assertedDN = *asserted;
1195 struct berval assertedUID = BER_BVNULL;
1196 struct berval valueDN = *value;
1197 struct berval valueUID = BER_BVNULL;
1198 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1200 if ( !BER_BVISEMPTY( asserted ) ) {
1201 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1202 if ( !BER_BVISNULL( &assertedUID ) ) {
1203 assertedUID.bv_val++;
1204 assertedUID.bv_len = assertedDN.bv_len
1205 - ( assertedUID.bv_val - assertedDN.bv_val );
1207 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1208 assertedDN.bv_len -= assertedUID.bv_len + 1;
1211 BER_BVZERO( &assertedUID );
1216 if ( !BER_BVISEMPTY( value ) ) {
1218 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1219 if ( !BER_BVISNULL( &valueUID ) ) {
1221 valueUID.bv_len = valueDN.bv_len
1222 - ( valueUID.bv_val - valueDN.bv_val );
1224 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1225 valueDN.bv_len -= valueUID.bv_len + 1;
1228 BER_BVZERO( &valueUID );
1233 if( valueUID.bv_len && assertedUID.bv_len ) {
1234 match = valueUID.bv_len - assertedUID.bv_len;
1237 return LDAP_SUCCESS;
1240 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1243 return LDAP_SUCCESS;
1246 } else if ( !approx && valueUID.bv_len ) {
1249 return LDAP_SUCCESS;
1251 } else if ( !approx && assertedUID.bv_len ) {
1254 return LDAP_SUCCESS;
1257 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1261 uniqueMemberIndexer(
1266 struct berval *prefix,
1274 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1275 /* just count them */
1279 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1281 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1282 struct berval assertedDN = values[i];
1283 struct berval assertedUID = BER_BVNULL;
1285 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1286 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1287 if ( !BER_BVISNULL( &assertedUID ) ) {
1288 assertedUID.bv_val++;
1289 assertedUID.bv_len = assertedDN.bv_len
1290 - ( assertedUID.bv_val - assertedDN.bv_val );
1292 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1293 assertedDN.bv_len -= assertedUID.bv_len + 1;
1296 BER_BVZERO( &assertedUID );
1301 dnvalues[i] = assertedDN;
1303 BER_BVZERO( &dnvalues[i] );
1305 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1306 dnvalues, keysp, ctx );
1308 slap_sl_free( dnvalues, ctx );
1318 struct berval *prefix,
1319 void * assertedValue,
1323 struct berval *asserted = (struct berval *) assertedValue;
1324 struct berval assertedDN = *asserted;
1325 struct berval assertedUID = BER_BVNULL;
1327 if ( !BER_BVISEMPTY( asserted ) ) {
1328 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1329 if ( !BER_BVISNULL( &assertedUID ) ) {
1330 assertedUID.bv_val++;
1331 assertedUID.bv_len = assertedDN.bv_len
1332 - ( assertedUID.bv_val - assertedDN.bv_val );
1334 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1335 assertedDN.bv_len -= assertedUID.bv_len + 1;
1338 BER_BVZERO( &assertedUID );
1343 return octetStringFilter( use, flags, syntax, mr, prefix,
1344 &assertedDN, keysp, ctx );
1349 * Handling boolean syntax and matching is quite rigid.
1350 * A more flexible approach would be to allow a variety
1351 * of strings to be normalized and prettied into TRUE
1359 /* very unforgiving validation, requires no normalization
1360 * before simplistic matching
1363 if( in->bv_len == 4 ) {
1364 if( bvmatch( in, &slap_true_bv ) ) {
1365 return LDAP_SUCCESS;
1367 } else if( in->bv_len == 5 ) {
1368 if( bvmatch( in, &slap_false_bv ) ) {
1369 return LDAP_SUCCESS;
1373 return LDAP_INVALID_SYNTAX;
1382 struct berval *value,
1383 void *assertedValue )
1385 /* simplistic matching allowed by rigid validation */
1386 struct berval *asserted = (struct berval *) assertedValue;
1387 *matchp = value->bv_len != asserted->bv_len;
1388 return LDAP_SUCCESS;
1391 /*-------------------------------------------------------------------
1392 LDAP/X.500 string syntax / matching rules have a few oddities. This
1393 comment attempts to detail how slapd(8) treats them.
1396 StringSyntax X.500 LDAP Matching/Comments
1397 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1398 PrintableString subset subset i/e + ignore insignificant spaces
1399 PrintableString subset subset i/e + ignore insignificant spaces
1400 NumericString subset subset ignore all spaces
1401 IA5String ASCII ASCII i/e + ignore insignificant spaces
1402 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1404 TelephoneNumber subset subset i + ignore all spaces and "-"
1406 See RFC 4518 for details.
1410 In X.500(93), a directory string can be either a PrintableString,
1411 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1412 In later versions, more CHOICEs were added. In all cases the string
1415 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1416 A directory string cannot be zero length.
1418 For matching, there are both case ignore and exact rules. Both
1419 also require that "insignificant" spaces be ignored.
1420 spaces before the first non-space are ignored;
1421 spaces after the last non-space are ignored;
1422 spaces after a space are ignored.
1423 Note: by these rules (and as clarified in X.520), a string of only
1424 spaces is to be treated as if held one space, not empty (which
1425 would be a syntax error).
1428 In ASN.1, numeric string is just a string of digits and spaces
1429 and could be empty. However, in X.500, all attribute values of
1430 numeric string carry a non-empty constraint. For example:
1432 internationalISDNNumber ATTRIBUTE ::= {
1433 WITH SYNTAX InternationalISDNNumber
1434 EQUALITY MATCHING RULE numericStringMatch
1435 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1436 ID id-at-internationalISDNNumber }
1437 InternationalISDNNumber ::=
1438 NumericString (SIZE(1..ub-international-isdn-number))
1440 Unforunately, some assertion values are don't carry the same
1441 constraint (but its unclear how such an assertion could ever
1442 be true). In LDAP, there is one syntax (numericString) not two
1443 (numericString with constraint, numericString without constraint).
1444 This should be treated as numericString with non-empty constraint.
1445 Note that while someone may have no ISDN number, there are no ISDN
1446 numbers which are zero length.
1448 In matching, spaces are ignored.
1451 In ASN.1, Printable string is just a string of printable characters
1452 and can be empty. In X.500, semantics much like NumericString (see
1453 serialNumber for a like example) excepting uses insignificant space
1454 handling instead of ignore all spaces. They must be non-empty.
1457 Basically same as PrintableString. There are no examples in X.500,
1458 but same logic applies. Empty strings are allowed.
1460 -------------------------------------------------------------------*/
1469 unsigned char *u = (unsigned char *)in->bv_val;
1471 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1472 /* directory strings cannot be empty */
1473 return LDAP_INVALID_SYNTAX;
1476 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1477 /* get the length indicated by the first byte */
1478 len = LDAP_UTF8_CHARLEN2( u, len );
1480 /* very basic checks */
1483 if( (u[5] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX;
1487 if( (u[4] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX;
1491 if( (u[3] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[2] & 0xC0 )!= 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 if( (u[1] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX;
1503 /* CHARLEN already validated it */
1506 return LDAP_INVALID_SYNTAX;
1509 /* make sure len corresponds with the offset
1510 to the next character */
1511 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1515 return LDAP_INVALID_SYNTAX;
1518 return LDAP_SUCCESS;
1522 UTF8StringNormalize(
1527 struct berval *normalized,
1530 struct berval tmp, nvalue;
1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1536 if( BER_BVISNULL( val ) ) {
1537 /* assume we're dealing with a syntax (e.g., UTF8String)
1538 * which allows empty strings
1540 BER_BVZERO( normalized );
1541 return LDAP_SUCCESS;
1544 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1545 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1546 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1547 ? LDAP_UTF8_APPROX : 0;
1549 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1554 /* collapse spaces (in place) */
1556 nvalue.bv_val = tmp.bv_val;
1558 /* trim leading spaces? */
1559 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1560 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1562 for( i = 0; i < tmp.bv_len; i++) {
1563 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1564 if( wasspace++ == 0 ) {
1565 /* trim repeated spaces */
1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1570 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1574 if( !BER_BVISEMPTY( &nvalue ) ) {
1575 /* trim trailing space? */
1577 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1578 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1582 nvalue.bv_val[nvalue.bv_len] = '\0';
1585 /* string of all spaces is treated as one space */
1586 nvalue.bv_val[0] = ' ';
1587 nvalue.bv_val[1] = '\0';
1591 *normalized = nvalue;
1592 return LDAP_SUCCESS;
1596 directoryStringSubstringsMatch(
1601 struct berval *value,
1602 void *assertedValue )
1605 SubstringsAssertion *sub = assertedValue;
1606 struct berval left = *value;
1610 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1611 if ( sub->sa_initial.bv_len > left.bv_len ) {
1612 /* not enough left */
1617 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1618 sub->sa_initial.bv_len );
1624 left.bv_val += sub->sa_initial.bv_len;
1625 left.bv_len -= sub->sa_initial.bv_len;
1627 priorspace = ASCII_SPACE(
1628 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1631 if ( sub->sa_any ) {
1632 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1636 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1637 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1639 /* allow next space to match */
1646 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1650 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1651 /* not enough left */
1656 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1663 idx = p - left.bv_val;
1665 if ( idx >= left.bv_len ) {
1666 /* this shouldn't happen */
1673 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1674 /* not enough left */
1679 match = memcmp( left.bv_val,
1680 sub->sa_any[i].bv_val,
1681 sub->sa_any[i].bv_len );
1689 left.bv_val += sub->sa_any[i].bv_len;
1690 left.bv_len -= sub->sa_any[i].bv_len;
1692 priorspace = ASCII_SPACE(
1693 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1697 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1698 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1699 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1701 /* allow next space to match */
1706 if ( sub->sa_final.bv_len > left.bv_len ) {
1707 /* not enough left */
1712 match = memcmp( sub->sa_final.bv_val,
1713 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1714 sub->sa_final.bv_len );
1723 return LDAP_SUCCESS;
1726 #if defined(SLAPD_APPROX_INITIALS)
1727 # define SLAPD_APPROX_DELIMITER "._ "
1728 # define SLAPD_APPROX_WORDLEN 2
1730 # define SLAPD_APPROX_DELIMITER " "
1731 # define SLAPD_APPROX_WORDLEN 1
1740 struct berval *value,
1741 void *assertedValue )
1743 struct berval *nval, *assertv;
1744 char *val, **values, **words, *c;
1745 int i, count, len, nextchunk=0, nextavail=0;
1747 /* Yes, this is necessary */
1748 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1749 if( nval == NULL ) {
1751 return LDAP_SUCCESS;
1754 /* Yes, this is necessary */
1755 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1756 NULL, LDAP_UTF8_APPROX, NULL );
1757 if( assertv == NULL ) {
1760 return LDAP_SUCCESS;
1763 /* Isolate how many words there are */
1764 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1765 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1766 if ( c == NULL ) break;
1771 /* Get a phonetic copy of each word */
1772 words = (char **)ch_malloc( count * sizeof(char *) );
1773 values = (char **)ch_malloc( count * sizeof(char *) );
1774 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1776 values[i] = phonetic(c);
1779 /* Work through the asserted value's words, to see if at least some
1780 of the words are there, in the same order. */
1782 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1783 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1788 #if defined(SLAPD_APPROX_INITIALS)
1789 else if( len == 1 ) {
1790 /* Single letter words need to at least match one word's initial */
1791 for( i=nextavail; i<count; i++ )
1792 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1799 /* Isolate the next word in the asserted value and phonetic it */
1800 assertv->bv_val[nextchunk+len] = '\0';
1801 val = phonetic( assertv->bv_val + nextchunk );
1803 /* See if this phonetic chunk is in the remaining words of *value */
1804 for( i=nextavail; i<count; i++ ){
1805 if( !strcmp( val, values[i] ) ){
1813 /* This chunk in the asserted value was NOT within the *value. */
1819 /* Go on to the next word in the asserted value */
1823 /* If some of the words were seen, call it a match */
1824 if( nextavail > 0 ) {
1831 /* Cleanup allocs */
1832 ber_bvfree( assertv );
1833 for( i=0; i<count; i++ ) {
1834 ch_free( values[i] );
1840 return LDAP_SUCCESS;
1849 struct berval *prefix,
1855 int i,j, len, wordcount, keycount=0;
1856 struct berval *newkeys;
1857 BerVarray keys=NULL;
1859 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1860 struct berval val = BER_BVNULL;
1861 /* Yes, this is necessary */
1862 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1863 assert( !BER_BVISNULL( &val ) );
1865 /* Isolate how many words there are. There will be a key for each */
1866 for( wordcount = 0, c = val.bv_val; *c; c++) {
1867 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1868 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1870 if (*c == '\0') break;
1874 /* Allocate/increase storage to account for new keys */
1875 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1876 * sizeof(struct berval) );
1877 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1878 if( keys ) ch_free( keys );
1881 /* Get a phonetic copy of each word */
1882 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1884 if( len < SLAPD_APPROX_WORDLEN ) continue;
1885 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1890 ber_memfree( val.bv_val );
1892 BER_BVZERO( &keys[keycount] );
1895 return LDAP_SUCCESS;
1904 struct berval *prefix,
1905 void * assertedValue,
1914 /* Yes, this is necessary */
1915 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1916 NULL, LDAP_UTF8_APPROX, NULL );
1917 if( val == NULL || BER_BVISNULL( val ) ) {
1918 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1919 BER_BVZERO( &keys[0] );
1922 return LDAP_SUCCESS;
1925 /* Isolate how many words there are. There will be a key for each */
1926 for( count = 0,c = val->bv_val; *c; c++) {
1927 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1928 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1930 if (*c == '\0') break;
1934 /* Allocate storage for new keys */
1935 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1937 /* Get a phonetic copy of each word */
1938 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1940 if( len < SLAPD_APPROX_WORDLEN ) continue;
1941 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1947 BER_BVZERO( &keys[count] );
1950 return LDAP_SUCCESS;
1953 /* Remove all spaces and '-' characters */
1955 telephoneNumberNormalize(
1960 struct berval *normalized,
1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1967 /* validator should have refused an empty string */
1968 assert( !BER_BVISEMPTY( val ) );
1970 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1972 for( p = val->bv_val; *p; p++ ) {
1973 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1979 normalized->bv_len = q - normalized->bv_val;
1981 if( BER_BVISEMPTY( normalized ) ) {
1982 slap_sl_free( normalized->bv_val, ctx );
1983 BER_BVZERO( normalized );
1984 return LDAP_INVALID_SYNTAX;
1987 return LDAP_SUCCESS;
1991 postalAddressValidate(
1995 struct berval bv = *in;
1998 for ( c = 0; c < in->bv_len; c++ ) {
1999 if ( in->bv_val[c] == '\\' ) {
2001 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2002 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2004 return LDAP_INVALID_SYNTAX;
2009 if ( in->bv_val[c] == '$' ) {
2010 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2011 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2012 return LDAP_INVALID_SYNTAX;
2014 bv.bv_val = &in->bv_val[c] + 1;
2018 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2019 return UTF8StringValidate( NULL, &bv );
2023 postalAddressNormalize(
2028 struct berval *normalized,
2031 BerVarray lines = NULL, nlines = NULL;
2034 int rc = LDAP_SUCCESS;
2035 MatchingRule *xmr = NULL;
2036 struct berval bv = BER_BVNULL;
2039 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2040 xmr = slap_schema.si_mr_caseIgnoreMatch;
2043 xmr = slap_schema.si_mr_caseExactMatch;
2046 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2047 if ( val->bv_val[c] == '$' ) {
2052 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2053 nlines = &lines[l + 2];
2055 lines[0].bv_val = val->bv_val;
2056 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2057 if ( val->bv_val[c] == '$' ) {
2058 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2060 lines[l].bv_val = &val->bv_val[c + 1];
2063 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2065 normalized->bv_len = l;
2067 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2071 ber_bvreplace_x( &bv, &lines[l], ctx );
2073 for ( d = 0, s = 0; s < oldlen; d++, s++ ) {
2074 if ( bv.bv_val[s] == '\\' ) {
2075 if ( &bv.bv_val[s] - &bv.bv_val[0] + STRLENOF( "\\XX" ) > oldlen ) {
2076 rc = LDAP_INVALID_SYNTAX;
2079 } else if ( strncasecmp( &bv.bv_val[s + 1], "24", STRLENOF( "24" ) ) == 0 ) {
2082 } else if ( strncasecmp( &bv.bv_val[s + 1], "5C", STRLENOF( "5C" ) ) == 0 ) {
2083 bv.bv_val[d] = '\\';
2086 rc = LDAP_INVALID_SYNTAX;
2095 bv.bv_val[d] = bv.bv_val[s];
2099 rc = UTF8StringNormalize( usage, NULL, xmr, &bv, &nlines[l], ctx );
2100 if ( rc != LDAP_SUCCESS ) {
2101 rc = LDAP_INVALID_SYNTAX;
2105 normalized->bv_len += nlines[l].bv_len;
2108 normalized->bv_len += 2*nescapes;
2110 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2112 p = normalized->bv_val;
2113 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2114 for ( c = 0; c < nlines[l].bv_len; c++ ) {
2115 switch ( nlines[l].bv_val[c] ) {
2117 p = lutil_strcopy( p, "\\5C" );
2121 p = lutil_strcopy( p, "\\24" );
2125 *p++ = nlines[l].bv_val[c];
2134 assert( p - normalized->bv_val == normalized->bv_len );
2137 if ( !BER_BVISNULL( &bv ) ) {
2138 ber_memfree_x( bv.bv_val, ctx );
2141 if ( nlines != NULL ) {
2142 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2143 slap_sl_free( nlines[l].bv_val, ctx );
2146 slap_sl_free( lines, ctx );
2157 struct berval val = *in;
2159 if( BER_BVISEMPTY( &val ) ) {
2160 /* disallow empty strings */
2161 return LDAP_INVALID_SYNTAX;
2164 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2165 if ( val.bv_len == 1 ) {
2166 return LDAP_SUCCESS;
2169 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2176 while ( OID_LEADCHAR( val.bv_val[0] )) {
2180 if ( val.bv_len == 0 ) {
2181 return LDAP_SUCCESS;
2185 if( !OID_SEPARATOR( val.bv_val[0] )) {
2193 return LDAP_INVALID_SYNTAX;
2202 struct berval val = *in;
2204 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2206 if ( val.bv_val[0] == '-' ) {
2210 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2211 return LDAP_INVALID_SYNTAX;
2214 if( val.bv_val[0] == '0' ) { /* "-0" */
2215 return LDAP_INVALID_SYNTAX;
2218 } else if ( val.bv_val[0] == '0' ) {
2219 if( val.bv_len > 1 ) { /* "0<more>" */
2220 return LDAP_INVALID_SYNTAX;
2223 return LDAP_SUCCESS;
2226 for( i=0; i < val.bv_len; i++ ) {
2227 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2228 return LDAP_INVALID_SYNTAX;
2232 return LDAP_SUCCESS;
2241 struct berval *value,
2242 void *assertedValue )
2244 struct berval *asserted = (struct berval *) assertedValue;
2245 int vsign = 1, asign = 1; /* default sign = '+' */
2250 if( v.bv_val[0] == '-' ) {
2256 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2259 if( a.bv_val[0] == '-' ) {
2265 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2267 match = vsign - asign;
2269 match = ( v.bv_len != a.bv_len
2270 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2271 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2272 if( vsign < 0 ) match = -match;
2276 return LDAP_SUCCESS;
2279 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2280 #define INDEX_INTLEN_CHOP 7
2281 #define INDEX_INTLEN_CHOPBYTES 3
2291 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2292 * two's complement value (sign-extended or chopped as needed),
2293 * however the top <number of exponent-bytes + 1> bits of first byte
2294 * above is the inverse sign. The next bit is the sign as delimiter.
2296 ber_slen_t k = index_intlen_strlen;
2298 unsigned signmask = ~0x7fU;
2299 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2300 struct berval val = *in, itmp = *tmp;
2302 if ( val.bv_val[0] != '-' ) {
2307 /* Chop least significant digits, increase length instead */
2308 if ( val.bv_len > (ber_len_t) k ) {
2309 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2310 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2311 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2314 if ( lutil_str2bin( &val, &itmp, ctx )) {
2315 return LDAP_INVALID_SYNTAX;
2318 /* Omit leading sign byte */
2319 if ( itmp.bv_val[0] == neg ) {
2324 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2326 assert( chop == 0 );
2327 memset( key->bv_val, neg, k ); /* sign-extend */
2328 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2329 lenp = lenbuf + sizeof(lenbuf);
2330 chop = - (ber_len_t) k;
2332 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2334 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2335 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2336 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2337 k = (lenbuf + sizeof(lenbuf)) - lenp;
2338 if ( k > (ber_slen_t) index_intlen )
2340 memcpy( key->bv_val, lenp, k );
2341 itmp.bv_len = index_intlen - k;
2343 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2344 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2348 /* Index generation function */
2355 struct berval *prefix,
2365 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2367 /* count the values and find max needed length */
2369 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2370 if ( vlen < values[i].bv_len )
2371 vlen = values[i].bv_len;
2373 if ( vlen > maxstrlen )
2376 /* we should have at least one value at this point */
2379 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2380 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2381 keys[i].bv_len = index_intlen;
2382 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2385 keys[i].bv_val = NULL;
2387 if ( vlen > sizeof(ibuf) ) {
2388 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2392 itmp.bv_len = sizeof(ibuf);
2394 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2395 if ( itmp.bv_val != ibuf ) {
2396 itmp.bv_len = values[i].bv_len;
2397 if ( itmp.bv_len <= sizeof(ibuf) )
2398 itmp.bv_len = sizeof(ibuf);
2399 else if ( itmp.bv_len > maxstrlen )
2400 itmp.bv_len = maxstrlen;
2402 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2408 if ( itmp.bv_val != ibuf ) {
2409 slap_sl_free( itmp.bv_val, ctx );
2414 /* Index generation function */
2421 struct berval *prefix,
2422 void * assertedValue,
2429 struct berval *value;
2432 value = (struct berval *) assertedValue;
2434 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2436 keys[0].bv_len = index_intlen;
2437 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2439 keys[1].bv_val = NULL;
2441 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2442 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2443 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2444 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2447 iv.bv_len = sizeof(ibuf);
2450 rc = integerVal2Key( value, keys, &iv, ctx );
2454 if ( iv.bv_val != ibuf ) {
2455 slap_sl_free( iv.bv_val, ctx );
2461 countryStringValidate(
2463 struct berval *val )
2465 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2467 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2468 return LDAP_INVALID_SYNTAX;
2470 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2471 return LDAP_INVALID_SYNTAX;
2474 return LDAP_SUCCESS;
2478 printableStringValidate(
2480 struct berval *val )
2484 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2486 for(i=0; i < val->bv_len; i++) {
2487 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2488 return LDAP_INVALID_SYNTAX;
2492 return LDAP_SUCCESS;
2496 printablesStringValidate(
2498 struct berval *val )
2502 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2504 for(i=0,len=0; i < val->bv_len; i++) {
2505 int c = val->bv_val[i];
2509 return LDAP_INVALID_SYNTAX;
2513 } else if ( SLAP_PRINTABLE(c) ) {
2516 return LDAP_INVALID_SYNTAX;
2521 return LDAP_INVALID_SYNTAX;
2524 return LDAP_SUCCESS;
2530 struct berval *val )
2534 for(i=0; i < val->bv_len; i++) {
2535 if( !LDAP_ASCII(val->bv_val[i]) ) {
2536 return LDAP_INVALID_SYNTAX;
2540 return LDAP_SUCCESS;
2549 struct berval *normalized,
2553 int casefold = !SLAP_MR_ASSOCIATED( mr,
2554 slap_schema.si_mr_caseExactIA5Match );
2556 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2560 /* Ignore initial whitespace */
2561 while ( ASCII_SPACE( *p ) ) p++;
2563 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2564 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2565 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2566 normalized->bv_val[normalized->bv_len] = '\0';
2568 p = q = normalized->bv_val;
2571 if ( ASCII_SPACE( *p ) ) {
2574 /* Ignore the extra whitespace */
2575 while ( ASCII_SPACE( *p ) ) {
2579 } else if ( casefold ) {
2580 /* Most IA5 rules require casefolding */
2581 *q++ = TOLOWER(*p); p++;
2588 assert( normalized->bv_val <= p );
2592 * If the string ended in space, backup the pointer one
2593 * position. One is enough because the above loop collapsed
2594 * all whitespace to a single space.
2596 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2598 /* null terminate */
2601 normalized->bv_len = q - normalized->bv_val;
2603 return LDAP_SUCCESS;
2612 if( in->bv_len != 36 ) {
2613 return LDAP_INVALID_SYNTAX;
2616 for( i=0; i<36; i++ ) {
2622 if( in->bv_val[i] != '-' ) {
2623 return LDAP_INVALID_SYNTAX;
2627 if( !ASCII_HEX( in->bv_val[i]) ) {
2628 return LDAP_INVALID_SYNTAX;
2633 return LDAP_SUCCESS;
2644 int rc=LDAP_INVALID_SYNTAX;
2646 assert( in != NULL );
2647 assert( out != NULL );
2649 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2652 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2654 for( i=0; i<36; i++ ) {
2660 if( in->bv_val[i] != '-' ) {
2663 out->bv_val[i] = '-';
2667 if( !ASCII_HEX( in->bv_val[i]) ) {
2670 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2675 out->bv_val[ out->bv_len ] = '\0';
2679 slap_sl_free( out->bv_val, ctx );
2692 struct berval *normalized,
2695 unsigned char octet = '\0';
2699 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2700 /* NOTE: must be a normalized UUID */
2701 assert( val->bv_len == 16 );
2703 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2704 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2705 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2706 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2708 return LDAP_SUCCESS;
2711 normalized->bv_len = 16;
2712 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2714 for( i=0, j=0; i<36; i++ ) {
2715 unsigned char nibble;
2716 if( val->bv_val[i] == '-' ) {
2719 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2720 nibble = val->bv_val[i] - '0';
2722 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2723 nibble = val->bv_val[i] - ('a'-10);
2725 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2726 nibble = val->bv_val[i] - ('A'-10);
2729 slap_sl_free( normalized->bv_val, ctx );
2730 return LDAP_INVALID_SYNTAX;
2735 normalized->bv_val[j>>1] = octet;
2737 octet = nibble << 4;
2742 normalized->bv_val[normalized->bv_len] = 0;
2743 return LDAP_SUCCESS;
2749 numericStringValidate(
2755 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2757 for(i=0; i < in->bv_len; i++) {
2758 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2759 return LDAP_INVALID_SYNTAX;
2763 return LDAP_SUCCESS;
2767 numericStringNormalize(
2772 struct berval *normalized,
2775 /* removal all spaces */
2778 assert( !BER_BVISEMPTY( val ) );
2780 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2783 q = normalized->bv_val;
2786 if ( ASCII_SPACE( *p ) ) {
2787 /* Ignore whitespace */
2794 /* we should have copied no more than is in val */
2795 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2797 /* null terminate */
2800 normalized->bv_len = q - normalized->bv_val;
2802 if( BER_BVISEMPTY( normalized ) ) {
2803 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2804 normalized->bv_val[0] = ' ';
2805 normalized->bv_val[1] = '\0';
2806 normalized->bv_len = 1;
2809 return LDAP_SUCCESS;
2813 * Integer conversion macros that will use the largest available
2816 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2817 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2818 # define SLAP_LONG long long
2820 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2821 # define SLAP_LONG long
2822 #endif /* HAVE_STRTOLL ... */
2830 struct berval *value,
2831 void *assertedValue )
2833 SLAP_LONG lValue, lAssertedValue;
2836 /* safe to assume integers are NUL terminated? */
2837 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2838 if( errno == ERANGE )
2840 return LDAP_CONSTRAINT_VIOLATION;
2843 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2845 if( errno == ERANGE )
2847 return LDAP_CONSTRAINT_VIOLATION;
2850 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2851 return LDAP_SUCCESS;
2860 struct berval *value,
2861 void *assertedValue )
2863 SLAP_LONG lValue, lAssertedValue;
2866 /* safe to assume integers are NUL terminated? */
2867 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2868 if( errno == ERANGE )
2870 return LDAP_CONSTRAINT_VIOLATION;
2873 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2875 if( errno == ERANGE )
2877 return LDAP_CONSTRAINT_VIOLATION;
2880 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2881 return LDAP_SUCCESS;
2885 serialNumberAndIssuerCheck(
2894 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2896 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2897 /* Parse old format */
2898 is->bv_val = ber_bvchr( in, '$' );
2899 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2901 sn->bv_val = in->bv_val;
2902 sn->bv_len = is->bv_val - in->bv_val;
2905 is->bv_len = in->bv_len - (sn->bv_len + 1);
2907 /* eat leading zeros */
2908 for( n=0; n < (sn->bv_len-1); n++ ) {
2909 if( sn->bv_val[n] != '0' ) break;
2914 for( n=0; n < sn->bv_len; n++ ) {
2915 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2919 /* Parse GSER format */
2920 int havesn = 0, haveissuer = 0, numdquotes = 0;
2921 struct berval x = *in;
2926 /* eat leading spaces */
2927 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2931 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2932 return LDAP_INVALID_SYNTAX;
2935 /* should be at issuer or serialNumber NamedValue */
2936 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2938 x.bv_val += STRLENOF("issuer");
2939 x.bv_len -= STRLENOF("issuer");
2941 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2942 x.bv_val++; x.bv_len--;
2944 /* eat leading spaces */
2945 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2949 /* For backward compatibility, this part is optional */
2950 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2951 x.bv_val += STRLENOF("rdnSequence:");
2952 x.bv_len -= STRLENOF("rdnSequence:");
2955 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2956 x.bv_val++; x.bv_len--;
2958 is->bv_val = x.bv_val;
2961 for( ; is->bv_len < x.bv_len; ) {
2962 if ( is->bv_val[is->bv_len] != '"' ) {
2966 if ( is->bv_val[is->bv_len+1] == '"' ) {
2973 x.bv_val += is->bv_len+1;
2974 x.bv_len -= is->bv_len+1;
2976 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2977 return LDAP_INVALID_SYNTAX;
2982 } else if( strncasecmp( x.bv_val, "serialNumber",
2983 STRLENOF("serialNumber")) == 0 )
2985 /* parse serialNumber */
2990 x.bv_val += STRLENOF("serialNumber");
2991 x.bv_len -= STRLENOF("serialNumber");
2993 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2994 x.bv_val++; x.bv_len--;
2996 /* eat leading spaces */
2997 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3001 sn->bv_val = x.bv_val;
3004 if( sn->bv_val[0] == '-' ) {
3009 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
3010 sn->bv_val[1] == 'X' ))
3013 first = sn->bv_val[2];
3016 sn->bv_len += STRLENOF("0x");
3017 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3018 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3021 } else if ( sn->bv_val[0] == '\'' ) {
3022 first = sn->bv_val[1];
3025 sn->bv_len += STRLENOF("'");
3027 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3028 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3030 if ( sn->bv_val[sn->bv_len] == '\'' &&
3031 sn->bv_val[sn->bv_len + 1] == 'H' )
3033 sn->bv_len += STRLENOF("'H");
3037 return LDAP_INVALID_SYNTAX;
3041 first = sn->bv_val[0];
3042 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3043 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
3047 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
3048 if (( sn->bv_len > extra+1+neg ) && ( first == '0' )) {
3049 return LDAP_INVALID_SYNTAX;
3052 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
3054 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3055 return LDAP_INVALID_SYNTAX;
3060 } else return LDAP_INVALID_SYNTAX;
3062 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3063 x.bv_val++; x.bv_len--;
3066 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3070 /* should be at remaining NamedValue */
3071 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3072 STRLENOF("issuer" )) == 0 ))
3075 x.bv_val += STRLENOF("issuer");
3076 x.bv_len -= STRLENOF("issuer");
3078 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3079 x.bv_val++; x.bv_len--;
3081 /* eat leading spaces */
3082 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3086 /* For backward compatibility, this part is optional */
3087 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
3088 x.bv_val += STRLENOF("rdnSequence:");
3089 x.bv_len -= STRLENOF("rdnSequence:");
3092 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3093 x.bv_val++; x.bv_len--;
3095 is->bv_val = x.bv_val;
3098 for( ; is->bv_len < x.bv_len; ) {
3099 if ( is->bv_val[is->bv_len] != '"' ) {
3103 if ( is->bv_val[is->bv_len+1] == '"' ) {
3111 x.bv_val += is->bv_len+1;
3112 x.bv_len -= is->bv_len+1;
3114 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3115 STRLENOF("serialNumber")) == 0 ))
3117 /* parse serialNumber */
3119 x.bv_val += STRLENOF("serialNumber");
3120 x.bv_len -= STRLENOF("serialNumber");
3122 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3123 x.bv_val++; x.bv_len--;
3125 /* eat leading spaces */
3126 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3130 sn->bv_val = x.bv_val;
3133 if( sn->bv_val[0] == '-' ) {
3138 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
3139 sn->bv_val[1] == 'X' )) {
3141 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3142 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3144 } else if ( sn->bv_val[0] == '\'' ) {
3145 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3146 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3148 if ( sn->bv_val[sn->bv_len] == '\'' &&
3149 sn->bv_val[sn->bv_len+1] == 'H' )
3152 return LDAP_INVALID_SYNTAX;
3155 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3156 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
3160 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
3161 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
3162 return LDAP_INVALID_SYNTAX;
3165 x.bv_val += sn->bv_len;
3166 x.bv_len -= sn->bv_len;
3168 } else return LDAP_INVALID_SYNTAX;
3170 /* eat trailing spaces */
3171 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3175 /* should have no characters left... */
3176 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3178 if ( numdquotes == 0 ) {
3179 ber_dupbv_x( &ni, is, ctx );
3183 ni.bv_len = is->bv_len - numdquotes;
3184 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3185 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3186 if ( is->bv_val[src] == '"' ) {
3189 ni.bv_val[dst] = is->bv_val[src];
3191 ni.bv_val[dst] = '\0';
3201 serialNumberAndIssuerValidate(
3206 struct berval sn, i;
3208 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3211 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3215 /* validate DN -- doesn't handle double dquote */
3216 rc = dnValidate( NULL, &i );
3218 rc = LDAP_INVALID_SYNTAX;
3220 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3221 slap_sl_free( i.bv_val, NULL );
3224 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3230 serialNumberAndIssuerPretty(
3237 struct berval sn, i, ni;
3239 assert( in != NULL );
3240 assert( out != NULL );
3242 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3245 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3249 rc = dnPretty( syntax, &i, &ni, ctx );
3251 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3252 slap_sl_free( i.bv_val, ctx );
3255 if( rc ) return LDAP_INVALID_SYNTAX;
3257 /* make room from sn + "$" */
3258 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3259 + sn.bv_len + ni.bv_len;
3260 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3262 if( out->bv_val == NULL ) {
3264 slap_sl_free( ni.bv_val, ctx );
3269 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3270 STRLENOF("{ serialNumber "));
3271 n = STRLENOF("{ serialNumber ");
3273 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3276 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3277 n += STRLENOF(", issuer rdnSequence:\"");
3279 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3282 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3283 n += STRLENOF("\" }");
3285 out->bv_val[n] = '\0';
3287 assert( n == out->bv_len );
3289 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3290 out->bv_val, 0, 0 );
3292 slap_sl_free( ni.bv_val, ctx );
3294 return LDAP_SUCCESS;
3298 * This routine is called by certificateExactNormalize when
3299 * certificateExactNormalize receives a search string instead of
3300 * a certificate. This routine checks if the search value is valid
3301 * and then returns the normalized value
3304 serialNumberAndIssuerNormalize(
3312 struct berval sn, sn2, i, ni;
3313 char sbuf[64], *stmp = sbuf;
3317 assert( in != NULL );
3318 assert( out != NULL );
3320 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3323 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3327 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3329 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3330 slap_sl_free( i.bv_val, ctx );
3333 if( rc ) return LDAP_INVALID_SYNTAX;
3335 /* Convert sn to canonical hex */
3336 if ( sn.bv_len > sizeof( sbuf )) {
3337 stmp = slap_sl_malloc( sn.bv_len, ctx );
3340 sn2.bv_len = sn.bv_len;
3341 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3342 rc = LDAP_INVALID_SYNTAX;
3346 /* make room for sn + "$" */
3347 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3348 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3349 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3351 if( out->bv_val == NULL ) {
3353 slap_sl_free( ni.bv_val, ctx );
3359 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3360 STRLENOF( "{ serialNumber " ));
3361 n = STRLENOF( "{ serialNumber " );
3363 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3366 unsigned char *v = (unsigned char *)sn2.bv_val;
3367 out->bv_val[n++] = '\'';
3368 for ( j = 0; j < sn2.bv_len; j++ ) {
3369 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3373 out->bv_val[n++] = '\'';
3374 out->bv_val[n++] = 'H';
3377 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3378 n += STRLENOF( ", issuer rdnSequence:\"" );
3380 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3383 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3384 n += STRLENOF( "\" }" );
3386 out->bv_val[n] = '\0';
3388 assert( n == out->bv_len );
3390 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3391 out->bv_val, 0, 0 );
3395 slap_sl_free( stmp, ctx );
3396 slap_sl_free( ni.bv_val, ctx );
3402 certificateExactNormalize(
3407 struct berval *normalized,
3410 BerElementBuffer berbuf;
3411 BerElement *ber = (BerElement *)&berbuf;
3415 char serialbuf[64], *serial = serialbuf;
3416 ber_len_t seriallen;
3417 struct berval issuer_dn = BER_BVNULL, bvdn;
3419 int rc = LDAP_INVALID_SYNTAX;
3421 if( BER_BVISEMPTY( val ) ) goto done;
3423 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3424 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3427 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3429 ber_init2( ber, val, LBER_USE_DER );
3430 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3431 tag = ber_skip_tag( ber, &len ); /* Sequence */
3432 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3433 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3434 tag = ber_skip_tag( ber, &len );
3435 tag = ber_get_int( ber, &i ); /* version */
3438 /* NOTE: move the test here from certificateValidate,
3439 * so that we can validate certs with serial longer
3440 * than sizeof(ber_int_t) */
3441 tag = ber_peek_tag( ber, &len ); /* serial */
3443 /* Use hex format. '123456789abcdef'H
3449 tag = ber_skip_tag( ber, &len );
3450 ptr = (unsigned char *)ber->ber_ptr;
3451 ber_skip_data( ber, len );
3453 /* Check for minimal encodings */
3455 if ( ptr[0] & 0x80 ) {
3456 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3457 return LDAP_INVALID_SYNTAX;
3458 } else if ( ptr[0] == 0 ) {
3459 if (!( ptr[1] & 0x80 ))
3460 return LDAP_INVALID_SYNTAX;
3464 seriallen = len * 2 + 4; /* quotes, H, NUL */
3465 if ( seriallen > sizeof( serialbuf ))
3466 serial = slap_sl_malloc( seriallen, ctx );
3469 for ( i = 0; i<len; i++ ) {
3470 sprintf( sptr, "%02X", ptr[i] );
3477 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3478 ber_skip_data( ber, len );
3479 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3480 len = ber_ptrlen( ber );
3481 bvdn.bv_val = val->bv_val + len;
3482 bvdn.bv_len = val->bv_len - len;
3484 rc = dnX509normalize( &bvdn, &issuer_dn );
3485 if( rc != LDAP_SUCCESS ) goto done;
3487 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3488 + seriallen + issuer_dn.bv_len;
3489 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3491 p = (unsigned char *)normalized->bv_val;
3493 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3494 p += STRLENOF( "{ serialNumber " );
3496 AC_MEMCPY(p, serial, seriallen);
3499 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3500 p += STRLENOF( ", issuer rdnSequence:\"" );
3502 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3503 p += issuer_dn.bv_len;
3505 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3506 p += STRLENOF( "\" }" );
3510 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3511 normalized->bv_val, NULL, NULL );
3516 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3517 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3529 assert( in != NULL );
3530 assert( !BER_BVISNULL( in ) );
3532 for ( i = 0; i < in->bv_len; i++ ) {
3533 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3534 return LDAP_INVALID_SYNTAX;
3538 return LDAP_SUCCESS;
3541 /* Normalize a SID as used inside a CSN:
3542 * three-digit numeric string */
3549 struct berval *normalized,
3554 assert( val != NULL );
3555 assert( normalized != NULL );
3557 ber_dupbv_x( normalized, val, ctx );
3559 for ( i = 0; i < normalized->bv_len; i++ ) {
3560 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3561 ber_memfree_x( normalized->bv_val, ctx );
3562 BER_BVZERO( normalized );
3563 return LDAP_INVALID_SYNTAX;
3566 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3569 return LDAP_SUCCESS;
3577 assert( in != NULL );
3578 assert( !BER_BVISNULL( in ) );
3580 if ( in->bv_len != 3 ) {
3581 return LDAP_INVALID_SYNTAX;
3584 return hexValidate( NULL, in );
3587 /* Normalize a SID as used inside a CSN:
3588 * three-digit numeric string */
3595 struct berval *normalized,
3598 if ( val->bv_len != 3 ) {
3599 return LDAP_INVALID_SYNTAX;
3602 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3612 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3615 /* Normalize a SID as used inside a CSN, either as-is
3616 * (assertion value) or extracted from the CSN
3617 * (attribute value) */
3624 struct berval *normalized,
3632 if ( BER_BVISEMPTY( val ) ) {
3633 return LDAP_INVALID_SYNTAX;
3636 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3637 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3640 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3642 ptr = ber_bvchr( val, '#' );
3643 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3644 return LDAP_INVALID_SYNTAX;
3647 bv.bv_val = ptr + 1;
3648 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3650 ptr = ber_bvchr( &bv, '#' );
3651 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3652 return LDAP_INVALID_SYNTAX;
3655 bv.bv_val = ptr + 1;
3656 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3658 ptr = ber_bvchr( &bv, '#' );
3659 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3660 return LDAP_INVALID_SYNTAX;
3663 bv.bv_len = ptr - bv.bv_val;
3665 if ( bv.bv_len == 2 ) {
3666 /* OpenLDAP 2.3 SID */
3668 buf[ 1 ] = bv.bv_val[ 0 ];
3669 buf[ 2 ] = bv.bv_val[ 1 ];
3676 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3688 assert( in != NULL );
3689 assert( !BER_BVISNULL( in ) );
3691 if ( BER_BVISEMPTY( in ) ) {
3692 return LDAP_INVALID_SYNTAX;
3697 ptr = ber_bvchr( &bv, '#' );
3698 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3699 return LDAP_INVALID_SYNTAX;
3702 bv.bv_len = ptr - bv.bv_val;
3703 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3704 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3706 return LDAP_INVALID_SYNTAX;
3709 rc = generalizedTimeValidate( NULL, &bv );
3710 if ( rc != LDAP_SUCCESS ) {
3714 bv.bv_val = ptr + 1;
3715 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3717 ptr = ber_bvchr( &bv, '#' );
3718 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3719 return LDAP_INVALID_SYNTAX;
3722 bv.bv_len = ptr - bv.bv_val;
3723 if ( bv.bv_len != 6 ) {
3724 return LDAP_INVALID_SYNTAX;
3727 rc = hexValidate( NULL, &bv );
3728 if ( rc != LDAP_SUCCESS ) {
3732 bv.bv_val = ptr + 1;
3733 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3735 ptr = ber_bvchr( &bv, '#' );
3736 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3737 return LDAP_INVALID_SYNTAX;
3740 bv.bv_len = ptr - bv.bv_val;
3741 if ( bv.bv_len == 2 ) {
3742 /* tolerate old 2-digit replica-id */
3743 rc = hexValidate( NULL, &bv );
3746 rc = sidValidate( NULL, &bv );
3748 if ( rc != LDAP_SUCCESS ) {
3752 bv.bv_val = ptr + 1;
3753 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3755 if ( bv.bv_len != 6 ) {
3756 return LDAP_INVALID_SYNTAX;
3759 return hexValidate( NULL, &bv );
3762 /* Normalize a CSN in OpenLDAP 2.1 format */
3769 struct berval *normalized,
3772 struct berval gt, cnt, sid, mod;
3774 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3778 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3779 assert( !BER_BVISEMPTY( val ) );
3783 ptr = ber_bvchr( >, '#' );
3784 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3785 return LDAP_INVALID_SYNTAX;
3788 gt.bv_len = ptr - gt.bv_val;
3789 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3790 return LDAP_INVALID_SYNTAX;
3793 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
3794 return LDAP_INVALID_SYNTAX;
3797 cnt.bv_val = ptr + 1;
3798 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3800 ptr = ber_bvchr( &cnt, '#' );
3801 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3802 return LDAP_INVALID_SYNTAX;
3805 cnt.bv_len = ptr - cnt.bv_val;
3806 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
3807 return LDAP_INVALID_SYNTAX;
3810 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
3811 return LDAP_INVALID_SYNTAX;
3814 cnt.bv_val += STRLENOF( "0x" );
3815 cnt.bv_len -= STRLENOF( "0x" );
3817 sid.bv_val = ptr + 1;
3818 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3820 ptr = ber_bvchr( &sid, '#' );
3821 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3822 return LDAP_INVALID_SYNTAX;
3825 sid.bv_len = ptr - sid.bv_val;
3826 if ( sid.bv_len != STRLENOF( "0" ) ) {
3827 return LDAP_INVALID_SYNTAX;
3830 mod.bv_val = ptr + 1;
3831 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3832 if ( mod.bv_len != STRLENOF( "0000" ) ) {
3833 return LDAP_INVALID_SYNTAX;
3836 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3840 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
3841 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
3843 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3845 ptr = lutil_strcopy( ptr, ".000000Z#00" );
3846 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3850 *ptr++ = sid.bv_val[ 0 ];
3854 for ( i = 0; i < mod.bv_len; i++ ) {
3855 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3859 assert( ptr - bv.bv_val == bv.bv_len );
3861 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3862 return LDAP_INVALID_SYNTAX;
3865 ber_dupbv_x( normalized, &bv, ctx );
3867 return LDAP_SUCCESS;
3870 /* Normalize a CSN in OpenLDAP 2.3 format */
3877 struct berval *normalized,
3880 struct berval gt, cnt, sid, mod;
3882 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3886 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3887 assert( !BER_BVISEMPTY( val ) );
3891 ptr = ber_bvchr( >, '#' );
3892 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3893 return LDAP_INVALID_SYNTAX;
3896 gt.bv_len = ptr - gt.bv_val;
3897 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3898 return LDAP_INVALID_SYNTAX;
3901 cnt.bv_val = ptr + 1;
3902 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3904 ptr = ber_bvchr( &cnt, '#' );
3905 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3906 return LDAP_INVALID_SYNTAX;
3909 cnt.bv_len = ptr - cnt.bv_val;
3910 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3911 return LDAP_INVALID_SYNTAX;
3914 sid.bv_val = ptr + 1;
3915 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3917 ptr = ber_bvchr( &sid, '#' );
3918 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3919 return LDAP_INVALID_SYNTAX;
3922 sid.bv_len = ptr - sid.bv_val;
3923 if ( sid.bv_len != STRLENOF( "00" ) ) {
3924 return LDAP_INVALID_SYNTAX;
3927 mod.bv_val = ptr + 1;
3928 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3929 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3930 return LDAP_INVALID_SYNTAX;
3933 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3937 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3938 ptr = lutil_strcopy( ptr, ".000000Z#" );
3939 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3942 for ( i = 0; i < sid.bv_len; i++ ) {
3943 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3946 for ( i = 0; i < mod.bv_len; i++ ) {
3947 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3951 assert( ptr - bv.bv_val == bv.bv_len );
3952 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3953 return LDAP_INVALID_SYNTAX;
3956 ber_dupbv_x( normalized, &bv, ctx );
3958 return LDAP_SUCCESS;
3961 /* Normalize a CSN */
3968 struct berval *normalized,
3971 struct berval cnt, sid, mod;
3975 assert( val != NULL );
3976 assert( normalized != NULL );
3978 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3980 if ( BER_BVISEMPTY( val ) ) {
3981 return LDAP_INVALID_SYNTAX;
3984 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3985 /* Openldap <= 2.3 */
3987 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3990 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3993 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
3996 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3997 return LDAP_INVALID_SYNTAX;
4000 ptr = ber_bvchr( val, '#' );
4001 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4002 return LDAP_INVALID_SYNTAX;
4005 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
4006 return LDAP_INVALID_SYNTAX;
4009 cnt.bv_val = ptr + 1;
4010 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4012 ptr = ber_bvchr( &cnt, '#' );
4013 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4014 return LDAP_INVALID_SYNTAX;
4017 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
4018 return LDAP_INVALID_SYNTAX;
4021 sid.bv_val = ptr + 1;
4022 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4024 ptr = ber_bvchr( &sid, '#' );
4025 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4026 return LDAP_INVALID_SYNTAX;
4029 sid.bv_len = ptr - sid.bv_val;
4030 if ( sid.bv_len != STRLENOF( "000" ) ) {
4031 return LDAP_INVALID_SYNTAX;
4034 mod.bv_val = ptr + 1;
4035 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4037 if ( mod.bv_len != STRLENOF( "000000" ) ) {
4038 return LDAP_INVALID_SYNTAX;
4041 ber_dupbv_x( normalized, val, ctx );
4043 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
4044 i < normalized->bv_len; i++ )
4046 /* assume it's already validated that's all hex digits */
4047 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4050 return LDAP_SUCCESS;
4060 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4063 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
4064 /* slight optimization - does not need the start parameter */
4065 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
4070 check_time_syntax (struct berval *val,
4073 struct berval *fraction)
4076 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
4077 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
4078 * GeneralizedTime supports leap seconds, UTCTime does not.
4080 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
4081 static const int mdays[2][12] = {
4082 /* non-leap years */
4083 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4085 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
4088 int part, c, c1, c2, tzoffset, leapyear = 0;
4091 e = p + val->bv_len;
4093 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4094 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
4096 for (part = start; part < 7 && p < e; part++) {
4098 if (!ASCII_DIGIT(c1)) {
4103 return LDAP_INVALID_SYNTAX;
4106 if (!ASCII_DIGIT(c)) {
4107 return LDAP_INVALID_SYNTAX;
4109 c += c1 * 10 - '0' * 11;
4110 if ((part | 1) == 3) {
4113 return LDAP_INVALID_SYNTAX;
4116 if (c >= ceiling[part]) {
4117 if (! (c == 60 && part == 6 && start == 0))
4118 return LDAP_INVALID_SYNTAX;
4122 if (part < 5 + start) {
4123 return LDAP_INVALID_SYNTAX;
4125 for (; part < 9; part++) {
4129 /* leapyear check for the Gregorian calendar (year>1581) */
4130 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4134 if (parts[3] >= mdays[leapyear][parts[2]]) {
4135 return LDAP_INVALID_SYNTAX;
4139 fraction->bv_val = p;
4140 fraction->bv_len = 0;
4141 if (p < e && (*p == '.' || *p == ',')) {
4143 while (++p < e && ASCII_DIGIT(*p)) {
4146 if (p - fraction->bv_val == 1) {
4147 return LDAP_INVALID_SYNTAX;
4149 for (end_num = p; end_num[-1] == '0'; --end_num) {
4152 c = end_num - fraction->bv_val;
4153 if (c != 1) fraction->bv_len = c;
4159 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4165 return LDAP_INVALID_SYNTAX;
4171 for (part = 7; part < 9 && p < e; part++) {
4173 if (!ASCII_DIGIT(c1)) {
4178 return LDAP_INVALID_SYNTAX;
4181 if (!ASCII_DIGIT(c2)) {
4182 return LDAP_INVALID_SYNTAX;
4184 parts[part] = c1 * 10 + c2 - '0' * 11;
4185 if (parts[part] >= ceiling[part]) {
4186 return LDAP_INVALID_SYNTAX;
4189 if (part < 8 + start) {
4190 return LDAP_INVALID_SYNTAX;
4193 if (tzoffset == '-') {
4194 /* negative offset to UTC, ie west of Greenwich */
4195 parts[4] += parts[7];
4196 parts[5] += parts[8];
4197 /* offset is just hhmm, no seconds */
4198 for (part = 6; --part >= 0; ) {
4202 c = mdays[leapyear][parts[2]];
4204 if (parts[part] >= c) {
4206 return LDAP_INVALID_SYNTAX;
4211 } else if (part != 5) {
4216 /* positive offset to UTC, ie east of Greenwich */
4217 parts[4] -= parts[7];
4218 parts[5] -= parts[8];
4219 for (part = 6; --part >= 0; ) {
4220 if (parts[part] < 0) {
4222 return LDAP_INVALID_SYNTAX;
4227 /* make first arg to % non-negative */
4228 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4233 } else if (part != 5) {
4240 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4243 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4250 struct berval *normalized )
4254 rc = check_time_syntax(val, 1, parts, NULL);
4255 if (rc != LDAP_SUCCESS) {
4259 normalized->bv_val = ch_malloc( 14 );
4260 if ( normalized->bv_val == NULL ) {
4261 return LBER_ERROR_MEMORY;
4264 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4265 parts[1], parts[2] + 1, parts[3] + 1,
4266 parts[4], parts[5], parts[6] );
4267 normalized->bv_len = 13;
4269 return LDAP_SUCCESS;
4279 return check_time_syntax(in, 1, parts, NULL);
4282 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4285 generalizedTimeValidate(
4290 struct berval fraction;
4291 return check_time_syntax(in, 0, parts, &fraction);
4295 generalizedTimeNormalize(
4300 struct berval *normalized,
4305 struct berval fraction;
4307 rc = check_time_syntax(val, 0, parts, &fraction);
4308 if (rc != LDAP_SUCCESS) {
4312 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4313 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4314 if ( BER_BVISNULL( normalized ) ) {
4315 return LBER_ERROR_MEMORY;
4318 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4319 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4320 parts[4], parts[5], parts[6] );
4321 if ( !BER_BVISEMPTY( &fraction ) ) {
4322 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4323 fraction.bv_val, fraction.bv_len );
4324 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4326 strcpy( normalized->bv_val + len-1, "Z" );
4327 normalized->bv_len = len;
4329 return LDAP_SUCCESS;
4333 generalizedTimeOrderingMatch(
4338 struct berval *value,
4339 void *assertedValue )
4341 struct berval *asserted = (struct berval *) assertedValue;
4342 ber_len_t v_len = value->bv_len;
4343 ber_len_t av_len = asserted->bv_len;
4345 /* ignore trailing 'Z' when comparing */
4346 int match = memcmp( value->bv_val, asserted->bv_val,
4347 (v_len < av_len ? v_len : av_len) - 1 );
4348 if ( match == 0 ) match = v_len - av_len;
4351 return LDAP_SUCCESS;
4354 /* Index generation function */
4355 int generalizedTimeIndexer(
4360 struct berval *prefix,
4368 BerValue bvtmp; /* 40 bit index */
4370 struct lutil_timet tt;
4372 bvtmp.bv_len = sizeof(tmp);
4374 for( i=0; values[i].bv_val != NULL; i++ ) {
4375 /* just count them */
4378 /* we should have at least one value at this point */
4381 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4383 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4384 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4385 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4386 /* Use 40 bits of time for key */
4387 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4388 lutil_tm2time( &tm, &tt );
4389 tmp[0] = tt.tt_gsec & 0xff;
4390 tmp[4] = tt.tt_sec & 0xff;
4392 tmp[3] = tt.tt_sec & 0xff;
4394 tmp[2] = tt.tt_sec & 0xff;
4396 tmp[1] = tt.tt_sec & 0xff;
4398 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4402 keys[j].bv_val = NULL;
4407 return LDAP_SUCCESS;
4410 /* Index generation function */
4411 int generalizedTimeFilter(
4416 struct berval *prefix,
4417 void * assertedValue,
4423 BerValue bvtmp; /* 40 bit index */
4424 BerValue *value = (BerValue *) assertedValue;
4426 struct lutil_timet tt;
4428 bvtmp.bv_len = sizeof(tmp);
4430 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4431 /* Use 40 bits of time for key */
4432 if ( value->bv_val && value->bv_len >= 10 &&
4433 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4435 lutil_tm2time( &tm, &tt );
4436 tmp[0] = tt.tt_gsec & 0xff;
4437 tmp[4] = tt.tt_sec & 0xff;
4439 tmp[3] = tt.tt_sec & 0xff;
4441 tmp[2] = tt.tt_sec & 0xff;
4443 tmp[1] = tt.tt_sec & 0xff;
4445 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4446 ber_dupbv_x(keys, &bvtmp, ctx );
4447 keys[1].bv_val = NULL;
4455 return LDAP_SUCCESS;
4459 deliveryMethodValidate(
4461 struct berval *val )
4464 #define LENOF(s) (sizeof(s)-1)
4465 struct berval tmp = *val;
4467 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4468 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4469 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4472 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4474 switch( tmp.bv_val[0] ) {
4477 if(( tmp.bv_len >= LENOF("any") ) &&
4478 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4480 tmp.bv_len -= LENOF("any");
4481 tmp.bv_val += LENOF("any");
4484 return LDAP_INVALID_SYNTAX;
4488 if(( tmp.bv_len >= LENOF("mhs") ) &&
4489 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4491 tmp.bv_len -= LENOF("mhs");
4492 tmp.bv_val += LENOF("mhs");
4495 return LDAP_INVALID_SYNTAX;
4499 if(( tmp.bv_len >= LENOF("physical") ) &&
4500 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4502 tmp.bv_len -= LENOF("physical");
4503 tmp.bv_val += LENOF("physical");
4506 return LDAP_INVALID_SYNTAX;
4509 case 'T': /* telex or teletex or telephone */
4510 if(( tmp.bv_len >= LENOF("telex") ) &&
4511 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4513 tmp.bv_len -= LENOF("telex");
4514 tmp.bv_val += LENOF("telex");
4517 if(( tmp.bv_len >= LENOF("teletex") ) &&
4518 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4520 tmp.bv_len -= LENOF("teletex");
4521 tmp.bv_val += LENOF("teletex");
4524 if(( tmp.bv_len >= LENOF("telephone") ) &&
4525 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4527 tmp.bv_len -= LENOF("telephone");
4528 tmp.bv_val += LENOF("telephone");
4531 return LDAP_INVALID_SYNTAX;
4534 case 'G': /* g3fax or g4fax */
4535 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4536 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4537 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4539 tmp.bv_len -= LENOF("g3fax");
4540 tmp.bv_val += LENOF("g3fax");
4543 return LDAP_INVALID_SYNTAX;
4547 if(( tmp.bv_len >= LENOF("ia5") ) &&
4548 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4550 tmp.bv_len -= LENOF("ia5");
4551 tmp.bv_val += LENOF("ia5");
4554 return LDAP_INVALID_SYNTAX;
4558 if(( tmp.bv_len >= LENOF("videotex") ) &&
4559 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4561 tmp.bv_len -= LENOF("videotex");
4562 tmp.bv_val += LENOF("videotex");
4565 return LDAP_INVALID_SYNTAX;
4568 return LDAP_INVALID_SYNTAX;
4571 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4573 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4577 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4581 return LDAP_INVALID_SYNTAX;
4583 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4592 nisNetgroupTripleValidate(
4594 struct berval *val )
4599 if ( BER_BVISEMPTY( val ) ) {
4600 return LDAP_INVALID_SYNTAX;
4603 p = (char *)val->bv_val;
4604 e = p + val->bv_len;
4606 if ( *p != '(' /*')'*/ ) {
4607 return LDAP_INVALID_SYNTAX;
4610 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4614 return LDAP_INVALID_SYNTAX;
4617 } else if ( !AD_CHAR( *p ) ) {
4618 return LDAP_INVALID_SYNTAX;
4622 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4623 return LDAP_INVALID_SYNTAX;
4629 return LDAP_INVALID_SYNTAX;
4632 return LDAP_SUCCESS;
4636 bootParameterValidate(
4638 struct berval *val )
4642 if ( BER_BVISEMPTY( val ) ) {
4643 return LDAP_INVALID_SYNTAX;
4646 p = (char *)val->bv_val;
4647 e = p + val->bv_len;
4650 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4651 if ( !AD_CHAR( *p ) ) {
4652 return LDAP_INVALID_SYNTAX;
4657 return LDAP_INVALID_SYNTAX;
4661 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4662 if ( !AD_CHAR( *p ) ) {
4663 return LDAP_INVALID_SYNTAX;
4668 return LDAP_INVALID_SYNTAX;
4672 for ( p++; p < e; p++ ) {
4673 if ( !SLAP_PRINTABLE( *p ) ) {
4674 return LDAP_INVALID_SYNTAX;
4678 return LDAP_SUCCESS;
4682 firstComponentNormalize(
4687 struct berval *normalized,
4694 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4695 ber_dupbv_x( normalized, val, ctx );
4696 return LDAP_SUCCESS;
4699 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4701 if( ! ( val->bv_val[0] == '(' /*')'*/
4702 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
4703 && ! ( val->bv_val[0] == '{' /*'}'*/
4704 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
4706 return LDAP_INVALID_SYNTAX;
4709 /* trim leading white space */
4711 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4717 /* grab next word */
4718 comp.bv_val = &val->bv_val[len];
4719 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
4720 for( comp.bv_len = 0;
4721 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4727 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4728 rc = numericoidValidate( NULL, &comp );
4729 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4730 rc = integerValidate( NULL, &comp );
4732 rc = LDAP_INVALID_SYNTAX;
4736 if( rc == LDAP_SUCCESS ) {
4737 ber_dupbv_x( normalized, &comp, ctx );
4743 static char *country_gen_syn[] = {
4744 "1.3.6.1.4.1.1466.115.121.1.15",
4745 "1.3.6.1.4.1.1466.115.121.1.26",
4746 "1.3.6.1.4.1.1466.115.121.1.44",
4750 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4751 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4753 static slap_syntax_defs_rec syntax_defs[] = {
4754 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4755 X_BINARY X_NOT_H_R ")",
4756 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4757 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4758 0, NULL, NULL, NULL},
4759 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4760 0, NULL, NULL, NULL},
4761 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4763 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4764 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4766 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4767 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4768 0, NULL, bitStringValidate, NULL },
4769 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4770 0, NULL, booleanValidate, NULL},
4771 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4772 X_BINARY X_NOT_H_R ")",
4773 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4774 NULL, certificateValidate, NULL},
4775 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4776 X_BINARY X_NOT_H_R ")",
4777 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4778 NULL, certificateListValidate, NULL},
4779 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4780 X_BINARY X_NOT_H_R ")",
4781 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4782 NULL, sequenceValidate, NULL},
4783 #if 0 /* need to go __after__ printableString */
4784 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4785 0, "1.3.6.1.4.1.1466.115.121.1.44",
4786 countryStringValidate, NULL},
4788 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4789 0, NULL, dnValidate, dnPretty},
4790 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4791 0, NULL, rdnValidate, rdnPretty},
4792 #ifdef LDAP_COMP_MATCH
4793 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4794 0, NULL, allComponentsValidate, NULL},
4795 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4796 0, NULL, componentFilterValidate, NULL},
4798 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4799 0, NULL, NULL, NULL},
4800 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4801 0, NULL, deliveryMethodValidate, NULL},
4802 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4803 0, NULL, UTF8StringValidate, NULL},
4804 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4805 0, NULL, NULL, NULL},
4806 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4807 0, NULL, NULL, NULL},
4808 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4809 0, NULL, NULL, NULL},
4810 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4811 0, NULL, NULL, NULL},
4812 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4813 0, NULL, NULL, NULL},
4814 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4815 0, NULL, printablesStringValidate, NULL},
4816 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4817 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4818 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4819 0, NULL, generalizedTimeValidate, NULL},
4820 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4821 0, NULL, NULL, NULL},
4822 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4823 0, NULL, IA5StringValidate, NULL},
4824 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4825 0, NULL, integerValidate, NULL},
4826 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4827 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4828 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4829 0, NULL, NULL, NULL},
4830 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4831 0, NULL, NULL, NULL},
4832 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4833 0, NULL, NULL, NULL},
4834 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4835 0, NULL, NULL, NULL},
4836 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4837 0, NULL, NULL, NULL},
4838 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4839 0, NULL, nameUIDValidate, nameUIDPretty },
4840 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4841 0, NULL, NULL, NULL},
4842 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4843 0, NULL, numericStringValidate, NULL},
4844 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4845 0, NULL, NULL, NULL},
4846 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4847 0, NULL, numericoidValidate, NULL},
4848 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4849 0, NULL, IA5StringValidate, NULL},
4850 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4851 0, NULL, blobValidate, NULL},
4852 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4853 0, NULL, postalAddressValidate, NULL},
4854 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4855 0, NULL, NULL, NULL},
4856 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4857 0, NULL, NULL, NULL},
4858 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4859 0, NULL, printableStringValidate, NULL},
4860 /* moved here because now depends on Directory String, IA5 String
4861 * and Printable String */
4862 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4863 0, country_gen_syn, countryStringValidate, NULL},
4864 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4865 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4866 0, NULL, subtreeSpecificationValidate, NULL},
4867 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4868 X_BINARY X_NOT_H_R ")",
4869 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4870 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4871 0, NULL, printableStringValidate, NULL},
4872 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4873 0, NULL, NULL, NULL},
4874 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4875 0, NULL, printablesStringValidate, NULL},
4876 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4877 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4878 0, NULL, utcTimeValidate, NULL},
4880 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4881 0, NULL, NULL, NULL},
4882 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4883 0, NULL, NULL, NULL},
4884 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4885 0, NULL, NULL, NULL},
4886 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4887 0, NULL, NULL, NULL},
4888 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4889 0, NULL, NULL, NULL},
4891 /* RFC 2307 NIS Syntaxes */
4892 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4893 0, NULL, nisNetgroupTripleValidate, NULL},
4894 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4895 0, NULL, bootParameterValidate, NULL},
4897 /* draft-zeilenga-ldap-x509 */
4898 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4899 SLAP_SYNTAX_HIDE, NULL,
4900 serialNumberAndIssuerValidate,
4901 serialNumberAndIssuerPretty},
4902 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4903 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4904 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4905 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4906 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4907 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4908 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4909 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4910 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4911 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4912 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4913 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4915 #ifdef SLAPD_AUTHPASSWD
4916 /* needs updating */
4917 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4918 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4921 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4922 0, NULL, UUIDValidate, UUIDPretty},
4924 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4925 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4927 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4928 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4930 /* OpenLDAP Void Syntax */
4931 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4932 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4934 /* FIXME: OID is unused, but not registered yet */
4935 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4936 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4938 {NULL, 0, NULL, NULL, NULL}
4941 char *csnSIDMatchSyntaxes[] = {
4942 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4945 char *certificateExactMatchSyntaxes[] = {
4946 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4949 #ifdef LDAP_COMP_MATCH
4950 char *componentFilterMatchSyntaxes[] = {
4951 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4955 char *directoryStringSyntaxes[] = {
4956 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4959 char *integerFirstComponentMatchSyntaxes[] = {
4960 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4961 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4964 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4965 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4966 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4967 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4968 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4969 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4970 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4971 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4972 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4977 * Other matching rules in X.520 that we do not use (yet):
4979 * 2.5.13.25 uTCTimeMatch
4980 * 2.5.13.26 uTCTimeOrderingMatch
4981 * 2.5.13.31* directoryStringFirstComponentMatch
4982 * 2.5.13.32* wordMatch
4983 * 2.5.13.33* keywordMatch
4984 * 2.5.13.36+ certificatePairExactMatch
4985 * 2.5.13.37+ certificatePairMatch
4986 * 2.5.13.38+ certificateListExactMatch
4987 * 2.5.13.39+ certificateListMatch
4988 * 2.5.13.40+ algorithmIdentifierMatch
4989 * 2.5.13.41* storedPrefixMatch
4990 * 2.5.13.42 attributeCertificateMatch
4991 * 2.5.13.43 readerAndKeyIDMatch
4992 * 2.5.13.44 attributeIntegrityMatch
4994 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4995 * (+) described in draft-zeilenga-ldap-x509
4997 static slap_mrule_defs_rec mrule_defs[] = {
4999 * EQUALITY matching rules must be listed after associated APPROX
5000 * matching rules. So, we list all APPROX matching rules first.
5002 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
5003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5004 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5005 NULL, NULL, directoryStringApproxMatch,
5006 directoryStringApproxIndexer, directoryStringApproxFilter,
5009 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
5010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5011 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5012 NULL, NULL, IA5StringApproxMatch,
5013 IA5StringApproxIndexer, IA5StringApproxFilter,
5017 * Other matching rules
5020 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
5021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5022 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5023 NULL, NULL, octetStringMatch,
5024 octetStringIndexer, octetStringFilter,
5027 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
5028 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5029 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5030 NULL, dnNormalize, dnMatch,
5031 octetStringIndexer, octetStringFilter,
5034 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
5035 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5036 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5037 NULL, dnNormalize, dnRelativeMatch,
5041 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
5042 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5043 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5044 NULL, dnNormalize, dnRelativeMatch,
5048 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
5049 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5050 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5051 NULL, dnNormalize, dnRelativeMatch,
5055 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
5056 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5057 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5058 NULL, dnNormalize, dnRelativeMatch,
5062 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
5063 "SYNTAX 1.2.36.79672281.1.5.0 )",
5064 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5065 NULL, rdnNormalize, rdnMatch,
5066 octetStringIndexer, octetStringFilter,
5069 #ifdef LDAP_COMP_MATCH
5070 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
5071 "SYNTAX 1.2.36.79672281.1.5.2 )",
5072 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
5073 NULL, NULL , componentFilterMatch,
5074 octetStringIndexer, octetStringFilter,
5077 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
5078 "SYNTAX 1.2.36.79672281.1.5.3 )",
5079 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5080 NULL, NULL , allComponentsMatch,
5081 octetStringIndexer, octetStringFilter,
5084 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
5085 "SYNTAX 1.2.36.79672281.1.5.3 )",
5086 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5087 NULL, NULL , directoryComponentsMatch,
5088 octetStringIndexer, octetStringFilter,
5092 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
5093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5094 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5095 NULL, UTF8StringNormalize, octetStringMatch,
5096 octetStringIndexer, octetStringFilter,
5097 directoryStringApproxMatchOID },
5099 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
5100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5101 SLAP_MR_ORDERING, directoryStringSyntaxes,
5102 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5104 "caseIgnoreMatch" },
5106 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
5107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5108 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5109 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5110 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5111 "caseIgnoreMatch" },
5113 {"( 2.5.13.5 NAME 'caseExactMatch' "
5114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5115 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5116 NULL, UTF8StringNormalize, octetStringMatch,
5117 octetStringIndexer, octetStringFilter,
5118 directoryStringApproxMatchOID },
5120 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
5121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5122 SLAP_MR_ORDERING, directoryStringSyntaxes,
5123 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5127 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
5128 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5129 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5130 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5131 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5134 {"( 2.5.13.8 NAME 'numericStringMatch' "
5135 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5136 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5137 NULL, numericStringNormalize, octetStringMatch,
5138 octetStringIndexer, octetStringFilter,
5141 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5142 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5143 SLAP_MR_ORDERING, NULL,
5144 NULL, numericStringNormalize, octetStringOrderingMatch,
5146 "numericStringMatch" },
5148 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5149 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5150 SLAP_MR_SUBSTR, NULL,
5151 NULL, numericStringNormalize, octetStringSubstringsMatch,
5152 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5153 "numericStringMatch" },
5155 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5156 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5157 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5158 NULL, postalAddressNormalize, octetStringMatch,
5159 octetStringIndexer, octetStringFilter,
5162 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5163 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5164 SLAP_MR_SUBSTR, NULL,
5165 NULL, NULL, NULL, NULL, NULL,
5166 "caseIgnoreListMatch" },
5168 {"( 2.5.13.13 NAME 'booleanMatch' "
5169 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5170 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5171 NULL, NULL, booleanMatch,
5172 octetStringIndexer, octetStringFilter,
5175 {"( 2.5.13.14 NAME 'integerMatch' "
5176 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5177 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5178 NULL, NULL, integerMatch,
5179 integerIndexer, integerFilter,
5182 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5183 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5184 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5185 NULL, NULL, integerMatch,
5189 {"( 2.5.13.16 NAME 'bitStringMatch' "
5190 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5191 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5192 NULL, NULL, octetStringMatch,
5193 octetStringIndexer, octetStringFilter,
5196 {"( 2.5.13.17 NAME 'octetStringMatch' "
5197 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5198 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5199 NULL, NULL, octetStringMatch,
5200 octetStringIndexer, octetStringFilter,
5203 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5204 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5205 SLAP_MR_ORDERING, NULL,
5206 NULL, NULL, octetStringOrderingMatch,
5208 "octetStringMatch" },
5210 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5211 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5212 SLAP_MR_SUBSTR, NULL,
5213 NULL, NULL, octetStringSubstringsMatch,
5214 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5215 "octetStringMatch" },
5217 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5218 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5219 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5221 telephoneNumberNormalize, octetStringMatch,
5222 octetStringIndexer, octetStringFilter,
5225 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5226 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5227 SLAP_MR_SUBSTR, NULL,
5228 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5229 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5230 "telephoneNumberMatch" },
5232 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5234 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5235 NULL, NULL, NULL, NULL, NULL, NULL },
5237 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5238 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5239 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5240 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5241 uniqueMemberIndexer, uniqueMemberFilter,
5244 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5245 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5246 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5247 NULL, NULL, NULL, NULL, NULL, NULL },
5249 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5250 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5251 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5252 NULL, generalizedTimeNormalize, octetStringMatch,
5253 generalizedTimeIndexer, generalizedTimeFilter,
5256 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5257 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5258 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5259 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5261 "generalizedTimeMatch" },
5263 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5264 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5265 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5266 integerFirstComponentMatchSyntaxes,
5267 NULL, firstComponentNormalize, integerMatch,
5268 octetStringIndexer, octetStringFilter,
5271 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5272 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5273 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5274 objectIdentifierFirstComponentMatchSyntaxes,
5275 NULL, firstComponentNormalize, octetStringMatch,
5276 octetStringIndexer, octetStringFilter,
5279 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5280 "SYNTAX 1.3.6.1.1.15.1 )",
5281 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5282 NULL, certificateExactNormalize, octetStringMatch,
5283 octetStringIndexer, octetStringFilter,
5286 {"( 2.5.13.35 NAME 'certificateMatch' "
5287 "SYNTAX 1.3.6.1.1.15.2 )",
5288 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5289 NULL, NULL, NULL, NULL, NULL,
5292 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5294 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5295 NULL, IA5StringNormalize, octetStringMatch,
5296 octetStringIndexer, octetStringFilter,
5297 IA5StringApproxMatchOID },
5299 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5301 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5302 NULL, IA5StringNormalize, octetStringMatch,
5303 octetStringIndexer, octetStringFilter,
5304 IA5StringApproxMatchOID },
5306 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5308 SLAP_MR_SUBSTR, NULL,
5309 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5310 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5311 "caseIgnoreIA5Match" },
5313 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5315 SLAP_MR_SUBSTR, NULL,
5316 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5317 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5318 "caseExactIA5Match" },
5320 #ifdef SLAPD_AUTHPASSWD
5321 /* needs updating */
5322 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5323 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5324 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5325 NULL, NULL, authPasswordMatch,
5330 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5333 NULL, NULL, integerBitAndMatch,
5337 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5338 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5340 NULL, NULL, integerBitOrMatch,
5344 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5345 "SYNTAX 1.3.6.1.1.16.1 )",
5346 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5347 NULL, UUIDNormalize, octetStringMatch,
5348 octetStringIndexer, octetStringFilter,
5351 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5352 "SYNTAX 1.3.6.1.1.16.1 )",
5353 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5354 NULL, UUIDNormalize, octetStringOrderingMatch,
5355 octetStringIndexer, octetStringFilter,
5358 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5359 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5360 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5361 NULL, csnNormalize, csnMatch,
5362 csnIndexer, csnFilter,
5365 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5366 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5367 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5368 NULL, NULL, csnOrderingMatch,
5372 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5373 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5374 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5375 NULL, csnSidNormalize, octetStringMatch,
5376 octetStringIndexer, octetStringFilter,
5379 /* FIXME: OID is unused, but not registered yet */
5380 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5381 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5382 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5383 NULL, authzNormalize, authzMatch,
5387 {NULL, SLAP_MR_NONE, NULL,
5388 NULL, NULL, NULL, NULL, NULL,
5393 slap_schema_init( void )
5398 /* we should only be called once (from main) */
5399 assert( schema_init_done == 0 );
5401 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5402 res = register_syntax( &syntax_defs[i] );
5405 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5406 syntax_defs[i].sd_desc );
5411 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5412 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5413 mrule_defs[i].mrd_compat_syntaxes == NULL )
5416 "slap_schema_init: Ignoring unusable matching rule %s\n",
5417 mrule_defs[i].mrd_desc );
5421 res = register_matching_rule( &mrule_defs[i] );
5425 "slap_schema_init: Error registering matching rule %s\n",
5426 mrule_defs[i].mrd_desc );
5431 res = slap_schema_load();
5432 schema_init_done = 1;
5437 schema_destroy( void )
5446 if( schema_init_done ) {
5447 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5448 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );