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;
1995 struct berval val = *in;
1997 if( BER_BVISEMPTY( &val ) ) {
1998 /* disallow empty strings */
1999 return LDAP_INVALID_SYNTAX;
2002 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2003 if ( val.bv_len == 1 ) {
2004 return LDAP_SUCCESS;
2007 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2014 while ( OID_LEADCHAR( val.bv_val[0] )) {
2018 if ( val.bv_len == 0 ) {
2019 return LDAP_SUCCESS;
2023 if( !OID_SEPARATOR( val.bv_val[0] )) {
2031 return LDAP_INVALID_SYNTAX;
2040 struct berval val = *in;
2042 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2044 if ( val.bv_val[0] == '-' ) {
2048 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2049 return LDAP_INVALID_SYNTAX;
2052 if( val.bv_val[0] == '0' ) { /* "-0" */
2053 return LDAP_INVALID_SYNTAX;
2056 } else if ( val.bv_val[0] == '0' ) {
2057 if( val.bv_len > 1 ) { /* "0<more>" */
2058 return LDAP_INVALID_SYNTAX;
2061 return LDAP_SUCCESS;
2064 for( i=0; i < val.bv_len; i++ ) {
2065 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2066 return LDAP_INVALID_SYNTAX;
2070 return LDAP_SUCCESS;
2079 struct berval *value,
2080 void *assertedValue )
2082 struct berval *asserted = (struct berval *) assertedValue;
2083 int vsign = 1, asign = 1; /* default sign = '+' */
2088 if( v.bv_val[0] == '-' ) {
2094 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2097 if( a.bv_val[0] == '-' ) {
2103 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2105 match = vsign - asign;
2107 match = ( v.bv_len != a.bv_len
2108 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2109 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2110 if( vsign < 0 ) match = -match;
2114 return LDAP_SUCCESS;
2117 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2118 #define INDEX_INTLEN_CHOP 7
2119 #define INDEX_INTLEN_CHOPBYTES 3
2129 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2130 * two's complement value (sign-extended or chopped as needed),
2131 * however the top <number of exponent-bytes + 1> bits of first byte
2132 * above is the inverse sign. The next bit is the sign as delimiter.
2134 ber_slen_t k = index_intlen_strlen;
2136 unsigned signmask = ~0x7fU;
2137 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2138 struct berval val = *in, itmp = *tmp;
2140 if ( val.bv_val[0] != '-' ) {
2145 /* Chop least significant digits, increase length instead */
2146 if ( val.bv_len > (ber_len_t) k ) {
2147 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2148 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2149 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2152 if ( lutil_str2bin( &val, &itmp, ctx )) {
2153 return LDAP_INVALID_SYNTAX;
2156 /* Omit leading sign byte */
2157 if ( itmp.bv_val[0] == neg ) {
2162 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2164 assert( chop == 0 );
2165 memset( key->bv_val, neg, k ); /* sign-extend */
2166 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2167 lenp = lenbuf + sizeof(lenbuf);
2168 chop = - (ber_len_t) k;
2170 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2172 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2173 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2174 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2175 k = (lenbuf + sizeof(lenbuf)) - lenp;
2176 if ( k > (ber_slen_t) index_intlen )
2178 memcpy( key->bv_val, lenp, k );
2179 itmp.bv_len = index_intlen - k;
2181 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2182 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2186 /* Index generation function */
2193 struct berval *prefix,
2203 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2205 /* count the values and find max needed length */
2207 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2208 if ( vlen < values[i].bv_len )
2209 vlen = values[i].bv_len;
2211 if ( vlen > maxstrlen )
2214 /* we should have at least one value at this point */
2217 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2218 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2219 keys[i].bv_len = index_intlen;
2220 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2223 keys[i].bv_val = NULL;
2225 if ( vlen > sizeof(ibuf) ) {
2226 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2230 itmp.bv_len = sizeof(ibuf);
2232 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2233 if ( itmp.bv_val != ibuf ) {
2234 itmp.bv_len = values[i].bv_len;
2235 if ( itmp.bv_len <= sizeof(ibuf) )
2236 itmp.bv_len = sizeof(ibuf);
2237 else if ( itmp.bv_len > maxstrlen )
2238 itmp.bv_len = maxstrlen;
2240 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2246 if ( itmp.bv_val != ibuf ) {
2247 slap_sl_free( itmp.bv_val, ctx );
2252 /* Index generation function */
2259 struct berval *prefix,
2260 void * assertedValue,
2267 struct berval *value;
2270 value = (struct berval *) assertedValue;
2272 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2274 keys[0].bv_len = index_intlen;
2275 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2277 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2278 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2279 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2280 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2283 iv.bv_len = sizeof(ibuf);
2286 rc = integerVal2Key( value, keys, &iv, ctx );
2290 if ( iv.bv_val != ibuf ) {
2291 slap_sl_free( iv.bv_val, ctx );
2297 countryStringValidate(
2299 struct berval *val )
2301 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2303 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2304 return LDAP_INVALID_SYNTAX;
2306 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2307 return LDAP_INVALID_SYNTAX;
2310 return LDAP_SUCCESS;
2314 printableStringValidate(
2316 struct berval *val )
2320 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2322 for(i=0; i < val->bv_len; i++) {
2323 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2324 return LDAP_INVALID_SYNTAX;
2328 return LDAP_SUCCESS;
2332 printablesStringValidate(
2334 struct berval *val )
2338 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2340 for(i=0,len=0; i < val->bv_len; i++) {
2341 int c = val->bv_val[i];
2345 return LDAP_INVALID_SYNTAX;
2349 } else if ( SLAP_PRINTABLE(c) ) {
2352 return LDAP_INVALID_SYNTAX;
2357 return LDAP_INVALID_SYNTAX;
2360 return LDAP_SUCCESS;
2366 struct berval *val )
2370 for(i=0; i < val->bv_len; i++) {
2371 if( !LDAP_ASCII(val->bv_val[i]) ) {
2372 return LDAP_INVALID_SYNTAX;
2376 return LDAP_SUCCESS;
2385 struct berval *normalized,
2389 int casefold = !SLAP_MR_ASSOCIATED( mr,
2390 slap_schema.si_mr_caseExactIA5Match );
2392 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2396 /* Ignore initial whitespace */
2397 while ( ASCII_SPACE( *p ) ) p++;
2399 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2400 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2401 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2402 normalized->bv_val[normalized->bv_len] = '\0';
2404 p = q = normalized->bv_val;
2407 if ( ASCII_SPACE( *p ) ) {
2410 /* Ignore the extra whitespace */
2411 while ( ASCII_SPACE( *p ) ) {
2415 } else if ( casefold ) {
2416 /* Most IA5 rules require casefolding */
2417 *q++ = TOLOWER(*p); p++;
2424 assert( normalized->bv_val <= p );
2428 * If the string ended in space, backup the pointer one
2429 * position. One is enough because the above loop collapsed
2430 * all whitespace to a single space.
2432 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2434 /* null terminate */
2437 normalized->bv_len = q - normalized->bv_val;
2439 return LDAP_SUCCESS;
2448 if( in->bv_len != 36 ) {
2449 return LDAP_INVALID_SYNTAX;
2452 for( i=0; i<36; i++ ) {
2458 if( in->bv_val[i] != '-' ) {
2459 return LDAP_INVALID_SYNTAX;
2463 if( !ASCII_HEX( in->bv_val[i]) ) {
2464 return LDAP_INVALID_SYNTAX;
2469 return LDAP_SUCCESS;
2480 int rc=LDAP_INVALID_SYNTAX;
2482 assert( in != NULL );
2483 assert( out != NULL );
2485 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2488 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2490 for( i=0; i<36; i++ ) {
2496 if( in->bv_val[i] != '-' ) {
2499 out->bv_val[i] = '-';
2503 if( !ASCII_HEX( in->bv_val[i]) ) {
2506 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2511 out->bv_val[ out->bv_len ] = '\0';
2515 slap_sl_free( out->bv_val, ctx );
2528 struct berval *normalized,
2531 unsigned char octet = '\0';
2535 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2536 /* NOTE: must be a normalized UUID */
2537 assert( val->bv_len == 16 );
2539 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2540 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2541 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2542 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2544 return LDAP_SUCCESS;
2547 normalized->bv_len = 16;
2548 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2550 for( i=0, j=0; i<36; i++ ) {
2551 unsigned char nibble;
2552 if( val->bv_val[i] == '-' ) {
2555 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2556 nibble = val->bv_val[i] - '0';
2558 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2559 nibble = val->bv_val[i] - ('a'-10);
2561 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2562 nibble = val->bv_val[i] - ('A'-10);
2565 slap_sl_free( normalized->bv_val, ctx );
2566 return LDAP_INVALID_SYNTAX;
2571 normalized->bv_val[j>>1] = octet;
2573 octet = nibble << 4;
2578 normalized->bv_val[normalized->bv_len] = 0;
2579 return LDAP_SUCCESS;
2585 numericStringValidate(
2591 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2593 for(i=0; i < in->bv_len; i++) {
2594 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2595 return LDAP_INVALID_SYNTAX;
2599 return LDAP_SUCCESS;
2603 numericStringNormalize(
2608 struct berval *normalized,
2611 /* removal all spaces */
2614 assert( !BER_BVISEMPTY( val ) );
2616 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2619 q = normalized->bv_val;
2622 if ( ASCII_SPACE( *p ) ) {
2623 /* Ignore whitespace */
2630 /* we should have copied no more than is in val */
2631 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2633 /* null terminate */
2636 normalized->bv_len = q - normalized->bv_val;
2638 if( BER_BVISEMPTY( normalized ) ) {
2639 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2640 normalized->bv_val[0] = ' ';
2641 normalized->bv_val[1] = '\0';
2642 normalized->bv_len = 1;
2645 return LDAP_SUCCESS;
2649 * Integer conversion macros that will use the largest available
2652 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2653 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2654 # define SLAP_LONG long long
2656 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2657 # define SLAP_LONG long
2658 #endif /* HAVE_STRTOLL ... */
2666 struct berval *value,
2667 void *assertedValue )
2669 SLAP_LONG lValue, lAssertedValue;
2672 /* safe to assume integers are NUL terminated? */
2673 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2674 if( errno == ERANGE )
2676 return LDAP_CONSTRAINT_VIOLATION;
2679 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2681 if( errno == ERANGE )
2683 return LDAP_CONSTRAINT_VIOLATION;
2686 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2687 return LDAP_SUCCESS;
2696 struct berval *value,
2697 void *assertedValue )
2699 SLAP_LONG lValue, lAssertedValue;
2702 /* safe to assume integers are NUL terminated? */
2703 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2704 if( errno == ERANGE )
2706 return LDAP_CONSTRAINT_VIOLATION;
2709 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2711 if( errno == ERANGE )
2713 return LDAP_CONSTRAINT_VIOLATION;
2716 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2717 return LDAP_SUCCESS;
2721 serialNumberAndIssuerCheck(
2730 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2732 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2733 /* Parse old format */
2734 is->bv_val = ber_bvchr( in, '$' );
2735 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2737 sn->bv_val = in->bv_val;
2738 sn->bv_len = is->bv_val - in->bv_val;
2741 is->bv_len = in->bv_len - (sn->bv_len + 1);
2743 /* eat leading zeros */
2744 for( n=0; n < (sn->bv_len-1); n++ ) {
2745 if( sn->bv_val[n] != '0' ) break;
2750 for( n=0; n < sn->bv_len; n++ ) {
2751 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2755 /* Parse GSER format */
2756 int havesn=0,haveissuer=0;
2757 struct berval x = *in;
2762 /* eat leading spaces */
2763 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2767 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2768 return LDAP_INVALID_SYNTAX;
2771 /* should be at issuer or serialNumber NamedValue */
2772 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2774 x.bv_val += STRLENOF("issuer");
2775 x.bv_len -= STRLENOF("issuer");
2777 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2778 x.bv_val++; x.bv_len--;
2780 /* eat leading spaces */
2781 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2785 /* For backward compatibility, this part is optional */
2786 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2787 x.bv_val += STRLENOF("rdnSequence:");
2788 x.bv_len -= STRLENOF("rdnSequence:");
2791 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2792 x.bv_val++; x.bv_len--;
2794 is->bv_val = x.bv_val;
2797 for( ; is->bv_len < x.bv_len; ) {
2798 if ( is->bv_val[is->bv_len] != '"' ) {
2802 if ( is->bv_val[is->bv_len+1] == '"' ) {
2809 x.bv_val += is->bv_len+1;
2810 x.bv_len -= is->bv_len+1;
2812 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2813 return LDAP_INVALID_SYNTAX;
2818 } else if( strncasecmp( x.bv_val, "serialNumber",
2819 STRLENOF("serialNumber")) == 0 )
2821 /* parse serialNumber */
2823 x.bv_val += STRLENOF("serialNumber");
2824 x.bv_len -= STRLENOF("serialNumber");
2826 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2827 x.bv_val++; x.bv_len--;
2829 /* eat leading spaces */
2830 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2834 sn->bv_val = x.bv_val;
2837 if( sn->bv_val[0] == '-' ) {
2842 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2843 sn->bv_val[1] == 'X' )) {
2845 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2846 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2848 } else if ( sn->bv_val[0] == '\'' ) {
2849 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2850 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2852 if ( sn->bv_val[sn->bv_len] == '\'' &&
2853 sn->bv_val[sn->bv_len+1] == 'H' )
2856 return LDAP_INVALID_SYNTAX;
2859 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2860 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2864 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2865 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2866 return LDAP_INVALID_SYNTAX;
2869 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2871 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2872 return LDAP_INVALID_SYNTAX;
2877 } else return LDAP_INVALID_SYNTAX;
2879 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2880 x.bv_val++; x.bv_len--;
2883 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2887 /* should be at remaining NamedValue */
2888 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2889 STRLENOF("issuer" )) == 0 ))
2892 x.bv_val += STRLENOF("issuer");
2893 x.bv_len -= STRLENOF("issuer");
2895 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2896 x.bv_val++; x.bv_len--;
2898 /* eat leading spaces */
2899 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2903 /* For backward compatibility, this part is optional */
2904 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2905 x.bv_val += STRLENOF("rdnSequence:");
2906 x.bv_len -= STRLENOF("rdnSequence:");
2909 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2910 x.bv_val++; x.bv_len--;
2912 is->bv_val = x.bv_val;
2915 for( ; is->bv_len < x.bv_len; ) {
2916 if ( is->bv_val[is->bv_len] != '"' ) {
2920 if ( is->bv_val[is->bv_len+1] == '"' ) {
2927 x.bv_val += is->bv_len+1;
2928 x.bv_len -= is->bv_len+1;
2930 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2931 STRLENOF("serialNumber")) == 0 ))
2933 /* parse serialNumber */
2935 x.bv_val += STRLENOF("serialNumber");
2936 x.bv_len -= STRLENOF("serialNumber");
2938 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2939 x.bv_val++; x.bv_len--;
2941 /* eat leading spaces */
2942 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2946 sn->bv_val = x.bv_val;
2949 if( sn->bv_val[0] == '-' ) {
2954 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2955 sn->bv_val[1] == 'X' )) {
2957 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2958 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2960 } else if ( sn->bv_val[0] == '\'' ) {
2961 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2962 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2964 if ( sn->bv_val[sn->bv_len] == '\'' &&
2965 sn->bv_val[sn->bv_len+1] == 'H' )
2968 return LDAP_INVALID_SYNTAX;
2971 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2972 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2976 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2977 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2978 return LDAP_INVALID_SYNTAX;
2981 x.bv_val += sn->bv_len;
2982 x.bv_len -= sn->bv_len;
2984 } else return LDAP_INVALID_SYNTAX;
2986 /* eat trailing spaces */
2987 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2991 /* should have no characters left... */
2992 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2994 ber_dupbv_x( &ni, is, ctx );
2997 /* need to handle double dquotes here */
3003 serialNumberAndIssuerValidate(
3008 struct berval sn, i;
3010 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3013 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3017 /* validate DN -- doesn't handle double dquote */
3018 rc = dnValidate( NULL, &i );
3020 rc = LDAP_INVALID_SYNTAX;
3022 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3023 slap_sl_free( i.bv_val, NULL );
3026 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3032 serialNumberAndIssuerPretty(
3039 struct berval sn, i, ni;
3041 assert( in != NULL );
3042 assert( out != NULL );
3044 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3047 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3051 rc = dnPretty( syntax, &i, &ni, ctx );
3053 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3054 slap_sl_free( i.bv_val, ctx );
3057 if( rc ) return LDAP_INVALID_SYNTAX;
3059 /* make room from sn + "$" */
3060 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3061 + sn.bv_len + ni.bv_len;
3062 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3064 if( out->bv_val == NULL ) {
3066 slap_sl_free( ni.bv_val, ctx );
3071 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3072 STRLENOF("{ serialNumber "));
3073 n = STRLENOF("{ serialNumber ");
3075 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3078 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3079 n += STRLENOF(", issuer rdnSequence:\"");
3081 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3084 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3085 n += STRLENOF("\" }");
3087 out->bv_val[n] = '\0';
3089 assert( n == out->bv_len );
3091 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3092 out->bv_val, 0, 0 );
3094 slap_sl_free( ni.bv_val, ctx );
3096 return LDAP_SUCCESS;
3100 * This routine is called by certificateExactNormalize when
3101 * certificateExactNormalize receives a search string instead of
3102 * a certificate. This routine checks if the search value is valid
3103 * and then returns the normalized value
3106 serialNumberAndIssuerNormalize(
3114 struct berval sn, sn2, i, ni;
3115 char sbuf[64], *stmp = sbuf;
3119 assert( in != NULL );
3120 assert( out != NULL );
3122 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3125 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3129 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3131 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3132 slap_sl_free( i.bv_val, ctx );
3135 if( rc ) return LDAP_INVALID_SYNTAX;
3137 /* Convert sn to canonical hex */
3138 if ( sn.bv_len > sizeof( sbuf )) {
3139 stmp = slap_sl_malloc( sn.bv_len, ctx );
3142 sn2.bv_len = sn.bv_len;
3143 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3144 rc = LDAP_INVALID_SYNTAX;
3148 /* make room for sn + "$" */
3149 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3150 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3151 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3153 if( out->bv_val == NULL ) {
3155 slap_sl_free( ni.bv_val, ctx );
3161 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3162 STRLENOF( "{ serialNumber " ));
3163 n = STRLENOF( "{ serialNumber " );
3165 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3168 unsigned char *v = (unsigned char *)sn2.bv_val;
3169 out->bv_val[n++] = '\'';
3170 for ( j = 0; j < sn2.bv_len; j++ ) {
3171 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3175 out->bv_val[n++] = '\'';
3176 out->bv_val[n++] = 'H';
3179 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3180 n += STRLENOF( ", issuer rdnSequence:\"" );
3182 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3185 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3186 n += STRLENOF( "\" }" );
3188 out->bv_val[n] = '\0';
3190 assert( n == out->bv_len );
3192 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3193 out->bv_val, 0, 0 );
3197 slap_sl_free( stmp, ctx );
3198 slap_sl_free( ni.bv_val, ctx );
3204 certificateExactNormalize(
3209 struct berval *normalized,
3212 BerElementBuffer berbuf;
3213 BerElement *ber = (BerElement *)&berbuf;
3217 char serialbuf[64], *serial = serialbuf;
3218 ber_len_t seriallen;
3219 struct berval issuer_dn = BER_BVNULL, bvdn;
3221 int rc = LDAP_INVALID_SYNTAX;
3223 if( BER_BVISEMPTY( val ) ) goto done;
3225 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3226 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3229 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3231 ber_init2( ber, val, LBER_USE_DER );
3232 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3233 tag = ber_skip_tag( ber, &len ); /* Sequence */
3234 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3235 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3236 tag = ber_skip_tag( ber, &len );
3237 tag = ber_get_int( ber, &i ); /* version */
3240 /* NOTE: move the test here from certificateValidate,
3241 * so that we can validate certs with serial longer
3242 * than sizeof(ber_int_t) */
3243 tag = ber_peek_tag( ber, &len ); /* serial */
3245 /* Use hex format. '123456789abcdef'H
3251 tag = ber_skip_tag( ber, &len );
3252 ptr = (unsigned char *)ber->ber_ptr;
3253 ber_skip_data( ber, len );
3255 /* Check for minimal encodings */
3257 if ( ptr[0] & 0x80 ) {
3258 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3259 return LDAP_INVALID_SYNTAX;
3260 } else if ( ptr[0] == 0 ) {
3261 if (!( ptr[1] & 0x80 ))
3262 return LDAP_INVALID_SYNTAX;
3266 seriallen = len * 2 + 4; /* quotes, H, NUL */
3267 if ( seriallen > sizeof( serialbuf ))
3268 serial = slap_sl_malloc( seriallen, ctx );
3271 for ( i = 0; i<len; i++ ) {
3272 sprintf( sptr, "%02X", ptr[i] );
3279 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3280 ber_skip_data( ber, len );
3281 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3282 len = ber_ptrlen( ber );
3283 bvdn.bv_val = val->bv_val + len;
3284 bvdn.bv_len = val->bv_len - len;
3286 rc = dnX509normalize( &bvdn, &issuer_dn );
3287 if( rc != LDAP_SUCCESS ) goto done;
3289 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3290 + seriallen + issuer_dn.bv_len;
3291 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3293 p = (unsigned char *)normalized->bv_val;
3295 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3296 p += STRLENOF( "{ serialNumber " );
3298 AC_MEMCPY(p, serial, seriallen);
3301 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3302 p += STRLENOF( ", issuer rdnSequence:\"" );
3304 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3305 p += issuer_dn.bv_len;
3307 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3308 p += STRLENOF( "\" }" );
3312 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3313 normalized->bv_val, NULL, NULL );
3318 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3319 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3331 assert( in != NULL );
3332 assert( !BER_BVISNULL( in ) );
3334 for ( i = 0; i < in->bv_len; i++ ) {
3335 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3336 return LDAP_INVALID_SYNTAX;
3340 return LDAP_SUCCESS;
3343 /* Normalize a SID as used inside a CSN:
3344 * three-digit numeric string */
3351 struct berval *normalized,
3356 assert( val != NULL );
3357 assert( normalized != NULL );
3359 ber_dupbv_x( normalized, val, ctx );
3361 for ( i = 0; i < normalized->bv_len; i++ ) {
3362 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3363 ber_memfree_x( normalized->bv_val, ctx );
3364 BER_BVZERO( normalized );
3365 return LDAP_INVALID_SYNTAX;
3368 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3371 return LDAP_SUCCESS;
3379 assert( in != NULL );
3380 assert( !BER_BVISNULL( in ) );
3382 if ( in->bv_len != 3 ) {
3383 return LDAP_INVALID_SYNTAX;
3386 return hexValidate( NULL, in );
3389 /* Normalize a SID as used inside a CSN:
3390 * three-digit numeric string */
3397 struct berval *normalized,
3400 if ( val->bv_len != 3 ) {
3401 return LDAP_INVALID_SYNTAX;
3404 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3414 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3417 /* Normalize a SID as used inside a CSN, either as-is
3418 * (assertion value) or extracted from the CSN
3419 * (attribute value) */
3426 struct berval *normalized,
3434 if ( BER_BVISEMPTY( val ) ) {
3435 return LDAP_INVALID_SYNTAX;
3438 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3439 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3442 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3444 ptr = ber_bvchr( val, '#' );
3445 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3446 return LDAP_INVALID_SYNTAX;
3449 bv.bv_val = ptr + 1;
3450 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3452 ptr = ber_bvchr( &bv, '#' );
3453 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3454 return LDAP_INVALID_SYNTAX;
3457 bv.bv_val = ptr + 1;
3458 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3460 ptr = ber_bvchr( &bv, '#' );
3461 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3462 return LDAP_INVALID_SYNTAX;
3465 bv.bv_len = ptr - bv.bv_val;
3467 if ( bv.bv_len == 2 ) {
3468 /* OpenLDAP 2.3 SID */
3470 buf[ 1 ] = bv.bv_val[ 0 ];
3471 buf[ 2 ] = bv.bv_val[ 1 ];
3478 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3490 assert( in != NULL );
3491 assert( !BER_BVISNULL( in ) );
3493 if ( BER_BVISEMPTY( in ) ) {
3494 return LDAP_INVALID_SYNTAX;
3499 ptr = ber_bvchr( &bv, '#' );
3500 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3501 return LDAP_INVALID_SYNTAX;
3504 bv.bv_len = ptr - bv.bv_val;
3505 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3506 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3508 return LDAP_INVALID_SYNTAX;
3511 rc = generalizedTimeValidate( NULL, &bv );
3512 if ( rc != LDAP_SUCCESS ) {
3516 bv.bv_val = ptr + 1;
3517 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3519 ptr = ber_bvchr( &bv, '#' );
3520 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3521 return LDAP_INVALID_SYNTAX;
3524 bv.bv_len = ptr - bv.bv_val;
3525 if ( bv.bv_len != 6 ) {
3526 return LDAP_INVALID_SYNTAX;
3529 rc = hexValidate( NULL, &bv );
3530 if ( rc != LDAP_SUCCESS ) {
3534 bv.bv_val = ptr + 1;
3535 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3537 ptr = ber_bvchr( &bv, '#' );
3538 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3539 return LDAP_INVALID_SYNTAX;
3542 bv.bv_len = ptr - bv.bv_val;
3543 if ( bv.bv_len == 2 ) {
3544 /* tolerate old 2-digit replica-id */
3545 rc = hexValidate( NULL, &bv );
3548 rc = sidValidate( NULL, &bv );
3550 if ( rc != LDAP_SUCCESS ) {
3554 bv.bv_val = ptr + 1;
3555 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3557 if ( bv.bv_len != 6 ) {
3558 return LDAP_INVALID_SYNTAX;
3561 return hexValidate( NULL, &bv );
3564 /* Normalize a CSN in OpenLDAP 2.1 format */
3571 struct berval *normalized,
3574 struct berval gt, cnt, sid, mod;
3576 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3580 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3581 assert( !BER_BVISEMPTY( val ) );
3585 ptr = ber_bvchr( >, '#' );
3586 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3587 return LDAP_INVALID_SYNTAX;
3590 gt.bv_len = ptr - gt.bv_val;
3591 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3592 return LDAP_INVALID_SYNTAX;
3595 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
3596 return LDAP_INVALID_SYNTAX;
3599 cnt.bv_val = ptr + 1;
3600 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3602 ptr = ber_bvchr( &cnt, '#' );
3603 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3604 return LDAP_INVALID_SYNTAX;
3607 cnt.bv_len = ptr - cnt.bv_val;
3608 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
3609 return LDAP_INVALID_SYNTAX;
3612 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
3613 return LDAP_INVALID_SYNTAX;
3616 cnt.bv_val += STRLENOF( "0x" );
3617 cnt.bv_len -= STRLENOF( "0x" );
3619 sid.bv_val = ptr + 1;
3620 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3622 ptr = ber_bvchr( &sid, '#' );
3623 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3624 return LDAP_INVALID_SYNTAX;
3627 sid.bv_len = ptr - sid.bv_val;
3628 if ( sid.bv_len != STRLENOF( "0" ) ) {
3629 return LDAP_INVALID_SYNTAX;
3632 mod.bv_val = ptr + 1;
3633 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3634 if ( mod.bv_len != STRLENOF( "0000" ) ) {
3635 return LDAP_INVALID_SYNTAX;
3638 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3642 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
3643 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
3645 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3647 ptr = lutil_strcopy( ptr, ".000000Z#00" );
3648 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3652 *ptr++ = sid.bv_val[ 0 ];
3656 for ( i = 0; i < mod.bv_len; i++ ) {
3657 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3661 assert( ptr - bv.bv_val == bv.bv_len );
3663 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3664 return LDAP_INVALID_SYNTAX;
3667 ber_dupbv_x( normalized, &bv, ctx );
3669 return LDAP_SUCCESS;
3672 /* Normalize a CSN in OpenLDAP 2.3 format */
3679 struct berval *normalized,
3682 struct berval gt, cnt, sid, mod;
3684 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3688 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3689 assert( !BER_BVISEMPTY( val ) );
3693 ptr = ber_bvchr( >, '#' );
3694 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3695 return LDAP_INVALID_SYNTAX;
3698 gt.bv_len = ptr - gt.bv_val;
3699 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3700 return LDAP_INVALID_SYNTAX;
3703 cnt.bv_val = ptr + 1;
3704 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3706 ptr = ber_bvchr( &cnt, '#' );
3707 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3708 return LDAP_INVALID_SYNTAX;
3711 cnt.bv_len = ptr - cnt.bv_val;
3712 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3713 return LDAP_INVALID_SYNTAX;
3716 sid.bv_val = ptr + 1;
3717 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3719 ptr = ber_bvchr( &sid, '#' );
3720 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3721 return LDAP_INVALID_SYNTAX;
3724 sid.bv_len = ptr - sid.bv_val;
3725 if ( sid.bv_len != STRLENOF( "00" ) ) {
3726 return LDAP_INVALID_SYNTAX;
3729 mod.bv_val = ptr + 1;
3730 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3731 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3732 return LDAP_INVALID_SYNTAX;
3735 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3739 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3740 ptr = lutil_strcopy( ptr, ".000000Z#" );
3741 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3744 for ( i = 0; i < sid.bv_len; i++ ) {
3745 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3748 for ( i = 0; i < mod.bv_len; i++ ) {
3749 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3753 assert( ptr - bv.bv_val == bv.bv_len );
3754 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3755 return LDAP_INVALID_SYNTAX;
3758 ber_dupbv_x( normalized, &bv, ctx );
3760 return LDAP_SUCCESS;
3763 /* Normalize a CSN */
3770 struct berval *normalized,
3773 struct berval cnt, sid, mod;
3777 assert( val != NULL );
3778 assert( normalized != NULL );
3780 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3782 if ( BER_BVISEMPTY( val ) ) {
3783 return LDAP_INVALID_SYNTAX;
3786 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3787 /* Openldap <= 2.3 */
3789 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3792 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3795 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
3798 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3799 return LDAP_INVALID_SYNTAX;
3802 ptr = ber_bvchr( val, '#' );
3803 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3804 return LDAP_INVALID_SYNTAX;
3807 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3808 return LDAP_INVALID_SYNTAX;
3811 cnt.bv_val = ptr + 1;
3812 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3814 ptr = ber_bvchr( &cnt, '#' );
3815 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3816 return LDAP_INVALID_SYNTAX;
3819 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
3820 return LDAP_INVALID_SYNTAX;
3823 sid.bv_val = ptr + 1;
3824 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3826 ptr = ber_bvchr( &sid, '#' );
3827 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3828 return LDAP_INVALID_SYNTAX;
3831 sid.bv_len = ptr - sid.bv_val;
3832 if ( sid.bv_len != STRLENOF( "000" ) ) {
3833 return LDAP_INVALID_SYNTAX;
3836 mod.bv_val = ptr + 1;
3837 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3839 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3840 return LDAP_INVALID_SYNTAX;
3843 ber_dupbv_x( normalized, val, ctx );
3845 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3846 i < normalized->bv_len; i++ )
3848 /* assume it's already validated that's all hex digits */
3849 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3852 return LDAP_SUCCESS;
3862 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3865 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3866 /* slight optimization - does not need the start parameter */
3867 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3872 check_time_syntax (struct berval *val,
3875 struct berval *fraction)
3878 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3879 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3880 * GeneralizedTime supports leap seconds, UTCTime does not.
3882 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3883 static const int mdays[2][12] = {
3884 /* non-leap years */
3885 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3887 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3890 int part, c, c1, c2, tzoffset, leapyear = 0;
3893 e = p + val->bv_len;
3895 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3896 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3898 for (part = start; part < 7 && p < e; part++) {
3900 if (!ASCII_DIGIT(c1)) {
3905 return LDAP_INVALID_SYNTAX;
3908 if (!ASCII_DIGIT(c)) {
3909 return LDAP_INVALID_SYNTAX;
3911 c += c1 * 10 - '0' * 11;
3912 if ((part | 1) == 3) {
3915 return LDAP_INVALID_SYNTAX;
3918 if (c >= ceiling[part]) {
3919 if (! (c == 60 && part == 6 && start == 0))
3920 return LDAP_INVALID_SYNTAX;
3924 if (part < 5 + start) {
3925 return LDAP_INVALID_SYNTAX;
3927 for (; part < 9; part++) {
3931 /* leapyear check for the Gregorian calendar (year>1581) */
3932 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3936 if (parts[3] >= mdays[leapyear][parts[2]]) {
3937 return LDAP_INVALID_SYNTAX;
3941 fraction->bv_val = p;
3942 fraction->bv_len = 0;
3943 if (p < e && (*p == '.' || *p == ',')) {
3945 while (++p < e && ASCII_DIGIT(*p)) {
3948 if (p - fraction->bv_val == 1) {
3949 return LDAP_INVALID_SYNTAX;
3951 for (end_num = p; end_num[-1] == '0'; --end_num) {
3954 c = end_num - fraction->bv_val;
3955 if (c != 1) fraction->bv_len = c;
3961 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3967 return LDAP_INVALID_SYNTAX;
3973 for (part = 7; part < 9 && p < e; part++) {
3975 if (!ASCII_DIGIT(c1)) {
3980 return LDAP_INVALID_SYNTAX;
3983 if (!ASCII_DIGIT(c2)) {
3984 return LDAP_INVALID_SYNTAX;
3986 parts[part] = c1 * 10 + c2 - '0' * 11;
3987 if (parts[part] >= ceiling[part]) {
3988 return LDAP_INVALID_SYNTAX;
3991 if (part < 8 + start) {
3992 return LDAP_INVALID_SYNTAX;
3995 if (tzoffset == '-') {
3996 /* negative offset to UTC, ie west of Greenwich */
3997 parts[4] += parts[7];
3998 parts[5] += parts[8];
3999 /* offset is just hhmm, no seconds */
4000 for (part = 6; --part >= 0; ) {
4004 c = mdays[leapyear][parts[2]];
4006 if (parts[part] >= c) {
4008 return LDAP_INVALID_SYNTAX;
4013 } else if (part != 5) {
4018 /* positive offset to UTC, ie east of Greenwich */
4019 parts[4] -= parts[7];
4020 parts[5] -= parts[8];
4021 for (part = 6; --part >= 0; ) {
4022 if (parts[part] < 0) {
4024 return LDAP_INVALID_SYNTAX;
4029 /* make first arg to % non-negative */
4030 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4035 } else if (part != 5) {
4042 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4045 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4052 struct berval *normalized )
4056 rc = check_time_syntax(val, 1, parts, NULL);
4057 if (rc != LDAP_SUCCESS) {
4061 normalized->bv_val = ch_malloc( 14 );
4062 if ( normalized->bv_val == NULL ) {
4063 return LBER_ERROR_MEMORY;
4066 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4067 parts[1], parts[2] + 1, parts[3] + 1,
4068 parts[4], parts[5], parts[6] );
4069 normalized->bv_len = 13;
4071 return LDAP_SUCCESS;
4081 return check_time_syntax(in, 1, parts, NULL);
4084 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4087 generalizedTimeValidate(
4092 struct berval fraction;
4093 return check_time_syntax(in, 0, parts, &fraction);
4097 generalizedTimeNormalize(
4102 struct berval *normalized,
4107 struct berval fraction;
4109 rc = check_time_syntax(val, 0, parts, &fraction);
4110 if (rc != LDAP_SUCCESS) {
4114 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4115 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4116 if ( BER_BVISNULL( normalized ) ) {
4117 return LBER_ERROR_MEMORY;
4120 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4121 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4122 parts[4], parts[5], parts[6] );
4123 if ( !BER_BVISEMPTY( &fraction ) ) {
4124 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4125 fraction.bv_val, fraction.bv_len );
4126 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4128 strcpy( normalized->bv_val + len-1, "Z" );
4129 normalized->bv_len = len;
4131 return LDAP_SUCCESS;
4135 generalizedTimeOrderingMatch(
4140 struct berval *value,
4141 void *assertedValue )
4143 struct berval *asserted = (struct berval *) assertedValue;
4144 ber_len_t v_len = value->bv_len;
4145 ber_len_t av_len = asserted->bv_len;
4147 /* ignore trailing 'Z' when comparing */
4148 int match = memcmp( value->bv_val, asserted->bv_val,
4149 (v_len < av_len ? v_len : av_len) - 1 );
4150 if ( match == 0 ) match = v_len - av_len;
4153 return LDAP_SUCCESS;
4156 /* Index generation function */
4157 int generalizedTimeIndexer(
4162 struct berval *prefix,
4170 BerValue bvtmp; /* 40 bit index */
4172 struct lutil_timet tt;
4174 bvtmp.bv_len = sizeof(tmp);
4176 for( i=0; values[i].bv_val != NULL; i++ ) {
4177 /* just count them */
4180 /* we should have at least one value at this point */
4183 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4185 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4186 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4187 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4188 /* Use 40 bits of time for key */
4189 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4190 lutil_tm2time( &tm, &tt );
4191 tmp[0] = tt.tt_gsec & 0xff;
4192 tmp[4] = tt.tt_sec & 0xff;
4194 tmp[3] = tt.tt_sec & 0xff;
4196 tmp[2] = tt.tt_sec & 0xff;
4198 tmp[1] = tt.tt_sec & 0xff;
4200 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4204 keys[j].bv_val = NULL;
4209 return LDAP_SUCCESS;
4212 /* Index generation function */
4213 int generalizedTimeFilter(
4218 struct berval *prefix,
4219 void * assertedValue,
4225 BerValue bvtmp; /* 40 bit index */
4226 BerValue *value = (BerValue *) assertedValue;
4228 struct lutil_timet tt;
4230 bvtmp.bv_len = sizeof(tmp);
4232 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4233 /* Use 40 bits of time for key */
4234 if ( value->bv_val && value->bv_len >= 10 &&
4235 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4237 lutil_tm2time( &tm, &tt );
4238 tmp[0] = tt.tt_gsec & 0xff;
4239 tmp[4] = tt.tt_sec & 0xff;
4241 tmp[3] = tt.tt_sec & 0xff;
4243 tmp[2] = tt.tt_sec & 0xff;
4245 tmp[1] = tt.tt_sec & 0xff;
4247 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4248 ber_dupbv_x(keys, &bvtmp, ctx );
4249 keys[1].bv_val = NULL;
4257 return LDAP_SUCCESS;
4261 deliveryMethodValidate(
4263 struct berval *val )
4266 #define LENOF(s) (sizeof(s)-1)
4267 struct berval tmp = *val;
4269 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4270 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4271 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4274 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4276 switch( tmp.bv_val[0] ) {
4279 if(( tmp.bv_len >= LENOF("any") ) &&
4280 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4282 tmp.bv_len -= LENOF("any");
4283 tmp.bv_val += LENOF("any");
4286 return LDAP_INVALID_SYNTAX;
4290 if(( tmp.bv_len >= LENOF("mhs") ) &&
4291 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4293 tmp.bv_len -= LENOF("mhs");
4294 tmp.bv_val += LENOF("mhs");
4297 return LDAP_INVALID_SYNTAX;
4301 if(( tmp.bv_len >= LENOF("physical") ) &&
4302 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4304 tmp.bv_len -= LENOF("physical");
4305 tmp.bv_val += LENOF("physical");
4308 return LDAP_INVALID_SYNTAX;
4311 case 'T': /* telex or teletex or telephone */
4312 if(( tmp.bv_len >= LENOF("telex") ) &&
4313 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4315 tmp.bv_len -= LENOF("telex");
4316 tmp.bv_val += LENOF("telex");
4319 if(( tmp.bv_len >= LENOF("teletex") ) &&
4320 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4322 tmp.bv_len -= LENOF("teletex");
4323 tmp.bv_val += LENOF("teletex");
4326 if(( tmp.bv_len >= LENOF("telephone") ) &&
4327 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4329 tmp.bv_len -= LENOF("telephone");
4330 tmp.bv_val += LENOF("telephone");
4333 return LDAP_INVALID_SYNTAX;
4336 case 'G': /* g3fax or g4fax */
4337 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4338 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4339 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4341 tmp.bv_len -= LENOF("g3fax");
4342 tmp.bv_val += LENOF("g3fax");
4345 return LDAP_INVALID_SYNTAX;
4349 if(( tmp.bv_len >= LENOF("ia5") ) &&
4350 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4352 tmp.bv_len -= LENOF("ia5");
4353 tmp.bv_val += LENOF("ia5");
4356 return LDAP_INVALID_SYNTAX;
4360 if(( tmp.bv_len >= LENOF("videotex") ) &&
4361 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4363 tmp.bv_len -= LENOF("videotex");
4364 tmp.bv_val += LENOF("videotex");
4367 return LDAP_INVALID_SYNTAX;
4370 return LDAP_INVALID_SYNTAX;
4373 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4375 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4379 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4383 return LDAP_INVALID_SYNTAX;
4385 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4394 nisNetgroupTripleValidate(
4396 struct berval *val )
4401 if ( BER_BVISEMPTY( val ) ) {
4402 return LDAP_INVALID_SYNTAX;
4405 p = (char *)val->bv_val;
4406 e = p + val->bv_len;
4408 if ( *p != '(' /*')'*/ ) {
4409 return LDAP_INVALID_SYNTAX;
4412 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4416 return LDAP_INVALID_SYNTAX;
4419 } else if ( !AD_CHAR( *p ) ) {
4420 return LDAP_INVALID_SYNTAX;
4424 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4425 return LDAP_INVALID_SYNTAX;
4431 return LDAP_INVALID_SYNTAX;
4434 return LDAP_SUCCESS;
4438 bootParameterValidate(
4440 struct berval *val )
4444 if ( BER_BVISEMPTY( val ) ) {
4445 return LDAP_INVALID_SYNTAX;
4448 p = (char *)val->bv_val;
4449 e = p + val->bv_len;
4452 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4453 if ( !AD_CHAR( *p ) ) {
4454 return LDAP_INVALID_SYNTAX;
4459 return LDAP_INVALID_SYNTAX;
4463 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4464 if ( !AD_CHAR( *p ) ) {
4465 return LDAP_INVALID_SYNTAX;
4470 return LDAP_INVALID_SYNTAX;
4474 for ( p++; p < e; p++ ) {
4475 if ( !SLAP_PRINTABLE( *p ) ) {
4476 return LDAP_INVALID_SYNTAX;
4480 return LDAP_SUCCESS;
4484 firstComponentNormalize(
4489 struct berval *normalized,
4496 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4497 ber_dupbv_x( normalized, val, ctx );
4498 return LDAP_SUCCESS;
4501 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4503 if( val->bv_val[0] != '(' /*')'*/ &&
4504 val->bv_val[0] != '{' /*'}'*/ )
4506 return LDAP_INVALID_SYNTAX;
4509 /* trim leading white space */
4511 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4517 /* grab next word */
4518 comp.bv_val = &val->bv_val[len];
4519 len = val->bv_len - len;
4520 for( comp.bv_len = 0;
4521 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4527 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4528 rc = numericoidValidate( NULL, &comp );
4529 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4530 rc = integerValidate( NULL, &comp );
4532 rc = LDAP_INVALID_SYNTAX;
4536 if( rc == LDAP_SUCCESS ) {
4537 ber_dupbv_x( normalized, &comp, ctx );
4543 static char *country_gen_syn[] = {
4544 "1.3.6.1.4.1.1466.115.121.1.15",
4545 "1.3.6.1.4.1.1466.115.121.1.26",
4546 "1.3.6.1.4.1.1466.115.121.1.44",
4550 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4551 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4553 static slap_syntax_defs_rec syntax_defs[] = {
4554 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4555 X_BINARY X_NOT_H_R ")",
4556 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4557 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4558 0, NULL, NULL, NULL},
4559 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4560 0, NULL, NULL, NULL},
4561 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4563 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4564 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4566 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4567 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4568 0, NULL, bitStringValidate, NULL },
4569 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4570 0, NULL, booleanValidate, NULL},
4571 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4572 X_BINARY X_NOT_H_R ")",
4573 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4574 NULL, certificateValidate, NULL},
4575 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4576 X_BINARY X_NOT_H_R ")",
4577 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4578 NULL, certificateListValidate, NULL},
4579 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4580 X_BINARY X_NOT_H_R ")",
4581 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4582 NULL, sequenceValidate, NULL},
4583 #if 0 /* need to go __after__ printableString */
4584 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4585 0, "1.3.6.1.4.1.1466.115.121.1.44",
4586 countryStringValidate, NULL},
4588 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4589 0, NULL, dnValidate, dnPretty},
4590 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4591 0, NULL, rdnValidate, rdnPretty},
4592 #ifdef LDAP_COMP_MATCH
4593 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4594 0, NULL, allComponentsValidate, NULL},
4595 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4596 0, NULL, componentFilterValidate, NULL},
4598 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4599 0, NULL, NULL, NULL},
4600 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4601 0, NULL, deliveryMethodValidate, NULL},
4602 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4603 0, NULL, UTF8StringValidate, NULL},
4604 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4605 0, NULL, NULL, NULL},
4606 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4607 0, NULL, NULL, NULL},
4608 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4609 0, NULL, NULL, NULL},
4610 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4611 0, NULL, NULL, NULL},
4612 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4613 0, NULL, NULL, NULL},
4614 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4615 0, NULL, printablesStringValidate, NULL},
4616 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4617 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4618 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4619 0, NULL, generalizedTimeValidate, NULL},
4620 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4621 0, NULL, NULL, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4623 0, NULL, IA5StringValidate, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4625 0, NULL, integerValidate, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4627 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4628 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4629 0, NULL, NULL, NULL},
4630 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4631 0, NULL, NULL, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4633 0, NULL, NULL, NULL},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4635 0, NULL, NULL, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4637 0, NULL, NULL, NULL},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4639 0, NULL, nameUIDValidate, nameUIDPretty },
4640 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4641 0, NULL, NULL, NULL},
4642 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4643 0, NULL, numericStringValidate, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4645 0, NULL, NULL, NULL},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4647 0, NULL, numericoidValidate, NULL},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4649 0, NULL, IA5StringValidate, NULL},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4651 0, NULL, blobValidate, NULL},
4652 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4653 0, NULL, UTF8StringValidate, NULL},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4655 0, NULL, NULL, NULL},
4656 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4657 0, NULL, NULL, NULL},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4659 0, NULL, printableStringValidate, NULL},
4660 /* moved here because now depends on Directory String, IA5 String
4661 * and Printable String */
4662 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4663 0, country_gen_syn, countryStringValidate, NULL},
4664 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4665 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4666 0, NULL, subtreeSpecificationValidate, NULL},
4667 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4668 X_BINARY X_NOT_H_R ")",
4669 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4670 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4671 0, NULL, printableStringValidate, NULL},
4672 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4673 0, NULL, NULL, NULL},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4675 0, NULL, printablesStringValidate, NULL},
4676 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4677 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4678 0, NULL, utcTimeValidate, NULL},
4680 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4681 0, NULL, NULL, NULL},
4682 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4683 0, NULL, NULL, NULL},
4684 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4685 0, NULL, NULL, NULL},
4686 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4687 0, NULL, NULL, NULL},
4688 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4689 0, NULL, NULL, NULL},
4691 /* RFC 2307 NIS Syntaxes */
4692 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4693 0, NULL, nisNetgroupTripleValidate, NULL},
4694 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4695 0, NULL, bootParameterValidate, NULL},
4697 /* draft-zeilenga-ldap-x509 */
4698 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4699 SLAP_SYNTAX_HIDE, NULL,
4700 serialNumberAndIssuerValidate,
4701 serialNumberAndIssuerPretty},
4702 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4703 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4704 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4705 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4706 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4707 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4708 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4709 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4710 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4711 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4712 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4713 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4715 #ifdef SLAPD_AUTHPASSWD
4716 /* needs updating */
4717 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4718 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4721 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4722 0, NULL, UUIDValidate, UUIDPretty},
4724 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4725 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4727 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4728 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4730 /* OpenLDAP Void Syntax */
4731 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4732 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4734 /* FIXME: OID is unused, but not registered yet */
4735 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4736 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4738 {NULL, 0, NULL, NULL, NULL}
4741 char *csnSIDMatchSyntaxes[] = {
4742 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4745 char *certificateExactMatchSyntaxes[] = {
4746 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4749 #ifdef LDAP_COMP_MATCH
4750 char *componentFilterMatchSyntaxes[] = {
4751 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4755 char *directoryStringSyntaxes[] = {
4756 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4759 char *integerFirstComponentMatchSyntaxes[] = {
4760 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4761 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4764 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4765 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4766 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4767 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4768 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4769 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4770 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4771 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4772 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4777 * Other matching rules in X.520 that we do not use (yet):
4779 * 2.5.13.25 uTCTimeMatch
4780 * 2.5.13.26 uTCTimeOrderingMatch
4781 * 2.5.13.31* directoryStringFirstComponentMatch
4782 * 2.5.13.32* wordMatch
4783 * 2.5.13.33* keywordMatch
4784 * 2.5.13.36+ certificatePairExactMatch
4785 * 2.5.13.37+ certificatePairMatch
4786 * 2.5.13.38+ certificateListExactMatch
4787 * 2.5.13.39+ certificateListMatch
4788 * 2.5.13.40+ algorithmIdentifierMatch
4789 * 2.5.13.41* storedPrefixMatch
4790 * 2.5.13.42 attributeCertificateMatch
4791 * 2.5.13.43 readerAndKeyIDMatch
4792 * 2.5.13.44 attributeIntegrityMatch
4794 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4795 * (+) described in draft-zeilenga-ldap-x509
4797 static slap_mrule_defs_rec mrule_defs[] = {
4799 * EQUALITY matching rules must be listed after associated APPROX
4800 * matching rules. So, we list all APPROX matching rules first.
4802 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4804 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4805 NULL, NULL, directoryStringApproxMatch,
4806 directoryStringApproxIndexer, directoryStringApproxFilter,
4809 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4811 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4812 NULL, NULL, IA5StringApproxMatch,
4813 IA5StringApproxIndexer, IA5StringApproxFilter,
4817 * Other matching rules
4820 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4821 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4822 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4823 NULL, NULL, octetStringMatch,
4824 octetStringIndexer, octetStringFilter,
4827 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4828 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4829 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4830 NULL, dnNormalize, dnMatch,
4831 octetStringIndexer, octetStringFilter,
4834 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4835 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4836 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4837 NULL, dnNormalize, dnRelativeMatch,
4841 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4842 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4843 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4844 NULL, dnNormalize, dnRelativeMatch,
4848 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4849 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4850 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4851 NULL, dnNormalize, dnRelativeMatch,
4855 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4857 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4858 NULL, dnNormalize, dnRelativeMatch,
4862 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4863 "SYNTAX 1.2.36.79672281.1.5.0 )",
4864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4865 NULL, rdnNormalize, rdnMatch,
4866 octetStringIndexer, octetStringFilter,
4869 #ifdef LDAP_COMP_MATCH
4870 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4871 "SYNTAX 1.2.36.79672281.1.5.2 )",
4872 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4873 NULL, NULL , componentFilterMatch,
4874 octetStringIndexer, octetStringFilter,
4877 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4878 "SYNTAX 1.2.36.79672281.1.5.3 )",
4879 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4880 NULL, NULL , allComponentsMatch,
4881 octetStringIndexer, octetStringFilter,
4884 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4885 "SYNTAX 1.2.36.79672281.1.5.3 )",
4886 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4887 NULL, NULL , directoryComponentsMatch,
4888 octetStringIndexer, octetStringFilter,
4892 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4893 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4894 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4895 NULL, UTF8StringNormalize, octetStringMatch,
4896 octetStringIndexer, octetStringFilter,
4897 directoryStringApproxMatchOID },
4899 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4900 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4901 SLAP_MR_ORDERING, directoryStringSyntaxes,
4902 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4904 "caseIgnoreMatch" },
4906 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4908 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4909 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4910 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4911 "caseIgnoreMatch" },
4913 {"( 2.5.13.5 NAME 'caseExactMatch' "
4914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4915 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4916 NULL, UTF8StringNormalize, octetStringMatch,
4917 octetStringIndexer, octetStringFilter,
4918 directoryStringApproxMatchOID },
4920 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4922 SLAP_MR_ORDERING, directoryStringSyntaxes,
4923 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4927 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4929 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4930 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4931 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4934 {"( 2.5.13.8 NAME 'numericStringMatch' "
4935 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4936 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4937 NULL, numericStringNormalize, octetStringMatch,
4938 octetStringIndexer, octetStringFilter,
4941 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4942 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4943 SLAP_MR_ORDERING, NULL,
4944 NULL, numericStringNormalize, octetStringOrderingMatch,
4946 "numericStringMatch" },
4948 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4950 SLAP_MR_SUBSTR, NULL,
4951 NULL, numericStringNormalize, octetStringSubstringsMatch,
4952 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4953 "numericStringMatch" },
4955 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4957 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4958 NULL, NULL, NULL, NULL, NULL, NULL },
4960 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4962 SLAP_MR_SUBSTR, NULL,
4963 NULL, NULL, NULL, NULL, NULL,
4964 "caseIgnoreListMatch" },
4966 {"( 2.5.13.13 NAME 'booleanMatch' "
4967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4968 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4969 NULL, NULL, booleanMatch,
4970 octetStringIndexer, octetStringFilter,
4973 {"( 2.5.13.14 NAME 'integerMatch' "
4974 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4975 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4976 NULL, NULL, integerMatch,
4977 integerIndexer, integerFilter,
4980 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4981 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4982 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4983 NULL, NULL, integerMatch,
4987 {"( 2.5.13.16 NAME 'bitStringMatch' "
4988 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4989 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4990 NULL, NULL, octetStringMatch,
4991 octetStringIndexer, octetStringFilter,
4994 {"( 2.5.13.17 NAME 'octetStringMatch' "
4995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4996 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4997 NULL, NULL, octetStringMatch,
4998 octetStringIndexer, octetStringFilter,
5001 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5003 SLAP_MR_ORDERING, NULL,
5004 NULL, NULL, octetStringOrderingMatch,
5006 "octetStringMatch" },
5008 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5009 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5010 SLAP_MR_SUBSTR, NULL,
5011 NULL, NULL, octetStringSubstringsMatch,
5012 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5013 "octetStringMatch" },
5015 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5016 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5017 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5019 telephoneNumberNormalize, octetStringMatch,
5020 octetStringIndexer, octetStringFilter,
5023 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5025 SLAP_MR_SUBSTR, NULL,
5026 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5027 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5028 "telephoneNumberMatch" },
5030 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5032 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5033 NULL, NULL, NULL, NULL, NULL, NULL },
5035 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5037 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5038 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5039 uniqueMemberIndexer, uniqueMemberFilter,
5042 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5043 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5044 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5045 NULL, NULL, NULL, NULL, NULL, NULL },
5047 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5049 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5050 NULL, generalizedTimeNormalize, octetStringMatch,
5051 generalizedTimeIndexer, generalizedTimeFilter,
5054 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5055 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5056 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5057 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5059 "generalizedTimeMatch" },
5061 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5062 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5063 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5064 integerFirstComponentMatchSyntaxes,
5065 NULL, firstComponentNormalize, integerMatch,
5066 octetStringIndexer, octetStringFilter,
5069 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5070 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5071 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5072 objectIdentifierFirstComponentMatchSyntaxes,
5073 NULL, firstComponentNormalize, octetStringMatch,
5074 octetStringIndexer, octetStringFilter,
5077 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5078 "SYNTAX 1.3.6.1.1.15.1 )",
5079 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5080 NULL, certificateExactNormalize, octetStringMatch,
5081 octetStringIndexer, octetStringFilter,
5084 {"( 2.5.13.35 NAME 'certificateMatch' "
5085 "SYNTAX 1.3.6.1.1.15.2 )",
5086 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5087 NULL, NULL, NULL, NULL, NULL,
5090 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5092 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5093 NULL, IA5StringNormalize, octetStringMatch,
5094 octetStringIndexer, octetStringFilter,
5095 IA5StringApproxMatchOID },
5097 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5099 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5100 NULL, IA5StringNormalize, octetStringMatch,
5101 octetStringIndexer, octetStringFilter,
5102 IA5StringApproxMatchOID },
5104 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5105 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5106 SLAP_MR_SUBSTR, NULL,
5107 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5108 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5109 "caseIgnoreIA5Match" },
5111 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5112 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5113 SLAP_MR_SUBSTR, NULL,
5114 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5115 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5116 "caseExactIA5Match" },
5118 #ifdef SLAPD_AUTHPASSWD
5119 /* needs updating */
5120 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5122 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5123 NULL, NULL, authPasswordMatch,
5128 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5129 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5131 NULL, NULL, integerBitAndMatch,
5135 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5136 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5138 NULL, NULL, integerBitOrMatch,
5142 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5143 "SYNTAX 1.3.6.1.1.16.1 )",
5144 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5145 NULL, UUIDNormalize, octetStringMatch,
5146 octetStringIndexer, octetStringFilter,
5149 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5150 "SYNTAX 1.3.6.1.1.16.1 )",
5151 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5152 NULL, UUIDNormalize, octetStringOrderingMatch,
5153 octetStringIndexer, octetStringFilter,
5156 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5157 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5158 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5159 NULL, csnNormalize, csnMatch,
5160 csnIndexer, csnFilter,
5163 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5164 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5165 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5166 NULL, NULL, csnOrderingMatch,
5170 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5171 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5172 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5173 NULL, csnSidNormalize, octetStringMatch,
5174 octetStringIndexer, octetStringFilter,
5177 /* FIXME: OID is unused, but not registered yet */
5178 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5179 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5180 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5181 NULL, authzNormalize, authzMatch,
5185 {NULL, SLAP_MR_NONE, NULL,
5186 NULL, NULL, NULL, NULL, NULL,
5191 slap_schema_init( void )
5196 /* we should only be called once (from main) */
5197 assert( schema_init_done == 0 );
5199 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5200 res = register_syntax( &syntax_defs[i] );
5203 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5204 syntax_defs[i].sd_desc );
5209 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5210 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5211 mrule_defs[i].mrd_compat_syntaxes == NULL )
5214 "slap_schema_init: Ignoring unusable matching rule %s\n",
5215 mrule_defs[i].mrd_desc );
5219 res = register_matching_rule( &mrule_defs[i] );
5223 "slap_schema_init: Error registering matching rule %s\n",
5224 mrule_defs[i].mrd_desc );
5229 res = slap_schema_load();
5230 schema_init_done = 1;
5235 schema_destroy( void )
5244 if( schema_init_done ) {
5245 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5246 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );