1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 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>
31 #include "ldap_utf8.h"
34 #include "lutil_hash.h"
35 #define HASH_BYTES LUTIL_HASH_BYTES
36 #define HASH_CONTEXT lutil_HASH_CTX
37 #define HASH_Init(c) lutil_HASHInit(c)
38 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
39 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
41 /* approx matching rules */
42 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
43 #define directoryStringApproxMatch approxMatch
44 #define directoryStringApproxIndexer approxIndexer
45 #define directoryStringApproxFilter approxFilter
46 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
47 #define IA5StringApproxMatch approxMatch
48 #define IA5StringApproxIndexer approxIndexer
49 #define IA5StringApproxFilter approxFilter
51 /* Change Sequence Number (CSN) - much of this will change */
52 #define csnValidate blobValidate
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 /* FIXME: temporary */
59 #define authzMatch octetStringMatch
61 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
62 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
63 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
64 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
66 ldap_pvt_thread_mutex_t ad_undef_mutex;
67 ldap_pvt_thread_mutex_t oc_undef_mutex;
74 /* no value allowed */
75 return LDAP_INVALID_SYNTAX;
83 /* any value allowed */
87 #define berValidate blobValidate
94 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
95 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
100 /* X.509 certificate validation */
101 static int certificateValidate( Syntax *syntax, struct berval *in )
103 BerElementBuffer berbuf;
104 BerElement *ber = (BerElement *)&berbuf;
107 ber_int_t i, version = 0;
109 ber_init2( ber, in, LBER_USE_DER );
110 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
111 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
112 tag = ber_skip_tag( ber, &len ); /* Sequence */
113 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
114 tag = ber_skip_tag( ber, &len );
115 if ( tag == 0xa0 ) { /* Optional version */
116 tag = ber_get_int( ber, &version );
117 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
119 tag = ber_get_int( ber, &i ); /* Serial */
120 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
121 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
122 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
123 ber_skip_data( ber, len );
124 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
125 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
126 ber_skip_data( ber, len );
127 tag = ber_skip_tag( ber, &len ); /* Validity */
128 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
129 ber_skip_data( ber, len );
130 tag = ber_skip_tag( ber, &len ); /* Subject DN */
131 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
132 ber_skip_data( ber, len );
133 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
134 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
135 ber_skip_data( ber, len );
136 tag = ber_skip_tag( ber, &len );
137 if ( tag == 0xa1 ) { /* issuerUniqueID */
138 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
139 ber_skip_data( ber, len );
140 tag = ber_skip_tag( ber, &len );
142 if ( tag == 0xa2 ) { /* subjectUniqueID */
143 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
144 ber_skip_data( ber, len );
145 tag = ber_skip_tag( ber, &len );
147 if ( tag == 0xa3 ) { /* Extensions */
148 if ( version < 2 ) return LDAP_INVALID_SYNTAX;
149 tag = ber_skip_tag( ber, &len );
150 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
151 ber_skip_data( ber, len );
152 tag = ber_skip_tag( ber, &len );
154 /* signatureAlgorithm */
155 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
156 ber_skip_data( ber, len );
157 tag = ber_skip_tag( ber, &len );
159 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len );
162 /* Must be at end now */
163 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
173 struct berval *value,
174 void *assertedValue )
176 struct berval *asserted = (struct berval *) assertedValue;
177 int match = value->bv_len - asserted->bv_len;
180 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
188 octetStringOrderingMatch(
193 struct berval *value,
194 void *assertedValue )
196 struct berval *asserted = (struct berval *) assertedValue;
197 ber_len_t v_len = value->bv_len;
198 ber_len_t av_len = asserted->bv_len;
200 int match = memcmp( value->bv_val, asserted->bv_val,
201 (v_len < av_len ? v_len : av_len) );
203 if( match == 0 ) match = v_len - av_len;
211 HASH_CONTEXT *HASHcontext,
212 struct berval *prefix,
217 HASH_Init(HASHcontext);
218 if(prefix && prefix->bv_len > 0) {
219 HASH_Update(HASHcontext,
220 (unsigned char *)prefix->bv_val, prefix->bv_len);
222 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
223 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
224 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
230 HASH_CONTEXT *HASHcontext,
231 unsigned char *HASHdigest,
232 unsigned char *value,
235 HASH_CONTEXT ctx = *HASHcontext;
236 HASH_Update( &ctx, value, len );
237 HASH_Final( HASHdigest, &ctx );
240 /* Index generation function */
241 int octetStringIndexer(
246 struct berval *prefix,
254 HASH_CONTEXT HASHcontext;
255 unsigned char HASHdigest[HASH_BYTES];
256 struct berval digest;
257 digest.bv_val = (char *)HASHdigest;
258 digest.bv_len = sizeof(HASHdigest);
260 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
261 /* just count them */
264 /* we should have at least one value at this point */
267 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
269 slen = syntax->ssyn_oidlen;
270 mlen = mr->smr_oidlen;
272 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
273 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
274 hashIter( &HASHcontext, HASHdigest,
275 (unsigned char *)values[i].bv_val, values[i].bv_len );
276 ber_dupbv_x( &keys[i], &digest, ctx );
279 BER_BVZERO( &keys[i] );
286 /* Index generation function */
287 int octetStringFilter(
292 struct berval *prefix,
293 void * assertedValue,
299 HASH_CONTEXT HASHcontext;
300 unsigned char HASHdigest[HASH_BYTES];
301 struct berval *value = (struct berval *) assertedValue;
302 struct berval digest;
303 digest.bv_val = (char *)HASHdigest;
304 digest.bv_len = sizeof(HASHdigest);
306 slen = syntax->ssyn_oidlen;
307 mlen = mr->smr_oidlen;
309 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
311 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
312 hashIter( &HASHcontext, HASHdigest,
313 (unsigned char *)value->bv_val, value->bv_len );
315 ber_dupbv_x( keys, &digest, ctx );
316 BER_BVZERO( &keys[1] );
324 octetStringSubstringsMatch(
329 struct berval *value,
330 void *assertedValue )
333 SubstringsAssertion *sub = assertedValue;
334 struct berval left = *value;
338 /* Add up asserted input length */
339 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
340 inlen += sub->sa_initial.bv_len;
343 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
344 inlen += sub->sa_any[i].bv_len;
347 if ( !BER_BVISNULL( &sub->sa_final ) ) {
348 inlen += sub->sa_final.bv_len;
351 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
352 if ( inlen > left.bv_len ) {
357 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
358 sub->sa_initial.bv_len );
364 left.bv_val += sub->sa_initial.bv_len;
365 left.bv_len -= sub->sa_initial.bv_len;
366 inlen -= sub->sa_initial.bv_len;
369 if ( !BER_BVISNULL( &sub->sa_final ) ) {
370 if ( inlen > left.bv_len ) {
375 match = memcmp( sub->sa_final.bv_val,
376 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
377 sub->sa_final.bv_len );
383 left.bv_len -= sub->sa_final.bv_len;
384 inlen -= sub->sa_final.bv_len;
388 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
393 if ( inlen > left.bv_len ) {
394 /* not enough length */
399 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
403 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
410 idx = p - left.bv_val;
412 if ( idx >= left.bv_len ) {
413 /* this shouldn't happen */
420 if ( sub->sa_any[i].bv_len > left.bv_len ) {
421 /* not enough left */
426 match = memcmp( left.bv_val,
427 sub->sa_any[i].bv_val,
428 sub->sa_any[i].bv_len );
436 left.bv_val += sub->sa_any[i].bv_len;
437 left.bv_len -= sub->sa_any[i].bv_len;
438 inlen -= sub->sa_any[i].bv_len;
447 /* Substrings Index generation function */
449 octetStringSubstringsIndexer(
454 struct berval *prefix,
463 HASH_CONTEXT HCany, HCini, HCfin;
464 unsigned char HASHdigest[HASH_BYTES];
465 struct berval digest;
466 digest.bv_val = (char *)HASHdigest;
467 digest.bv_len = sizeof(HASHdigest);
471 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
472 /* count number of indices to generate */
473 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
474 if( values[i].bv_len >= index_substr_if_maxlen ) {
475 nkeys += index_substr_if_maxlen -
476 (index_substr_if_minlen - 1);
477 } else if( values[i].bv_len >= index_substr_if_minlen ) {
478 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
482 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
483 if( values[i].bv_len >= index_substr_any_len ) {
484 nkeys += values[i].bv_len - (index_substr_any_len - 1);
488 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
489 if( values[i].bv_len >= index_substr_if_maxlen ) {
490 nkeys += index_substr_if_maxlen -
491 (index_substr_if_minlen - 1);
492 } else if( values[i].bv_len >= index_substr_if_minlen ) {
493 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
499 /* no keys to generate */
504 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
506 slen = syntax->ssyn_oidlen;
507 mlen = mr->smr_oidlen;
509 if ( flags & SLAP_INDEX_SUBSTR_ANY )
510 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
511 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
512 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
513 if( flags & SLAP_INDEX_SUBSTR_FINAL )
514 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
517 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
520 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
521 ( values[i].bv_len >= index_substr_any_len ) )
523 max = values[i].bv_len - (index_substr_any_len - 1);
525 for( j=0; j<max; j++ ) {
526 hashIter( &HCany, HASHdigest,
527 (unsigned char *)&values[i].bv_val[j],
528 index_substr_any_len );
529 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
533 /* skip if too short */
534 if( values[i].bv_len < index_substr_if_minlen ) continue;
536 max = index_substr_if_maxlen < values[i].bv_len
537 ? index_substr_if_maxlen : values[i].bv_len;
539 for( j=index_substr_if_minlen; j<=max; j++ ) {
541 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
542 hashIter( &HCini, HASHdigest,
543 (unsigned char *)values[i].bv_val, j );
544 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
547 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
548 hashIter( &HCfin, HASHdigest,
549 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
550 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
557 BER_BVZERO( &keys[nkeys] );
568 octetStringSubstringsFilter (
573 struct berval *prefix,
574 void * assertedValue,
578 SubstringsAssertion *sa;
581 size_t slen, mlen, klen;
583 HASH_CONTEXT HASHcontext;
584 unsigned char HASHdigest[HASH_BYTES];
585 struct berval *value;
586 struct berval digest;
588 sa = (SubstringsAssertion *) assertedValue;
590 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
591 !BER_BVISNULL( &sa->sa_initial ) &&
592 sa->sa_initial.bv_len >= index_substr_if_minlen )
595 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
596 ( flags & SLAP_INDEX_SUBSTR_ANY ))
598 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
602 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
604 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
605 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
606 /* don't bother accounting with stepping */
607 nkeys += sa->sa_any[i].bv_len -
608 ( index_substr_any_len - 1 );
613 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
614 !BER_BVISNULL( &sa->sa_final ) &&
615 sa->sa_final.bv_len >= index_substr_if_minlen )
618 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
619 ( flags & SLAP_INDEX_SUBSTR_ANY ))
621 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
630 digest.bv_val = (char *)HASHdigest;
631 digest.bv_len = sizeof(HASHdigest);
633 slen = syntax->ssyn_oidlen;
634 mlen = mr->smr_oidlen;
636 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
639 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
640 !BER_BVISNULL( &sa->sa_initial ) &&
641 sa->sa_initial.bv_len >= index_substr_if_minlen )
643 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
644 value = &sa->sa_initial;
646 klen = index_substr_if_maxlen < value->bv_len
647 ? index_substr_if_maxlen : value->bv_len;
649 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
650 hashIter( &HASHcontext, HASHdigest,
651 (unsigned char *)value->bv_val, klen );
652 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
654 /* If initial is too long and we have subany indexed, use it
655 * to match the excess...
657 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
660 pre = SLAP_INDEX_SUBSTR_PREFIX;
661 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
662 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
664 hashIter( &HASHcontext, HASHdigest,
665 (unsigned char *)&value->bv_val[j], index_substr_any_len );
666 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
671 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
673 pre = SLAP_INDEX_SUBSTR_PREFIX;
674 klen = index_substr_any_len;
676 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
677 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
681 value = &sa->sa_any[i];
683 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
685 j <= value->bv_len - index_substr_any_len;
686 j += index_substr_any_step )
688 hashIter( &HASHcontext, HASHdigest,
689 (unsigned char *)&value->bv_val[j], klen );
690 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
695 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
696 !BER_BVISNULL( &sa->sa_final ) &&
697 sa->sa_final.bv_len >= index_substr_if_minlen )
699 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
700 value = &sa->sa_final;
702 klen = index_substr_if_maxlen < value->bv_len
703 ? index_substr_if_maxlen : value->bv_len;
705 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
706 hashIter( &HASHcontext, HASHdigest,
707 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
708 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
710 /* If final is too long and we have subany indexed, use it
711 * to match the excess...
713 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
716 pre = SLAP_INDEX_SUBSTR_PREFIX;
717 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
718 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
720 hashIter( &HASHcontext, HASHdigest,
721 (unsigned char *)&value->bv_val[j], index_substr_any_len );
722 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
728 BER_BVZERO( &keys[nkeys] );
745 /* very unforgiving validation, requires no normalization
746 * before simplistic matching
748 if( in->bv_len < 3 ) {
749 return LDAP_INVALID_SYNTAX;
752 /* RFC 4517 Section 3.3.2 Bit String:
753 * BitString = SQUOTE *binary-digit SQUOTE "B"
754 * binary-digit = "0" / "1"
756 * where SQUOTE [RFC4512] is
757 * SQUOTE = %x27 ; single quote ("'")
759 * Example: '0101111101'B
762 if( in->bv_val[0] != '\'' ||
763 in->bv_val[in->bv_len - 2] != '\'' ||
764 in->bv_val[in->bv_len - 1] != 'B' )
766 return LDAP_INVALID_SYNTAX;
769 for( i = in->bv_len - 3; i > 0; i-- ) {
770 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
771 return LDAP_INVALID_SYNTAX;
779 * Syntaxes from RFC 4517
784 A value of the Bit String syntax is a sequence of binary digits. The
785 LDAP-specific encoding of a value of this syntax is defined by the
788 BitString = SQUOTE *binary-digit SQUOTE "B"
790 binary-digit = "0" / "1"
792 The <SQUOTE> rule is defined in [MODELS].
797 The LDAP definition for the Bit String syntax is:
799 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
801 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
805 3.3.21. Name and Optional UID
807 A value of the Name and Optional UID syntax is the distinguished name
808 [MODELS] of an entity optionally accompanied by a unique identifier
809 that serves to differentiate the entity from others with an identical
812 The LDAP-specific encoding of a value of this syntax is defined by
815 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
817 The <BitString> rule is defined in Section 3.3.2. The
818 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
821 Note that although the '#' character may occur in the string
822 representation of a distinguished name, no additional escaping of
823 this character is performed when a <distinguishedName> is encoded in
824 a <NameAndOptionalUID>.
827 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
829 The LDAP definition for the Name and Optional UID syntax is:
831 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
833 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
840 1.4. Common ABNF Productions
843 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
845 SQUOTE = %x27 ; single quote ("'")
849 * Note: normalization strips any leading "0"s, unless the
850 * bit string is exactly "'0'B", so the normalized example,
851 * in slapd, would result in
853 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
855 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
856 * be escaped except when at the beginning of a value, the
857 * definition of Name and Optional UID appears to be flawed,
858 * because there is no clear means to determine whether the
859 * UID part is present or not.
863 * cn=Someone,dc=example,dc=com#'1'B
865 * could be either a NameAndOptionalUID with trailing UID, i.e.
867 * DN = "cn=Someone,dc=example,dc=com"
870 * or a NameAndOptionalUID with no trailing UID, and the AVA
871 * in the last RDN made of
874 * attributeValue = com#'1'B
876 * in fact "com#'1'B" is a valid IA5 string.
878 * As a consequence, current slapd code assumes that the
879 * presence of portions of a BitString at the end of the string
880 * representation of a NameAndOptionalUID means a BitString
881 * is expected, and cause an error otherwise. This is quite
882 * arbitrary, and might change in the future.
892 struct berval dn, uid;
894 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
896 ber_dupbv( &dn, in );
897 if( !dn.bv_val ) return LDAP_OTHER;
899 /* if there's a "#", try bitStringValidate()... */
900 uid.bv_val = strrchr( dn.bv_val, '#' );
901 if ( !BER_BVISNULL( &uid ) ) {
903 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
905 rc = bitStringValidate( NULL, &uid );
906 if ( rc == LDAP_SUCCESS ) {
907 /* in case of success, trim the UID,
908 * otherwise treat it as part of the DN */
909 dn.bv_len -= uid.bv_len + 1;
910 uid.bv_val[-1] = '\0';
914 rc = dnValidate( NULL, &dn );
916 ber_memfree( dn.bv_val );
927 assert( val != NULL );
928 assert( out != NULL );
931 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
933 if( BER_BVISEMPTY( val ) ) {
934 ber_dupbv_x( out, val, ctx );
936 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
937 return LDAP_INVALID_SYNTAX;
941 struct berval dnval = *val;
942 struct berval uidval = BER_BVNULL;
944 uidval.bv_val = strrchr( val->bv_val, '#' );
945 if ( !BER_BVISNULL( &uidval ) ) {
947 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
949 rc = bitStringValidate( NULL, &uidval );
951 if ( rc == LDAP_SUCCESS ) {
952 ber_dupbv_x( &dnval, val, ctx );
953 dnval.bv_len -= uidval.bv_len + 1;
954 dnval.bv_val[dnval.bv_len] = '\0';
957 BER_BVZERO( &uidval );
961 rc = dnPretty( syntax, &dnval, out, ctx );
962 if ( dnval.bv_val != val->bv_val ) {
963 slap_sl_free( dnval.bv_val, ctx );
965 if( rc != LDAP_SUCCESS ) {
969 if( !BER_BVISNULL( &uidval ) ) {
973 tmp = slap_sl_realloc( out->bv_val, out->bv_len
974 + STRLENOF( "#" ) + uidval.bv_len + 1,
977 ber_memfree_x( out->bv_val, ctx );
981 out->bv_val[out->bv_len++] = '#';
982 out->bv_val[out->bv_len++] = '\'';
984 got1 = uidval.bv_len < sizeof("'0'B");
985 for( i = 1; i < uidval.bv_len - 2; i++ ) {
986 c = uidval.bv_val[i];
989 if( got1 ) out->bv_val[out->bv_len++] = c;
993 out->bv_val[out->bv_len++] = c;
998 out->bv_val[out->bv_len++] = '\'';
999 out->bv_val[out->bv_len++] = 'B';
1000 out->bv_val[out->bv_len] = '\0';
1004 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1006 return LDAP_SUCCESS;
1010 uniqueMemberNormalize(
1015 struct berval *normalized,
1021 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1023 ber_dupbv_x( &out, val, ctx );
1024 if ( BER_BVISEMPTY( &out ) ) {
1028 struct berval uid = BER_BVNULL;
1030 uid.bv_val = strrchr( out.bv_val, '#' );
1031 if ( !BER_BVISNULL( &uid ) ) {
1033 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1035 rc = bitStringValidate( NULL, &uid );
1036 if ( rc == LDAP_SUCCESS ) {
1037 uid.bv_val[-1] = '\0';
1038 out.bv_len -= uid.bv_len + 1;
1044 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1046 if( rc != LDAP_SUCCESS ) {
1047 slap_sl_free( out.bv_val, ctx );
1048 return LDAP_INVALID_SYNTAX;
1051 if( !BER_BVISNULL( &uid ) ) {
1054 tmp = ch_realloc( normalized->bv_val,
1055 normalized->bv_len + uid.bv_len
1056 + STRLENOF("#") + 1 );
1057 if ( tmp == NULL ) {
1058 ber_memfree_x( normalized->bv_val, ctx );
1062 normalized->bv_val = tmp;
1064 /* insert the separator */
1065 normalized->bv_val[normalized->bv_len++] = '#';
1067 /* append the UID */
1068 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1069 uid.bv_val, uid.bv_len );
1070 normalized->bv_len += uid.bv_len;
1073 normalized->bv_val[normalized->bv_len] = '\0';
1076 slap_sl_free( out.bv_val, ctx );
1079 return LDAP_SUCCESS;
1088 struct berval *value,
1089 void *assertedValue )
1092 struct berval *asserted = (struct berval *) assertedValue;
1093 struct berval assertedDN = *asserted;
1094 struct berval assertedUID = BER_BVNULL;
1095 struct berval valueDN = *value;
1096 struct berval valueUID = BER_BVNULL;
1097 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1099 if ( !BER_BVISEMPTY( asserted ) ) {
1100 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1101 if ( !BER_BVISNULL( &assertedUID ) ) {
1102 assertedUID.bv_val++;
1103 assertedUID.bv_len = assertedDN.bv_len
1104 - ( assertedUID.bv_val - assertedDN.bv_val );
1106 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1107 assertedDN.bv_len -= assertedUID.bv_len + 1;
1110 BER_BVZERO( &assertedUID );
1115 if ( !BER_BVISEMPTY( value ) ) {
1117 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1118 if ( !BER_BVISNULL( &valueUID ) ) {
1120 valueUID.bv_len = valueDN.bv_len
1121 - ( valueUID.bv_val - valueDN.bv_val );
1123 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1124 valueDN.bv_len -= valueUID.bv_len + 1;
1127 BER_BVZERO( &valueUID );
1132 if( valueUID.bv_len && assertedUID.bv_len ) {
1133 match = valueUID.bv_len - assertedUID.bv_len;
1136 return LDAP_SUCCESS;
1139 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1142 return LDAP_SUCCESS;
1145 } else if ( !approx && valueUID.bv_len ) {
1148 return LDAP_SUCCESS;
1150 } else if ( !approx && assertedUID.bv_len ) {
1153 return LDAP_SUCCESS;
1156 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1160 uniqueMemberIndexer(
1165 struct berval *prefix,
1173 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1174 /* just count them */
1178 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1180 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1181 struct berval assertedDN = values[i];
1182 struct berval assertedUID = BER_BVNULL;
1184 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1185 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1186 if ( !BER_BVISNULL( &assertedUID ) ) {
1187 assertedUID.bv_val++;
1188 assertedUID.bv_len = assertedDN.bv_len
1189 - ( assertedUID.bv_val - assertedDN.bv_val );
1191 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1192 assertedDN.bv_len -= assertedUID.bv_len + 1;
1195 BER_BVZERO( &assertedUID );
1200 dnvalues[i] = assertedDN;
1202 BER_BVZERO( &dnvalues[i] );
1204 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1205 dnvalues, keysp, ctx );
1207 slap_sl_free( dnvalues, ctx );
1217 struct berval *prefix,
1218 void * assertedValue,
1222 struct berval *asserted = (struct berval *) assertedValue;
1223 struct berval assertedDN = *asserted;
1224 struct berval assertedUID = BER_BVNULL;
1226 if ( !BER_BVISEMPTY( asserted ) ) {
1227 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1228 if ( !BER_BVISNULL( &assertedUID ) ) {
1229 assertedUID.bv_val++;
1230 assertedUID.bv_len = assertedDN.bv_len
1231 - ( assertedUID.bv_val - assertedDN.bv_val );
1233 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1234 assertedDN.bv_len -= assertedUID.bv_len + 1;
1237 BER_BVZERO( &assertedUID );
1242 return octetStringFilter( use, flags, syntax, mr, prefix,
1243 &assertedDN, keysp, ctx );
1248 * Handling boolean syntax and matching is quite rigid.
1249 * A more flexible approach would be to allow a variety
1250 * of strings to be normalized and prettied into TRUE
1258 /* very unforgiving validation, requires no normalization
1259 * before simplistic matching
1262 if( in->bv_len == 4 ) {
1263 if( bvmatch( in, &slap_true_bv ) ) {
1264 return LDAP_SUCCESS;
1266 } else if( in->bv_len == 5 ) {
1267 if( bvmatch( in, &slap_false_bv ) ) {
1268 return LDAP_SUCCESS;
1272 return LDAP_INVALID_SYNTAX;
1281 struct berval *value,
1282 void *assertedValue )
1284 /* simplistic matching allowed by rigid validation */
1285 struct berval *asserted = (struct berval *) assertedValue;
1286 *matchp = value->bv_len != asserted->bv_len;
1287 return LDAP_SUCCESS;
1290 /*-------------------------------------------------------------------
1291 LDAP/X.500 string syntax / matching rules have a few oddities. This
1292 comment attempts to detail how slapd(8) treats them.
1295 StringSyntax X.500 LDAP Matching/Comments
1296 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1297 PrintableString subset subset i/e + ignore insignificant spaces
1298 PrintableString subset subset i/e + ignore insignificant spaces
1299 NumericString subset subset ignore all spaces
1300 IA5String ASCII ASCII i/e + ignore insignificant spaces
1301 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1303 TelephoneNumber subset subset i + ignore all spaces and "-"
1305 See RFC 4518 for details.
1309 In X.500(93), a directory string can be either a PrintableString,
1310 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1311 In later versions, more CHOICEs were added. In all cases the string
1314 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1315 A directory string cannot be zero length.
1317 For matching, there are both case ignore and exact rules. Both
1318 also require that "insignificant" spaces be ignored.
1319 spaces before the first non-space are ignored;
1320 spaces after the last non-space are ignored;
1321 spaces after a space are ignored.
1322 Note: by these rules (and as clarified in X.520), a string of only
1323 spaces is to be treated as if held one space, not empty (which
1324 would be a syntax error).
1327 In ASN.1, numeric string is just a string of digits and spaces
1328 and could be empty. However, in X.500, all attribute values of
1329 numeric string carry a non-empty constraint. For example:
1331 internationalISDNNumber ATTRIBUTE ::= {
1332 WITH SYNTAX InternationalISDNNumber
1333 EQUALITY MATCHING RULE numericStringMatch
1334 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1335 ID id-at-internationalISDNNumber }
1336 InternationalISDNNumber ::=
1337 NumericString (SIZE(1..ub-international-isdn-number))
1339 Unforunately, some assertion values are don't carry the same
1340 constraint (but its unclear how such an assertion could ever
1341 be true). In LDAP, there is one syntax (numericString) not two
1342 (numericString with constraint, numericString without constraint).
1343 This should be treated as numericString with non-empty constraint.
1344 Note that while someone may have no ISDN number, there are no ISDN
1345 numbers which are zero length.
1347 In matching, spaces are ignored.
1350 In ASN.1, Printable string is just a string of printable characters
1351 and can be empty. In X.500, semantics much like NumericString (see
1352 serialNumber for a like example) excepting uses insignificant space
1353 handling instead of ignore all spaces.
1356 Basically same as PrintableString. There are no examples in X.500,
1357 but same logic applies. So we require them to be non-empty as
1360 -------------------------------------------------------------------*/
1369 unsigned char *u = (unsigned char *)in->bv_val;
1371 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1372 /* directory strings cannot be empty */
1373 return LDAP_INVALID_SYNTAX;
1376 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1377 /* get the length indicated by the first byte */
1378 len = LDAP_UTF8_CHARLEN2( u, len );
1380 /* very basic checks */
1383 if( (u[5] & 0xC0) != 0x80 ) {
1384 return LDAP_INVALID_SYNTAX;
1387 if( (u[4] & 0xC0) != 0x80 ) {
1388 return LDAP_INVALID_SYNTAX;
1391 if( (u[3] & 0xC0) != 0x80 ) {
1392 return LDAP_INVALID_SYNTAX;
1395 if( (u[2] & 0xC0 )!= 0x80 ) {
1396 return LDAP_INVALID_SYNTAX;
1399 if( (u[1] & 0xC0) != 0x80 ) {
1400 return LDAP_INVALID_SYNTAX;
1403 /* CHARLEN already validated it */
1406 return LDAP_INVALID_SYNTAX;
1409 /* make sure len corresponds with the offset
1410 to the next character */
1411 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1415 return LDAP_INVALID_SYNTAX;
1418 return LDAP_SUCCESS;
1422 UTF8StringNormalize(
1427 struct berval *normalized,
1430 struct berval tmp, nvalue;
1434 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1436 if( BER_BVISNULL( val ) ) {
1437 /* assume we're dealing with a syntax (e.g., UTF8String)
1438 * which allows empty strings
1440 BER_BVZERO( normalized );
1441 return LDAP_SUCCESS;
1444 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1445 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1446 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1447 ? LDAP_UTF8_APPROX : 0;
1449 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1454 /* collapse spaces (in place) */
1456 nvalue.bv_val = tmp.bv_val;
1458 /* trim leading spaces? */
1459 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1460 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1462 for( i = 0; i < tmp.bv_len; i++) {
1463 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1464 if( wasspace++ == 0 ) {
1465 /* trim repeated spaces */
1466 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1470 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1474 if( !BER_BVISEMPTY( &nvalue ) ) {
1475 /* trim trailing space? */
1477 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1478 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1482 nvalue.bv_val[nvalue.bv_len] = '\0';
1485 /* string of all spaces is treated as one space */
1486 nvalue.bv_val[0] = ' ';
1487 nvalue.bv_val[1] = '\0';
1491 *normalized = nvalue;
1492 return LDAP_SUCCESS;
1496 directoryStringSubstringsMatch(
1501 struct berval *value,
1502 void *assertedValue )
1505 SubstringsAssertion *sub = assertedValue;
1506 struct berval left = *value;
1510 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1511 if ( sub->sa_initial.bv_len > left.bv_len ) {
1512 /* not enough left */
1517 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1518 sub->sa_initial.bv_len );
1524 left.bv_val += sub->sa_initial.bv_len;
1525 left.bv_len -= sub->sa_initial.bv_len;
1527 priorspace = ASCII_SPACE(
1528 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1531 if ( sub->sa_any ) {
1532 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1536 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1537 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1539 /* allow next space to match */
1546 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1550 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1551 /* not enough left */
1556 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1563 idx = p - left.bv_val;
1565 if ( idx >= left.bv_len ) {
1566 /* this shouldn't happen */
1573 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1574 /* not enough left */
1579 match = memcmp( left.bv_val,
1580 sub->sa_any[i].bv_val,
1581 sub->sa_any[i].bv_len );
1589 left.bv_val += sub->sa_any[i].bv_len;
1590 left.bv_len -= sub->sa_any[i].bv_len;
1592 priorspace = ASCII_SPACE(
1593 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1597 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1598 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1599 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1601 /* allow next space to match */
1606 if ( sub->sa_final.bv_len > left.bv_len ) {
1607 /* not enough left */
1612 match = memcmp( sub->sa_final.bv_val,
1613 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1614 sub->sa_final.bv_len );
1623 return LDAP_SUCCESS;
1626 #if defined(SLAPD_APPROX_INITIALS)
1627 # define SLAPD_APPROX_DELIMITER "._ "
1628 # define SLAPD_APPROX_WORDLEN 2
1630 # define SLAPD_APPROX_DELIMITER " "
1631 # define SLAPD_APPROX_WORDLEN 1
1640 struct berval *value,
1641 void *assertedValue )
1643 struct berval *nval, *assertv;
1644 char *val, **values, **words, *c;
1645 int i, count, len, nextchunk=0, nextavail=0;
1647 /* Yes, this is necessary */
1648 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1649 if( nval == NULL ) {
1651 return LDAP_SUCCESS;
1654 /* Yes, this is necessary */
1655 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1656 NULL, LDAP_UTF8_APPROX, NULL );
1657 if( assertv == NULL ) {
1660 return LDAP_SUCCESS;
1663 /* Isolate how many words there are */
1664 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1665 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1666 if ( c == NULL ) break;
1671 /* Get a phonetic copy of each word */
1672 words = (char **)ch_malloc( count * sizeof(char *) );
1673 values = (char **)ch_malloc( count * sizeof(char *) );
1674 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1676 values[i] = phonetic(c);
1679 /* Work through the asserted value's words, to see if at least some
1680 of the words are there, in the same order. */
1682 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1683 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1688 #if defined(SLAPD_APPROX_INITIALS)
1689 else if( len == 1 ) {
1690 /* Single letter words need to at least match one word's initial */
1691 for( i=nextavail; i<count; i++ )
1692 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1699 /* Isolate the next word in the asserted value and phonetic it */
1700 assertv->bv_val[nextchunk+len] = '\0';
1701 val = phonetic( assertv->bv_val + nextchunk );
1703 /* See if this phonetic chunk is in the remaining words of *value */
1704 for( i=nextavail; i<count; i++ ){
1705 if( !strcmp( val, values[i] ) ){
1713 /* This chunk in the asserted value was NOT within the *value. */
1719 /* Go on to the next word in the asserted value */
1723 /* If some of the words were seen, call it a match */
1724 if( nextavail > 0 ) {
1731 /* Cleanup allocs */
1732 ber_bvfree( assertv );
1733 for( i=0; i<count; i++ ) {
1734 ch_free( values[i] );
1740 return LDAP_SUCCESS;
1749 struct berval *prefix,
1755 int i,j, len, wordcount, keycount=0;
1756 struct berval *newkeys;
1757 BerVarray keys=NULL;
1759 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1760 struct berval val = BER_BVNULL;
1761 /* Yes, this is necessary */
1762 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1763 assert( !BER_BVISNULL( &val ) );
1765 /* Isolate how many words there are. There will be a key for each */
1766 for( wordcount = 0, c = val.bv_val; *c; c++) {
1767 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1768 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1770 if (*c == '\0') break;
1774 /* Allocate/increase storage to account for new keys */
1775 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1776 * sizeof(struct berval) );
1777 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1778 if( keys ) ch_free( keys );
1781 /* Get a phonetic copy of each word */
1782 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1784 if( len < SLAPD_APPROX_WORDLEN ) continue;
1785 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1790 ber_memfree( val.bv_val );
1792 BER_BVZERO( &keys[keycount] );
1795 return LDAP_SUCCESS;
1804 struct berval *prefix,
1805 void * assertedValue,
1814 /* Yes, this is necessary */
1815 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1816 NULL, LDAP_UTF8_APPROX, NULL );
1817 if( val == NULL || BER_BVISNULL( val ) ) {
1818 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1819 BER_BVZERO( &keys[0] );
1822 return LDAP_SUCCESS;
1825 /* Isolate how many words there are. There will be a key for each */
1826 for( count = 0,c = val->bv_val; *c; c++) {
1827 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1828 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1830 if (*c == '\0') break;
1834 /* Allocate storage for new keys */
1835 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1837 /* Get a phonetic copy of each word */
1838 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1840 if( len < SLAPD_APPROX_WORDLEN ) continue;
1841 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1847 BER_BVZERO( &keys[count] );
1850 return LDAP_SUCCESS;
1853 /* Remove all spaces and '-' characters */
1855 telephoneNumberNormalize(
1860 struct berval *normalized,
1865 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1867 /* validator should have refused an empty string */
1868 assert( !BER_BVISEMPTY( val ) );
1870 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1872 for( p = val->bv_val; *p; p++ ) {
1873 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1879 normalized->bv_len = q - normalized->bv_val;
1881 if( BER_BVISEMPTY( normalized ) ) {
1882 slap_sl_free( normalized->bv_val, ctx );
1883 BER_BVZERO( normalized );
1884 return LDAP_INVALID_SYNTAX;
1887 return LDAP_SUCCESS;
1895 struct berval val = *in;
1897 if( BER_BVISEMPTY( &val ) ) {
1898 /* disallow empty strings */
1899 return LDAP_INVALID_SYNTAX;
1902 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1903 if ( val.bv_len == 1 ) {
1904 return LDAP_SUCCESS;
1907 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1914 while ( OID_LEADCHAR( val.bv_val[0] )) {
1918 if ( val.bv_len == 0 ) {
1919 return LDAP_SUCCESS;
1923 if( !OID_SEPARATOR( val.bv_val[0] )) {
1931 return LDAP_INVALID_SYNTAX;
1940 struct berval val = *in;
1942 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1944 if ( val.bv_val[0] == '-' ) {
1948 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1949 return LDAP_INVALID_SYNTAX;
1952 if( val.bv_val[0] == '0' ) { /* "-0" */
1953 return LDAP_INVALID_SYNTAX;
1956 } else if ( val.bv_val[0] == '0' ) {
1957 if( val.bv_len > 1 ) { /* "0<more>" */
1958 return LDAP_INVALID_SYNTAX;
1961 return LDAP_SUCCESS;
1964 for( i=0; i < val.bv_len; i++ ) {
1965 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1966 return LDAP_INVALID_SYNTAX;
1970 return LDAP_SUCCESS;
1979 struct berval *value,
1980 void *assertedValue )
1982 struct berval *asserted = (struct berval *) assertedValue;
1983 int vsign = 1, asign = 1; /* default sign = '+' */
1988 if( v.bv_val[0] == '-' ) {
1994 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1997 if( a.bv_val[0] == '-' ) {
2003 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2005 match = vsign - asign;
2007 match = ( v.bv_len != a.bv_len
2008 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2009 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2010 if( vsign < 0 ) match = -match;
2014 return LDAP_SUCCESS;
2018 countryStringValidate(
2020 struct berval *val )
2022 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2024 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2025 return LDAP_INVALID_SYNTAX;
2027 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2028 return LDAP_INVALID_SYNTAX;
2031 return LDAP_SUCCESS;
2035 printableStringValidate(
2037 struct berval *val )
2041 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2043 for(i=0; i < val->bv_len; i++) {
2044 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2045 return LDAP_INVALID_SYNTAX;
2049 return LDAP_SUCCESS;
2053 printablesStringValidate(
2055 struct berval *val )
2059 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2061 for(i=0,len=0; i < val->bv_len; i++) {
2062 int c = val->bv_val[i];
2066 return LDAP_INVALID_SYNTAX;
2070 } else if ( SLAP_PRINTABLE(c) ) {
2073 return LDAP_INVALID_SYNTAX;
2078 return LDAP_INVALID_SYNTAX;
2081 return LDAP_SUCCESS;
2087 struct berval *val )
2091 for(i=0; i < val->bv_len; i++) {
2092 if( !LDAP_ASCII(val->bv_val[i]) ) {
2093 return LDAP_INVALID_SYNTAX;
2097 return LDAP_SUCCESS;
2106 struct berval *normalized,
2110 int casefold = !SLAP_MR_ASSOCIATED( mr,
2111 slap_schema.si_mr_caseExactIA5Match );
2113 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2117 /* Ignore initial whitespace */
2118 while ( ASCII_SPACE( *p ) ) p++;
2120 normalized->bv_val = ber_strdup_x( p, ctx );
2121 p = q = normalized->bv_val;
2124 if ( ASCII_SPACE( *p ) ) {
2127 /* Ignore the extra whitespace */
2128 while ( ASCII_SPACE( *p ) ) {
2132 } else if ( casefold ) {
2133 /* Most IA5 rules require casefolding */
2134 *q++ = TOLOWER(*p); p++;
2141 assert( normalized->bv_val <= p );
2145 * If the string ended in space, backup the pointer one
2146 * position. One is enough because the above loop collapsed
2147 * all whitespace to a single space.
2149 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2151 /* null terminate */
2154 normalized->bv_len = q - normalized->bv_val;
2156 return LDAP_SUCCESS;
2165 if( in->bv_len != 36 ) {
2166 return LDAP_INVALID_SYNTAX;
2169 for( i=0; i<36; i++ ) {
2175 if( in->bv_val[i] != '-' ) {
2176 return LDAP_INVALID_SYNTAX;
2180 if( !ASCII_HEX( in->bv_val[i]) ) {
2181 return LDAP_INVALID_SYNTAX;
2186 return LDAP_SUCCESS;
2197 int rc=LDAP_INVALID_SYNTAX;
2199 assert( in != NULL );
2200 assert( out != NULL );
2202 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2205 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2207 for( i=0; i<36; i++ ) {
2213 if( in->bv_val[i] != '-' ) {
2216 out->bv_val[i] = '-';
2220 if( !ASCII_HEX( in->bv_val[i]) ) {
2223 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2228 out->bv_val[ out->bv_len ] = '\0';
2232 slap_sl_free( out->bv_val, ctx );
2245 struct berval *normalized,
2248 unsigned char octet = '\0';
2251 normalized->bv_len = 16;
2252 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2254 for( i=0, j=0; i<36; i++ ) {
2255 unsigned char nibble;
2256 if( val->bv_val[i] == '-' ) {
2259 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2260 nibble = val->bv_val[i] - '0';
2262 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2263 nibble = val->bv_val[i] - ('a'-10);
2265 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2266 nibble = val->bv_val[i] - ('A'-10);
2269 slap_sl_free( normalized->bv_val, ctx );
2270 return LDAP_INVALID_SYNTAX;
2275 normalized->bv_val[j>>1] = octet;
2277 octet = nibble << 4;
2282 normalized->bv_val[normalized->bv_len] = 0;
2283 return LDAP_SUCCESS;
2289 numericStringValidate(
2295 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2297 for(i=0; i < in->bv_len; i++) {
2298 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2299 return LDAP_INVALID_SYNTAX;
2303 return LDAP_SUCCESS;
2307 numericStringNormalize(
2312 struct berval *normalized,
2315 /* removal all spaces */
2318 assert( !BER_BVISEMPTY( val ) );
2320 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2323 q = normalized->bv_val;
2326 if ( ASCII_SPACE( *p ) ) {
2327 /* Ignore whitespace */
2334 /* we should have copied no more then is in val */
2335 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2337 /* null terminate */
2340 normalized->bv_len = q - normalized->bv_val;
2342 if( BER_BVISEMPTY( normalized ) ) {
2343 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2344 normalized->bv_val[0] = ' ';
2345 normalized->bv_val[1] = '\0';
2346 normalized->bv_len = 1;
2349 return LDAP_SUCCESS;
2353 * Integer conversion macros that will use the largest available
2356 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2357 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2358 # define SLAP_LONG long long
2360 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2361 # define SLAP_LONG long
2362 #endif /* HAVE_STRTOLL ... */
2370 struct berval *value,
2371 void *assertedValue )
2373 SLAP_LONG lValue, lAssertedValue;
2376 /* safe to assume integers are NUL terminated? */
2377 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2378 if( errno == ERANGE )
2380 return LDAP_CONSTRAINT_VIOLATION;
2383 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2385 if( errno == ERANGE )
2387 return LDAP_CONSTRAINT_VIOLATION;
2390 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2391 return LDAP_SUCCESS;
2400 struct berval *value,
2401 void *assertedValue )
2403 SLAP_LONG lValue, lAssertedValue;
2406 /* safe to assume integers are NUL terminated? */
2407 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2408 if( errno == ERANGE )
2410 return LDAP_CONSTRAINT_VIOLATION;
2413 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2415 if( errno == ERANGE )
2417 return LDAP_CONSTRAINT_VIOLATION;
2420 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2421 return LDAP_SUCCESS;
2425 serialNumberAndIssuerValidate(
2431 struct berval sn, i;
2433 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2436 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2438 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2439 /* Parse old format */
2440 i.bv_val = ber_bvchr( in, '$' );
2441 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2443 sn.bv_val = in->bv_val;
2444 sn.bv_len = i.bv_val - in->bv_val;
2447 i.bv_len = in->bv_len - (sn.bv_len + 1);
2449 /* eat leading zeros */
2450 for( n=0; n < (sn.bv_len-1); n++ ) {
2451 if( sn.bv_val[n] != '0' ) break;
2456 for( n=0; n < sn.bv_len; n++ ) {
2457 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2461 /* Parse GSER format */
2462 int havesn=0,haveissuer=0;
2463 struct berval x = *in;
2467 /* eat leading spaces */
2468 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2472 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2473 return LDAP_INVALID_SYNTAX;
2476 /* should be at issuer or serialNumber NamedValue */
2477 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2479 x.bv_val += STRLENOF("issuer");
2480 x.bv_len -= STRLENOF("issuer");
2482 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2483 x.bv_val++; x.bv_len--;
2485 /* eat leading spaces */
2486 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2490 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2491 x.bv_val++; x.bv_len--;
2493 i.bv_val = x.bv_val;
2496 for( ; i.bv_len < x.bv_len; ) {
2497 if ( i.bv_val[i.bv_len] != '"' ) {
2501 if ( i.bv_val[i.bv_len+1] == '"' ) {
2508 x.bv_val += i.bv_len+1;
2509 x.bv_len -= i.bv_len+1;
2511 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2512 return LDAP_INVALID_SYNTAX;
2517 } else if( strncasecmp( x.bv_val, "serialNumber",
2518 STRLENOF("serialNumber")) == 0 )
2520 /* parse serialNumber */
2522 x.bv_val += STRLENOF("serialNumber");
2523 x.bv_len -= STRLENOF("serialNumber");
2525 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2526 x.bv_val++; x.bv_len--;
2528 /* eat leading spaces */
2529 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2533 sn.bv_val = x.bv_val;
2536 if( sn.bv_val[0] == '-' ) {
2541 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2542 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2545 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2546 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2547 return LDAP_INVALID_SYNTAX;
2550 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2552 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2553 return LDAP_INVALID_SYNTAX;
2558 } else return LDAP_INVALID_SYNTAX;
2560 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2561 x.bv_val++; x.bv_len--;
2564 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2568 /* should be at remaining NamedValue */
2569 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2570 STRLENOF("issuer" )) == 0 ))
2573 x.bv_val += STRLENOF("issuer");
2574 x.bv_len -= STRLENOF("issuer");
2576 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2577 x.bv_val++; x.bv_len--;
2579 /* eat leading spaces */
2580 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2584 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2585 x.bv_val++; x.bv_len--;
2587 i.bv_val = x.bv_val;
2590 for( ; i.bv_len < x.bv_len; ) {
2591 if ( i.bv_val[i.bv_len] != '"' ) {
2595 if ( i.bv_val[i.bv_len+1] == '"' ) {
2602 x.bv_val += i.bv_len+1;
2603 x.bv_len -= i.bv_len+1;
2605 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2606 STRLENOF("serialNumber")) == 0 ))
2608 /* parse serialNumber */
2610 x.bv_val += STRLENOF("serialNumber");
2611 x.bv_len -= STRLENOF("serialNumber");
2613 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2614 x.bv_val++; x.bv_len--;
2616 /* eat leading spaces */
2617 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2621 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2622 x.bv_val++; x.bv_len--;
2624 sn.bv_val = x.bv_val;
2627 if( sn.bv_val[0] == '-' ) {
2632 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2633 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2636 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2637 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2638 return LDAP_INVALID_SYNTAX;
2641 x.bv_val += sn.bv_len;
2642 x.bv_len -= sn.bv_len;
2644 } else return LDAP_INVALID_SYNTAX;
2646 /* eat trailing spaces */
2647 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2651 /* should have no characters left... */
2652 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2655 /* validate DN -- doesn't handle double dquote */
2656 rc = dnValidate( NULL, &i );
2657 if( rc ) return LDAP_INVALID_SYNTAX;
2659 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2661 return LDAP_SUCCESS;
2665 serialNumberAndIssuerPretty(
2673 struct berval sn, i, ni;
2675 assert( in != NULL );
2676 assert( out != NULL );
2678 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2681 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2683 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2684 /* Parse old format */
2685 i.bv_val = ber_bvchr( in, '$' );
2686 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2688 sn.bv_val = in->bv_val;
2689 sn.bv_len = i.bv_val - in->bv_val;
2692 i.bv_len = in->bv_len - (sn.bv_len + 1);
2694 /* eat leading zeros */
2695 for( n=0; n < (sn.bv_len-1); n++ ) {
2696 if( sn.bv_val[n] != '0' ) break;
2701 for( n=0; n < sn.bv_len; n++ ) {
2702 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2706 /* Parse GSER format */
2707 int havesn=0,haveissuer=0;
2708 struct berval x = *in;
2712 /* eat leading spaces */
2713 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2717 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2718 return LDAP_INVALID_SYNTAX;
2721 /* should be at issuer or serialNumber NamedValue */
2722 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2724 x.bv_val += STRLENOF("issuer");
2725 x.bv_len -= STRLENOF("issuer");
2727 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2728 x.bv_val++; x.bv_len--;
2730 /* eat leading spaces */
2731 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2735 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2736 x.bv_val++; x.bv_len--;
2738 i.bv_val = x.bv_val;
2741 for( ; i.bv_len < x.bv_len; ) {
2742 if ( i.bv_val[i.bv_len] != '"' ) {
2746 if ( i.bv_val[i.bv_len+1] == '"' ) {
2753 x.bv_val += i.bv_len+1;
2754 x.bv_len -= i.bv_len+1;
2756 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2757 return LDAP_INVALID_SYNTAX;
2762 } else if( strncasecmp( x.bv_val, "serialNumber",
2763 STRLENOF("serialNumber")) == 0 )
2765 /* parse serialNumber */
2767 x.bv_val += STRLENOF("serialNumber");
2768 x.bv_len -= STRLENOF("serialNumber");
2770 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2771 x.bv_val++; x.bv_len--;
2773 /* eat leading spaces */
2774 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2778 sn.bv_val = x.bv_val;
2781 if( sn.bv_val[0] == '-' ) {
2786 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2787 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2790 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2791 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2792 return LDAP_INVALID_SYNTAX;
2795 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2797 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2798 return LDAP_INVALID_SYNTAX;
2803 } else return LDAP_INVALID_SYNTAX;
2805 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2806 x.bv_val++; x.bv_len--;
2809 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2813 /* should be at remaining NamedValue */
2814 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2815 STRLENOF("issuer" )) == 0 ))
2818 x.bv_val += STRLENOF("issuer");
2819 x.bv_len -= STRLENOF("issuer");
2821 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2822 x.bv_val++; x.bv_len--;
2824 /* eat leading spaces */
2825 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2829 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2830 x.bv_val++; x.bv_len--;
2832 i.bv_val = x.bv_val;
2835 for( ; i.bv_len < x.bv_len; ) {
2836 if ( i.bv_val[i.bv_len] != '"' ) {
2840 if ( i.bv_val[i.bv_len+1] == '"' ) {
2847 x.bv_val += i.bv_len+1;
2848 x.bv_len -= i.bv_len+1;
2850 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2851 STRLENOF("serialNumber")) == 0 ))
2853 /* parse serialNumber */
2855 x.bv_val += STRLENOF("serialNumber");
2856 x.bv_len -= STRLENOF("serialNumber");
2858 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2859 x.bv_val++; x.bv_len--;
2861 /* eat leading spaces */
2862 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2866 sn.bv_val = x.bv_val;
2869 if( sn.bv_val[0] == '-' ) {
2874 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2875 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2878 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2879 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2880 return LDAP_INVALID_SYNTAX;
2883 x.bv_val += sn.bv_len;
2884 x.bv_len -= sn.bv_len;
2886 } else return LDAP_INVALID_SYNTAX;
2888 /* eat trailing spaces */
2889 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2893 /* should have no characters left... */
2894 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2896 ber_dupbv_x( &ni, &i, ctx );
2899 /* need to handle double dquotes here */
2902 rc = dnPretty( syntax, &i, &ni, ctx );
2904 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2905 slap_sl_free( i.bv_val, ctx );
2908 if( rc ) return LDAP_INVALID_SYNTAX;
2910 /* make room from sn + "$" */
2911 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2912 + sn.bv_len + ni.bv_len;
2913 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2915 if( out->bv_val == NULL ) {
2917 slap_sl_free( ni.bv_val, ctx );
2922 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2923 STRLENOF("{ serialNumber "));
2924 n = STRLENOF("{ serialNumber ");
2926 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2929 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2930 n += STRLENOF(", issuer \"");
2932 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2935 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2936 n += STRLENOF("\" }");
2938 out->bv_val[n] = '\0';
2940 assert( n == out->bv_len );
2942 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2943 out->bv_val, 0, 0 );
2945 slap_sl_free( ni.bv_val, ctx );
2947 return LDAP_SUCCESS;
2951 * This routine is called by certificateExactNormalize when
2952 * certificateExactNormalize receives a search string instead of
2953 * a certificate. This routine checks if the search value is valid
2954 * and then returns the normalized value
2957 serialNumberAndIssuerNormalize(
2967 struct berval sn, i, ni;
2969 assert( in != NULL );
2970 assert( out != NULL );
2972 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2975 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2977 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2978 /* Parse old format */
2979 i.bv_val = ber_bvchr( in, '$' );
2980 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2982 sn.bv_val = in->bv_val;
2983 sn.bv_len = i.bv_val - in->bv_val;
2986 i.bv_len = in->bv_len - (sn.bv_len + 1);
2988 /* eat leading zeros */
2989 for( n=0; n < (sn.bv_len-1); n++ ) {
2990 if( sn.bv_val[n] != '0' ) break;
2995 for( n=0; n < sn.bv_len; n++ ) {
2996 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3000 /* Parse GSER format */
3001 int havesn=0,haveissuer=0;
3002 struct berval x = *in;
3006 /* eat leading spaces */
3007 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3011 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3012 return LDAP_INVALID_SYNTAX;
3015 /* should be at issuer or serialNumber NamedValue */
3016 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3018 x.bv_val += STRLENOF("issuer");
3019 x.bv_len -= STRLENOF("issuer");
3021 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3022 x.bv_val++; x.bv_len--;
3024 /* eat leading spaces */
3025 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3029 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3030 x.bv_val++; x.bv_len--;
3032 i.bv_val = x.bv_val;
3035 for( ; i.bv_len < x.bv_len; ) {
3036 if ( i.bv_val[i.bv_len] != '"' ) {
3040 if ( i.bv_val[i.bv_len+1] == '"' ) {
3047 x.bv_val += i.bv_len+1;
3048 x.bv_len -= i.bv_len+1;
3050 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3051 return LDAP_INVALID_SYNTAX;
3056 } else if( strncasecmp( x.bv_val, "serialNumber",
3057 STRLENOF("serialNumber")) == 0 )
3059 /* parse serialNumber */
3061 x.bv_val += STRLENOF("serialNumber");
3062 x.bv_len -= STRLENOF("serialNumber");
3064 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3065 x.bv_val++; x.bv_len--;
3067 /* eat leading spaces */
3068 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3072 sn.bv_val = x.bv_val;
3075 if( sn.bv_val[0] == '-' ) {
3080 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3081 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3084 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3085 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3086 return LDAP_INVALID_SYNTAX;
3089 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3091 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3092 return LDAP_INVALID_SYNTAX;
3097 } else return LDAP_INVALID_SYNTAX;
3099 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3100 x.bv_val++; x.bv_len--;
3103 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3107 /* should be at remaining NamedValue */
3108 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3109 STRLENOF("issuer" )) == 0 ))
3112 x.bv_val += STRLENOF("issuer");
3113 x.bv_len -= STRLENOF("issuer");
3115 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3116 x.bv_val++; x.bv_len--;
3118 /* eat leading spaces */
3119 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3123 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3124 x.bv_val++; x.bv_len--;
3126 i.bv_val = x.bv_val;
3129 for( ; i.bv_len < x.bv_len; ) {
3130 if ( i.bv_val[i.bv_len] != '"' ) {
3134 if ( i.bv_val[i.bv_len+1] == '"' ) {
3141 x.bv_val += i.bv_len+1;
3142 x.bv_len -= i.bv_len+1;
3144 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3145 STRLENOF("serialNumber")) == 0 ))
3147 /* parse serialNumber */
3149 x.bv_val += STRLENOF("serialNumber");
3150 x.bv_len -= STRLENOF("serialNumber");
3152 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3153 x.bv_val++; x.bv_len--;
3155 /* eat leading spaces */
3156 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3160 sn.bv_val = x.bv_val;
3163 if( sn.bv_val[0] == '-' ) {
3168 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3169 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3172 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3173 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3174 return LDAP_INVALID_SYNTAX;
3177 x.bv_val += sn.bv_len;
3178 x.bv_len -= sn.bv_len;
3180 } else return LDAP_INVALID_SYNTAX;
3182 /* eat trailing spaces */
3183 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3187 /* should have no characters left... */
3188 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3190 ber_dupbv_x( &ni, &i, ctx );
3193 /* need to handle double dquotes here */
3196 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3198 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3199 slap_sl_free( i.bv_val, ctx );
3202 if( rc ) return LDAP_INVALID_SYNTAX;
3204 /* make room from sn + "$" */
3205 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3206 + sn.bv_len + ni.bv_len;
3207 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3209 if( out->bv_val == NULL ) {
3211 slap_sl_free( ni.bv_val, ctx );
3216 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3217 STRLENOF( "{ serialNumber " ));
3218 n = STRLENOF( "{ serialNumber " );
3220 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3223 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3224 n += STRLENOF( ", issuer \"" );
3226 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3229 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3230 n += STRLENOF( "\" }" );
3232 out->bv_val[n] = '\0';
3234 assert( n == out->bv_len );
3236 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3237 out->bv_val, 0, 0 );
3239 slap_sl_free( ni.bv_val, ctx );
3241 return LDAP_SUCCESS;
3245 certificateExactNormalize(
3250 struct berval *normalized,
3253 BerElementBuffer berbuf;
3254 BerElement *ber = (BerElement *)&berbuf;
3259 ber_len_t seriallen;
3260 struct berval issuer_dn = BER_BVNULL, bvdn;
3262 int rc = LDAP_INVALID_SYNTAX;
3264 if( BER_BVISEMPTY( val ) ) goto done;
3266 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3267 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3270 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3272 ber_init2( ber, val, LBER_USE_DER );
3273 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3274 tag = ber_skip_tag( ber, &len ); /* Sequence */
3275 tag = ber_skip_tag( ber, &len ); /* Optional version? */
3277 tag = ber_get_int( ber, &i ); /* version */
3278 ber_get_int( ber, &i ); /* serial */
3280 seriallen = snprintf( serial, sizeof(serial), "%d", i );
3281 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3282 ber_skip_data( ber, len );
3283 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3284 len = ber_ptrlen( ber );
3285 bvdn.bv_val = val->bv_val + len;
3286 bvdn.bv_len = val->bv_len - len;
3288 rc = dnX509normalize( &bvdn, &issuer_dn );
3289 if( rc != LDAP_SUCCESS ) goto done;
3291 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3292 + seriallen + issuer_dn.bv_len;
3293 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3295 p = (unsigned char *)normalized->bv_val;
3297 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3298 p += STRLENOF( "{ serialNumber " );
3300 AC_MEMCPY(p, serial, seriallen);
3303 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3304 p += STRLENOF( ", issuer \"" );
3306 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3307 p += issuer_dn.bv_len;
3309 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3310 p += STRLENOF( "\" }" );
3314 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3315 normalized->bv_val, NULL, NULL );
3320 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3326 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3327 /* slight optimization - does not need the start parameter */
3328 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3333 check_time_syntax (struct berval *val,
3336 struct berval *fraction)
3339 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3340 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3341 * GeneralizedTime supports leap seconds, UTCTime does not.
3343 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3344 static const int mdays[2][12] = {
3345 /* non-leap years */
3346 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3348 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3351 int part, c, c1, c2, tzoffset, leapyear = 0;
3354 e = p + val->bv_len;
3356 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3357 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3359 for (part = start; part < 7 && p < e; part++) {
3361 if (!ASCII_DIGIT(c1)) {
3366 return LDAP_INVALID_SYNTAX;
3369 if (!ASCII_DIGIT(c)) {
3370 return LDAP_INVALID_SYNTAX;
3372 c += c1 * 10 - '0' * 11;
3373 if ((part | 1) == 3) {
3376 return LDAP_INVALID_SYNTAX;
3379 if (c >= ceiling[part]) {
3380 if (! (c == 60 && part == 6 && start == 0))
3381 return LDAP_INVALID_SYNTAX;
3385 if (part < 5 + start) {
3386 return LDAP_INVALID_SYNTAX;
3388 for (; part < 9; part++) {
3392 /* leapyear check for the Gregorian calendar (year>1581) */
3393 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3397 if (parts[3] >= mdays[leapyear][parts[2]]) {
3398 return LDAP_INVALID_SYNTAX;
3402 fraction->bv_val = p;
3403 fraction->bv_len = 0;
3404 if (p < e && (*p == '.' || *p == ',')) {
3406 while (++p < e && ASCII_DIGIT(*p)) {
3409 if (p - fraction->bv_val == 1) {
3410 return LDAP_INVALID_SYNTAX;
3412 for (end_num = p; end_num[-1] == '0'; --end_num) {
3415 c = end_num - fraction->bv_val;
3416 if (c != 1) fraction->bv_len = c;
3422 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3428 return LDAP_INVALID_SYNTAX;
3434 for (part = 7; part < 9 && p < e; part++) {
3436 if (!ASCII_DIGIT(c1)) {
3441 return LDAP_INVALID_SYNTAX;
3444 if (!ASCII_DIGIT(c2)) {
3445 return LDAP_INVALID_SYNTAX;
3447 parts[part] = c1 * 10 + c2 - '0' * 11;
3448 if (parts[part] >= ceiling[part]) {
3449 return LDAP_INVALID_SYNTAX;
3452 if (part < 8 + start) {
3453 return LDAP_INVALID_SYNTAX;
3456 if (tzoffset == '-') {
3457 /* negative offset to UTC, ie west of Greenwich */
3458 parts[4] += parts[7];
3459 parts[5] += parts[8];
3460 /* offset is just hhmm, no seconds */
3461 for (part = 6; --part >= 0; ) {
3465 c = mdays[leapyear][parts[2]];
3467 if (parts[part] >= c) {
3469 return LDAP_INVALID_SYNTAX;
3474 } else if (part != 5) {
3479 /* positive offset to UTC, ie east of Greenwich */
3480 parts[4] -= parts[7];
3481 parts[5] -= parts[8];
3482 for (part = 6; --part >= 0; ) {
3483 if (parts[part] < 0) {
3485 return LDAP_INVALID_SYNTAX;
3490 /* make first arg to % non-negative */
3491 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3496 } else if (part != 5) {
3503 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3506 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3513 struct berval *normalized )
3517 rc = check_time_syntax(val, 1, parts, NULL);
3518 if (rc != LDAP_SUCCESS) {
3522 normalized->bv_val = ch_malloc( 14 );
3523 if ( normalized->bv_val == NULL ) {
3524 return LBER_ERROR_MEMORY;
3527 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3528 parts[1], parts[2] + 1, parts[3] + 1,
3529 parts[4], parts[5], parts[6] );
3530 normalized->bv_len = 13;
3532 return LDAP_SUCCESS;
3542 return check_time_syntax(in, 1, parts, NULL);
3545 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3548 generalizedTimeValidate(
3553 struct berval fraction;
3554 return check_time_syntax(in, 0, parts, &fraction);
3558 generalizedTimeNormalize(
3563 struct berval *normalized,
3568 struct berval fraction;
3570 rc = check_time_syntax(val, 0, parts, &fraction);
3571 if (rc != LDAP_SUCCESS) {
3575 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3576 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3577 if ( BER_BVISNULL( normalized ) ) {
3578 return LBER_ERROR_MEMORY;
3581 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3582 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3583 parts[4], parts[5], parts[6] );
3584 if ( !BER_BVISEMPTY( &fraction ) ) {
3585 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3586 fraction.bv_val, fraction.bv_len );
3587 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3589 strcpy( normalized->bv_val + len-1, "Z" );
3590 normalized->bv_len = len;
3592 return LDAP_SUCCESS;
3596 generalizedTimeOrderingMatch(
3601 struct berval *value,
3602 void *assertedValue )
3604 struct berval *asserted = (struct berval *) assertedValue;
3605 ber_len_t v_len = value->bv_len;
3606 ber_len_t av_len = asserted->bv_len;
3608 /* ignore trailing 'Z' when comparing */
3609 int match = memcmp( value->bv_val, asserted->bv_val,
3610 (v_len < av_len ? v_len : av_len) - 1 );
3611 if ( match == 0 ) match = v_len - av_len;
3614 return LDAP_SUCCESS;
3617 /* Index generation function */
3618 int generalizedTimeIndexer(
3623 struct berval *prefix,
3631 BerValue bvtmp; /* 40 bit index */
3633 struct lutil_timet tt;
3635 bvtmp.bv_len = sizeof(tmp);
3637 for( i=0; values[i].bv_val != NULL; i++ ) {
3638 /* just count them */
3641 /* we should have at least one value at this point */
3644 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3646 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3647 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3648 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3649 /* Use 40 bits of time for key */
3650 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3651 lutil_tm2time( &tm, &tt );
3652 tmp[0] = tt.tt_gsec & 0xff;
3653 tmp[4] = tt.tt_sec & 0xff;
3655 tmp[3] = tt.tt_sec & 0xff;
3657 tmp[2] = tt.tt_sec & 0xff;
3659 tmp[1] = tt.tt_sec & 0xff;
3661 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3665 keys[j].bv_val = NULL;
3670 return LDAP_SUCCESS;
3673 /* Index generation function */
3674 int generalizedTimeFilter(
3679 struct berval *prefix,
3680 void * assertedValue,
3686 BerValue bvtmp; /* 40 bit index */
3687 BerValue *value = (BerValue *) assertedValue;
3689 struct lutil_timet tt;
3691 bvtmp.bv_len = sizeof(tmp);
3693 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3694 /* Use 40 bits of time for key */
3695 if ( value->bv_val && value->bv_len >= 10 &&
3696 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3698 lutil_tm2time( &tm, &tt );
3699 tmp[0] = tt.tt_gsec & 0xff;
3700 tmp[4] = tt.tt_sec & 0xff;
3702 tmp[3] = tt.tt_sec & 0xff;
3704 tmp[2] = tt.tt_sec & 0xff;
3706 tmp[1] = tt.tt_sec & 0xff;
3708 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3709 ber_dupbv_x(keys, &bvtmp, ctx );
3710 keys[1].bv_val = NULL;
3718 return LDAP_SUCCESS;
3722 deliveryMethodValidate(
3724 struct berval *val )
3727 #define LENOF(s) (sizeof(s)-1)
3728 struct berval tmp = *val;
3730 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3731 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3732 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3735 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3737 switch( tmp.bv_val[0] ) {
3740 if(( tmp.bv_len >= LENOF("any") ) &&
3741 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3743 tmp.bv_len -= LENOF("any");
3744 tmp.bv_val += LENOF("any");
3747 return LDAP_INVALID_SYNTAX;
3751 if(( tmp.bv_len >= LENOF("mhs") ) &&
3752 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3754 tmp.bv_len -= LENOF("mhs");
3755 tmp.bv_val += LENOF("mhs");
3758 return LDAP_INVALID_SYNTAX;
3762 if(( tmp.bv_len >= LENOF("physical") ) &&
3763 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3765 tmp.bv_len -= LENOF("physical");
3766 tmp.bv_val += LENOF("physical");
3769 return LDAP_INVALID_SYNTAX;
3772 case 'T': /* telex or teletex or telephone */
3773 if(( tmp.bv_len >= LENOF("telex") ) &&
3774 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3776 tmp.bv_len -= LENOF("telex");
3777 tmp.bv_val += LENOF("telex");
3780 if(( tmp.bv_len >= LENOF("teletex") ) &&
3781 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3783 tmp.bv_len -= LENOF("teletex");
3784 tmp.bv_val += LENOF("teletex");
3787 if(( tmp.bv_len >= LENOF("telephone") ) &&
3788 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3790 tmp.bv_len -= LENOF("telephone");
3791 tmp.bv_val += LENOF("telephone");
3794 return LDAP_INVALID_SYNTAX;
3797 case 'G': /* g3fax or g4fax */
3798 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3799 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3800 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3802 tmp.bv_len -= LENOF("g3fax");
3803 tmp.bv_val += LENOF("g3fax");
3806 return LDAP_INVALID_SYNTAX;
3810 if(( tmp.bv_len >= LENOF("ia5") ) &&
3811 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3813 tmp.bv_len -= LENOF("ia5");
3814 tmp.bv_val += LENOF("ia5");
3817 return LDAP_INVALID_SYNTAX;
3821 if(( tmp.bv_len >= LENOF("videotex") ) &&
3822 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3824 tmp.bv_len -= LENOF("videotex");
3825 tmp.bv_val += LENOF("videotex");
3828 return LDAP_INVALID_SYNTAX;
3831 return LDAP_INVALID_SYNTAX;
3834 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3836 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3840 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3844 return LDAP_INVALID_SYNTAX;
3846 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3855 nisNetgroupTripleValidate(
3857 struct berval *val )
3862 if ( BER_BVISEMPTY( val ) ) {
3863 return LDAP_INVALID_SYNTAX;
3866 p = (char *)val->bv_val;
3867 e = p + val->bv_len;
3869 if ( *p != '(' /*')'*/ ) {
3870 return LDAP_INVALID_SYNTAX;
3873 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3877 return LDAP_INVALID_SYNTAX;
3880 } else if ( !AD_CHAR( *p ) ) {
3881 return LDAP_INVALID_SYNTAX;
3885 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3886 return LDAP_INVALID_SYNTAX;
3892 return LDAP_INVALID_SYNTAX;
3895 return LDAP_SUCCESS;
3899 bootParameterValidate(
3901 struct berval *val )
3905 if ( BER_BVISEMPTY( val ) ) {
3906 return LDAP_INVALID_SYNTAX;
3909 p = (char *)val->bv_val;
3910 e = p + val->bv_len;
3913 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3914 if ( !AD_CHAR( *p ) ) {
3915 return LDAP_INVALID_SYNTAX;
3920 return LDAP_INVALID_SYNTAX;
3924 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3925 if ( !AD_CHAR( *p ) ) {
3926 return LDAP_INVALID_SYNTAX;
3931 return LDAP_INVALID_SYNTAX;
3935 for ( p++; p < e; p++ ) {
3936 if ( !SLAP_PRINTABLE( *p ) ) {
3937 return LDAP_INVALID_SYNTAX;
3941 return LDAP_SUCCESS;
3945 firstComponentNormalize(
3950 struct berval *normalized,
3957 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3958 ber_dupbv_x( normalized, val, ctx );
3959 return LDAP_SUCCESS;
3962 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3964 if( val->bv_val[0] != '(' /*')'*/ &&
3965 val->bv_val[0] != '{' /*'}'*/ )
3967 return LDAP_INVALID_SYNTAX;
3970 /* trim leading white space */
3972 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3978 /* grab next word */
3979 comp.bv_val = &val->bv_val[len];
3980 len = val->bv_len - len;
3981 for( comp.bv_len = 0;
3982 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3988 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3989 rc = numericoidValidate( NULL, &comp );
3990 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3991 rc = integerValidate( NULL, &comp );
3993 rc = LDAP_INVALID_SYNTAX;
3997 if( rc == LDAP_SUCCESS ) {
3998 ber_dupbv_x( normalized, &comp, ctx );
4005 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4006 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4008 static slap_syntax_defs_rec syntax_defs[] = {
4009 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4010 X_BINARY X_NOT_H_R ")",
4011 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
4012 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4014 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4016 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4018 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4019 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4021 SLAP_SYNTAX_BER, berValidate, NULL},
4022 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4023 0, bitStringValidate, NULL },
4024 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4025 0, booleanValidate, NULL},
4026 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4027 X_BINARY X_NOT_H_R ")",
4028 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
4029 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4030 X_BINARY X_NOT_H_R ")",
4031 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4032 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4033 X_BINARY X_NOT_H_R ")",
4034 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4035 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4036 0, countryStringValidate, NULL},
4037 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4038 0, dnValidate, dnPretty},
4039 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4040 0, rdnValidate, rdnPretty},
4041 #ifdef LDAP_COMP_MATCH
4042 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4043 0, allComponentsValidate, NULL},
4044 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4045 0, componentFilterValidate, NULL},
4047 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4049 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4050 0, deliveryMethodValidate, NULL},
4051 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4052 0, UTF8StringValidate, NULL},
4053 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4055 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4057 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4059 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4061 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4063 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4064 0, printablesStringValidate, NULL},
4065 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4066 SLAP_SYNTAX_BLOB, NULL, NULL},
4067 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4068 0, generalizedTimeValidate, NULL},
4069 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4071 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4072 0, IA5StringValidate, NULL},
4073 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4074 0, integerValidate, NULL},
4075 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4076 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4077 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4079 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4081 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4083 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4085 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4087 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4088 0, nameUIDValidate, nameUIDPretty },
4089 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4091 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4092 0, numericStringValidate, NULL},
4093 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4095 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4096 0, numericoidValidate, NULL},
4097 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4098 0, IA5StringValidate, NULL},
4099 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4100 0, blobValidate, NULL},
4101 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4102 0, UTF8StringValidate, NULL},
4103 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4105 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4107 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4108 0, printableStringValidate, NULL},
4109 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4110 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4111 0, subtreeSpecificationValidate, NULL},
4112 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4113 X_BINARY X_NOT_H_R ")",
4114 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4115 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4116 0, printableStringValidate, NULL},
4117 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4119 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4120 0, printablesStringValidate, NULL},
4121 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4122 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4123 0, utcTimeValidate, NULL},
4125 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4127 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4129 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4131 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4133 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4136 /* RFC 2307 NIS Syntaxes */
4137 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4138 0, nisNetgroupTripleValidate, NULL},
4139 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4140 0, bootParameterValidate, NULL},
4142 /* draft-zeilenga-ldap-x509 */
4143 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4145 serialNumberAndIssuerValidate,
4146 serialNumberAndIssuerPretty},
4147 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4148 SLAP_SYNTAX_HIDE, NULL, NULL},
4149 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4150 SLAP_SYNTAX_HIDE, NULL, NULL},
4151 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4152 SLAP_SYNTAX_HIDE, NULL, NULL},
4153 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4154 SLAP_SYNTAX_HIDE, NULL, NULL},
4155 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4156 SLAP_SYNTAX_HIDE, NULL, NULL},
4157 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4158 SLAP_SYNTAX_HIDE, NULL, NULL},
4160 #ifdef SLAPD_AUTHPASSWD
4161 /* needs updating */
4162 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4163 SLAP_SYNTAX_HIDE, NULL, NULL},
4166 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4167 0, UUIDValidate, UUIDPretty},
4169 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4170 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4172 /* OpenLDAP Void Syntax */
4173 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4174 SLAP_SYNTAX_HIDE, inValidate, NULL},
4176 /* FIXME: OID is unused, but not registered yet */
4177 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4178 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4180 {NULL, 0, NULL, NULL}
4183 char *certificateExactMatchSyntaxes[] = {
4184 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4187 #ifdef LDAP_COMP_MATCH
4188 char *componentFilterMatchSyntaxes[] = {
4189 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4193 char *directoryStringSyntaxes[] = {
4194 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4197 char *integerFirstComponentMatchSyntaxes[] = {
4198 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4199 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4202 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4203 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4204 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4205 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4206 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4207 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4208 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4209 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4210 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4215 * Other matching rules in X.520 that we do not use (yet):
4217 * 2.5.13.25 uTCTimeMatch
4218 * 2.5.13.26 uTCTimeOrderingMatch
4219 * 2.5.13.31* directoryStringFirstComponentMatch
4220 * 2.5.13.32* wordMatch
4221 * 2.5.13.33* keywordMatch
4222 * 2.5.13.36+ certificatePairExactMatch
4223 * 2.5.13.37+ certificatePairMatch
4224 * 2.5.13.38+ certificateListExactMatch
4225 * 2.5.13.39+ certificateListMatch
4226 * 2.5.13.40+ algorithmIdentifierMatch
4227 * 2.5.13.41* storedPrefixMatch
4228 * 2.5.13.42 attributeCertificateMatch
4229 * 2.5.13.43 readerAndKeyIDMatch
4230 * 2.5.13.44 attributeIntegrityMatch
4232 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4233 * (+) described in draft-zeilenga-ldap-x509
4235 static slap_mrule_defs_rec mrule_defs[] = {
4237 * EQUALITY matching rules must be listed after associated APPROX
4238 * matching rules. So, we list all APPROX matching rules first.
4240 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4241 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4242 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4243 NULL, NULL, directoryStringApproxMatch,
4244 directoryStringApproxIndexer, directoryStringApproxFilter,
4247 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4248 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4249 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4250 NULL, NULL, IA5StringApproxMatch,
4251 IA5StringApproxIndexer, IA5StringApproxFilter,
4255 * Other matching rules
4258 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4259 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4260 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4261 NULL, NULL, octetStringMatch,
4262 octetStringIndexer, octetStringFilter,
4265 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4267 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4268 NULL, dnNormalize, dnMatch,
4269 octetStringIndexer, octetStringFilter,
4272 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4273 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4274 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4275 NULL, dnNormalize, dnRelativeMatch,
4279 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4280 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4281 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4282 NULL, dnNormalize, dnRelativeMatch,
4286 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4287 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4288 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4289 NULL, dnNormalize, dnRelativeMatch,
4293 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4294 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4295 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4296 NULL, dnNormalize, dnRelativeMatch,
4300 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4301 "SYNTAX 1.2.36.79672281.1.5.0 )",
4302 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4303 NULL, rdnNormalize, rdnMatch,
4304 octetStringIndexer, octetStringFilter,
4307 #ifdef LDAP_COMP_MATCH
4308 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4309 "SYNTAX 1.2.36.79672281.1.5.2 )",
4310 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4311 NULL, NULL , componentFilterMatch,
4312 octetStringIndexer, octetStringFilter,
4315 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4316 "SYNTAX 1.2.36.79672281.1.5.3 )",
4317 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4318 NULL, NULL , allComponentsMatch,
4319 octetStringIndexer, octetStringFilter,
4322 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4323 "SYNTAX 1.2.36.79672281.1.5.3 )",
4324 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4325 NULL, NULL , directoryComponentsMatch,
4326 octetStringIndexer, octetStringFilter,
4330 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4332 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4333 NULL, UTF8StringNormalize, octetStringMatch,
4334 octetStringIndexer, octetStringFilter,
4335 directoryStringApproxMatchOID },
4337 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4338 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4339 SLAP_MR_ORDERING, directoryStringSyntaxes,
4340 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4342 "caseIgnoreMatch" },
4344 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4345 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4346 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4347 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4348 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4349 "caseIgnoreMatch" },
4351 {"( 2.5.13.5 NAME 'caseExactMatch' "
4352 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4353 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4354 NULL, UTF8StringNormalize, octetStringMatch,
4355 octetStringIndexer, octetStringFilter,
4356 directoryStringApproxMatchOID },
4358 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4359 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4360 SLAP_MR_ORDERING, directoryStringSyntaxes,
4361 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4365 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4366 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4367 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4368 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4369 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4372 {"( 2.5.13.8 NAME 'numericStringMatch' "
4373 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4374 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4375 NULL, numericStringNormalize, octetStringMatch,
4376 octetStringIndexer, octetStringFilter,
4379 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4380 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4381 SLAP_MR_ORDERING, NULL,
4382 NULL, numericStringNormalize, octetStringOrderingMatch,
4384 "numericStringMatch" },
4386 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4387 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4388 SLAP_MR_SUBSTR, NULL,
4389 NULL, numericStringNormalize, octetStringSubstringsMatch,
4390 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4391 "numericStringMatch" },
4393 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4395 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4396 NULL, NULL, NULL, NULL, NULL, NULL },
4398 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4400 SLAP_MR_SUBSTR, NULL,
4401 NULL, NULL, NULL, NULL, NULL,
4402 "caseIgnoreListMatch" },
4404 {"( 2.5.13.13 NAME 'booleanMatch' "
4405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4406 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4407 NULL, NULL, booleanMatch,
4408 octetStringIndexer, octetStringFilter,
4411 {"( 2.5.13.14 NAME 'integerMatch' "
4412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4413 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4414 NULL, NULL, integerMatch,
4415 octetStringIndexer, octetStringFilter,
4418 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4420 SLAP_MR_ORDERING, NULL,
4421 NULL, NULL, integerMatch,
4425 {"( 2.5.13.16 NAME 'bitStringMatch' "
4426 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4427 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4428 NULL, NULL, octetStringMatch,
4429 octetStringIndexer, octetStringFilter,
4432 {"( 2.5.13.17 NAME 'octetStringMatch' "
4433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4434 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4435 NULL, NULL, octetStringMatch,
4436 octetStringIndexer, octetStringFilter,
4439 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4441 SLAP_MR_ORDERING, NULL,
4442 NULL, NULL, octetStringOrderingMatch,
4444 "octetStringMatch" },
4446 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4447 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4448 SLAP_MR_SUBSTR, NULL,
4449 NULL, NULL, octetStringSubstringsMatch,
4450 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4451 "octetStringMatch" },
4453 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4455 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4457 telephoneNumberNormalize, octetStringMatch,
4458 octetStringIndexer, octetStringFilter,
4461 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4463 SLAP_MR_SUBSTR, NULL,
4464 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4465 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4466 "telephoneNumberMatch" },
4468 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4470 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4471 NULL, NULL, NULL, NULL, NULL, NULL },
4473 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4475 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4476 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4477 uniqueMemberIndexer, uniqueMemberFilter,
4480 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4481 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4482 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4483 NULL, NULL, NULL, NULL, NULL, NULL },
4485 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4487 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4488 NULL, generalizedTimeNormalize, octetStringMatch,
4489 generalizedTimeIndexer, generalizedTimeFilter,
4492 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4494 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4495 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4497 "generalizedTimeMatch" },
4499 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4500 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4501 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4502 integerFirstComponentMatchSyntaxes,
4503 NULL, firstComponentNormalize, integerMatch,
4504 octetStringIndexer, octetStringFilter,
4507 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4509 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4510 objectIdentifierFirstComponentMatchSyntaxes,
4511 NULL, firstComponentNormalize, octetStringMatch,
4512 octetStringIndexer, octetStringFilter,
4515 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4516 "SYNTAX 1.3.6.1.1.15.1 )",
4517 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4519 NULL, certificateExactNormalize, octetStringMatch,
4520 octetStringIndexer, octetStringFilter,
4522 NULL, NULL, NULL, NULL, NULL,
4526 {"( 2.5.13.35 NAME 'certificateMatch' "
4527 "SYNTAX 1.3.6.1.1.15.2 )",
4528 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4529 NULL, NULL, NULL, NULL, NULL,
4532 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4534 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4535 NULL, IA5StringNormalize, octetStringMatch,
4536 octetStringIndexer, octetStringFilter,
4537 IA5StringApproxMatchOID },
4539 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4541 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4542 NULL, IA5StringNormalize, octetStringMatch,
4543 octetStringIndexer, octetStringFilter,
4544 IA5StringApproxMatchOID },
4546 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4548 SLAP_MR_SUBSTR, NULL,
4549 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4550 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4551 "caseIgnoreIA5Match" },
4553 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4555 SLAP_MR_SUBSTR, NULL,
4556 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4557 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4558 "caseExactIA5Match" },
4560 #ifdef SLAPD_AUTHPASSWD
4561 /* needs updating */
4562 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4563 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4564 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4565 NULL, NULL, authPasswordMatch,
4570 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4571 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4573 NULL, NULL, integerBitAndMatch,
4577 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4578 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4580 NULL, NULL, integerBitOrMatch,
4584 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4585 "SYNTAX 1.3.6.1.1.16.1 )",
4586 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4587 NULL, UUIDNormalize, octetStringMatch,
4588 octetStringIndexer, octetStringFilter,
4591 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4592 "SYNTAX 1.3.6.1.1.16.1 )",
4593 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4594 NULL, UUIDNormalize, octetStringOrderingMatch,
4595 octetStringIndexer, octetStringFilter,
4598 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4599 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4600 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4601 NULL, NULL, csnMatch,
4602 csnIndexer, csnFilter,
4605 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4606 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4607 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4608 NULL, NULL, csnOrderingMatch,
4612 /* FIXME: OID is unused, but not registered yet */
4613 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4614 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4615 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4616 NULL, authzNormalize, authzMatch,
4620 {NULL, SLAP_MR_NONE, NULL,
4621 NULL, NULL, NULL, NULL, NULL,
4626 slap_schema_init( void )
4631 /* we should only be called once (from main) */
4632 assert( schema_init_done == 0 );
4634 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4635 res = register_syntax( &syntax_defs[i] );
4638 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4639 syntax_defs[i].sd_desc );
4644 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4645 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4646 mrule_defs[i].mrd_compat_syntaxes == NULL )
4649 "slap_schema_init: Ignoring unusable matching rule %s\n",
4650 mrule_defs[i].mrd_desc );
4654 res = register_matching_rule( &mrule_defs[i] );
4658 "slap_schema_init: Error registering matching rule %s\n",
4659 mrule_defs[i].mrd_desc );
4664 res = slap_schema_load();
4665 schema_init_done = 1;
4670 schema_destroy( void )
4679 if( schema_init_done ) {
4680 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4681 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );