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_len = val->bv_len - ( p - val->bv_val );
2121 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2122 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2123 normalized->bv_val[normalized->bv_len] = '\0';
2125 p = q = normalized->bv_val;
2128 if ( ASCII_SPACE( *p ) ) {
2131 /* Ignore the extra whitespace */
2132 while ( ASCII_SPACE( *p ) ) {
2136 } else if ( casefold ) {
2137 /* Most IA5 rules require casefolding */
2138 *q++ = TOLOWER(*p); p++;
2145 assert( normalized->bv_val <= p );
2149 * If the string ended in space, backup the pointer one
2150 * position. One is enough because the above loop collapsed
2151 * all whitespace to a single space.
2153 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2155 /* null terminate */
2158 normalized->bv_len = q - normalized->bv_val;
2160 return LDAP_SUCCESS;
2169 if( in->bv_len != 36 ) {
2170 return LDAP_INVALID_SYNTAX;
2173 for( i=0; i<36; i++ ) {
2179 if( in->bv_val[i] != '-' ) {
2180 return LDAP_INVALID_SYNTAX;
2184 if( !ASCII_HEX( in->bv_val[i]) ) {
2185 return LDAP_INVALID_SYNTAX;
2190 return LDAP_SUCCESS;
2201 int rc=LDAP_INVALID_SYNTAX;
2203 assert( in != NULL );
2204 assert( out != NULL );
2206 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2209 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2211 for( i=0; i<36; i++ ) {
2217 if( in->bv_val[i] != '-' ) {
2220 out->bv_val[i] = '-';
2224 if( !ASCII_HEX( in->bv_val[i]) ) {
2227 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2232 out->bv_val[ out->bv_len ] = '\0';
2236 slap_sl_free( out->bv_val, ctx );
2249 struct berval *normalized,
2252 unsigned char octet = '\0';
2255 normalized->bv_len = 16;
2256 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2258 for( i=0, j=0; i<36; i++ ) {
2259 unsigned char nibble;
2260 if( val->bv_val[i] == '-' ) {
2263 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2264 nibble = val->bv_val[i] - '0';
2266 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2267 nibble = val->bv_val[i] - ('a'-10);
2269 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2270 nibble = val->bv_val[i] - ('A'-10);
2273 slap_sl_free( normalized->bv_val, ctx );
2274 return LDAP_INVALID_SYNTAX;
2279 normalized->bv_val[j>>1] = octet;
2281 octet = nibble << 4;
2286 normalized->bv_val[normalized->bv_len] = 0;
2287 return LDAP_SUCCESS;
2293 numericStringValidate(
2299 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2301 for(i=0; i < in->bv_len; i++) {
2302 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2303 return LDAP_INVALID_SYNTAX;
2307 return LDAP_SUCCESS;
2311 numericStringNormalize(
2316 struct berval *normalized,
2319 /* removal all spaces */
2322 assert( !BER_BVISEMPTY( val ) );
2324 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2327 q = normalized->bv_val;
2330 if ( ASCII_SPACE( *p ) ) {
2331 /* Ignore whitespace */
2338 /* we should have copied no more then is in val */
2339 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2341 /* null terminate */
2344 normalized->bv_len = q - normalized->bv_val;
2346 if( BER_BVISEMPTY( normalized ) ) {
2347 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2348 normalized->bv_val[0] = ' ';
2349 normalized->bv_val[1] = '\0';
2350 normalized->bv_len = 1;
2353 return LDAP_SUCCESS;
2357 * Integer conversion macros that will use the largest available
2360 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2361 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2362 # define SLAP_LONG long long
2364 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2365 # define SLAP_LONG long
2366 #endif /* HAVE_STRTOLL ... */
2374 struct berval *value,
2375 void *assertedValue )
2377 SLAP_LONG lValue, lAssertedValue;
2380 /* safe to assume integers are NUL terminated? */
2381 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2382 if( errno == ERANGE )
2384 return LDAP_CONSTRAINT_VIOLATION;
2387 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2389 if( errno == ERANGE )
2391 return LDAP_CONSTRAINT_VIOLATION;
2394 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2395 return LDAP_SUCCESS;
2404 struct berval *value,
2405 void *assertedValue )
2407 SLAP_LONG lValue, lAssertedValue;
2410 /* safe to assume integers are NUL terminated? */
2411 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2412 if( errno == ERANGE )
2414 return LDAP_CONSTRAINT_VIOLATION;
2417 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2419 if( errno == ERANGE )
2421 return LDAP_CONSTRAINT_VIOLATION;
2424 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2425 return LDAP_SUCCESS;
2429 serialNumberAndIssuerValidate(
2435 struct berval sn, i;
2437 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2440 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2442 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2443 /* Parse old format */
2444 i.bv_val = ber_bvchr( in, '$' );
2445 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2447 sn.bv_val = in->bv_val;
2448 sn.bv_len = i.bv_val - in->bv_val;
2451 i.bv_len = in->bv_len - (sn.bv_len + 1);
2453 /* eat leading zeros */
2454 for( n=0; n < (sn.bv_len-1); n++ ) {
2455 if( sn.bv_val[n] != '0' ) break;
2460 for( n=0; n < sn.bv_len; n++ ) {
2461 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2465 /* Parse GSER format */
2466 int havesn=0,haveissuer=0;
2467 struct berval x = *in;
2471 /* eat leading spaces */
2472 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2476 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2477 return LDAP_INVALID_SYNTAX;
2480 /* should be at issuer or serialNumber NamedValue */
2481 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2483 x.bv_val += STRLENOF("issuer");
2484 x.bv_len -= STRLENOF("issuer");
2486 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2487 x.bv_val++; x.bv_len--;
2489 /* eat leading spaces */
2490 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2494 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2495 x.bv_val++; x.bv_len--;
2497 i.bv_val = x.bv_val;
2500 for( ; i.bv_len < x.bv_len; ) {
2501 if ( i.bv_val[i.bv_len] != '"' ) {
2505 if ( i.bv_val[i.bv_len+1] == '"' ) {
2512 x.bv_val += i.bv_len+1;
2513 x.bv_len -= i.bv_len+1;
2515 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2516 return LDAP_INVALID_SYNTAX;
2521 } else if( strncasecmp( x.bv_val, "serialNumber",
2522 STRLENOF("serialNumber")) == 0 )
2524 /* parse serialNumber */
2526 x.bv_val += STRLENOF("serialNumber");
2527 x.bv_len -= STRLENOF("serialNumber");
2529 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2530 x.bv_val++; x.bv_len--;
2532 /* eat leading spaces */
2533 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2537 sn.bv_val = x.bv_val;
2540 if( sn.bv_val[0] == '-' ) {
2545 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2546 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2549 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2550 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2551 return LDAP_INVALID_SYNTAX;
2554 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2556 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2557 return LDAP_INVALID_SYNTAX;
2562 } else return LDAP_INVALID_SYNTAX;
2564 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2565 x.bv_val++; x.bv_len--;
2568 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2572 /* should be at remaining NamedValue */
2573 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2574 STRLENOF("issuer" )) == 0 ))
2577 x.bv_val += STRLENOF("issuer");
2578 x.bv_len -= STRLENOF("issuer");
2580 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2581 x.bv_val++; x.bv_len--;
2583 /* eat leading spaces */
2584 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2588 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2589 x.bv_val++; x.bv_len--;
2591 i.bv_val = x.bv_val;
2594 for( ; i.bv_len < x.bv_len; ) {
2595 if ( i.bv_val[i.bv_len] != '"' ) {
2599 if ( i.bv_val[i.bv_len+1] == '"' ) {
2606 x.bv_val += i.bv_len+1;
2607 x.bv_len -= i.bv_len+1;
2609 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2610 STRLENOF("serialNumber")) == 0 ))
2612 /* parse serialNumber */
2614 x.bv_val += STRLENOF("serialNumber");
2615 x.bv_len -= STRLENOF("serialNumber");
2617 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2618 x.bv_val++; x.bv_len--;
2620 /* eat leading spaces */
2621 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2625 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2626 x.bv_val++; x.bv_len--;
2628 sn.bv_val = x.bv_val;
2631 if( sn.bv_val[0] == '-' ) {
2636 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2637 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2640 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2641 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2642 return LDAP_INVALID_SYNTAX;
2645 x.bv_val += sn.bv_len;
2646 x.bv_len -= sn.bv_len;
2648 } else return LDAP_INVALID_SYNTAX;
2650 /* eat trailing spaces */
2651 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2655 /* should have no characters left... */
2656 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2659 /* validate DN -- doesn't handle double dquote */
2660 rc = dnValidate( NULL, &i );
2661 if( rc ) return LDAP_INVALID_SYNTAX;
2663 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2665 return LDAP_SUCCESS;
2669 serialNumberAndIssuerPretty(
2677 struct berval sn, i, ni;
2679 assert( in != NULL );
2680 assert( out != NULL );
2682 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2685 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2687 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2688 /* Parse old format */
2689 i.bv_val = ber_bvchr( in, '$' );
2690 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2692 sn.bv_val = in->bv_val;
2693 sn.bv_len = i.bv_val - in->bv_val;
2696 i.bv_len = in->bv_len - (sn.bv_len + 1);
2698 /* eat leading zeros */
2699 for( n=0; n < (sn.bv_len-1); n++ ) {
2700 if( sn.bv_val[n] != '0' ) break;
2705 for( n=0; n < sn.bv_len; n++ ) {
2706 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2710 /* Parse GSER format */
2711 int havesn=0,haveissuer=0;
2712 struct berval x = *in;
2716 /* eat leading spaces */
2717 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2721 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2722 return LDAP_INVALID_SYNTAX;
2725 /* should be at issuer or serialNumber NamedValue */
2726 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2728 x.bv_val += STRLENOF("issuer");
2729 x.bv_len -= STRLENOF("issuer");
2731 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2732 x.bv_val++; x.bv_len--;
2734 /* eat leading spaces */
2735 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2739 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2740 x.bv_val++; x.bv_len--;
2742 i.bv_val = x.bv_val;
2745 for( ; i.bv_len < x.bv_len; ) {
2746 if ( i.bv_val[i.bv_len] != '"' ) {
2750 if ( i.bv_val[i.bv_len+1] == '"' ) {
2757 x.bv_val += i.bv_len+1;
2758 x.bv_len -= i.bv_len+1;
2760 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2761 return LDAP_INVALID_SYNTAX;
2766 } else if( strncasecmp( x.bv_val, "serialNumber",
2767 STRLENOF("serialNumber")) == 0 )
2769 /* parse serialNumber */
2771 x.bv_val += STRLENOF("serialNumber");
2772 x.bv_len -= STRLENOF("serialNumber");
2774 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2775 x.bv_val++; x.bv_len--;
2777 /* eat leading spaces */
2778 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2782 sn.bv_val = x.bv_val;
2785 if( sn.bv_val[0] == '-' ) {
2790 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2791 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2794 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2795 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2796 return LDAP_INVALID_SYNTAX;
2799 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2801 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2802 return LDAP_INVALID_SYNTAX;
2807 } else return LDAP_INVALID_SYNTAX;
2809 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2810 x.bv_val++; x.bv_len--;
2813 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2817 /* should be at remaining NamedValue */
2818 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2819 STRLENOF("issuer" )) == 0 ))
2822 x.bv_val += STRLENOF("issuer");
2823 x.bv_len -= STRLENOF("issuer");
2825 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2826 x.bv_val++; x.bv_len--;
2828 /* eat leading spaces */
2829 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2833 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2834 x.bv_val++; x.bv_len--;
2836 i.bv_val = x.bv_val;
2839 for( ; i.bv_len < x.bv_len; ) {
2840 if ( i.bv_val[i.bv_len] != '"' ) {
2844 if ( i.bv_val[i.bv_len+1] == '"' ) {
2851 x.bv_val += i.bv_len+1;
2852 x.bv_len -= i.bv_len+1;
2854 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2855 STRLENOF("serialNumber")) == 0 ))
2857 /* parse serialNumber */
2859 x.bv_val += STRLENOF("serialNumber");
2860 x.bv_len -= STRLENOF("serialNumber");
2862 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2863 x.bv_val++; x.bv_len--;
2865 /* eat leading spaces */
2866 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2870 sn.bv_val = x.bv_val;
2873 if( sn.bv_val[0] == '-' ) {
2878 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2879 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2882 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2883 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2884 return LDAP_INVALID_SYNTAX;
2887 x.bv_val += sn.bv_len;
2888 x.bv_len -= sn.bv_len;
2890 } else return LDAP_INVALID_SYNTAX;
2892 /* eat trailing spaces */
2893 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2897 /* should have no characters left... */
2898 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2900 ber_dupbv_x( &ni, &i, ctx );
2903 /* need to handle double dquotes here */
2906 rc = dnPretty( syntax, &i, &ni, ctx );
2908 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2909 slap_sl_free( i.bv_val, ctx );
2912 if( rc ) return LDAP_INVALID_SYNTAX;
2914 /* make room from sn + "$" */
2915 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2916 + sn.bv_len + ni.bv_len;
2917 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2919 if( out->bv_val == NULL ) {
2921 slap_sl_free( ni.bv_val, ctx );
2926 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2927 STRLENOF("{ serialNumber "));
2928 n = STRLENOF("{ serialNumber ");
2930 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2933 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2934 n += STRLENOF(", issuer \"");
2936 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2939 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2940 n += STRLENOF("\" }");
2942 out->bv_val[n] = '\0';
2944 assert( n == out->bv_len );
2946 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2947 out->bv_val, 0, 0 );
2949 slap_sl_free( ni.bv_val, ctx );
2951 return LDAP_SUCCESS;
2955 * This routine is called by certificateExactNormalize when
2956 * certificateExactNormalize receives a search string instead of
2957 * a certificate. This routine checks if the search value is valid
2958 * and then returns the normalized value
2961 serialNumberAndIssuerNormalize(
2971 struct berval sn, i, ni;
2973 assert( in != NULL );
2974 assert( out != NULL );
2976 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2979 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2981 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2982 /* Parse old format */
2983 i.bv_val = ber_bvchr( in, '$' );
2984 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2986 sn.bv_val = in->bv_val;
2987 sn.bv_len = i.bv_val - in->bv_val;
2990 i.bv_len = in->bv_len - (sn.bv_len + 1);
2992 /* eat leading zeros */
2993 for( n=0; n < (sn.bv_len-1); n++ ) {
2994 if( sn.bv_val[n] != '0' ) break;
2999 for( n=0; n < sn.bv_len; n++ ) {
3000 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3004 /* Parse GSER format */
3005 int havesn=0,haveissuer=0;
3006 struct berval x = *in;
3010 /* eat leading spaces */
3011 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3015 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3016 return LDAP_INVALID_SYNTAX;
3019 /* should be at issuer or serialNumber NamedValue */
3020 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3022 x.bv_val += STRLENOF("issuer");
3023 x.bv_len -= STRLENOF("issuer");
3025 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3026 x.bv_val++; x.bv_len--;
3028 /* eat leading spaces */
3029 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3033 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3034 x.bv_val++; x.bv_len--;
3036 i.bv_val = x.bv_val;
3039 for( ; i.bv_len < x.bv_len; ) {
3040 if ( i.bv_val[i.bv_len] != '"' ) {
3044 if ( i.bv_val[i.bv_len+1] == '"' ) {
3051 x.bv_val += i.bv_len+1;
3052 x.bv_len -= i.bv_len+1;
3054 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3055 return LDAP_INVALID_SYNTAX;
3060 } else if( strncasecmp( x.bv_val, "serialNumber",
3061 STRLENOF("serialNumber")) == 0 )
3063 /* parse serialNumber */
3065 x.bv_val += STRLENOF("serialNumber");
3066 x.bv_len -= STRLENOF("serialNumber");
3068 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3069 x.bv_val++; x.bv_len--;
3071 /* eat leading spaces */
3072 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3076 sn.bv_val = x.bv_val;
3079 if( sn.bv_val[0] == '-' ) {
3084 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3085 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3088 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3089 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3090 return LDAP_INVALID_SYNTAX;
3093 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3095 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3096 return LDAP_INVALID_SYNTAX;
3101 } else return LDAP_INVALID_SYNTAX;
3103 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3104 x.bv_val++; x.bv_len--;
3107 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3111 /* should be at remaining NamedValue */
3112 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3113 STRLENOF("issuer" )) == 0 ))
3116 x.bv_val += STRLENOF("issuer");
3117 x.bv_len -= STRLENOF("issuer");
3119 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3120 x.bv_val++; x.bv_len--;
3122 /* eat leading spaces */
3123 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3127 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3128 x.bv_val++; x.bv_len--;
3130 i.bv_val = x.bv_val;
3133 for( ; i.bv_len < x.bv_len; ) {
3134 if ( i.bv_val[i.bv_len] != '"' ) {
3138 if ( i.bv_val[i.bv_len+1] == '"' ) {
3145 x.bv_val += i.bv_len+1;
3146 x.bv_len -= i.bv_len+1;
3148 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3149 STRLENOF("serialNumber")) == 0 ))
3151 /* parse serialNumber */
3153 x.bv_val += STRLENOF("serialNumber");
3154 x.bv_len -= STRLENOF("serialNumber");
3156 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3157 x.bv_val++; x.bv_len--;
3159 /* eat leading spaces */
3160 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3164 sn.bv_val = x.bv_val;
3167 if( sn.bv_val[0] == '-' ) {
3172 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3173 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3176 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3177 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3178 return LDAP_INVALID_SYNTAX;
3181 x.bv_val += sn.bv_len;
3182 x.bv_len -= sn.bv_len;
3184 } else return LDAP_INVALID_SYNTAX;
3186 /* eat trailing spaces */
3187 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3191 /* should have no characters left... */
3192 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3194 ber_dupbv_x( &ni, &i, ctx );
3197 /* need to handle double dquotes here */
3200 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3202 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3203 slap_sl_free( i.bv_val, ctx );
3206 if( rc ) return LDAP_INVALID_SYNTAX;
3208 /* make room from sn + "$" */
3209 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3210 + sn.bv_len + ni.bv_len;
3211 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3213 if( out->bv_val == NULL ) {
3215 slap_sl_free( ni.bv_val, ctx );
3220 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3221 STRLENOF( "{ serialNumber " ));
3222 n = STRLENOF( "{ serialNumber " );
3224 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3227 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3228 n += STRLENOF( ", issuer \"" );
3230 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3233 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3234 n += STRLENOF( "\" }" );
3236 out->bv_val[n] = '\0';
3238 assert( n == out->bv_len );
3240 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3241 out->bv_val, 0, 0 );
3243 slap_sl_free( ni.bv_val, ctx );
3245 return LDAP_SUCCESS;
3249 certificateExactNormalize(
3254 struct berval *normalized,
3257 BerElementBuffer berbuf;
3258 BerElement *ber = (BerElement *)&berbuf;
3263 ber_len_t seriallen;
3264 struct berval issuer_dn = BER_BVNULL, bvdn;
3266 int rc = LDAP_INVALID_SYNTAX;
3268 if( BER_BVISEMPTY( val ) ) goto done;
3270 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3271 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3274 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3276 ber_init2( ber, val, LBER_USE_DER );
3277 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3278 tag = ber_skip_tag( ber, &len ); /* Sequence */
3279 tag = ber_skip_tag( ber, &len ); /* Optional version? */
3281 tag = ber_get_int( ber, &i ); /* version */
3282 ber_get_int( ber, &i ); /* serial */
3284 seriallen = snprintf( serial, sizeof(serial), "%d", i );
3285 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3286 ber_skip_data( ber, len );
3287 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3288 len = ber_ptrlen( ber );
3289 bvdn.bv_val = val->bv_val + len;
3290 bvdn.bv_len = val->bv_len - len;
3292 rc = dnX509normalize( &bvdn, &issuer_dn );
3293 if( rc != LDAP_SUCCESS ) goto done;
3295 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3296 + seriallen + issuer_dn.bv_len;
3297 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3299 p = (unsigned char *)normalized->bv_val;
3301 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3302 p += STRLENOF( "{ serialNumber " );
3304 AC_MEMCPY(p, serial, seriallen);
3307 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3308 p += STRLENOF( ", issuer \"" );
3310 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3311 p += issuer_dn.bv_len;
3313 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3314 p += STRLENOF( "\" }" );
3318 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3319 normalized->bv_val, NULL, NULL );
3324 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3330 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3331 /* slight optimization - does not need the start parameter */
3332 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3337 check_time_syntax (struct berval *val,
3340 struct berval *fraction)
3343 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3344 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3345 * GeneralizedTime supports leap seconds, UTCTime does not.
3347 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3348 static const int mdays[2][12] = {
3349 /* non-leap years */
3350 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3352 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3355 int part, c, c1, c2, tzoffset, leapyear = 0;
3358 e = p + val->bv_len;
3360 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3361 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3363 for (part = start; part < 7 && p < e; part++) {
3365 if (!ASCII_DIGIT(c1)) {
3370 return LDAP_INVALID_SYNTAX;
3373 if (!ASCII_DIGIT(c)) {
3374 return LDAP_INVALID_SYNTAX;
3376 c += c1 * 10 - '0' * 11;
3377 if ((part | 1) == 3) {
3380 return LDAP_INVALID_SYNTAX;
3383 if (c >= ceiling[part]) {
3384 if (! (c == 60 && part == 6 && start == 0))
3385 return LDAP_INVALID_SYNTAX;
3389 if (part < 5 + start) {
3390 return LDAP_INVALID_SYNTAX;
3392 for (; part < 9; part++) {
3396 /* leapyear check for the Gregorian calendar (year>1581) */
3397 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3401 if (parts[3] >= mdays[leapyear][parts[2]]) {
3402 return LDAP_INVALID_SYNTAX;
3406 fraction->bv_val = p;
3407 fraction->bv_len = 0;
3408 if (p < e && (*p == '.' || *p == ',')) {
3410 while (++p < e && ASCII_DIGIT(*p)) {
3413 if (p - fraction->bv_val == 1) {
3414 return LDAP_INVALID_SYNTAX;
3416 for (end_num = p; end_num[-1] == '0'; --end_num) {
3419 c = end_num - fraction->bv_val;
3420 if (c != 1) fraction->bv_len = c;
3426 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3432 return LDAP_INVALID_SYNTAX;
3438 for (part = 7; part < 9 && p < e; part++) {
3440 if (!ASCII_DIGIT(c1)) {
3445 return LDAP_INVALID_SYNTAX;
3448 if (!ASCII_DIGIT(c2)) {
3449 return LDAP_INVALID_SYNTAX;
3451 parts[part] = c1 * 10 + c2 - '0' * 11;
3452 if (parts[part] >= ceiling[part]) {
3453 return LDAP_INVALID_SYNTAX;
3456 if (part < 8 + start) {
3457 return LDAP_INVALID_SYNTAX;
3460 if (tzoffset == '-') {
3461 /* negative offset to UTC, ie west of Greenwich */
3462 parts[4] += parts[7];
3463 parts[5] += parts[8];
3464 /* offset is just hhmm, no seconds */
3465 for (part = 6; --part >= 0; ) {
3469 c = mdays[leapyear][parts[2]];
3471 if (parts[part] >= c) {
3473 return LDAP_INVALID_SYNTAX;
3478 } else if (part != 5) {
3483 /* positive offset to UTC, ie east of Greenwich */
3484 parts[4] -= parts[7];
3485 parts[5] -= parts[8];
3486 for (part = 6; --part >= 0; ) {
3487 if (parts[part] < 0) {
3489 return LDAP_INVALID_SYNTAX;
3494 /* make first arg to % non-negative */
3495 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3500 } else if (part != 5) {
3507 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3510 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3517 struct berval *normalized )
3521 rc = check_time_syntax(val, 1, parts, NULL);
3522 if (rc != LDAP_SUCCESS) {
3526 normalized->bv_val = ch_malloc( 14 );
3527 if ( normalized->bv_val == NULL ) {
3528 return LBER_ERROR_MEMORY;
3531 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3532 parts[1], parts[2] + 1, parts[3] + 1,
3533 parts[4], parts[5], parts[6] );
3534 normalized->bv_len = 13;
3536 return LDAP_SUCCESS;
3546 return check_time_syntax(in, 1, parts, NULL);
3549 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3552 generalizedTimeValidate(
3557 struct berval fraction;
3558 return check_time_syntax(in, 0, parts, &fraction);
3562 generalizedTimeNormalize(
3567 struct berval *normalized,
3572 struct berval fraction;
3574 rc = check_time_syntax(val, 0, parts, &fraction);
3575 if (rc != LDAP_SUCCESS) {
3579 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3580 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3581 if ( BER_BVISNULL( normalized ) ) {
3582 return LBER_ERROR_MEMORY;
3585 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3586 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3587 parts[4], parts[5], parts[6] );
3588 if ( !BER_BVISEMPTY( &fraction ) ) {
3589 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3590 fraction.bv_val, fraction.bv_len );
3591 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3593 strcpy( normalized->bv_val + len-1, "Z" );
3594 normalized->bv_len = len;
3596 return LDAP_SUCCESS;
3600 generalizedTimeOrderingMatch(
3605 struct berval *value,
3606 void *assertedValue )
3608 struct berval *asserted = (struct berval *) assertedValue;
3609 ber_len_t v_len = value->bv_len;
3610 ber_len_t av_len = asserted->bv_len;
3612 /* ignore trailing 'Z' when comparing */
3613 int match = memcmp( value->bv_val, asserted->bv_val,
3614 (v_len < av_len ? v_len : av_len) - 1 );
3615 if ( match == 0 ) match = v_len - av_len;
3618 return LDAP_SUCCESS;
3621 /* Index generation function */
3622 int generalizedTimeIndexer(
3627 struct berval *prefix,
3635 BerValue bvtmp; /* 40 bit index */
3637 struct lutil_timet tt;
3639 bvtmp.bv_len = sizeof(tmp);
3641 for( i=0; values[i].bv_val != NULL; i++ ) {
3642 /* just count them */
3645 /* we should have at least one value at this point */
3648 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3650 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3651 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3652 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3653 /* Use 40 bits of time for key */
3654 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3655 lutil_tm2time( &tm, &tt );
3656 tmp[0] = tt.tt_gsec & 0xff;
3657 tmp[4] = tt.tt_sec & 0xff;
3659 tmp[3] = tt.tt_sec & 0xff;
3661 tmp[2] = tt.tt_sec & 0xff;
3663 tmp[1] = tt.tt_sec & 0xff;
3665 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3669 keys[j].bv_val = NULL;
3674 return LDAP_SUCCESS;
3677 /* Index generation function */
3678 int generalizedTimeFilter(
3683 struct berval *prefix,
3684 void * assertedValue,
3690 BerValue bvtmp; /* 40 bit index */
3691 BerValue *value = (BerValue *) assertedValue;
3693 struct lutil_timet tt;
3695 bvtmp.bv_len = sizeof(tmp);
3697 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3698 /* Use 40 bits of time for key */
3699 if ( value->bv_val && value->bv_len >= 10 &&
3700 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3702 lutil_tm2time( &tm, &tt );
3703 tmp[0] = tt.tt_gsec & 0xff;
3704 tmp[4] = tt.tt_sec & 0xff;
3706 tmp[3] = tt.tt_sec & 0xff;
3708 tmp[2] = tt.tt_sec & 0xff;
3710 tmp[1] = tt.tt_sec & 0xff;
3712 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3713 ber_dupbv_x(keys, &bvtmp, ctx );
3714 keys[1].bv_val = NULL;
3722 return LDAP_SUCCESS;
3726 deliveryMethodValidate(
3728 struct berval *val )
3731 #define LENOF(s) (sizeof(s)-1)
3732 struct berval tmp = *val;
3734 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3735 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3736 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3739 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3741 switch( tmp.bv_val[0] ) {
3744 if(( tmp.bv_len >= LENOF("any") ) &&
3745 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3747 tmp.bv_len -= LENOF("any");
3748 tmp.bv_val += LENOF("any");
3751 return LDAP_INVALID_SYNTAX;
3755 if(( tmp.bv_len >= LENOF("mhs") ) &&
3756 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3758 tmp.bv_len -= LENOF("mhs");
3759 tmp.bv_val += LENOF("mhs");
3762 return LDAP_INVALID_SYNTAX;
3766 if(( tmp.bv_len >= LENOF("physical") ) &&
3767 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3769 tmp.bv_len -= LENOF("physical");
3770 tmp.bv_val += LENOF("physical");
3773 return LDAP_INVALID_SYNTAX;
3776 case 'T': /* telex or teletex or telephone */
3777 if(( tmp.bv_len >= LENOF("telex") ) &&
3778 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3780 tmp.bv_len -= LENOF("telex");
3781 tmp.bv_val += LENOF("telex");
3784 if(( tmp.bv_len >= LENOF("teletex") ) &&
3785 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3787 tmp.bv_len -= LENOF("teletex");
3788 tmp.bv_val += LENOF("teletex");
3791 if(( tmp.bv_len >= LENOF("telephone") ) &&
3792 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3794 tmp.bv_len -= LENOF("telephone");
3795 tmp.bv_val += LENOF("telephone");
3798 return LDAP_INVALID_SYNTAX;
3801 case 'G': /* g3fax or g4fax */
3802 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3803 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3804 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3806 tmp.bv_len -= LENOF("g3fax");
3807 tmp.bv_val += LENOF("g3fax");
3810 return LDAP_INVALID_SYNTAX;
3814 if(( tmp.bv_len >= LENOF("ia5") ) &&
3815 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3817 tmp.bv_len -= LENOF("ia5");
3818 tmp.bv_val += LENOF("ia5");
3821 return LDAP_INVALID_SYNTAX;
3825 if(( tmp.bv_len >= LENOF("videotex") ) &&
3826 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3828 tmp.bv_len -= LENOF("videotex");
3829 tmp.bv_val += LENOF("videotex");
3832 return LDAP_INVALID_SYNTAX;
3835 return LDAP_INVALID_SYNTAX;
3838 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3840 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3844 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3848 return LDAP_INVALID_SYNTAX;
3850 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3859 nisNetgroupTripleValidate(
3861 struct berval *val )
3866 if ( BER_BVISEMPTY( val ) ) {
3867 return LDAP_INVALID_SYNTAX;
3870 p = (char *)val->bv_val;
3871 e = p + val->bv_len;
3873 if ( *p != '(' /*')'*/ ) {
3874 return LDAP_INVALID_SYNTAX;
3877 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3881 return LDAP_INVALID_SYNTAX;
3884 } else if ( !AD_CHAR( *p ) ) {
3885 return LDAP_INVALID_SYNTAX;
3889 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3890 return LDAP_INVALID_SYNTAX;
3896 return LDAP_INVALID_SYNTAX;
3899 return LDAP_SUCCESS;
3903 bootParameterValidate(
3905 struct berval *val )
3909 if ( BER_BVISEMPTY( val ) ) {
3910 return LDAP_INVALID_SYNTAX;
3913 p = (char *)val->bv_val;
3914 e = p + val->bv_len;
3917 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3918 if ( !AD_CHAR( *p ) ) {
3919 return LDAP_INVALID_SYNTAX;
3924 return LDAP_INVALID_SYNTAX;
3928 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3929 if ( !AD_CHAR( *p ) ) {
3930 return LDAP_INVALID_SYNTAX;
3935 return LDAP_INVALID_SYNTAX;
3939 for ( p++; p < e; p++ ) {
3940 if ( !SLAP_PRINTABLE( *p ) ) {
3941 return LDAP_INVALID_SYNTAX;
3945 return LDAP_SUCCESS;
3949 firstComponentNormalize(
3954 struct berval *normalized,
3961 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3962 ber_dupbv_x( normalized, val, ctx );
3963 return LDAP_SUCCESS;
3966 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3968 if( val->bv_val[0] != '(' /*')'*/ &&
3969 val->bv_val[0] != '{' /*'}'*/ )
3971 return LDAP_INVALID_SYNTAX;
3974 /* trim leading white space */
3976 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3982 /* grab next word */
3983 comp.bv_val = &val->bv_val[len];
3984 len = val->bv_len - len;
3985 for( comp.bv_len = 0;
3986 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3992 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3993 rc = numericoidValidate( NULL, &comp );
3994 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3995 rc = integerValidate( NULL, &comp );
3997 rc = LDAP_INVALID_SYNTAX;
4001 if( rc == LDAP_SUCCESS ) {
4002 ber_dupbv_x( normalized, &comp, ctx );
4008 static char *country_gen_syn[] = {
4009 "1.3.6.1.4.1.1466.115.121.1.15",
4010 "1.3.6.1.4.1.1466.115.121.1.26",
4011 "1.3.6.1.4.1.1466.115.121.1.44",
4015 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4016 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4018 static slap_syntax_defs_rec syntax_defs[] = {
4019 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4020 X_BINARY X_NOT_H_R ")",
4021 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4022 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4023 0, NULL, NULL, NULL},
4024 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4025 0, NULL, NULL, NULL},
4026 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4028 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4029 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4031 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4032 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4033 0, NULL, bitStringValidate, NULL },
4034 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4035 0, NULL, booleanValidate, NULL},
4036 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4037 X_BINARY X_NOT_H_R ")",
4038 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4039 NULL, certificateValidate, NULL},
4040 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4041 X_BINARY X_NOT_H_R ")",
4042 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4043 NULL, sequenceValidate, NULL},
4044 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4045 X_BINARY X_NOT_H_R ")",
4046 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4047 NULL, sequenceValidate, NULL},
4048 #if 0 /* need to go __after__ printableString */
4049 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4050 0, "1.3.6.1.4.1.1466.115.121.1.44",
4051 countryStringValidate, NULL},
4053 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4054 0, NULL, dnValidate, dnPretty},
4055 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4056 0, NULL, rdnValidate, rdnPretty},
4057 #ifdef LDAP_COMP_MATCH
4058 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4059 0, NULL, allComponentsValidate, NULL},
4060 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4061 0, NULL, componentFilterValidate, NULL},
4063 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4064 0, NULL, NULL, NULL},
4065 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4066 0, NULL, deliveryMethodValidate, NULL},
4067 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4068 0, NULL, UTF8StringValidate, NULL},
4069 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4070 0, NULL, NULL, NULL},
4071 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4072 0, NULL, NULL, NULL},
4073 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4074 0, NULL, NULL, NULL},
4075 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4076 0, NULL, NULL, NULL},
4077 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4078 0, NULL, NULL, NULL},
4079 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4080 0, NULL, printablesStringValidate, NULL},
4081 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4082 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4083 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4084 0, NULL, generalizedTimeValidate, NULL},
4085 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4086 0, NULL, NULL, NULL},
4087 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4088 0, NULL, IA5StringValidate, NULL},
4089 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4090 0, NULL, integerValidate, NULL},
4091 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4092 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4093 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4094 0, NULL, NULL, NULL},
4095 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4096 0, NULL, NULL, NULL},
4097 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4098 0, NULL, NULL, NULL},
4099 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4100 0, NULL, NULL, NULL},
4101 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4102 0, NULL, NULL, NULL},
4103 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4104 0, NULL, nameUIDValidate, nameUIDPretty },
4105 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4106 0, NULL, NULL, NULL},
4107 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4108 0, NULL, numericStringValidate, NULL},
4109 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4110 0, NULL, NULL, NULL},
4111 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4112 0, NULL, numericoidValidate, NULL},
4113 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4114 0, NULL, IA5StringValidate, NULL},
4115 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4116 0, NULL, blobValidate, NULL},
4117 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4118 0, NULL, UTF8StringValidate, NULL},
4119 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4120 0, NULL, NULL, NULL},
4121 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4122 0, NULL, NULL, NULL},
4123 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4124 0, NULL, printableStringValidate, NULL},
4125 /* moved here because now depends on Directory String, IA5 String
4126 * and Printable String */
4127 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4128 0, country_gen_syn, countryStringValidate, NULL},
4129 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4130 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4131 0, NULL, subtreeSpecificationValidate, NULL},
4132 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4133 X_BINARY X_NOT_H_R ")",
4134 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4135 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4136 0, NULL, printableStringValidate, NULL},
4137 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4138 0, NULL, NULL, NULL},
4139 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4140 0, NULL, printablesStringValidate, NULL},
4141 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4142 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4143 0, NULL, utcTimeValidate, NULL},
4145 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4146 0, NULL, NULL, NULL},
4147 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4148 0, NULL, NULL, NULL},
4149 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4150 0, NULL, NULL, NULL},
4151 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4152 0, NULL, NULL, NULL},
4153 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4154 0, NULL, NULL, NULL},
4156 /* RFC 2307 NIS Syntaxes */
4157 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4158 0, NULL, nisNetgroupTripleValidate, NULL},
4159 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4160 0, NULL, bootParameterValidate, NULL},
4162 /* draft-zeilenga-ldap-x509 */
4163 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4164 SLAP_SYNTAX_HIDE, NULL,
4165 serialNumberAndIssuerValidate,
4166 serialNumberAndIssuerPretty},
4167 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4168 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4169 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4170 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4171 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4172 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4173 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4174 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4175 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4176 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4177 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4178 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4180 #ifdef SLAPD_AUTHPASSWD
4181 /* needs updating */
4182 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4183 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4186 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4187 0, NULL, UUIDValidate, UUIDPretty},
4189 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4190 SLAP_SYNTAX_HIDE, NULL, csnValidate, NULL},
4192 /* OpenLDAP Void Syntax */
4193 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4194 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4196 /* FIXME: OID is unused, but not registered yet */
4197 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4198 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4200 {NULL, 0, NULL, NULL, NULL}
4203 char *certificateExactMatchSyntaxes[] = {
4204 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4207 #ifdef LDAP_COMP_MATCH
4208 char *componentFilterMatchSyntaxes[] = {
4209 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4213 char *directoryStringSyntaxes[] = {
4214 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4217 char *integerFirstComponentMatchSyntaxes[] = {
4218 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4219 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4222 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4223 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4224 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4225 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4226 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4227 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4228 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4229 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4230 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4235 * Other matching rules in X.520 that we do not use (yet):
4237 * 2.5.13.25 uTCTimeMatch
4238 * 2.5.13.26 uTCTimeOrderingMatch
4239 * 2.5.13.31* directoryStringFirstComponentMatch
4240 * 2.5.13.32* wordMatch
4241 * 2.5.13.33* keywordMatch
4242 * 2.5.13.36+ certificatePairExactMatch
4243 * 2.5.13.37+ certificatePairMatch
4244 * 2.5.13.38+ certificateListExactMatch
4245 * 2.5.13.39+ certificateListMatch
4246 * 2.5.13.40+ algorithmIdentifierMatch
4247 * 2.5.13.41* storedPrefixMatch
4248 * 2.5.13.42 attributeCertificateMatch
4249 * 2.5.13.43 readerAndKeyIDMatch
4250 * 2.5.13.44 attributeIntegrityMatch
4252 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4253 * (+) described in draft-zeilenga-ldap-x509
4255 static slap_mrule_defs_rec mrule_defs[] = {
4257 * EQUALITY matching rules must be listed after associated APPROX
4258 * matching rules. So, we list all APPROX matching rules first.
4260 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4261 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4262 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4263 NULL, NULL, directoryStringApproxMatch,
4264 directoryStringApproxIndexer, directoryStringApproxFilter,
4267 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4269 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4270 NULL, NULL, IA5StringApproxMatch,
4271 IA5StringApproxIndexer, IA5StringApproxFilter,
4275 * Other matching rules
4278 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4279 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4280 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4281 NULL, NULL, octetStringMatch,
4282 octetStringIndexer, octetStringFilter,
4285 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4286 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4287 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4288 NULL, dnNormalize, dnMatch,
4289 octetStringIndexer, octetStringFilter,
4292 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4294 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4295 NULL, dnNormalize, dnRelativeMatch,
4299 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4301 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4302 NULL, dnNormalize, dnRelativeMatch,
4306 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4308 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4309 NULL, dnNormalize, dnRelativeMatch,
4313 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4315 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4316 NULL, dnNormalize, dnRelativeMatch,
4320 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4321 "SYNTAX 1.2.36.79672281.1.5.0 )",
4322 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4323 NULL, rdnNormalize, rdnMatch,
4324 octetStringIndexer, octetStringFilter,
4327 #ifdef LDAP_COMP_MATCH
4328 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4329 "SYNTAX 1.2.36.79672281.1.5.2 )",
4330 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4331 NULL, NULL , componentFilterMatch,
4332 octetStringIndexer, octetStringFilter,
4335 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4336 "SYNTAX 1.2.36.79672281.1.5.3 )",
4337 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4338 NULL, NULL , allComponentsMatch,
4339 octetStringIndexer, octetStringFilter,
4342 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4343 "SYNTAX 1.2.36.79672281.1.5.3 )",
4344 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4345 NULL, NULL , directoryComponentsMatch,
4346 octetStringIndexer, octetStringFilter,
4350 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4351 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4352 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4353 NULL, UTF8StringNormalize, octetStringMatch,
4354 octetStringIndexer, octetStringFilter,
4355 directoryStringApproxMatchOID },
4357 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4359 SLAP_MR_ORDERING, directoryStringSyntaxes,
4360 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4362 "caseIgnoreMatch" },
4364 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4366 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4367 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4368 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4369 "caseIgnoreMatch" },
4371 {"( 2.5.13.5 NAME 'caseExactMatch' "
4372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4373 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4374 NULL, UTF8StringNormalize, octetStringMatch,
4375 octetStringIndexer, octetStringFilter,
4376 directoryStringApproxMatchOID },
4378 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4380 SLAP_MR_ORDERING, directoryStringSyntaxes,
4381 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4385 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4387 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4388 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4389 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4392 {"( 2.5.13.8 NAME 'numericStringMatch' "
4393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4394 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4395 NULL, numericStringNormalize, octetStringMatch,
4396 octetStringIndexer, octetStringFilter,
4399 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4401 SLAP_MR_ORDERING, NULL,
4402 NULL, numericStringNormalize, octetStringOrderingMatch,
4404 "numericStringMatch" },
4406 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4408 SLAP_MR_SUBSTR, NULL,
4409 NULL, numericStringNormalize, octetStringSubstringsMatch,
4410 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4411 "numericStringMatch" },
4413 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4415 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4416 NULL, NULL, NULL, NULL, NULL, NULL },
4418 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4420 SLAP_MR_SUBSTR, NULL,
4421 NULL, NULL, NULL, NULL, NULL,
4422 "caseIgnoreListMatch" },
4424 {"( 2.5.13.13 NAME 'booleanMatch' "
4425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4426 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4427 NULL, NULL, booleanMatch,
4428 octetStringIndexer, octetStringFilter,
4431 {"( 2.5.13.14 NAME 'integerMatch' "
4432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4433 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4434 NULL, NULL, integerMatch,
4435 octetStringIndexer, octetStringFilter,
4438 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4440 SLAP_MR_ORDERING, NULL,
4441 NULL, NULL, integerMatch,
4445 {"( 2.5.13.16 NAME 'bitStringMatch' "
4446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4447 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4448 NULL, NULL, octetStringMatch,
4449 octetStringIndexer, octetStringFilter,
4452 {"( 2.5.13.17 NAME 'octetStringMatch' "
4453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4455 NULL, NULL, octetStringMatch,
4456 octetStringIndexer, octetStringFilter,
4459 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4461 SLAP_MR_ORDERING, NULL,
4462 NULL, NULL, octetStringOrderingMatch,
4464 "octetStringMatch" },
4466 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4468 SLAP_MR_SUBSTR, NULL,
4469 NULL, NULL, octetStringSubstringsMatch,
4470 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4471 "octetStringMatch" },
4473 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4475 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4477 telephoneNumberNormalize, octetStringMatch,
4478 octetStringIndexer, octetStringFilter,
4481 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4483 SLAP_MR_SUBSTR, NULL,
4484 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4485 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4486 "telephoneNumberMatch" },
4488 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4490 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4491 NULL, NULL, NULL, NULL, NULL, NULL },
4493 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4495 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4496 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4497 uniqueMemberIndexer, uniqueMemberFilter,
4500 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4501 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4502 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4503 NULL, NULL, NULL, NULL, NULL, NULL },
4505 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4507 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4508 NULL, generalizedTimeNormalize, octetStringMatch,
4509 generalizedTimeIndexer, generalizedTimeFilter,
4512 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4514 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4515 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4517 "generalizedTimeMatch" },
4519 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4521 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4522 integerFirstComponentMatchSyntaxes,
4523 NULL, firstComponentNormalize, integerMatch,
4524 octetStringIndexer, octetStringFilter,
4527 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4529 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4530 objectIdentifierFirstComponentMatchSyntaxes,
4531 NULL, firstComponentNormalize, octetStringMatch,
4532 octetStringIndexer, octetStringFilter,
4535 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4536 "SYNTAX 1.3.6.1.1.15.1 )",
4537 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4539 NULL, certificateExactNormalize, octetStringMatch,
4540 octetStringIndexer, octetStringFilter,
4542 NULL, NULL, NULL, NULL, NULL,
4546 {"( 2.5.13.35 NAME 'certificateMatch' "
4547 "SYNTAX 1.3.6.1.1.15.2 )",
4548 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4549 NULL, NULL, NULL, NULL, NULL,
4552 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4553 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4554 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4555 NULL, IA5StringNormalize, octetStringMatch,
4556 octetStringIndexer, octetStringFilter,
4557 IA5StringApproxMatchOID },
4559 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4560 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4561 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4562 NULL, IA5StringNormalize, octetStringMatch,
4563 octetStringIndexer, octetStringFilter,
4564 IA5StringApproxMatchOID },
4566 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4568 SLAP_MR_SUBSTR, NULL,
4569 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4570 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4571 "caseIgnoreIA5Match" },
4573 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4574 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4575 SLAP_MR_SUBSTR, NULL,
4576 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4577 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4578 "caseExactIA5Match" },
4580 #ifdef SLAPD_AUTHPASSWD
4581 /* needs updating */
4582 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4584 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4585 NULL, NULL, authPasswordMatch,
4590 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4591 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4593 NULL, NULL, integerBitAndMatch,
4597 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4598 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4600 NULL, NULL, integerBitOrMatch,
4604 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4605 "SYNTAX 1.3.6.1.1.16.1 )",
4606 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4607 NULL, UUIDNormalize, octetStringMatch,
4608 octetStringIndexer, octetStringFilter,
4611 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4612 "SYNTAX 1.3.6.1.1.16.1 )",
4613 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4614 NULL, UUIDNormalize, octetStringOrderingMatch,
4615 octetStringIndexer, octetStringFilter,
4618 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4619 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4620 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4621 NULL, NULL, csnMatch,
4622 csnIndexer, csnFilter,
4625 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4626 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4627 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4628 NULL, NULL, csnOrderingMatch,
4632 /* FIXME: OID is unused, but not registered yet */
4633 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4634 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4635 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4636 NULL, authzNormalize, authzMatch,
4640 {NULL, SLAP_MR_NONE, NULL,
4641 NULL, NULL, NULL, NULL, NULL,
4646 slap_schema_init( void )
4651 /* we should only be called once (from main) */
4652 assert( schema_init_done == 0 );
4654 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4655 res = register_syntax( &syntax_defs[i] );
4658 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4659 syntax_defs[i].sd_desc );
4664 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4665 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4666 mrule_defs[i].mrd_compat_syntaxes == NULL )
4669 "slap_schema_init: Ignoring unusable matching rule %s\n",
4670 mrule_defs[i].mrd_desc );
4674 res = register_matching_rule( &mrule_defs[i] );
4678 "slap_schema_init: Error registering matching rule %s\n",
4679 mrule_defs[i].mrd_desc );
4684 res = slap_schema_load();
4685 schema_init_done = 1;
4690 schema_destroy( void )
4699 if( schema_init_done ) {
4700 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4701 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );