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;
2033 int rc = LDAP_SUCCESS;
2034 MatchingRule *xmr = NULL;
2037 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2038 xmr = slap_schema.si_mr_caseIgnoreMatch;
2041 xmr = slap_schema.si_mr_caseExactMatch;
2044 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2045 if ( val->bv_val[c] == '$' ) {
2050 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2051 nlines = &lines[l + 2];
2053 lines[0].bv_val = val->bv_val;
2054 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2055 if ( val->bv_val[c] == '$' ) {
2056 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2058 lines[l].bv_val = &val->bv_val[c + 1];
2061 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2063 normalized->bv_len = l;
2065 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2066 /* NOTE: we directly normalize each line,
2067 * without unescaping the values, since the special
2068 * values '\24' ('$') and '\5C' ('\') are not affected
2069 * by normalization */
2070 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2071 if ( rc != LDAP_SUCCESS ) {
2072 rc = LDAP_INVALID_SYNTAX;
2076 normalized->bv_len += nlines[l].bv_len;
2079 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2081 p = normalized->bv_val;
2082 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2083 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2089 assert( p - normalized->bv_val == normalized->bv_len );
2092 if ( nlines != NULL ) {
2093 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2094 slap_sl_free( nlines[l].bv_val, ctx );
2097 slap_sl_free( lines, ctx );
2108 struct berval val = *in;
2110 if( BER_BVISEMPTY( &val ) ) {
2111 /* disallow empty strings */
2112 return LDAP_INVALID_SYNTAX;
2115 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2116 if ( val.bv_len == 1 ) {
2117 return LDAP_SUCCESS;
2120 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2127 while ( OID_LEADCHAR( val.bv_val[0] )) {
2131 if ( val.bv_len == 0 ) {
2132 return LDAP_SUCCESS;
2136 if( !OID_SEPARATOR( val.bv_val[0] )) {
2144 return LDAP_INVALID_SYNTAX;
2153 struct berval val = *in;
2155 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2157 if ( val.bv_val[0] == '-' ) {
2161 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2162 return LDAP_INVALID_SYNTAX;
2165 if( val.bv_val[0] == '0' ) { /* "-0" */
2166 return LDAP_INVALID_SYNTAX;
2169 } else if ( val.bv_val[0] == '0' ) {
2170 if( val.bv_len > 1 ) { /* "0<more>" */
2171 return LDAP_INVALID_SYNTAX;
2174 return LDAP_SUCCESS;
2177 for( i=0; i < val.bv_len; i++ ) {
2178 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2179 return LDAP_INVALID_SYNTAX;
2183 return LDAP_SUCCESS;
2192 struct berval *value,
2193 void *assertedValue )
2195 struct berval *asserted = (struct berval *) assertedValue;
2196 int vsign = 1, asign = 1; /* default sign = '+' */
2201 if( v.bv_val[0] == '-' ) {
2207 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2210 if( a.bv_val[0] == '-' ) {
2216 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2218 match = vsign - asign;
2220 match = ( v.bv_len != a.bv_len
2221 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2222 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2223 if( vsign < 0 ) match = -match;
2227 return LDAP_SUCCESS;
2230 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2231 #define INDEX_INTLEN_CHOP 7
2232 #define INDEX_INTLEN_CHOPBYTES 3
2242 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2243 * two's complement value (sign-extended or chopped as needed),
2244 * however the top <number of exponent-bytes + 1> bits of first byte
2245 * above is the inverse sign. The next bit is the sign as delimiter.
2247 ber_slen_t k = index_intlen_strlen;
2249 unsigned signmask = ~0x7fU;
2250 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2251 struct berval val = *in, itmp = *tmp;
2253 if ( val.bv_val[0] != '-' ) {
2258 /* Chop least significant digits, increase length instead */
2259 if ( val.bv_len > (ber_len_t) k ) {
2260 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2261 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2262 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2265 if ( lutil_str2bin( &val, &itmp, ctx )) {
2266 return LDAP_INVALID_SYNTAX;
2269 /* Omit leading sign byte */
2270 if ( itmp.bv_val[0] == neg ) {
2275 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2277 assert( chop == 0 );
2278 memset( key->bv_val, neg, k ); /* sign-extend */
2279 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2280 lenp = lenbuf + sizeof(lenbuf);
2281 chop = - (ber_len_t) k;
2283 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2285 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2286 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2287 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2288 k = (lenbuf + sizeof(lenbuf)) - lenp;
2289 if ( k > (ber_slen_t) index_intlen )
2291 memcpy( key->bv_val, lenp, k );
2292 itmp.bv_len = index_intlen - k;
2294 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2295 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2299 /* Index generation function */
2306 struct berval *prefix,
2316 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2318 /* count the values and find max needed length */
2320 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2321 if ( vlen < values[i].bv_len )
2322 vlen = values[i].bv_len;
2324 if ( vlen > maxstrlen )
2327 /* we should have at least one value at this point */
2330 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2331 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2332 keys[i].bv_len = index_intlen;
2333 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2336 keys[i].bv_val = NULL;
2338 if ( vlen > sizeof(ibuf) ) {
2339 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2343 itmp.bv_len = sizeof(ibuf);
2345 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2346 if ( itmp.bv_val != ibuf ) {
2347 itmp.bv_len = values[i].bv_len;
2348 if ( itmp.bv_len <= sizeof(ibuf) )
2349 itmp.bv_len = sizeof(ibuf);
2350 else if ( itmp.bv_len > maxstrlen )
2351 itmp.bv_len = maxstrlen;
2353 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2359 if ( itmp.bv_val != ibuf ) {
2360 slap_sl_free( itmp.bv_val, ctx );
2365 /* Index generation function */
2372 struct berval *prefix,
2373 void * assertedValue,
2380 struct berval *value;
2383 value = (struct berval *) assertedValue;
2385 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2387 keys[0].bv_len = index_intlen;
2388 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2390 keys[1].bv_val = NULL;
2392 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2393 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2394 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2395 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2398 iv.bv_len = sizeof(ibuf);
2401 rc = integerVal2Key( value, keys, &iv, ctx );
2405 if ( iv.bv_val != ibuf ) {
2406 slap_sl_free( iv.bv_val, ctx );
2412 countryStringValidate(
2414 struct berval *val )
2416 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2418 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2419 return LDAP_INVALID_SYNTAX;
2421 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2422 return LDAP_INVALID_SYNTAX;
2425 return LDAP_SUCCESS;
2429 printableStringValidate(
2431 struct berval *val )
2435 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2437 for(i=0; i < val->bv_len; i++) {
2438 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2439 return LDAP_INVALID_SYNTAX;
2443 return LDAP_SUCCESS;
2447 printablesStringValidate(
2449 struct berval *val )
2453 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2455 for(i=0,len=0; i < val->bv_len; i++) {
2456 int c = val->bv_val[i];
2460 return LDAP_INVALID_SYNTAX;
2464 } else if ( SLAP_PRINTABLE(c) ) {
2467 return LDAP_INVALID_SYNTAX;
2472 return LDAP_INVALID_SYNTAX;
2475 return LDAP_SUCCESS;
2481 struct berval *val )
2485 for(i=0; i < val->bv_len; i++) {
2486 if( !LDAP_ASCII(val->bv_val[i]) ) {
2487 return LDAP_INVALID_SYNTAX;
2491 return LDAP_SUCCESS;
2500 struct berval *normalized,
2504 int casefold = !SLAP_MR_ASSOCIATED( mr,
2505 slap_schema.si_mr_caseExactIA5Match );
2507 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2511 /* Ignore initial whitespace */
2512 while ( ASCII_SPACE( *p ) ) p++;
2514 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2515 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2516 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2517 normalized->bv_val[normalized->bv_len] = '\0';
2519 p = q = normalized->bv_val;
2522 if ( ASCII_SPACE( *p ) ) {
2525 /* Ignore the extra whitespace */
2526 while ( ASCII_SPACE( *p ) ) {
2530 } else if ( casefold ) {
2531 /* Most IA5 rules require casefolding */
2532 *q++ = TOLOWER(*p); p++;
2539 assert( normalized->bv_val <= p );
2543 * If the string ended in space, backup the pointer one
2544 * position. One is enough because the above loop collapsed
2545 * all whitespace to a single space.
2547 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2549 /* null terminate */
2552 normalized->bv_len = q - normalized->bv_val;
2554 return LDAP_SUCCESS;
2563 if( in->bv_len != 36 ) {
2564 return LDAP_INVALID_SYNTAX;
2567 for( i=0; i<36; i++ ) {
2573 if( in->bv_val[i] != '-' ) {
2574 return LDAP_INVALID_SYNTAX;
2578 if( !ASCII_HEX( in->bv_val[i]) ) {
2579 return LDAP_INVALID_SYNTAX;
2584 return LDAP_SUCCESS;
2595 int rc=LDAP_INVALID_SYNTAX;
2597 assert( in != NULL );
2598 assert( out != NULL );
2600 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2603 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2605 for( i=0; i<36; i++ ) {
2611 if( in->bv_val[i] != '-' ) {
2614 out->bv_val[i] = '-';
2618 if( !ASCII_HEX( in->bv_val[i]) ) {
2621 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2626 out->bv_val[ out->bv_len ] = '\0';
2630 slap_sl_free( out->bv_val, ctx );
2643 struct berval *normalized,
2646 unsigned char octet = '\0';
2650 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2651 /* NOTE: must be a normalized UUID */
2652 assert( val->bv_len == 16 );
2654 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2655 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2656 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2657 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2659 return LDAP_SUCCESS;
2662 normalized->bv_len = 16;
2663 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2665 for( i=0, j=0; i<36; i++ ) {
2666 unsigned char nibble;
2667 if( val->bv_val[i] == '-' ) {
2670 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2671 nibble = val->bv_val[i] - '0';
2673 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2674 nibble = val->bv_val[i] - ('a'-10);
2676 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2677 nibble = val->bv_val[i] - ('A'-10);
2680 slap_sl_free( normalized->bv_val, ctx );
2681 return LDAP_INVALID_SYNTAX;
2686 normalized->bv_val[j>>1] = octet;
2688 octet = nibble << 4;
2693 normalized->bv_val[normalized->bv_len] = 0;
2694 return LDAP_SUCCESS;
2700 numericStringValidate(
2706 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2708 for(i=0; i < in->bv_len; i++) {
2709 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2710 return LDAP_INVALID_SYNTAX;
2714 return LDAP_SUCCESS;
2718 numericStringNormalize(
2723 struct berval *normalized,
2726 /* removal all spaces */
2729 assert( !BER_BVISEMPTY( val ) );
2731 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2734 q = normalized->bv_val;
2737 if ( ASCII_SPACE( *p ) ) {
2738 /* Ignore whitespace */
2745 /* we should have copied no more than is in val */
2746 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2748 /* null terminate */
2751 normalized->bv_len = q - normalized->bv_val;
2753 if( BER_BVISEMPTY( normalized ) ) {
2754 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2755 normalized->bv_val[0] = ' ';
2756 normalized->bv_val[1] = '\0';
2757 normalized->bv_len = 1;
2760 return LDAP_SUCCESS;
2764 * Integer conversion macros that will use the largest available
2767 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2768 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2769 # define SLAP_LONG long long
2771 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2772 # define SLAP_LONG long
2773 #endif /* HAVE_STRTOLL ... */
2781 struct berval *value,
2782 void *assertedValue )
2784 SLAP_LONG lValue, lAssertedValue;
2787 /* safe to assume integers are NUL terminated? */
2788 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2789 if( errno == ERANGE )
2791 return LDAP_CONSTRAINT_VIOLATION;
2794 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2796 if( errno == ERANGE )
2798 return LDAP_CONSTRAINT_VIOLATION;
2801 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2802 return LDAP_SUCCESS;
2811 struct berval *value,
2812 void *assertedValue )
2814 SLAP_LONG lValue, lAssertedValue;
2817 /* safe to assume integers are NUL terminated? */
2818 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2819 if( errno == ERANGE )
2821 return LDAP_CONSTRAINT_VIOLATION;
2824 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2826 if( errno == ERANGE )
2828 return LDAP_CONSTRAINT_VIOLATION;
2831 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2832 return LDAP_SUCCESS;
2836 serialNumberAndIssuerCheck(
2845 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2847 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2848 /* Parse old format */
2849 is->bv_val = ber_bvchr( in, '$' );
2850 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2852 sn->bv_val = in->bv_val;
2853 sn->bv_len = is->bv_val - in->bv_val;
2856 is->bv_len = in->bv_len - (sn->bv_len + 1);
2858 /* eat leading zeros */
2859 for( n=0; n < (sn->bv_len-1); n++ ) {
2860 if( sn->bv_val[n] != '0' ) break;
2865 for( n=0; n < sn->bv_len; n++ ) {
2866 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2870 /* Parse GSER format */
2871 int havesn = 0, haveissuer = 0, numdquotes = 0;
2872 struct berval x = *in;
2877 /* eat leading spaces */
2878 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2882 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2883 return LDAP_INVALID_SYNTAX;
2886 /* should be at issuer or serialNumber NamedValue */
2887 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2889 x.bv_val += STRLENOF("issuer");
2890 x.bv_len -= STRLENOF("issuer");
2892 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2893 x.bv_val++; x.bv_len--;
2895 /* eat leading spaces */
2896 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2900 /* For backward compatibility, this part is optional */
2901 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2902 x.bv_val += STRLENOF("rdnSequence:");
2903 x.bv_len -= STRLENOF("rdnSequence:");
2906 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2907 x.bv_val++; x.bv_len--;
2909 is->bv_val = x.bv_val;
2912 for( ; is->bv_len < x.bv_len; ) {
2913 if ( is->bv_val[is->bv_len] != '"' ) {
2917 if ( is->bv_val[is->bv_len+1] == '"' ) {
2924 x.bv_val += is->bv_len+1;
2925 x.bv_len -= is->bv_len+1;
2927 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2928 return LDAP_INVALID_SYNTAX;
2933 } else if( strncasecmp( x.bv_val, "serialNumber",
2934 STRLENOF("serialNumber")) == 0 )
2936 /* parse serialNumber */
2941 x.bv_val += STRLENOF("serialNumber");
2942 x.bv_len -= STRLENOF("serialNumber");
2944 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2945 x.bv_val++; x.bv_len--;
2947 /* eat leading spaces */
2948 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2952 sn->bv_val = x.bv_val;
2955 if( sn->bv_val[0] == '-' ) {
2960 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2961 sn->bv_val[1] == 'X' ))
2964 first = sn->bv_val[2];
2967 sn->bv_len += STRLENOF("0x");
2968 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2969 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2972 } else if ( sn->bv_val[0] == '\'' ) {
2973 first = sn->bv_val[1];
2976 sn->bv_len += STRLENOF("'");
2978 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2979 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2981 if ( sn->bv_val[sn->bv_len] == '\'' &&
2982 sn->bv_val[sn->bv_len + 1] == 'H' )
2984 sn->bv_len += STRLENOF("'H");
2988 return LDAP_INVALID_SYNTAX;
2992 first = sn->bv_val[0];
2993 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2994 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2998 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2999 if (( sn->bv_len > extra+1+neg ) && ( first == '0' )) {
3000 return LDAP_INVALID_SYNTAX;
3003 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
3005 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3006 return LDAP_INVALID_SYNTAX;
3011 } else return LDAP_INVALID_SYNTAX;
3013 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3014 x.bv_val++; x.bv_len--;
3017 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3021 /* should be at remaining NamedValue */
3022 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3023 STRLENOF("issuer" )) == 0 ))
3026 x.bv_val += STRLENOF("issuer");
3027 x.bv_len -= STRLENOF("issuer");
3029 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3030 x.bv_val++; x.bv_len--;
3032 /* eat leading spaces */
3033 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3037 /* For backward compatibility, this part is optional */
3038 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
3039 x.bv_val += STRLENOF("rdnSequence:");
3040 x.bv_len -= STRLENOF("rdnSequence:");
3043 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3044 x.bv_val++; x.bv_len--;
3046 is->bv_val = x.bv_val;
3049 for( ; is->bv_len < x.bv_len; ) {
3050 if ( is->bv_val[is->bv_len] != '"' ) {
3054 if ( is->bv_val[is->bv_len+1] == '"' ) {
3062 x.bv_val += is->bv_len+1;
3063 x.bv_len -= is->bv_len+1;
3065 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3066 STRLENOF("serialNumber")) == 0 ))
3068 /* parse serialNumber */
3070 x.bv_val += STRLENOF("serialNumber");
3071 x.bv_len -= STRLENOF("serialNumber");
3073 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3074 x.bv_val++; x.bv_len--;
3076 /* eat leading spaces */
3077 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3081 sn->bv_val = x.bv_val;
3084 if( sn->bv_val[0] == '-' ) {
3089 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
3090 sn->bv_val[1] == 'X' )) {
3092 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3093 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3095 } else if ( sn->bv_val[0] == '\'' ) {
3096 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3097 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
3099 if ( sn->bv_val[sn->bv_len] == '\'' &&
3100 sn->bv_val[sn->bv_len+1] == 'H' )
3103 return LDAP_INVALID_SYNTAX;
3106 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
3107 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
3111 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
3112 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
3113 return LDAP_INVALID_SYNTAX;
3116 x.bv_val += sn->bv_len;
3117 x.bv_len -= sn->bv_len;
3119 } else return LDAP_INVALID_SYNTAX;
3121 /* eat trailing spaces */
3122 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3126 /* should have no characters left... */
3127 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3129 if ( numdquotes == 0 ) {
3130 ber_dupbv_x( &ni, is, ctx );
3134 ni.bv_len = is->bv_len - numdquotes;
3135 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3136 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3137 if ( is->bv_val[src] == '"' ) {
3140 ni.bv_val[dst] = is->bv_val[src];
3142 ni.bv_val[dst] = '\0';
3152 serialNumberAndIssuerValidate(
3157 struct berval sn, i;
3159 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3162 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3166 /* validate DN -- doesn't handle double dquote */
3167 rc = dnValidate( NULL, &i );
3169 rc = LDAP_INVALID_SYNTAX;
3171 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3172 slap_sl_free( i.bv_val, NULL );
3175 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3181 serialNumberAndIssuerPretty(
3188 struct berval sn, i, ni;
3190 assert( in != NULL );
3191 assert( out != NULL );
3193 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3196 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3200 rc = dnPretty( syntax, &i, &ni, ctx );
3202 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3203 slap_sl_free( i.bv_val, ctx );
3206 if( rc ) return LDAP_INVALID_SYNTAX;
3208 /* make room from sn + "$" */
3209 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3210 + sn.bv_len + ni.bv_len;
3211 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3213 if( out->bv_val == NULL ) {
3215 slap_sl_free( ni.bv_val, ctx );
3220 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3221 STRLENOF("{ serialNumber "));
3222 n = STRLENOF("{ serialNumber ");
3224 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3227 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3228 n += STRLENOF(", issuer rdnSequence:\"");
3230 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3233 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3234 n += STRLENOF("\" }");
3236 out->bv_val[n] = '\0';
3238 assert( n == out->bv_len );
3240 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3241 out->bv_val, 0, 0 );
3243 slap_sl_free( ni.bv_val, ctx );
3245 return LDAP_SUCCESS;
3249 * This routine is called by certificateExactNormalize when
3250 * certificateExactNormalize receives a search string instead of
3251 * a certificate. This routine checks if the search value is valid
3252 * and then returns the normalized value
3255 serialNumberAndIssuerNormalize(
3263 struct berval sn, sn2, i, ni;
3264 char sbuf[64], *stmp = sbuf;
3268 assert( in != NULL );
3269 assert( out != NULL );
3271 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3274 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3278 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3280 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3281 slap_sl_free( i.bv_val, ctx );
3284 if( rc ) return LDAP_INVALID_SYNTAX;
3286 /* Convert sn to canonical hex */
3287 if ( sn.bv_len > sizeof( sbuf )) {
3288 stmp = slap_sl_malloc( sn.bv_len, ctx );
3291 sn2.bv_len = sn.bv_len;
3292 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3293 rc = LDAP_INVALID_SYNTAX;
3297 /* make room for sn + "$" */
3298 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3299 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3300 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3302 if( out->bv_val == NULL ) {
3304 slap_sl_free( ni.bv_val, ctx );
3310 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3311 STRLENOF( "{ serialNumber " ));
3312 n = STRLENOF( "{ serialNumber " );
3314 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3317 unsigned char *v = (unsigned char *)sn2.bv_val;
3318 out->bv_val[n++] = '\'';
3319 for ( j = 0; j < sn2.bv_len; j++ ) {
3320 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3324 out->bv_val[n++] = '\'';
3325 out->bv_val[n++] = 'H';
3328 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3329 n += STRLENOF( ", issuer rdnSequence:\"" );
3331 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3334 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3335 n += STRLENOF( "\" }" );
3337 out->bv_val[n] = '\0';
3339 assert( n == out->bv_len );
3341 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3342 out->bv_val, 0, 0 );
3346 slap_sl_free( stmp, ctx );
3347 slap_sl_free( ni.bv_val, ctx );
3353 certificateExactNormalize(
3358 struct berval *normalized,
3361 BerElementBuffer berbuf;
3362 BerElement *ber = (BerElement *)&berbuf;
3366 char serialbuf[64], *serial = serialbuf;
3367 ber_len_t seriallen;
3368 struct berval issuer_dn = BER_BVNULL, bvdn;
3370 int rc = LDAP_INVALID_SYNTAX;
3372 if( BER_BVISEMPTY( val ) ) goto done;
3374 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3375 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3378 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3380 ber_init2( ber, val, LBER_USE_DER );
3381 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3382 tag = ber_skip_tag( ber, &len ); /* Sequence */
3383 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3384 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3385 tag = ber_skip_tag( ber, &len );
3386 tag = ber_get_int( ber, &i ); /* version */
3389 /* NOTE: move the test here from certificateValidate,
3390 * so that we can validate certs with serial longer
3391 * than sizeof(ber_int_t) */
3392 tag = ber_peek_tag( ber, &len ); /* serial */
3394 /* Use hex format. '123456789abcdef'H
3400 tag = ber_skip_tag( ber, &len );
3401 ptr = (unsigned char *)ber->ber_ptr;
3402 ber_skip_data( ber, len );
3404 /* Check for minimal encodings */
3406 if ( ptr[0] & 0x80 ) {
3407 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3408 return LDAP_INVALID_SYNTAX;
3409 } else if ( ptr[0] == 0 ) {
3410 if (!( ptr[1] & 0x80 ))
3411 return LDAP_INVALID_SYNTAX;
3415 seriallen = len * 2 + 4; /* quotes, H, NUL */
3416 if ( seriallen > sizeof( serialbuf ))
3417 serial = slap_sl_malloc( seriallen, ctx );
3420 for ( i = 0; i<len; i++ ) {
3421 sprintf( sptr, "%02X", ptr[i] );
3428 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3429 ber_skip_data( ber, len );
3430 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3431 len = ber_ptrlen( ber );
3432 bvdn.bv_val = val->bv_val + len;
3433 bvdn.bv_len = val->bv_len - len;
3435 rc = dnX509normalize( &bvdn, &issuer_dn );
3436 if( rc != LDAP_SUCCESS ) goto done;
3438 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3439 + seriallen + issuer_dn.bv_len;
3440 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3442 p = (unsigned char *)normalized->bv_val;
3444 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3445 p += STRLENOF( "{ serialNumber " );
3447 AC_MEMCPY(p, serial, seriallen);
3450 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3451 p += STRLENOF( ", issuer rdnSequence:\"" );
3453 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3454 p += issuer_dn.bv_len;
3456 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3457 p += STRLENOF( "\" }" );
3461 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3462 normalized->bv_val, NULL, NULL );
3467 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3468 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3480 assert( in != NULL );
3481 assert( !BER_BVISNULL( in ) );
3483 for ( i = 0; i < in->bv_len; i++ ) {
3484 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3485 return LDAP_INVALID_SYNTAX;
3489 return LDAP_SUCCESS;
3492 /* Normalize a SID as used inside a CSN:
3493 * three-digit numeric string */
3500 struct berval *normalized,
3505 assert( val != NULL );
3506 assert( normalized != NULL );
3508 ber_dupbv_x( normalized, val, ctx );
3510 for ( i = 0; i < normalized->bv_len; i++ ) {
3511 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3512 ber_memfree_x( normalized->bv_val, ctx );
3513 BER_BVZERO( normalized );
3514 return LDAP_INVALID_SYNTAX;
3517 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3520 return LDAP_SUCCESS;
3528 assert( in != NULL );
3529 assert( !BER_BVISNULL( in ) );
3531 if ( in->bv_len != 3 ) {
3532 return LDAP_INVALID_SYNTAX;
3535 return hexValidate( NULL, in );
3538 /* Normalize a SID as used inside a CSN:
3539 * three-digit numeric string */
3546 struct berval *normalized,
3549 if ( val->bv_len != 3 ) {
3550 return LDAP_INVALID_SYNTAX;
3553 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3563 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3566 /* Normalize a SID as used inside a CSN, either as-is
3567 * (assertion value) or extracted from the CSN
3568 * (attribute value) */
3575 struct berval *normalized,
3583 if ( BER_BVISEMPTY( val ) ) {
3584 return LDAP_INVALID_SYNTAX;
3587 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3588 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3591 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3593 ptr = ber_bvchr( val, '#' );
3594 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3595 return LDAP_INVALID_SYNTAX;
3598 bv.bv_val = ptr + 1;
3599 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3601 ptr = ber_bvchr( &bv, '#' );
3602 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3603 return LDAP_INVALID_SYNTAX;
3606 bv.bv_val = ptr + 1;
3607 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3609 ptr = ber_bvchr( &bv, '#' );
3610 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3611 return LDAP_INVALID_SYNTAX;
3614 bv.bv_len = ptr - bv.bv_val;
3616 if ( bv.bv_len == 2 ) {
3617 /* OpenLDAP 2.3 SID */
3619 buf[ 1 ] = bv.bv_val[ 0 ];
3620 buf[ 2 ] = bv.bv_val[ 1 ];
3627 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3639 assert( in != NULL );
3640 assert( !BER_BVISNULL( in ) );
3642 if ( BER_BVISEMPTY( in ) ) {
3643 return LDAP_INVALID_SYNTAX;
3648 ptr = ber_bvchr( &bv, '#' );
3649 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3650 return LDAP_INVALID_SYNTAX;
3653 bv.bv_len = ptr - bv.bv_val;
3654 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3655 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3657 return LDAP_INVALID_SYNTAX;
3660 rc = generalizedTimeValidate( NULL, &bv );
3661 if ( rc != LDAP_SUCCESS ) {
3665 bv.bv_val = ptr + 1;
3666 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3668 ptr = ber_bvchr( &bv, '#' );
3669 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3670 return LDAP_INVALID_SYNTAX;
3673 bv.bv_len = ptr - bv.bv_val;
3674 if ( bv.bv_len != 6 ) {
3675 return LDAP_INVALID_SYNTAX;
3678 rc = hexValidate( NULL, &bv );
3679 if ( rc != LDAP_SUCCESS ) {
3683 bv.bv_val = ptr + 1;
3684 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3686 ptr = ber_bvchr( &bv, '#' );
3687 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3688 return LDAP_INVALID_SYNTAX;
3691 bv.bv_len = ptr - bv.bv_val;
3692 if ( bv.bv_len == 2 ) {
3693 /* tolerate old 2-digit replica-id */
3694 rc = hexValidate( NULL, &bv );
3697 rc = sidValidate( NULL, &bv );
3699 if ( rc != LDAP_SUCCESS ) {
3703 bv.bv_val = ptr + 1;
3704 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3706 if ( bv.bv_len != 6 ) {
3707 return LDAP_INVALID_SYNTAX;
3710 return hexValidate( NULL, &bv );
3713 /* Normalize a CSN in OpenLDAP 2.1 format */
3720 struct berval *normalized,
3723 struct berval gt, cnt, sid, mod;
3725 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3729 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3730 assert( !BER_BVISEMPTY( val ) );
3734 ptr = ber_bvchr( >, '#' );
3735 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3736 return LDAP_INVALID_SYNTAX;
3739 gt.bv_len = ptr - gt.bv_val;
3740 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3741 return LDAP_INVALID_SYNTAX;
3744 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
3745 return LDAP_INVALID_SYNTAX;
3748 cnt.bv_val = ptr + 1;
3749 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3751 ptr = ber_bvchr( &cnt, '#' );
3752 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3753 return LDAP_INVALID_SYNTAX;
3756 cnt.bv_len = ptr - cnt.bv_val;
3757 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
3758 return LDAP_INVALID_SYNTAX;
3761 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
3762 return LDAP_INVALID_SYNTAX;
3765 cnt.bv_val += STRLENOF( "0x" );
3766 cnt.bv_len -= STRLENOF( "0x" );
3768 sid.bv_val = ptr + 1;
3769 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3771 ptr = ber_bvchr( &sid, '#' );
3772 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3773 return LDAP_INVALID_SYNTAX;
3776 sid.bv_len = ptr - sid.bv_val;
3777 if ( sid.bv_len != STRLENOF( "0" ) ) {
3778 return LDAP_INVALID_SYNTAX;
3781 mod.bv_val = ptr + 1;
3782 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3783 if ( mod.bv_len != STRLENOF( "0000" ) ) {
3784 return LDAP_INVALID_SYNTAX;
3787 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3791 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
3792 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
3794 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3796 ptr = lutil_strcopy( ptr, ".000000Z#00" );
3797 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3801 *ptr++ = sid.bv_val[ 0 ];
3805 for ( i = 0; i < mod.bv_len; i++ ) {
3806 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3810 assert( ptr - bv.bv_val == bv.bv_len );
3812 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3813 return LDAP_INVALID_SYNTAX;
3816 ber_dupbv_x( normalized, &bv, ctx );
3818 return LDAP_SUCCESS;
3821 /* Normalize a CSN in OpenLDAP 2.3 format */
3828 struct berval *normalized,
3831 struct berval gt, cnt, sid, mod;
3833 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3837 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3838 assert( !BER_BVISEMPTY( val ) );
3842 ptr = ber_bvchr( >, '#' );
3843 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3844 return LDAP_INVALID_SYNTAX;
3847 gt.bv_len = ptr - gt.bv_val;
3848 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3849 return LDAP_INVALID_SYNTAX;
3852 cnt.bv_val = ptr + 1;
3853 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3855 ptr = ber_bvchr( &cnt, '#' );
3856 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3857 return LDAP_INVALID_SYNTAX;
3860 cnt.bv_len = ptr - cnt.bv_val;
3861 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3862 return LDAP_INVALID_SYNTAX;
3865 sid.bv_val = ptr + 1;
3866 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3868 ptr = ber_bvchr( &sid, '#' );
3869 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3870 return LDAP_INVALID_SYNTAX;
3873 sid.bv_len = ptr - sid.bv_val;
3874 if ( sid.bv_len != STRLENOF( "00" ) ) {
3875 return LDAP_INVALID_SYNTAX;
3878 mod.bv_val = ptr + 1;
3879 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3880 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3881 return LDAP_INVALID_SYNTAX;
3884 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3888 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3889 ptr = lutil_strcopy( ptr, ".000000Z#" );
3890 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3893 for ( i = 0; i < sid.bv_len; i++ ) {
3894 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3897 for ( i = 0; i < mod.bv_len; i++ ) {
3898 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3902 assert( ptr - bv.bv_val == bv.bv_len );
3903 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3904 return LDAP_INVALID_SYNTAX;
3907 ber_dupbv_x( normalized, &bv, ctx );
3909 return LDAP_SUCCESS;
3912 /* Normalize a CSN */
3919 struct berval *normalized,
3922 struct berval cnt, sid, mod;
3926 assert( val != NULL );
3927 assert( normalized != NULL );
3929 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3931 if ( BER_BVISEMPTY( val ) ) {
3932 return LDAP_INVALID_SYNTAX;
3935 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3936 /* Openldap <= 2.3 */
3938 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3941 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3944 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
3947 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3948 return LDAP_INVALID_SYNTAX;
3951 ptr = ber_bvchr( val, '#' );
3952 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3953 return LDAP_INVALID_SYNTAX;
3956 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3957 return LDAP_INVALID_SYNTAX;
3960 cnt.bv_val = ptr + 1;
3961 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3963 ptr = ber_bvchr( &cnt, '#' );
3964 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3965 return LDAP_INVALID_SYNTAX;
3968 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
3969 return LDAP_INVALID_SYNTAX;
3972 sid.bv_val = ptr + 1;
3973 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3975 ptr = ber_bvchr( &sid, '#' );
3976 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3977 return LDAP_INVALID_SYNTAX;
3980 sid.bv_len = ptr - sid.bv_val;
3981 if ( sid.bv_len != STRLENOF( "000" ) ) {
3982 return LDAP_INVALID_SYNTAX;
3985 mod.bv_val = ptr + 1;
3986 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3988 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3989 return LDAP_INVALID_SYNTAX;
3992 ber_dupbv_x( normalized, val, ctx );
3994 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3995 i < normalized->bv_len; i++ )
3997 /* assume it's already validated that's all hex digits */
3998 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4001 return LDAP_SUCCESS;
4011 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4014 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
4015 /* slight optimization - does not need the start parameter */
4016 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
4021 check_time_syntax (struct berval *val,
4024 struct berval *fraction)
4027 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
4028 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
4029 * GeneralizedTime supports leap seconds, UTCTime does not.
4031 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
4032 static const int mdays[2][12] = {
4033 /* non-leap years */
4034 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4036 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
4039 int part, c, c1, c2, tzoffset, leapyear = 0;
4042 e = p + val->bv_len;
4044 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4045 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
4047 for (part = start; part < 7 && p < e; part++) {
4049 if (!ASCII_DIGIT(c1)) {
4054 return LDAP_INVALID_SYNTAX;
4057 if (!ASCII_DIGIT(c)) {
4058 return LDAP_INVALID_SYNTAX;
4060 c += c1 * 10 - '0' * 11;
4061 if ((part | 1) == 3) {
4064 return LDAP_INVALID_SYNTAX;
4067 if (c >= ceiling[part]) {
4068 if (! (c == 60 && part == 6 && start == 0))
4069 return LDAP_INVALID_SYNTAX;
4073 if (part < 5 + start) {
4074 return LDAP_INVALID_SYNTAX;
4076 for (; part < 9; part++) {
4080 /* leapyear check for the Gregorian calendar (year>1581) */
4081 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4085 if (parts[3] >= mdays[leapyear][parts[2]]) {
4086 return LDAP_INVALID_SYNTAX;
4090 fraction->bv_val = p;
4091 fraction->bv_len = 0;
4092 if (p < e && (*p == '.' || *p == ',')) {
4094 while (++p < e && ASCII_DIGIT(*p)) {
4097 if (p - fraction->bv_val == 1) {
4098 return LDAP_INVALID_SYNTAX;
4100 for (end_num = p; end_num[-1] == '0'; --end_num) {
4103 c = end_num - fraction->bv_val;
4104 if (c != 1) fraction->bv_len = c;
4110 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4116 return LDAP_INVALID_SYNTAX;
4122 for (part = 7; part < 9 && p < e; part++) {
4124 if (!ASCII_DIGIT(c1)) {
4129 return LDAP_INVALID_SYNTAX;
4132 if (!ASCII_DIGIT(c2)) {
4133 return LDAP_INVALID_SYNTAX;
4135 parts[part] = c1 * 10 + c2 - '0' * 11;
4136 if (parts[part] >= ceiling[part]) {
4137 return LDAP_INVALID_SYNTAX;
4140 if (part < 8 + start) {
4141 return LDAP_INVALID_SYNTAX;
4144 if (tzoffset == '-') {
4145 /* negative offset to UTC, ie west of Greenwich */
4146 parts[4] += parts[7];
4147 parts[5] += parts[8];
4148 /* offset is just hhmm, no seconds */
4149 for (part = 6; --part >= 0; ) {
4153 c = mdays[leapyear][parts[2]];
4155 if (parts[part] >= c) {
4157 return LDAP_INVALID_SYNTAX;
4162 } else if (part != 5) {
4167 /* positive offset to UTC, ie east of Greenwich */
4168 parts[4] -= parts[7];
4169 parts[5] -= parts[8];
4170 for (part = 6; --part >= 0; ) {
4171 if (parts[part] < 0) {
4173 return LDAP_INVALID_SYNTAX;
4178 /* make first arg to % non-negative */
4179 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4184 } else if (part != 5) {
4191 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4194 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4201 struct berval *normalized )
4205 rc = check_time_syntax(val, 1, parts, NULL);
4206 if (rc != LDAP_SUCCESS) {
4210 normalized->bv_val = ch_malloc( 14 );
4211 if ( normalized->bv_val == NULL ) {
4212 return LBER_ERROR_MEMORY;
4215 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4216 parts[1], parts[2] + 1, parts[3] + 1,
4217 parts[4], parts[5], parts[6] );
4218 normalized->bv_len = 13;
4220 return LDAP_SUCCESS;
4230 return check_time_syntax(in, 1, parts, NULL);
4233 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4236 generalizedTimeValidate(
4241 struct berval fraction;
4242 return check_time_syntax(in, 0, parts, &fraction);
4246 generalizedTimeNormalize(
4251 struct berval *normalized,
4256 struct berval fraction;
4258 rc = check_time_syntax(val, 0, parts, &fraction);
4259 if (rc != LDAP_SUCCESS) {
4263 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4264 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4265 if ( BER_BVISNULL( normalized ) ) {
4266 return LBER_ERROR_MEMORY;
4269 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4270 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4271 parts[4], parts[5], parts[6] );
4272 if ( !BER_BVISEMPTY( &fraction ) ) {
4273 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4274 fraction.bv_val, fraction.bv_len );
4275 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4277 strcpy( normalized->bv_val + len-1, "Z" );
4278 normalized->bv_len = len;
4280 return LDAP_SUCCESS;
4284 generalizedTimeOrderingMatch(
4289 struct berval *value,
4290 void *assertedValue )
4292 struct berval *asserted = (struct berval *) assertedValue;
4293 ber_len_t v_len = value->bv_len;
4294 ber_len_t av_len = asserted->bv_len;
4296 /* ignore trailing 'Z' when comparing */
4297 int match = memcmp( value->bv_val, asserted->bv_val,
4298 (v_len < av_len ? v_len : av_len) - 1 );
4299 if ( match == 0 ) match = v_len - av_len;
4302 return LDAP_SUCCESS;
4305 /* Index generation function */
4306 int generalizedTimeIndexer(
4311 struct berval *prefix,
4319 BerValue bvtmp; /* 40 bit index */
4321 struct lutil_timet tt;
4323 bvtmp.bv_len = sizeof(tmp);
4325 for( i=0; values[i].bv_val != NULL; i++ ) {
4326 /* just count them */
4329 /* we should have at least one value at this point */
4332 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4334 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4335 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4336 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4337 /* Use 40 bits of time for key */
4338 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4339 lutil_tm2time( &tm, &tt );
4340 tmp[0] = tt.tt_gsec & 0xff;
4341 tmp[4] = tt.tt_sec & 0xff;
4343 tmp[3] = tt.tt_sec & 0xff;
4345 tmp[2] = tt.tt_sec & 0xff;
4347 tmp[1] = tt.tt_sec & 0xff;
4349 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4353 keys[j].bv_val = NULL;
4358 return LDAP_SUCCESS;
4361 /* Index generation function */
4362 int generalizedTimeFilter(
4367 struct berval *prefix,
4368 void * assertedValue,
4374 BerValue bvtmp; /* 40 bit index */
4375 BerValue *value = (BerValue *) assertedValue;
4377 struct lutil_timet tt;
4379 bvtmp.bv_len = sizeof(tmp);
4381 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4382 /* Use 40 bits of time for key */
4383 if ( value->bv_val && value->bv_len >= 10 &&
4384 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4386 lutil_tm2time( &tm, &tt );
4387 tmp[0] = tt.tt_gsec & 0xff;
4388 tmp[4] = tt.tt_sec & 0xff;
4390 tmp[3] = tt.tt_sec & 0xff;
4392 tmp[2] = tt.tt_sec & 0xff;
4394 tmp[1] = tt.tt_sec & 0xff;
4396 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4397 ber_dupbv_x(keys, &bvtmp, ctx );
4398 keys[1].bv_val = NULL;
4406 return LDAP_SUCCESS;
4410 deliveryMethodValidate(
4412 struct berval *val )
4415 #define LENOF(s) (sizeof(s)-1)
4416 struct berval tmp = *val;
4418 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4419 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4420 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4423 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4425 switch( tmp.bv_val[0] ) {
4428 if(( tmp.bv_len >= LENOF("any") ) &&
4429 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4431 tmp.bv_len -= LENOF("any");
4432 tmp.bv_val += LENOF("any");
4435 return LDAP_INVALID_SYNTAX;
4439 if(( tmp.bv_len >= LENOF("mhs") ) &&
4440 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4442 tmp.bv_len -= LENOF("mhs");
4443 tmp.bv_val += LENOF("mhs");
4446 return LDAP_INVALID_SYNTAX;
4450 if(( tmp.bv_len >= LENOF("physical") ) &&
4451 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4453 tmp.bv_len -= LENOF("physical");
4454 tmp.bv_val += LENOF("physical");
4457 return LDAP_INVALID_SYNTAX;
4460 case 'T': /* telex or teletex or telephone */
4461 if(( tmp.bv_len >= LENOF("telex") ) &&
4462 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4464 tmp.bv_len -= LENOF("telex");
4465 tmp.bv_val += LENOF("telex");
4468 if(( tmp.bv_len >= LENOF("teletex") ) &&
4469 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4471 tmp.bv_len -= LENOF("teletex");
4472 tmp.bv_val += LENOF("teletex");
4475 if(( tmp.bv_len >= LENOF("telephone") ) &&
4476 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4478 tmp.bv_len -= LENOF("telephone");
4479 tmp.bv_val += LENOF("telephone");
4482 return LDAP_INVALID_SYNTAX;
4485 case 'G': /* g3fax or g4fax */
4486 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4487 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4488 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4490 tmp.bv_len -= LENOF("g3fax");
4491 tmp.bv_val += LENOF("g3fax");
4494 return LDAP_INVALID_SYNTAX;
4498 if(( tmp.bv_len >= LENOF("ia5") ) &&
4499 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4501 tmp.bv_len -= LENOF("ia5");
4502 tmp.bv_val += LENOF("ia5");
4505 return LDAP_INVALID_SYNTAX;
4509 if(( tmp.bv_len >= LENOF("videotex") ) &&
4510 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4512 tmp.bv_len -= LENOF("videotex");
4513 tmp.bv_val += LENOF("videotex");
4516 return LDAP_INVALID_SYNTAX;
4519 return LDAP_INVALID_SYNTAX;
4522 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4524 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4528 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4532 return LDAP_INVALID_SYNTAX;
4534 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4543 nisNetgroupTripleValidate(
4545 struct berval *val )
4550 if ( BER_BVISEMPTY( val ) ) {
4551 return LDAP_INVALID_SYNTAX;
4554 p = (char *)val->bv_val;
4555 e = p + val->bv_len;
4557 if ( *p != '(' /*')'*/ ) {
4558 return LDAP_INVALID_SYNTAX;
4561 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4565 return LDAP_INVALID_SYNTAX;
4568 } else if ( !AD_CHAR( *p ) ) {
4569 return LDAP_INVALID_SYNTAX;
4573 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4574 return LDAP_INVALID_SYNTAX;
4580 return LDAP_INVALID_SYNTAX;
4583 return LDAP_SUCCESS;
4587 bootParameterValidate(
4589 struct berval *val )
4593 if ( BER_BVISEMPTY( val ) ) {
4594 return LDAP_INVALID_SYNTAX;
4597 p = (char *)val->bv_val;
4598 e = p + val->bv_len;
4601 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4602 if ( !AD_CHAR( *p ) ) {
4603 return LDAP_INVALID_SYNTAX;
4608 return LDAP_INVALID_SYNTAX;
4612 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4613 if ( !AD_CHAR( *p ) ) {
4614 return LDAP_INVALID_SYNTAX;
4619 return LDAP_INVALID_SYNTAX;
4623 for ( p++; p < e; p++ ) {
4624 if ( !SLAP_PRINTABLE( *p ) ) {
4625 return LDAP_INVALID_SYNTAX;
4629 return LDAP_SUCCESS;
4633 firstComponentNormalize(
4638 struct berval *normalized,
4645 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4646 ber_dupbv_x( normalized, val, ctx );
4647 return LDAP_SUCCESS;
4650 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4652 if( ! ( val->bv_val[0] == '(' /*')'*/
4653 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
4654 && ! ( val->bv_val[0] == '{' /*'}'*/
4655 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
4657 return LDAP_INVALID_SYNTAX;
4660 /* trim leading white space */
4662 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4668 /* grab next word */
4669 comp.bv_val = &val->bv_val[len];
4670 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
4671 for( comp.bv_len = 0;
4672 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4678 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4679 rc = numericoidValidate( NULL, &comp );
4680 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4681 rc = integerValidate( NULL, &comp );
4683 rc = LDAP_INVALID_SYNTAX;
4687 if( rc == LDAP_SUCCESS ) {
4688 ber_dupbv_x( normalized, &comp, ctx );
4694 static char *country_gen_syn[] = {
4695 "1.3.6.1.4.1.1466.115.121.1.15",
4696 "1.3.6.1.4.1.1466.115.121.1.26",
4697 "1.3.6.1.4.1.1466.115.121.1.44",
4701 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4702 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4704 static slap_syntax_defs_rec syntax_defs[] = {
4705 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4706 X_BINARY X_NOT_H_R ")",
4707 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4708 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4709 0, NULL, NULL, NULL},
4710 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4711 0, NULL, NULL, NULL},
4712 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4714 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4715 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4717 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4718 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4719 0, NULL, bitStringValidate, NULL },
4720 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4721 0, NULL, booleanValidate, NULL},
4722 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4723 X_BINARY X_NOT_H_R ")",
4724 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4725 NULL, certificateValidate, NULL},
4726 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4727 X_BINARY X_NOT_H_R ")",
4728 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4729 NULL, certificateListValidate, NULL},
4730 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4731 X_BINARY X_NOT_H_R ")",
4732 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4733 NULL, sequenceValidate, NULL},
4734 #if 0 /* need to go __after__ printableString */
4735 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4736 0, "1.3.6.1.4.1.1466.115.121.1.44",
4737 countryStringValidate, NULL},
4739 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4740 0, NULL, dnValidate, dnPretty},
4741 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4742 0, NULL, rdnValidate, rdnPretty},
4743 #ifdef LDAP_COMP_MATCH
4744 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4745 0, NULL, allComponentsValidate, NULL},
4746 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4747 0, NULL, componentFilterValidate, NULL},
4749 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4750 0, NULL, NULL, NULL},
4751 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4752 0, NULL, deliveryMethodValidate, NULL},
4753 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4754 0, NULL, UTF8StringValidate, NULL},
4755 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4756 0, NULL, NULL, NULL},
4757 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4758 0, NULL, NULL, NULL},
4759 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4760 0, NULL, NULL, NULL},
4761 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4762 0, NULL, NULL, NULL},
4763 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4764 0, NULL, NULL, NULL},
4765 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4766 0, NULL, printablesStringValidate, NULL},
4767 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4768 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4769 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4770 0, NULL, generalizedTimeValidate, NULL},
4771 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4772 0, NULL, NULL, NULL},
4773 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4774 0, NULL, IA5StringValidate, NULL},
4775 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4776 0, NULL, integerValidate, NULL},
4777 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4778 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4779 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4780 0, NULL, NULL, NULL},
4781 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4782 0, NULL, NULL, NULL},
4783 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4784 0, NULL, NULL, NULL},
4785 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4786 0, NULL, NULL, NULL},
4787 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4788 0, NULL, NULL, NULL},
4789 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4790 0, NULL, nameUIDValidate, nameUIDPretty },
4791 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4792 0, NULL, NULL, NULL},
4793 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4794 0, NULL, numericStringValidate, NULL},
4795 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4796 0, NULL, NULL, NULL},
4797 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4798 0, NULL, numericoidValidate, NULL},
4799 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4800 0, NULL, IA5StringValidate, NULL},
4801 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4802 0, NULL, blobValidate, NULL},
4803 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4804 0, NULL, postalAddressValidate, NULL},
4805 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4806 0, NULL, NULL, NULL},
4807 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4808 0, NULL, NULL, NULL},
4809 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4810 0, NULL, printableStringValidate, NULL},
4811 /* moved here because now depends on Directory String, IA5 String
4812 * and Printable String */
4813 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4814 0, country_gen_syn, countryStringValidate, NULL},
4815 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4816 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4817 0, NULL, subtreeSpecificationValidate, NULL},
4818 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4819 X_BINARY X_NOT_H_R ")",
4820 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4821 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4822 0, NULL, printableStringValidate, NULL},
4823 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4824 0, NULL, NULL, NULL},
4825 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4826 0, NULL, printablesStringValidate, NULL},
4827 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4828 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4829 0, NULL, utcTimeValidate, NULL},
4831 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4832 0, NULL, NULL, NULL},
4833 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4834 0, NULL, NULL, NULL},
4835 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4836 0, NULL, NULL, NULL},
4837 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4838 0, NULL, NULL, NULL},
4839 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4840 0, NULL, NULL, NULL},
4842 /* RFC 2307 NIS Syntaxes */
4843 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4844 0, NULL, nisNetgroupTripleValidate, NULL},
4845 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4846 0, NULL, bootParameterValidate, NULL},
4848 /* draft-zeilenga-ldap-x509 */
4849 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4850 SLAP_SYNTAX_HIDE, NULL,
4851 serialNumberAndIssuerValidate,
4852 serialNumberAndIssuerPretty},
4853 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4854 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4855 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4856 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4857 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4858 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4859 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4860 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4861 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4862 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4863 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4864 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4866 #ifdef SLAPD_AUTHPASSWD
4867 /* needs updating */
4868 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4869 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4872 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4873 0, NULL, UUIDValidate, UUIDPretty},
4875 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4876 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4878 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4879 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4881 /* OpenLDAP Void Syntax */
4882 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4883 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4885 /* FIXME: OID is unused, but not registered yet */
4886 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4887 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4889 {NULL, 0, NULL, NULL, NULL}
4892 char *csnSIDMatchSyntaxes[] = {
4893 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4896 char *certificateExactMatchSyntaxes[] = {
4897 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4900 #ifdef LDAP_COMP_MATCH
4901 char *componentFilterMatchSyntaxes[] = {
4902 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4906 char *directoryStringSyntaxes[] = {
4907 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4910 char *integerFirstComponentMatchSyntaxes[] = {
4911 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4912 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4915 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4916 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4917 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4918 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4919 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4920 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4921 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4922 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4923 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4928 * Other matching rules in X.520 that we do not use (yet):
4930 * 2.5.13.25 uTCTimeMatch
4931 * 2.5.13.26 uTCTimeOrderingMatch
4932 * 2.5.13.31* directoryStringFirstComponentMatch
4933 * 2.5.13.32* wordMatch
4934 * 2.5.13.33* keywordMatch
4935 * 2.5.13.36+ certificatePairExactMatch
4936 * 2.5.13.37+ certificatePairMatch
4937 * 2.5.13.38+ certificateListExactMatch
4938 * 2.5.13.39+ certificateListMatch
4939 * 2.5.13.40+ algorithmIdentifierMatch
4940 * 2.5.13.41* storedPrefixMatch
4941 * 2.5.13.42 attributeCertificateMatch
4942 * 2.5.13.43 readerAndKeyIDMatch
4943 * 2.5.13.44 attributeIntegrityMatch
4945 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4946 * (+) described in draft-zeilenga-ldap-x509
4948 static slap_mrule_defs_rec mrule_defs[] = {
4950 * EQUALITY matching rules must be listed after associated APPROX
4951 * matching rules. So, we list all APPROX matching rules first.
4953 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4955 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4956 NULL, NULL, directoryStringApproxMatch,
4957 directoryStringApproxIndexer, directoryStringApproxFilter,
4960 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4962 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4963 NULL, NULL, IA5StringApproxMatch,
4964 IA5StringApproxIndexer, IA5StringApproxFilter,
4968 * Other matching rules
4971 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4974 NULL, NULL, octetStringMatch,
4975 octetStringIndexer, octetStringFilter,
4978 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4981 NULL, dnNormalize, dnMatch,
4982 octetStringIndexer, octetStringFilter,
4985 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4987 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4988 NULL, dnNormalize, dnRelativeMatch,
4992 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4994 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4995 NULL, dnNormalize, dnRelativeMatch,
4999 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
5000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5001 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5002 NULL, dnNormalize, dnRelativeMatch,
5006 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
5007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5008 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5009 NULL, dnNormalize, dnRelativeMatch,
5013 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
5014 "SYNTAX 1.2.36.79672281.1.5.0 )",
5015 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5016 NULL, rdnNormalize, rdnMatch,
5017 octetStringIndexer, octetStringFilter,
5020 #ifdef LDAP_COMP_MATCH
5021 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
5022 "SYNTAX 1.2.36.79672281.1.5.2 )",
5023 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
5024 NULL, NULL , componentFilterMatch,
5025 octetStringIndexer, octetStringFilter,
5028 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
5029 "SYNTAX 1.2.36.79672281.1.5.3 )",
5030 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5031 NULL, NULL , allComponentsMatch,
5032 octetStringIndexer, octetStringFilter,
5035 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
5036 "SYNTAX 1.2.36.79672281.1.5.3 )",
5037 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5038 NULL, NULL , directoryComponentsMatch,
5039 octetStringIndexer, octetStringFilter,
5043 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
5044 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5045 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5046 NULL, UTF8StringNormalize, octetStringMatch,
5047 octetStringIndexer, octetStringFilter,
5048 directoryStringApproxMatchOID },
5050 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
5051 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5052 SLAP_MR_ORDERING, directoryStringSyntaxes,
5053 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5055 "caseIgnoreMatch" },
5057 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
5058 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5059 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5060 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5061 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5062 "caseIgnoreMatch" },
5064 {"( 2.5.13.5 NAME 'caseExactMatch' "
5065 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5066 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5067 NULL, UTF8StringNormalize, octetStringMatch,
5068 octetStringIndexer, octetStringFilter,
5069 directoryStringApproxMatchOID },
5071 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
5072 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5073 SLAP_MR_ORDERING, directoryStringSyntaxes,
5074 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5078 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
5079 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5080 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5081 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5082 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5085 {"( 2.5.13.8 NAME 'numericStringMatch' "
5086 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5087 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5088 NULL, numericStringNormalize, octetStringMatch,
5089 octetStringIndexer, octetStringFilter,
5092 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5094 SLAP_MR_ORDERING, NULL,
5095 NULL, numericStringNormalize, octetStringOrderingMatch,
5097 "numericStringMatch" },
5099 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5101 SLAP_MR_SUBSTR, NULL,
5102 NULL, numericStringNormalize, octetStringSubstringsMatch,
5103 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5104 "numericStringMatch" },
5106 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5108 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5109 NULL, postalAddressNormalize, octetStringMatch,
5110 octetStringIndexer, octetStringFilter,
5113 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5115 SLAP_MR_SUBSTR, NULL,
5116 NULL, NULL, NULL, NULL, NULL,
5117 "caseIgnoreListMatch" },
5119 {"( 2.5.13.13 NAME 'booleanMatch' "
5120 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5121 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5122 NULL, NULL, booleanMatch,
5123 octetStringIndexer, octetStringFilter,
5126 {"( 2.5.13.14 NAME 'integerMatch' "
5127 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5128 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5129 NULL, NULL, integerMatch,
5130 integerIndexer, integerFilter,
5133 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5134 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5135 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5136 NULL, NULL, integerMatch,
5140 {"( 2.5.13.16 NAME 'bitStringMatch' "
5141 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5142 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5143 NULL, NULL, octetStringMatch,
5144 octetStringIndexer, octetStringFilter,
5147 {"( 2.5.13.17 NAME 'octetStringMatch' "
5148 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5149 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5150 NULL, NULL, octetStringMatch,
5151 octetStringIndexer, octetStringFilter,
5154 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5155 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5156 SLAP_MR_ORDERING, NULL,
5157 NULL, NULL, octetStringOrderingMatch,
5159 "octetStringMatch" },
5161 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5162 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5163 SLAP_MR_SUBSTR, NULL,
5164 NULL, NULL, octetStringSubstringsMatch,
5165 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5166 "octetStringMatch" },
5168 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5169 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5170 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5172 telephoneNumberNormalize, octetStringMatch,
5173 octetStringIndexer, octetStringFilter,
5176 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5177 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5178 SLAP_MR_SUBSTR, NULL,
5179 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5180 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5181 "telephoneNumberMatch" },
5183 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5184 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5185 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5186 NULL, NULL, NULL, NULL, NULL, NULL },
5188 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5189 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5190 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5191 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5192 uniqueMemberIndexer, uniqueMemberFilter,
5195 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5196 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5197 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5198 NULL, NULL, NULL, NULL, NULL, NULL },
5200 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5201 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5202 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5203 NULL, generalizedTimeNormalize, octetStringMatch,
5204 generalizedTimeIndexer, generalizedTimeFilter,
5207 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5208 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5209 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5210 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5212 "generalizedTimeMatch" },
5214 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5215 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5216 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5217 integerFirstComponentMatchSyntaxes,
5218 NULL, firstComponentNormalize, integerMatch,
5219 octetStringIndexer, octetStringFilter,
5222 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5223 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5224 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5225 objectIdentifierFirstComponentMatchSyntaxes,
5226 NULL, firstComponentNormalize, octetStringMatch,
5227 octetStringIndexer, octetStringFilter,
5230 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5231 "SYNTAX 1.3.6.1.1.15.1 )",
5232 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5233 NULL, certificateExactNormalize, octetStringMatch,
5234 octetStringIndexer, octetStringFilter,
5237 {"( 2.5.13.35 NAME 'certificateMatch' "
5238 "SYNTAX 1.3.6.1.1.15.2 )",
5239 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5240 NULL, NULL, NULL, NULL, NULL,
5243 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5244 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5245 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5246 NULL, IA5StringNormalize, octetStringMatch,
5247 octetStringIndexer, octetStringFilter,
5248 IA5StringApproxMatchOID },
5250 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5251 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5252 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5253 NULL, IA5StringNormalize, octetStringMatch,
5254 octetStringIndexer, octetStringFilter,
5255 IA5StringApproxMatchOID },
5257 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5258 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5259 SLAP_MR_SUBSTR, NULL,
5260 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5261 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5262 "caseIgnoreIA5Match" },
5264 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5265 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5266 SLAP_MR_SUBSTR, NULL,
5267 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5268 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5269 "caseExactIA5Match" },
5271 #ifdef SLAPD_AUTHPASSWD
5272 /* needs updating */
5273 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5274 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5275 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5276 NULL, NULL, authPasswordMatch,
5281 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5282 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5284 NULL, NULL, integerBitAndMatch,
5288 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5289 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5291 NULL, NULL, integerBitOrMatch,
5295 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5296 "SYNTAX 1.3.6.1.1.16.1 )",
5297 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5298 NULL, UUIDNormalize, octetStringMatch,
5299 octetStringIndexer, octetStringFilter,
5302 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5303 "SYNTAX 1.3.6.1.1.16.1 )",
5304 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5305 NULL, UUIDNormalize, octetStringOrderingMatch,
5306 octetStringIndexer, octetStringFilter,
5309 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5310 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5311 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5312 NULL, csnNormalize, csnMatch,
5313 csnIndexer, csnFilter,
5316 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5317 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5318 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5319 NULL, NULL, csnOrderingMatch,
5323 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5324 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5325 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5326 NULL, csnSidNormalize, octetStringMatch,
5327 octetStringIndexer, octetStringFilter,
5330 /* FIXME: OID is unused, but not registered yet */
5331 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5332 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5333 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5334 NULL, authzNormalize, authzMatch,
5338 {NULL, SLAP_MR_NONE, NULL,
5339 NULL, NULL, NULL, NULL, NULL,
5344 slap_schema_init( void )
5349 /* we should only be called once (from main) */
5350 assert( schema_init_done == 0 );
5352 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5353 res = register_syntax( &syntax_defs[i] );
5356 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5357 syntax_defs[i].sd_desc );
5362 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5363 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5364 mrule_defs[i].mrd_compat_syntaxes == NULL )
5367 "slap_schema_init: Ignoring unusable matching rule %s\n",
5368 mrule_defs[i].mrd_desc );
5372 res = register_matching_rule( &mrule_defs[i] );
5376 "slap_schema_init: Error registering matching rule %s\n",
5377 mrule_defs[i].mrd_desc );
5382 res = slap_schema_load();
5383 schema_init_done = 1;
5388 schema_destroy( void )
5397 if( schema_init_done ) {
5398 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5399 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );