1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 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 <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
46 #include "lutil_hash.h"
47 #define HASH_BYTES LUTIL_HASH_BYTES
48 #define HASH_CONTEXT lutil_HASH_CTX
49 #define HASH_Init(c) lutil_HASHInit(c)
50 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
51 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
53 /* approx matching rules */
54 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
55 #define directoryStringApproxMatch approxMatch
56 #define directoryStringApproxIndexer approxIndexer
57 #define directoryStringApproxFilter approxFilter
58 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch approxMatch
60 #define IA5StringApproxIndexer approxIndexer
61 #define IA5StringApproxFilter approxFilter
63 /* Change Sequence Number (CSN) - much of this will change */
64 #define csnValidate blobValidate
65 #define csnMatch octetStringMatch
66 #define csnOrderingMatch octetStringOrderingMatch
67 #define csnIndexer generalizedTimeIndexer
68 #define csnFilter generalizedTimeFilter
70 #ifdef SLAP_AUTHZ_SYNTAX
71 /* FIXME: temporary */
72 #define authzMatch octetStringMatch
73 #endif /* SLAP_AUTHZ_SYNTAX */
75 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
76 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
77 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
78 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
80 ldap_pvt_thread_mutex_t ad_undef_mutex;
81 ldap_pvt_thread_mutex_t oc_undef_mutex;
88 /* no value allowed */
89 return LDAP_INVALID_SYNTAX;
97 /* any value allowed */
101 #define berValidate blobValidate
108 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
109 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
116 static int certificateValidate( Syntax *syntax, struct berval *in )
119 unsigned char *p = (unsigned char *)in->bv_val;
121 xcert = d2i_X509(NULL, &p, in->bv_len);
122 if ( !xcert ) return LDAP_INVALID_SYNTAX;
127 #define certificateValidate sequenceValidate
136 struct berval *value,
137 void *assertedValue )
139 struct berval *asserted = (struct berval *) assertedValue;
140 int match = value->bv_len - asserted->bv_len;
143 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
151 octetStringOrderingMatch(
156 struct berval *value,
157 void *assertedValue )
159 struct berval *asserted = (struct berval *) assertedValue;
160 ber_len_t v_len = value->bv_len;
161 ber_len_t av_len = asserted->bv_len;
163 int match = memcmp( value->bv_val, asserted->bv_val,
164 (v_len < av_len ? v_len : av_len) );
166 if( match == 0 ) match = v_len - av_len;
174 HASH_CONTEXT *HASHcontext,
175 unsigned char *HASHdigest,
176 struct berval *prefix,
180 unsigned char *value,
183 HASH_Init(HASHcontext);
184 if(prefix && prefix->bv_len > 0) {
185 HASH_Update(HASHcontext,
186 (unsigned char *)prefix->bv_val, prefix->bv_len);
188 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
189 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
190 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
191 HASH_Update(HASHcontext, value, value_len);
192 HASH_Final(HASHdigest, HASHcontext);
196 /* Index generation function */
197 int octetStringIndexer(
202 struct berval *prefix,
210 HASH_CONTEXT HASHcontext;
211 unsigned char HASHdigest[HASH_BYTES];
212 struct berval digest;
213 digest.bv_val = (char *)HASHdigest;
214 digest.bv_len = sizeof(HASHdigest);
216 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
217 /* just count them */
220 /* we should have at least one value at this point */
223 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
225 slen = syntax->ssyn_oidlen;
226 mlen = mr->smr_oidlen;
228 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
229 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
230 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
231 ber_dupbv_x( &keys[i], &digest, ctx );
234 BER_BVZERO( &keys[i] );
241 /* Index generation function */
242 int octetStringFilter(
247 struct berval *prefix,
248 void * assertedValue,
254 HASH_CONTEXT HASHcontext;
255 unsigned char HASHdigest[HASH_BYTES];
256 struct berval *value = (struct berval *) assertedValue;
257 struct berval digest;
258 digest.bv_val = (char *)HASHdigest;
259 digest.bv_len = sizeof(HASHdigest);
261 slen = syntax->ssyn_oidlen;
262 mlen = mr->smr_oidlen;
264 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
266 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
267 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
269 ber_dupbv_x( keys, &digest, ctx );
270 BER_BVZERO( &keys[1] );
278 octetStringSubstringsMatch(
283 struct berval *value,
284 void *assertedValue )
287 SubstringsAssertion *sub = assertedValue;
288 struct berval left = *value;
292 /* Add up asserted input length */
293 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
294 inlen += sub->sa_initial.bv_len;
297 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
298 inlen += sub->sa_any[i].bv_len;
301 if ( !BER_BVISNULL( &sub->sa_final ) ) {
302 inlen += sub->sa_final.bv_len;
305 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
306 if ( inlen > left.bv_len ) {
311 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
312 sub->sa_initial.bv_len );
318 left.bv_val += sub->sa_initial.bv_len;
319 left.bv_len -= sub->sa_initial.bv_len;
320 inlen -= sub->sa_initial.bv_len;
323 if ( !BER_BVISNULL( &sub->sa_final ) ) {
324 if ( inlen > left.bv_len ) {
329 match = memcmp( sub->sa_final.bv_val,
330 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
331 sub->sa_final.bv_len );
337 left.bv_len -= sub->sa_final.bv_len;
338 inlen -= sub->sa_final.bv_len;
342 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
347 if ( inlen > left.bv_len ) {
348 /* not enough length */
353 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
357 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
364 idx = p - left.bv_val;
366 if ( idx >= left.bv_len ) {
367 /* this shouldn't happen */
374 if ( sub->sa_any[i].bv_len > left.bv_len ) {
375 /* not enough left */
380 match = memcmp( left.bv_val,
381 sub->sa_any[i].bv_val,
382 sub->sa_any[i].bv_len );
390 left.bv_val += sub->sa_any[i].bv_len;
391 left.bv_len -= sub->sa_any[i].bv_len;
392 inlen -= sub->sa_any[i].bv_len;
401 /* Substrings Index generation function */
403 octetStringSubstringsIndexer(
408 struct berval *prefix,
417 HASH_CONTEXT HASHcontext;
418 unsigned char HASHdigest[HASH_BYTES];
419 struct berval digest;
420 digest.bv_val = (char *)HASHdigest;
421 digest.bv_len = sizeof(HASHdigest);
425 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
426 /* count number of indices to generate */
427 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
428 if( values[i].bv_len >= index_substr_if_maxlen ) {
429 nkeys += index_substr_if_maxlen -
430 (index_substr_if_minlen - 1);
431 } else if( values[i].bv_len >= index_substr_if_minlen ) {
432 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
436 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
437 if( values[i].bv_len >= index_substr_any_len ) {
438 nkeys += values[i].bv_len - (index_substr_any_len - 1);
442 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
443 if( values[i].bv_len >= index_substr_if_maxlen ) {
444 nkeys += index_substr_if_maxlen -
445 (index_substr_if_minlen - 1);
446 } else if( values[i].bv_len >= index_substr_if_minlen ) {
447 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
453 /* no keys to generate */
458 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
460 slen = syntax->ssyn_oidlen;
461 mlen = mr->smr_oidlen;
464 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
467 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
468 ( values[i].bv_len >= index_substr_any_len ) )
470 char pre = SLAP_INDEX_SUBSTR_PREFIX;
471 max = values[i].bv_len - (index_substr_any_len - 1);
473 for( j=0; j<max; j++ ) {
474 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
475 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
476 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
480 /* skip if too short */
481 if( values[i].bv_len < index_substr_if_minlen ) continue;
483 max = index_substr_if_maxlen < values[i].bv_len
484 ? index_substr_if_maxlen : values[i].bv_len;
486 for( j=index_substr_if_minlen; j<=max; j++ ) {
489 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
490 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
491 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
492 syntax, mr, (unsigned char *)values[i].bv_val, j );
493 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
496 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
497 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
498 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
499 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
500 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
507 BER_BVZERO( &keys[nkeys] );
518 octetStringSubstringsFilter (
523 struct berval *prefix,
524 void * assertedValue,
528 SubstringsAssertion *sa;
531 size_t slen, mlen, klen;
533 HASH_CONTEXT HASHcontext;
534 unsigned char HASHdigest[HASH_BYTES];
535 struct berval *value;
536 struct berval digest;
538 sa = (SubstringsAssertion *) assertedValue;
540 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
541 !BER_BVISNULL( &sa->sa_initial ) &&
542 sa->sa_initial.bv_len >= index_substr_if_minlen )
545 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
546 ( flags & SLAP_INDEX_SUBSTR_ANY ))
548 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
552 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
554 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
555 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
556 /* don't bother accounting with stepping */
557 nkeys += sa->sa_any[i].bv_len -
558 ( index_substr_any_len - 1 );
563 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
564 !BER_BVISNULL( &sa->sa_final ) &&
565 sa->sa_final.bv_len >= index_substr_if_minlen )
568 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
569 ( flags & SLAP_INDEX_SUBSTR_ANY ))
571 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
580 digest.bv_val = (char *)HASHdigest;
581 digest.bv_len = sizeof(HASHdigest);
583 slen = syntax->ssyn_oidlen;
584 mlen = mr->smr_oidlen;
586 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
589 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
590 !BER_BVISNULL( &sa->sa_initial ) &&
591 sa->sa_initial.bv_len >= index_substr_if_minlen )
593 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
594 value = &sa->sa_initial;
596 klen = index_substr_if_maxlen < value->bv_len
597 ? index_substr_if_maxlen : value->bv_len;
599 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
600 syntax, mr, (unsigned char *)value->bv_val, klen );
601 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
603 /* If initial is too long and we have subany indexed, use it
604 * to match the excess...
606 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
609 pre = SLAP_INDEX_SUBSTR_PREFIX;
610 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
612 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
613 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
614 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
619 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
621 pre = SLAP_INDEX_SUBSTR_PREFIX;
622 klen = index_substr_any_len;
624 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
625 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
629 value = &sa->sa_any[i];
632 j <= value->bv_len - index_substr_any_len;
633 j += index_substr_any_step )
635 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
636 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
637 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
642 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
643 !BER_BVISNULL( &sa->sa_final ) &&
644 sa->sa_final.bv_len >= index_substr_if_minlen )
646 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
647 value = &sa->sa_final;
649 klen = index_substr_if_maxlen < value->bv_len
650 ? index_substr_if_maxlen : value->bv_len;
652 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
653 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
654 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 /* If final is too long and we have subany indexed, use it
657 * to match the excess...
659 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
662 pre = SLAP_INDEX_SUBSTR_PREFIX;
663 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
665 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
666 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
667 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
673 BER_BVZERO( &keys[nkeys] );
690 /* very unforgiving validation, requires no normalization
691 * before simplistic matching
693 if( in->bv_len < 3 ) {
694 return LDAP_INVALID_SYNTAX;
698 * RFC 2252 section 6.3 Bit String
699 * bitstring = "'" *binary-digit "'B"
700 * binary-digit = "0" / "1"
701 * example: '0101111101'B
704 if( in->bv_val[0] != '\'' ||
705 in->bv_val[in->bv_len - 2] != '\'' ||
706 in->bv_val[in->bv_len - 1] != 'B' )
708 return LDAP_INVALID_SYNTAX;
711 for( i = in->bv_len - 3; i > 0; i-- ) {
712 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
713 return LDAP_INVALID_SYNTAX;
721 * Syntax is [RFC2252]:
726 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
728 Values in this syntax are encoded according to the following BNF:
730 bitstring = "'" *binary-digit "'B"
732 binary-digit = "0" / "1"
736 6.21. Name And Optional UID
738 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
740 Values in this syntax are encoded according to the following BNF:
742 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
744 Although the '#' character may occur in a string representation of a
745 distinguished name, no additional special quoting is done. This
746 syntax has been added subsequent to RFC 1778.
750 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
753 * draft-ietf-ldapbis-syntaxes-xx.txt says:
758 A value of the Bit String syntax is a sequence of binary digits. The
759 LDAP-specific encoding of a value of this syntax is defined by the
762 BitString = SQUOTE *binary-digit SQUOTE "B"
764 binary-digit = "0" / "1"
766 The <SQUOTE> rule is defined in [MODELS].
771 The LDAP definition for the Bit String syntax is:
773 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
775 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
779 3.3.21. Name and Optional UID
781 A value of the Name and Optional UID syntax is the distinguished name
782 [MODELS] of an entity optionally accompanied by a unique identifier
783 that serves to differentiate the entity from others with an identical
786 The LDAP-specific encoding of a value of this syntax is defined by
789 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
791 The <BitString> rule is defined in Section 3.3.2. The
792 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
795 Note that although the '#' character may occur in the string
796 representation of a distinguished name, no additional escaping of
797 this character is performed when a <distinguishedName> is encoded in
798 a <NameAndOptionalUID>.
801 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
803 The LDAP definition for the Name and Optional UID syntax is:
805 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
807 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
811 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
814 1.4. Common ABNF Productions
817 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
819 SQUOTE = %x27 ; single quote ("'")
823 * Note: normalization strips any leading "0"s, unless the
824 * bit string is exactly "'0'B", so the normalized example,
825 * in slapd, would result in
827 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
829 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
830 * i.e. "#", doesn't have to be escaped except when at the
831 * beginning of a value, the definition of Name and Optional
832 * UID appears to be flawed, because there is no clear means
833 * to determine whether the UID part is present or not.
837 * cn=Someone,dc=example,dc=com#'1'B
839 * could be either a NameAndOptionalUID with trailing UID, i.e.
841 * DN = "cn=Someone,dc=example,dc=com"
844 * or a NameAndOptionalUID with no trailing UID, and the AVA
845 * in the last RDN made of
848 * attributeValue = com#'1'B
850 * in fact "com#'1'B" is a valid IA5 string.
852 * As a consequence, current slapd code assumes that the
853 * presence of portions of a BitString at the end of the string
854 * representation of a NameAndOptionalUID means a BitString
855 * is expected, and cause an error otherwise. This is quite
856 * arbitrary, and might change in the future.
866 struct berval dn, uid;
868 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
870 ber_dupbv( &dn, in );
871 if( !dn.bv_val ) return LDAP_OTHER;
873 /* if there's a "#", try bitStringValidate()... */
874 uid.bv_val = strrchr( dn.bv_val, '#' );
875 if ( !BER_BVISNULL( &uid ) ) {
877 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
879 rc = bitStringValidate( NULL, &uid );
880 if ( rc == LDAP_SUCCESS ) {
881 /* in case of success, trim the UID,
882 * otherwise treat it as part of the DN */
883 dn.bv_len -= uid.bv_len + 1;
884 uid.bv_val[-1] = '\0';
888 rc = dnValidate( NULL, &dn );
890 ber_memfree( dn.bv_val );
901 assert( val != NULL );
902 assert( out != NULL );
905 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
907 if( BER_BVISEMPTY( val ) ) {
908 ber_dupbv_x( out, val, ctx );
910 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
911 return LDAP_INVALID_SYNTAX;
915 struct berval dnval = *val;
916 struct berval uidval = BER_BVNULL;
918 uidval.bv_val = strrchr( val->bv_val, '#' );
919 if ( !BER_BVISNULL( &uidval ) ) {
921 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
923 rc = bitStringValidate( NULL, &uidval );
925 if ( rc == LDAP_SUCCESS ) {
926 ber_dupbv_x( &dnval, val, ctx );
927 dnval.bv_len -= uidval.bv_len + 1;
928 dnval.bv_val[dnval.bv_len] = '\0';
931 BER_BVZERO( &uidval );
935 rc = dnPretty( syntax, &dnval, out, ctx );
936 if ( dnval.bv_val != val->bv_val ) {
937 slap_sl_free( dnval.bv_val, ctx );
939 if( rc != LDAP_SUCCESS ) {
943 if( !BER_BVISNULL( &uidval ) ) {
947 tmp = slap_sl_realloc( out->bv_val, out->bv_len
948 + STRLENOF( "#" ) + uidval.bv_len + 1,
951 ber_memfree_x( out->bv_val, ctx );
955 out->bv_val[out->bv_len++] = '#';
956 out->bv_val[out->bv_len++] = '\'';
958 got1 = uidval.bv_len < sizeof("'0'B");
959 for( i = 1; i < uidval.bv_len - 2; i++ ) {
960 c = uidval.bv_val[i];
963 if( got1 ) out->bv_val[out->bv_len++] = c;
967 out->bv_val[out->bv_len++] = c;
972 out->bv_val[out->bv_len++] = '\'';
973 out->bv_val[out->bv_len++] = 'B';
974 out->bv_val[out->bv_len] = '\0';
978 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
984 uniqueMemberNormalize(
989 struct berval *normalized,
995 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
997 ber_dupbv_x( &out, val, ctx );
998 if ( BER_BVISEMPTY( &out ) ) {
1002 struct berval uid = BER_BVNULL;
1004 uid.bv_val = strrchr( out.bv_val, '#' );
1005 if ( !BER_BVISNULL( &uid ) ) {
1007 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1009 rc = bitStringValidate( NULL, &uid );
1010 if ( rc == LDAP_SUCCESS ) {
1011 uid.bv_val[-1] = '\0';
1012 out.bv_len -= uid.bv_len + 1;
1018 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1020 if( rc != LDAP_SUCCESS ) {
1021 slap_sl_free( out.bv_val, ctx );
1022 return LDAP_INVALID_SYNTAX;
1025 if( !BER_BVISNULL( &uid ) ) {
1028 tmp = ch_realloc( normalized->bv_val,
1029 normalized->bv_len + uid.bv_len
1030 + STRLENOF("#") + 1 );
1031 if ( tmp == NULL ) {
1032 ber_memfree_x( normalized->bv_val, ctx );
1036 normalized->bv_val = tmp;
1038 /* insert the separator */
1039 normalized->bv_val[normalized->bv_len++] = '#';
1041 /* append the UID */
1042 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1043 uid.bv_val, uid.bv_len );
1044 normalized->bv_len += uid.bv_len;
1047 normalized->bv_val[normalized->bv_len] = '\0';
1050 slap_sl_free( out.bv_val, ctx );
1053 return LDAP_SUCCESS;
1062 struct berval *value,
1063 void *assertedValue )
1066 struct berval *asserted = (struct berval *) assertedValue;
1067 struct berval assertedDN = *asserted;
1068 struct berval assertedUID = BER_BVNULL;
1069 struct berval valueDN = BER_BVNULL;
1070 struct berval valueUID = BER_BVNULL;
1071 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1073 if ( !BER_BVISEMPTY( asserted ) ) {
1074 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1075 if ( !BER_BVISNULL( &assertedUID ) ) {
1076 assertedUID.bv_val++;
1077 assertedUID.bv_len = assertedDN.bv_len
1078 - ( assertedUID.bv_val - assertedDN.bv_val );
1080 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1081 assertedDN.bv_len -= assertedUID.bv_len + 1;
1084 BER_BVZERO( &assertedUID );
1090 if ( !BER_BVISEMPTY( value ) ) {
1092 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1093 if ( !BER_BVISNULL( &valueUID ) ) {
1095 valueUID.bv_len = valueDN.bv_len
1096 - ( valueUID.bv_val - valueDN.bv_val );
1098 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1099 valueDN.bv_len -= valueUID.bv_len + 1;
1102 BER_BVZERO( &valueUID );
1107 if( valueUID.bv_len && assertedUID.bv_len ) {
1108 match = valueUID.bv_len - assertedUID.bv_len;
1111 return LDAP_SUCCESS;
1114 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1117 return LDAP_SUCCESS;
1120 } else if ( !approx && valueUID.bv_len ) {
1123 return LDAP_SUCCESS;
1125 } else if ( !approx && assertedUID.bv_len ) {
1128 return LDAP_SUCCESS;
1131 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1135 uniqueMemberIndexer(
1140 struct berval *prefix,
1148 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1149 /* just count them */
1153 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1155 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1156 struct berval assertedDN = values[i];
1157 struct berval assertedUID = BER_BVNULL;
1159 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1160 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1161 if ( !BER_BVISNULL( &assertedUID ) ) {
1162 assertedUID.bv_val++;
1163 assertedUID.bv_len = assertedDN.bv_len
1164 - ( assertedUID.bv_val - assertedDN.bv_val );
1166 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1167 assertedDN.bv_len -= assertedUID.bv_len + 1;
1170 BER_BVZERO( &assertedUID );
1175 dnvalues[i] = assertedDN;
1177 BER_BVZERO( &dnvalues[i] );
1179 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1180 dnvalues, keysp, ctx );
1182 slap_sl_free( dnvalues, ctx );
1192 struct berval *prefix,
1193 void * assertedValue,
1197 struct berval *asserted = (struct berval *) assertedValue;
1198 struct berval assertedDN = *asserted;
1199 struct berval assertedUID = BER_BVNULL;
1201 if ( !BER_BVISEMPTY( asserted ) ) {
1202 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1203 if ( !BER_BVISNULL( &assertedUID ) ) {
1204 assertedUID.bv_val++;
1205 assertedUID.bv_len = assertedDN.bv_len
1206 - ( assertedUID.bv_val - assertedDN.bv_val );
1208 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1209 assertedDN.bv_len -= assertedUID.bv_len + 1;
1212 BER_BVZERO( &assertedUID );
1217 return octetStringFilter( use, flags, syntax, mr, prefix,
1218 &assertedDN, keysp, ctx );
1223 * Handling boolean syntax and matching is quite rigid.
1224 * A more flexible approach would be to allow a variety
1225 * of strings to be normalized and prettied into TRUE
1233 /* very unforgiving validation, requires no normalization
1234 * before simplistic matching
1237 if( in->bv_len == 4 ) {
1238 if( bvmatch( in, &slap_true_bv ) ) {
1239 return LDAP_SUCCESS;
1241 } else if( in->bv_len == 5 ) {
1242 if( bvmatch( in, &slap_false_bv ) ) {
1243 return LDAP_SUCCESS;
1247 return LDAP_INVALID_SYNTAX;
1256 struct berval *value,
1257 void *assertedValue )
1259 /* simplistic matching allowed by rigid validation */
1260 struct berval *asserted = (struct berval *) assertedValue;
1261 *matchp = value->bv_len != asserted->bv_len;
1262 return LDAP_SUCCESS;
1265 /*-------------------------------------------------------------------
1266 LDAP/X.500 string syntax / matching rules have a few oddities. This
1267 comment attempts to detail how slapd(8) treats them.
1270 StringSyntax X.500 LDAP Matching/Comments
1271 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1272 PrintableString subset subset i/e + ignore insignificant spaces
1273 PrintableString subset subset i/e + ignore insignificant spaces
1274 NumericString subset subset ignore all spaces
1275 IA5String ASCII ASCII i/e + ignore insignificant spaces
1276 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1278 TelephoneNumber subset subset i + ignore all spaces and "-"
1280 See draft-ietf-ldapbis-strpro for details (once published).
1284 In X.500(93), a directory string can be either a PrintableString,
1285 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1286 In later versions, more CHOICEs were added. In all cases the string
1289 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1290 A directory string cannot be zero length.
1292 For matching, there are both case ignore and exact rules. Both
1293 also require that "insignificant" spaces be ignored.
1294 spaces before the first non-space are ignored;
1295 spaces after the last non-space are ignored;
1296 spaces after a space are ignored.
1297 Note: by these rules (and as clarified in X.520), a string of only
1298 spaces is to be treated as if held one space, not empty (which
1299 would be a syntax error).
1302 In ASN.1, numeric string is just a string of digits and spaces
1303 and could be empty. However, in X.500, all attribute values of
1304 numeric string carry a non-empty constraint. For example:
1306 internationalISDNNumber ATTRIBUTE ::= {
1307 WITH SYNTAX InternationalISDNNumber
1308 EQUALITY MATCHING RULE numericStringMatch
1309 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1310 ID id-at-internationalISDNNumber }
1311 InternationalISDNNumber ::=
1312 NumericString (SIZE(1..ub-international-isdn-number))
1314 Unforunately, some assertion values are don't carry the same
1315 constraint (but its unclear how such an assertion could ever
1316 be true). In LDAP, there is one syntax (numericString) not two
1317 (numericString with constraint, numericString without constraint).
1318 This should be treated as numericString with non-empty constraint.
1319 Note that while someone may have no ISDN number, there are no ISDN
1320 numbers which are zero length.
1322 In matching, spaces are ignored.
1325 In ASN.1, Printable string is just a string of printable characters
1326 and can be empty. In X.500, semantics much like NumericString (see
1327 serialNumber for a like example) excepting uses insignificant space
1328 handling instead of ignore all spaces.
1331 Basically same as PrintableString. There are no examples in X.500,
1332 but same logic applies. So we require them to be non-empty as
1335 -------------------------------------------------------------------*/
1344 unsigned char *u = (unsigned char *)in->bv_val;
1346 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1347 /* directory strings cannot be empty */
1348 return LDAP_INVALID_SYNTAX;
1351 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1352 /* get the length indicated by the first byte */
1353 len = LDAP_UTF8_CHARLEN2( u, len );
1355 /* very basic checks */
1358 if( (u[5] & 0xC0) != 0x80 ) {
1359 return LDAP_INVALID_SYNTAX;
1362 if( (u[4] & 0xC0) != 0x80 ) {
1363 return LDAP_INVALID_SYNTAX;
1366 if( (u[3] & 0xC0) != 0x80 ) {
1367 return LDAP_INVALID_SYNTAX;
1370 if( (u[2] & 0xC0 )!= 0x80 ) {
1371 return LDAP_INVALID_SYNTAX;
1374 if( (u[1] & 0xC0) != 0x80 ) {
1375 return LDAP_INVALID_SYNTAX;
1378 /* CHARLEN already validated it */
1381 return LDAP_INVALID_SYNTAX;
1384 /* make sure len corresponds with the offset
1385 to the next character */
1386 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1390 return LDAP_INVALID_SYNTAX;
1393 return LDAP_SUCCESS;
1397 UTF8StringNormalize(
1402 struct berval *normalized,
1405 struct berval tmp, nvalue;
1409 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1411 if( BER_BVISNULL( val ) ) {
1412 /* assume we're dealing with a syntax (e.g., UTF8String)
1413 * which allows empty strings
1415 BER_BVZERO( normalized );
1416 return LDAP_SUCCESS;
1419 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1420 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1421 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1422 ? LDAP_UTF8_APPROX : 0;
1424 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1429 /* collapse spaces (in place) */
1431 nvalue.bv_val = tmp.bv_val;
1433 /* trim leading spaces? */
1434 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1435 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1437 for( i = 0; i < tmp.bv_len; i++) {
1438 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1439 if( wasspace++ == 0 ) {
1440 /* trim repeated spaces */
1441 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1445 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1449 if( !BER_BVISEMPTY( &nvalue ) ) {
1450 /* trim trailing space? */
1452 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1453 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1457 nvalue.bv_val[nvalue.bv_len] = '\0';
1460 /* string of all spaces is treated as one space */
1461 nvalue.bv_val[0] = ' ';
1462 nvalue.bv_val[1] = '\0';
1466 *normalized = nvalue;
1467 return LDAP_SUCCESS;
1471 directoryStringSubstringsMatch(
1476 struct berval *value,
1477 void *assertedValue )
1480 SubstringsAssertion *sub = assertedValue;
1481 struct berval left = *value;
1485 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1486 if ( sub->sa_initial.bv_len > left.bv_len ) {
1487 /* not enough left */
1492 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1493 sub->sa_initial.bv_len );
1499 left.bv_val += sub->sa_initial.bv_len;
1500 left.bv_len -= sub->sa_initial.bv_len;
1502 priorspace = ASCII_SPACE(
1503 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1506 if ( sub->sa_any ) {
1507 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1511 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1512 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1514 /* allow next space to match */
1521 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1525 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1526 /* not enough left */
1531 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1538 idx = p - left.bv_val;
1540 if ( idx >= left.bv_len ) {
1541 /* this shouldn't happen */
1548 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1549 /* not enough left */
1554 match = memcmp( left.bv_val,
1555 sub->sa_any[i].bv_val,
1556 sub->sa_any[i].bv_len );
1564 left.bv_val += sub->sa_any[i].bv_len;
1565 left.bv_len -= sub->sa_any[i].bv_len;
1567 priorspace = ASCII_SPACE(
1568 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1572 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1573 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1574 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1576 /* allow next space to match */
1581 if ( sub->sa_final.bv_len > left.bv_len ) {
1582 /* not enough left */
1587 match = memcmp( sub->sa_final.bv_val,
1588 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1589 sub->sa_final.bv_len );
1598 return LDAP_SUCCESS;
1601 #if defined(SLAPD_APPROX_INITIALS)
1602 # define SLAPD_APPROX_DELIMITER "._ "
1603 # define SLAPD_APPROX_WORDLEN 2
1605 # define SLAPD_APPROX_DELIMITER " "
1606 # define SLAPD_APPROX_WORDLEN 1
1615 struct berval *value,
1616 void *assertedValue )
1618 struct berval *nval, *assertv;
1619 char *val, **values, **words, *c;
1620 int i, count, len, nextchunk=0, nextavail=0;
1622 /* Yes, this is necessary */
1623 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1624 if( nval == NULL ) {
1626 return LDAP_SUCCESS;
1629 /* Yes, this is necessary */
1630 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1631 NULL, LDAP_UTF8_APPROX, NULL );
1632 if( assertv == NULL ) {
1635 return LDAP_SUCCESS;
1638 /* Isolate how many words there are */
1639 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1640 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1641 if ( c == NULL ) break;
1646 /* Get a phonetic copy of each word */
1647 words = (char **)ch_malloc( count * sizeof(char *) );
1648 values = (char **)ch_malloc( count * sizeof(char *) );
1649 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1651 values[i] = phonetic(c);
1654 /* Work through the asserted value's words, to see if at least some
1655 of the words are there, in the same order. */
1657 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1658 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1663 #if defined(SLAPD_APPROX_INITIALS)
1664 else if( len == 1 ) {
1665 /* Single letter words need to at least match one word's initial */
1666 for( i=nextavail; i<count; i++ )
1667 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1674 /* Isolate the next word in the asserted value and phonetic it */
1675 assertv->bv_val[nextchunk+len] = '\0';
1676 val = phonetic( assertv->bv_val + nextchunk );
1678 /* See if this phonetic chunk is in the remaining words of *value */
1679 for( i=nextavail; i<count; i++ ){
1680 if( !strcmp( val, values[i] ) ){
1688 /* This chunk in the asserted value was NOT within the *value. */
1694 /* Go on to the next word in the asserted value */
1698 /* If some of the words were seen, call it a match */
1699 if( nextavail > 0 ) {
1706 /* Cleanup allocs */
1707 ber_bvfree( assertv );
1708 for( i=0; i<count; i++ ) {
1709 ch_free( values[i] );
1715 return LDAP_SUCCESS;
1724 struct berval *prefix,
1730 int i,j, len, wordcount, keycount=0;
1731 struct berval *newkeys;
1732 BerVarray keys=NULL;
1734 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1735 struct berval val = BER_BVNULL;
1736 /* Yes, this is necessary */
1737 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1738 assert( !BER_BVISNULL( &val ) );
1740 /* Isolate how many words there are. There will be a key for each */
1741 for( wordcount = 0, c = val.bv_val; *c; c++) {
1742 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1743 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1745 if (*c == '\0') break;
1749 /* Allocate/increase storage to account for new keys */
1750 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1751 * sizeof(struct berval) );
1752 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1753 if( keys ) ch_free( keys );
1756 /* Get a phonetic copy of each word */
1757 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1759 if( len < SLAPD_APPROX_WORDLEN ) continue;
1760 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1765 ber_memfree( val.bv_val );
1767 BER_BVZERO( &keys[keycount] );
1770 return LDAP_SUCCESS;
1779 struct berval *prefix,
1780 void * assertedValue,
1789 /* Yes, this is necessary */
1790 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1791 NULL, LDAP_UTF8_APPROX, NULL );
1792 if( val == NULL || BER_BVISNULL( val ) ) {
1793 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1794 BER_BVZERO( &keys[0] );
1797 return LDAP_SUCCESS;
1800 /* Isolate how many words there are. There will be a key for each */
1801 for( count = 0,c = val->bv_val; *c; c++) {
1802 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1803 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1805 if (*c == '\0') break;
1809 /* Allocate storage for new keys */
1810 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1812 /* Get a phonetic copy of each word */
1813 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1815 if( len < SLAPD_APPROX_WORDLEN ) continue;
1816 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1822 BER_BVZERO( &keys[count] );
1825 return LDAP_SUCCESS;
1828 /* Remove all spaces and '-' characters */
1830 telephoneNumberNormalize(
1835 struct berval *normalized,
1840 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1842 /* validator should have refused an empty string */
1843 assert( !BER_BVISEMPTY( val ) );
1845 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1847 for( p = val->bv_val; *p; p++ ) {
1848 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1854 normalized->bv_len = q - normalized->bv_val;
1856 if( BER_BVISEMPTY( normalized ) ) {
1857 slap_sl_free( normalized->bv_val, ctx );
1858 BER_BVZERO( normalized );
1859 return LDAP_INVALID_SYNTAX;
1862 return LDAP_SUCCESS;
1870 struct berval val = *in;
1872 if( BER_BVISEMPTY( &val ) ) {
1873 /* disallow empty strings */
1874 return LDAP_INVALID_SYNTAX;
1877 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1878 if ( val.bv_len == 1 ) {
1879 return LDAP_SUCCESS;
1882 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1889 while ( OID_LEADCHAR( val.bv_val[0] )) {
1893 if ( val.bv_len == 0 ) {
1894 return LDAP_SUCCESS;
1898 if( !OID_SEPARATOR( val.bv_val[0] )) {
1906 return LDAP_INVALID_SYNTAX;
1915 struct berval val = *in;
1917 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1919 if ( val.bv_val[0] == '-' ) {
1923 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1924 return LDAP_INVALID_SYNTAX;
1927 if( val.bv_val[0] == '0' ) { /* "-0" */
1928 return LDAP_INVALID_SYNTAX;
1931 } else if ( val.bv_val[0] == '0' ) {
1932 if( val.bv_len > 1 ) { /* "0<more>" */
1933 return LDAP_INVALID_SYNTAX;
1936 return LDAP_SUCCESS;
1939 for( i=0; i < val.bv_len; i++ ) {
1940 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1941 return LDAP_INVALID_SYNTAX;
1945 return LDAP_SUCCESS;
1954 struct berval *value,
1955 void *assertedValue )
1957 struct berval *asserted = (struct berval *) assertedValue;
1958 int vsign = 1, asign = 1; /* default sign = '+' */
1963 if( v.bv_val[0] == '-' ) {
1969 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1972 if( a.bv_val[0] == '-' ) {
1978 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1980 match = vsign - asign;
1982 match = ( v.bv_len != a.bv_len
1983 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1984 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1985 if( vsign < 0 ) match = -match;
1989 return LDAP_SUCCESS;
1993 countryStringValidate(
1995 struct berval *val )
1997 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1999 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2000 return LDAP_INVALID_SYNTAX;
2002 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2003 return LDAP_INVALID_SYNTAX;
2006 return LDAP_SUCCESS;
2010 printableStringValidate(
2012 struct berval *val )
2016 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2018 for(i=0; i < val->bv_len; i++) {
2019 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2020 return LDAP_INVALID_SYNTAX;
2024 return LDAP_SUCCESS;
2028 printablesStringValidate(
2030 struct berval *val )
2034 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2036 for(i=0,len=0; i < val->bv_len; i++) {
2037 int c = val->bv_val[i];
2041 return LDAP_INVALID_SYNTAX;
2045 } else if ( SLAP_PRINTABLE(c) ) {
2048 return LDAP_INVALID_SYNTAX;
2053 return LDAP_INVALID_SYNTAX;
2056 return LDAP_SUCCESS;
2062 struct berval *val )
2066 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2068 for(i=0; i < val->bv_len; i++) {
2069 if( !LDAP_ASCII(val->bv_val[i]) ) {
2070 return LDAP_INVALID_SYNTAX;
2074 return LDAP_SUCCESS;
2083 struct berval *normalized,
2087 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2089 assert( !BER_BVISEMPTY( val ) );
2091 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2095 /* Ignore initial whitespace */
2096 while ( ASCII_SPACE( *p ) ) p++;
2098 normalized->bv_val = ber_strdup_x( p, ctx );
2099 p = q = normalized->bv_val;
2102 if ( ASCII_SPACE( *p ) ) {
2105 /* Ignore the extra whitespace */
2106 while ( ASCII_SPACE( *p ) ) {
2110 } else if ( casefold ) {
2111 /* Most IA5 rules require casefolding */
2112 *q++ = TOLOWER(*p); p++;
2119 assert( normalized->bv_val <= p );
2123 * If the string ended in space, backup the pointer one
2124 * position. One is enough because the above loop collapsed
2125 * all whitespace to a single space.
2127 if ( ASCII_SPACE( q[-1] ) ) --q;
2129 /* null terminate */
2132 normalized->bv_len = q - normalized->bv_val;
2133 if( BER_BVISEMPTY( normalized ) ) {
2134 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2135 normalized->bv_val[0] = ' ';
2136 normalized->bv_val[1] = '\0';
2137 normalized->bv_len = 1;
2140 return LDAP_SUCCESS;
2149 if( in->bv_len != 36 ) {
2150 return LDAP_INVALID_SYNTAX;
2153 for( i=0; i<36; i++ ) {
2159 if( in->bv_val[i] != '-' ) {
2160 return LDAP_INVALID_SYNTAX;
2164 if( !ASCII_HEX( in->bv_val[i]) ) {
2165 return LDAP_INVALID_SYNTAX;
2170 return LDAP_SUCCESS;
2179 struct berval *normalized,
2182 unsigned char octet = '\0';
2185 normalized->bv_len = 16;
2186 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2188 for( i=0, j=0; i<36; i++ ) {
2189 unsigned char nibble;
2190 if( val->bv_val[i] == '-' ) {
2193 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2194 nibble = val->bv_val[i] - '0';
2196 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2197 nibble = val->bv_val[i] - ('a'-10);
2199 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2200 nibble = val->bv_val[i] - ('A'-10);
2203 slap_sl_free( normalized->bv_val, ctx );
2204 return LDAP_INVALID_SYNTAX;
2209 normalized->bv_val[j>>1] = octet;
2211 octet = nibble << 4;
2216 normalized->bv_val[normalized->bv_len] = 0;
2217 return LDAP_SUCCESS;
2223 numericStringValidate(
2229 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2231 for(i=0; i < in->bv_len; i++) {
2232 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2233 return LDAP_INVALID_SYNTAX;
2237 return LDAP_SUCCESS;
2241 numericStringNormalize(
2246 struct berval *normalized,
2249 /* removal all spaces */
2252 assert( !BER_BVISEMPTY( val ) );
2254 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2257 q = normalized->bv_val;
2260 if ( ASCII_SPACE( *p ) ) {
2261 /* Ignore whitespace */
2268 /* we should have copied no more then is in val */
2269 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2271 /* null terminate */
2274 normalized->bv_len = q - normalized->bv_val;
2276 if( BER_BVISEMPTY( normalized ) ) {
2277 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2278 normalized->bv_val[0] = ' ';
2279 normalized->bv_val[1] = '\0';
2280 normalized->bv_len = 1;
2283 return LDAP_SUCCESS;
2287 * Integer conversion macros that will use the largest available
2290 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2291 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2292 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2293 # define SLAP_LONG_MAX LLONG_MAX
2294 # define SLAP_LONG_MIN LLONG_MIN
2295 # define SLAP_LONG long long
2297 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2298 # define SLAP_LONG_MAX LONG_MAX
2299 # define SLAP_LONG_MIN LONG_MIN
2300 # define SLAP_LONG long
2301 #endif /* HAVE_STRTOLL ... */
2309 struct berval *value,
2310 void *assertedValue )
2312 SLAP_LONG lValue, lAssertedValue;
2314 /* safe to assume integers are NUL terminated? */
2315 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2316 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2319 return LDAP_CONSTRAINT_VIOLATION;
2322 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2324 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2327 return LDAP_CONSTRAINT_VIOLATION;
2330 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2331 return LDAP_SUCCESS;
2340 struct berval *value,
2341 void *assertedValue )
2343 SLAP_LONG lValue, lAssertedValue;
2345 /* safe to assume integers are NUL terminated? */
2346 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2347 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2350 return LDAP_CONSTRAINT_VIOLATION;
2353 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2355 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2358 return LDAP_CONSTRAINT_VIOLATION;
2361 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2362 return LDAP_SUCCESS;
2366 serialNumberAndIssuerValidate(
2372 struct berval sn, i;
2373 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2375 i.bv_val = strchr( in->bv_val, '$' );
2376 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2378 sn.bv_val = in->bv_val;
2379 sn.bv_len = i.bv_val - in->bv_val;
2382 i.bv_len = in->bv_len - (sn.bv_len + 1);
2384 /* validate serial number (strict for now) */
2385 for( n=0; n < sn.bv_len; n++ ) {
2386 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2390 rc = dnValidate( NULL, &i );
2391 if( rc ) return LDAP_INVALID_SYNTAX;
2393 return LDAP_SUCCESS;
2397 serialNumberAndIssuerPretty(
2405 struct berval sn, i, newi;
2407 assert( val != NULL );
2408 assert( out != NULL );
2410 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2411 val->bv_val, 0, 0 );
2413 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2415 i.bv_val = strchr( val->bv_val, '$' );
2416 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2418 sn.bv_val = val->bv_val;
2419 sn.bv_len = i.bv_val - val->bv_val;
2422 i.bv_len = val->bv_len - (sn.bv_len + 1);
2424 /* eat leading zeros */
2425 for( n=0; n < (sn.bv_len-1); n++ ) {
2426 if( sn.bv_val[n] != '0' ) break;
2431 for( n=0; n < sn.bv_len; n++ ) {
2432 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2436 rc = dnPretty( syntax, &i, &newi, ctx );
2437 if( rc ) return LDAP_INVALID_SYNTAX;
2439 /* make room from sn + "$" */
2440 out->bv_len = sn.bv_len + newi.bv_len + 1;
2441 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2443 if( out->bv_val == NULL ) {
2445 slap_sl_free( newi.bv_val, ctx );
2449 /* push issuer over */
2450 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2451 /* insert sn and "$" */
2452 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2453 out->bv_val[sn.bv_len] = '$';
2455 out->bv_val[out->bv_len] = '\0';
2457 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2458 out->bv_val, 0, 0 );
2460 return LDAP_SUCCESS;
2464 * This routine is called by certificateExactNormalize when
2465 * certificateExactNormalize receives a search string instead of
2466 * a certificate. This routine checks if the search value is valid
2467 * and then returns the normalized value
2470 serialNumberAndIssuerNormalize(
2480 struct berval sn, i, newi;
2482 assert( val != NULL );
2483 assert( out != NULL );
2485 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2486 val->bv_val, 0, 0 );
2488 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2490 i.bv_val = strchr( val->bv_val, '$' );
2491 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2493 sn.bv_val = val->bv_val;
2494 sn.bv_len = i.bv_val - val->bv_val;
2497 i.bv_len = val->bv_len - (sn.bv_len + 1);
2499 /* eat leading zeros */
2500 for( n=0; n < (sn.bv_len-1); n++ ) {
2501 if( sn.bv_val[n] != '0' ) break;
2506 for( n=0; n < sn.bv_len; n++ ) {
2507 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2508 return LDAP_INVALID_SYNTAX;
2513 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2514 if( rc ) return LDAP_INVALID_SYNTAX;
2516 /* make room from sn + "$" */
2517 out->bv_len = sn.bv_len + newi.bv_len + 1;
2518 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2520 if( out->bv_val == NULL ) {
2522 slap_sl_free( newi.bv_val, ctx );
2526 /* push issuer over */
2527 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2528 /* insert sn and "$" */
2529 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2530 out->bv_val[sn.bv_len] = '$';
2532 out->bv_val[out->bv_len] = '\0';
2534 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2535 out->bv_val, 0, 0 );
2542 certificateExactNormalize(
2547 struct berval *normalized,
2550 int rc = LDAP_INVALID_SYNTAX;
2552 char *serial = NULL;
2553 ber_len_t seriallen;
2554 struct berval issuer_dn = BER_BVNULL;
2555 X509_NAME *name = NULL;
2556 ASN1_INTEGER *sn = NULL;
2559 if( BER_BVISEMPTY( val ) ) goto done;
2561 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2562 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2565 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2567 p = (unsigned char *)val->bv_val;
2568 xcert = d2i_X509( NULL, &p, val->bv_len);
2569 if( xcert == NULL ) goto done;
2571 sn=X509_get_serialNumber(xcert);
2572 if ( sn == NULL ) goto done;
2573 serial=i2s_ASN1_INTEGER(0, sn );
2574 if( serial == NULL ) goto done;
2575 seriallen=strlen(serial);
2577 name=X509_get_issuer_name(xcert);
2578 if( name == NULL ) goto done;
2579 rc = dnX509normalize( name, &issuer_dn );
2580 if( rc != LDAP_SUCCESS ) goto done;
2582 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2583 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2584 p = (unsigned char *)normalized->bv_val;
2585 AC_MEMCPY(p, serial, seriallen);
2588 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2589 p += issuer_dn.bv_len;
2592 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2593 normalized->bv_val, NULL, NULL );
2596 if (xcert) X509_free(xcert);
2597 if (serial) ch_free(serial);
2598 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2602 #endif /* HAVE_TLS */
2605 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2606 /* slight optimization - does not need the start parameter */
2607 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2612 check_time_syntax (struct berval *val,
2615 struct berval *fraction)
2618 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2619 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2620 * GeneralizedTime supports leap seconds, UTCTime does not.
2622 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2623 static const int mdays[2][12] = {
2624 /* non-leap years */
2625 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2627 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2630 int part, c, c1, c2, tzoffset, leapyear = 0;
2633 e = p + val->bv_len;
2635 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2636 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2638 for (part = start; part < 7 && p < e; part++) {
2640 if (!ASCII_DIGIT(c1)) {
2645 return LDAP_INVALID_SYNTAX;
2648 if (!ASCII_DIGIT(c)) {
2649 return LDAP_INVALID_SYNTAX;
2651 c += c1 * 10 - '0' * 11;
2652 if ((part | 1) == 3) {
2655 return LDAP_INVALID_SYNTAX;
2658 if (c >= ceiling[part]) {
2659 if (! (c == 60 && part == 6 && start == 0))
2660 return LDAP_INVALID_SYNTAX;
2664 if (part < 5 + start) {
2665 return LDAP_INVALID_SYNTAX;
2667 for (; part < 9; part++) {
2671 /* leapyear check for the Gregorian calendar (year>1581) */
2672 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2676 if (parts[3] >= mdays[leapyear][parts[2]]) {
2677 return LDAP_INVALID_SYNTAX;
2681 fraction->bv_val = p;
2682 fraction->bv_len = 0;
2683 if (p < e && (*p == '.' || *p == ',')) {
2685 while (++p < e && ASCII_DIGIT(*p)) {
2688 if (p - fraction->bv_val == 1) {
2689 return LDAP_INVALID_SYNTAX;
2691 for (end_num = p; end_num[-1] == '0'; --end_num) {
2694 c = end_num - fraction->bv_val;
2695 if (c != 1) fraction->bv_len = c;
2701 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2707 return LDAP_INVALID_SYNTAX;
2713 for (part = 7; part < 9 && p < e; part++) {
2715 if (!ASCII_DIGIT(c1)) {
2720 return LDAP_INVALID_SYNTAX;
2723 if (!ASCII_DIGIT(c2)) {
2724 return LDAP_INVALID_SYNTAX;
2726 parts[part] = c1 * 10 + c2 - '0' * 11;
2727 if (parts[part] >= ceiling[part]) {
2728 return LDAP_INVALID_SYNTAX;
2731 if (part < 8 + start) {
2732 return LDAP_INVALID_SYNTAX;
2735 if (tzoffset == '-') {
2736 /* negative offset to UTC, ie west of Greenwich */
2737 parts[4] += parts[7];
2738 parts[5] += parts[8];
2739 /* offset is just hhmm, no seconds */
2740 for (part = 6; --part >= 0; ) {
2744 c = mdays[leapyear][parts[2]];
2746 if (parts[part] >= c) {
2748 return LDAP_INVALID_SYNTAX;
2753 } else if (part != 5) {
2758 /* positive offset to UTC, ie east of Greenwich */
2759 parts[4] -= parts[7];
2760 parts[5] -= parts[8];
2761 for (part = 6; --part >= 0; ) {
2762 if (parts[part] < 0) {
2764 return LDAP_INVALID_SYNTAX;
2769 /* make first arg to % non-negative */
2770 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2775 } else if (part != 5) {
2782 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2785 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2792 struct berval *normalized )
2796 rc = check_time_syntax(val, 1, parts, NULL);
2797 if (rc != LDAP_SUCCESS) {
2801 normalized->bv_val = ch_malloc( 14 );
2802 if ( normalized->bv_val == NULL ) {
2803 return LBER_ERROR_MEMORY;
2806 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2807 parts[1], parts[2] + 1, parts[3] + 1,
2808 parts[4], parts[5], parts[6] );
2809 normalized->bv_len = 13;
2811 return LDAP_SUCCESS;
2821 return check_time_syntax(in, 1, parts, NULL);
2824 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2827 generalizedTimeValidate(
2832 struct berval fraction;
2833 return check_time_syntax(in, 0, parts, &fraction);
2837 generalizedTimeNormalize(
2842 struct berval *normalized,
2847 struct berval fraction;
2849 rc = check_time_syntax(val, 0, parts, &fraction);
2850 if (rc != LDAP_SUCCESS) {
2854 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2855 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2856 if ( BER_BVISNULL( normalized ) ) {
2857 return LBER_ERROR_MEMORY;
2860 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2861 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2862 parts[4], parts[5], parts[6] );
2863 if ( !BER_BVISEMPTY( &fraction ) ) {
2864 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2865 fraction.bv_val, fraction.bv_len );
2866 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2868 strcpy( normalized->bv_val + len-1, "Z" );
2869 normalized->bv_len = len;
2871 return LDAP_SUCCESS;
2875 generalizedTimeOrderingMatch(
2880 struct berval *value,
2881 void *assertedValue )
2883 struct berval *asserted = (struct berval *) assertedValue;
2884 ber_len_t v_len = value->bv_len;
2885 ber_len_t av_len = asserted->bv_len;
2887 /* ignore trailing 'Z' when comparing */
2888 int match = memcmp( value->bv_val, asserted->bv_val,
2889 (v_len < av_len ? v_len : av_len) - 1 );
2890 if ( match == 0 ) match = v_len - av_len;
2893 return LDAP_SUCCESS;
2896 /* Index generation function */
2897 int generalizedTimeIndexer(
2902 struct berval *prefix,
2910 BerValue bvtmp; /* 40 bit index */
2912 struct lutil_timet tt;
2914 bvtmp.bv_len = sizeof(tmp);
2916 for( i=0; values[i].bv_val != NULL; i++ ) {
2917 /* just count them */
2920 /* we should have at least one value at this point */
2923 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2925 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2926 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2927 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2928 /* Use 40 bits of time for key */
2929 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2930 lutil_tm2time( &tm, &tt );
2931 tmp[0] = tt.tt_gsec & 0xff;
2932 tmp[4] = tt.tt_sec & 0xff;
2934 tmp[3] = tt.tt_sec & 0xff;
2936 tmp[2] = tt.tt_sec & 0xff;
2938 tmp[1] = tt.tt_sec & 0xff;
2940 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2944 keys[j].bv_val = NULL;
2949 return LDAP_SUCCESS;
2952 /* Index generation function */
2953 int generalizedTimeFilter(
2958 struct berval *prefix,
2959 void * assertedValue,
2965 BerValue bvtmp; /* 40 bit index */
2966 BerValue *value = (BerValue *) assertedValue;
2968 struct lutil_timet tt;
2970 bvtmp.bv_len = sizeof(tmp);
2972 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2973 /* Use 40 bits of time for key */
2974 if ( value->bv_val && value->bv_len >= 10 &&
2975 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2977 lutil_tm2time( &tm, &tt );
2978 tmp[0] = tt.tt_gsec & 0xff;
2979 tmp[4] = tt.tt_sec & 0xff;
2981 tmp[3] = tt.tt_sec & 0xff;
2983 tmp[2] = tt.tt_sec & 0xff;
2985 tmp[1] = tt.tt_sec & 0xff;
2987 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2988 ber_dupbv_x(keys, &bvtmp, ctx );
2989 keys[1].bv_val = NULL;
2997 return LDAP_SUCCESS;
3001 deliveryMethodValidate(
3003 struct berval *val )
3006 #define LENOF(s) (sizeof(s)-1)
3007 struct berval tmp = *val;
3009 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3010 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3011 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3014 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3016 switch( tmp.bv_val[0] ) {
3019 if(( tmp.bv_len >= LENOF("any") ) &&
3020 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3022 tmp.bv_len -= LENOF("any");
3023 tmp.bv_val += LENOF("any");
3026 return LDAP_INVALID_SYNTAX;
3030 if(( tmp.bv_len >= LENOF("mhs") ) &&
3031 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3033 tmp.bv_len -= LENOF("mhs");
3034 tmp.bv_val += LENOF("mhs");
3037 return LDAP_INVALID_SYNTAX;
3041 if(( tmp.bv_len >= LENOF("physical") ) &&
3042 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3044 tmp.bv_len -= LENOF("physical");
3045 tmp.bv_val += LENOF("physical");
3048 return LDAP_INVALID_SYNTAX;
3051 case 'T': /* telex or teletex or telephone */
3052 if(( tmp.bv_len >= LENOF("telex") ) &&
3053 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3055 tmp.bv_len -= LENOF("telex");
3056 tmp.bv_val += LENOF("telex");
3059 if(( tmp.bv_len >= LENOF("teletex") ) &&
3060 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3062 tmp.bv_len -= LENOF("teletex");
3063 tmp.bv_val += LENOF("teletex");
3066 if(( tmp.bv_len >= LENOF("telephone") ) &&
3067 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3069 tmp.bv_len -= LENOF("telephone");
3070 tmp.bv_val += LENOF("telephone");
3073 return LDAP_INVALID_SYNTAX;
3076 case 'G': /* g3fax or g4fax */
3077 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3078 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3079 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3081 tmp.bv_len -= LENOF("g3fax");
3082 tmp.bv_val += LENOF("g3fax");
3085 return LDAP_INVALID_SYNTAX;
3089 if(( tmp.bv_len >= LENOF("ia5") ) &&
3090 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3092 tmp.bv_len -= LENOF("ia5");
3093 tmp.bv_val += LENOF("ia5");
3096 return LDAP_INVALID_SYNTAX;
3100 if(( tmp.bv_len >= LENOF("videotex") ) &&
3101 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3103 tmp.bv_len -= LENOF("videotex");
3104 tmp.bv_val += LENOF("videotex");
3107 return LDAP_INVALID_SYNTAX;
3110 return LDAP_INVALID_SYNTAX;
3113 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3115 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3119 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3123 return LDAP_INVALID_SYNTAX;
3125 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3134 nisNetgroupTripleValidate(
3136 struct berval *val )
3141 if ( BER_BVISEMPTY( val ) ) {
3142 return LDAP_INVALID_SYNTAX;
3145 p = (char *)val->bv_val;
3146 e = p + val->bv_len;
3148 if ( *p != '(' /*')'*/ ) {
3149 return LDAP_INVALID_SYNTAX;
3152 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3156 return LDAP_INVALID_SYNTAX;
3159 } else if ( !AD_CHAR( *p ) ) {
3160 return LDAP_INVALID_SYNTAX;
3164 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3165 return LDAP_INVALID_SYNTAX;
3171 return LDAP_INVALID_SYNTAX;
3174 return LDAP_SUCCESS;
3178 bootParameterValidate(
3180 struct berval *val )
3184 if ( BER_BVISEMPTY( val ) ) {
3185 return LDAP_INVALID_SYNTAX;
3188 p = (char *)val->bv_val;
3189 e = p + val->bv_len;
3192 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3193 if ( !AD_CHAR( *p ) ) {
3194 return LDAP_INVALID_SYNTAX;
3199 return LDAP_INVALID_SYNTAX;
3203 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3204 if ( !AD_CHAR( *p ) ) {
3205 return LDAP_INVALID_SYNTAX;
3210 return LDAP_INVALID_SYNTAX;
3214 for ( p++; p < e; p++ ) {
3215 if ( !SLAP_PRINTABLE( *p ) ) {
3216 return LDAP_INVALID_SYNTAX;
3220 return LDAP_SUCCESS;
3224 firstComponentNormalize(
3229 struct berval *normalized,
3236 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3237 ber_dupbv_x( normalized, val, ctx );
3238 return LDAP_SUCCESS;
3241 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3243 if( val->bv_val[0] != '(' /*')'*/ &&
3244 val->bv_val[0] != '{' /*'}'*/ )
3246 return LDAP_INVALID_SYNTAX;
3249 /* trim leading white space */
3251 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3257 /* grab next word */
3258 comp.bv_val = &val->bv_val[len];
3259 len = val->bv_len - len;
3260 for( comp.bv_len = 0;
3261 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3267 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3268 rc = numericoidValidate( NULL, &comp );
3269 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3270 rc = integerValidate( NULL, &comp );
3272 rc = LDAP_INVALID_SYNTAX;
3276 if( rc == LDAP_SUCCESS ) {
3277 ber_dupbv_x( normalized, &comp, ctx );
3284 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3285 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3287 static slap_syntax_defs_rec syntax_defs[] = {
3288 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3289 X_BINARY X_NOT_H_R ")",
3290 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3291 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3293 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3295 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3297 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3298 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3300 SLAP_SYNTAX_BER, berValidate, NULL},
3301 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3302 0, bitStringValidate, NULL },
3303 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3304 0, booleanValidate, NULL},
3305 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3306 X_BINARY X_NOT_H_R ")",
3307 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3308 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3309 X_BINARY X_NOT_H_R ")",
3310 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3311 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3312 X_BINARY X_NOT_H_R ")",
3313 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3314 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3315 0, countryStringValidate, NULL},
3316 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3317 0, dnValidate, dnPretty},
3318 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3319 0, rdnValidate, rdnPretty},
3320 #ifdef LDAP_COMP_MATCH
3321 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3322 0, allComponentsValidate, NULL},
3323 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3324 0, componentFilterValidate, NULL},
3326 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3328 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3329 0, deliveryMethodValidate, NULL},
3330 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3331 0, UTF8StringValidate, NULL},
3332 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3334 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3336 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3338 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3340 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3342 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3343 0, printablesStringValidate, NULL},
3344 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3345 SLAP_SYNTAX_BLOB, NULL, NULL},
3346 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3347 0, generalizedTimeValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3350 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3351 0, IA5StringValidate, NULL},
3352 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3353 0, integerValidate, NULL},
3354 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3355 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3356 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3358 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3360 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3362 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3364 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3366 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3367 0, nameUIDValidate, nameUIDPretty },
3368 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3370 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3371 0, numericStringValidate, NULL},
3372 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3374 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3375 0, numericoidValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3377 0, IA5StringValidate, NULL},
3378 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3379 0, blobValidate, NULL},
3380 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3381 0, UTF8StringValidate, NULL},
3382 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3384 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3386 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3387 0, printableStringValidate, NULL},
3388 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3389 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3390 0, subtreeSpecificationValidate, NULL},
3391 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3392 X_BINARY X_NOT_H_R ")",
3393 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3394 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3395 0, printableStringValidate, NULL},
3396 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3398 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3399 0, printablesStringValidate, NULL},
3400 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3401 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3402 0, utcTimeValidate, NULL},
3404 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3406 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3408 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3410 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3412 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3415 /* RFC 2307 NIS Syntaxes */
3416 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3417 0, nisNetgroupTripleValidate, NULL},
3418 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3419 0, bootParameterValidate, NULL},
3421 /* From PKIX *//* This OID is not published yet. */
3422 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3424 serialNumberAndIssuerValidate,
3425 serialNumberAndIssuerPretty},
3427 #ifdef SLAPD_AUTHPASSWD
3428 /* needs updating */
3429 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3430 SLAP_SYNTAX_HIDE, NULL, NULL},
3433 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3434 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3436 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3437 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3439 /* OpenLDAP Void Syntax */
3440 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3441 SLAP_SYNTAX_HIDE, inValidate, NULL},
3443 #ifdef SLAP_AUTHZ_SYNTAX
3444 /* FIXME: OID is unused, but not registered yet */
3445 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3446 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3447 #endif /* SLAP_AUTHZ_SYNTAX */
3449 {NULL, 0, NULL, NULL}
3452 char *certificateExactMatchSyntaxes[] = {
3453 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3456 #ifdef LDAP_COMP_MATCH
3457 char *componentFilterMatchSyntaxes[] = {
3458 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3462 char *directoryStringSyntaxes[] = {
3463 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3466 char *integerFirstComponentMatchSyntaxes[] = {
3467 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3468 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3471 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3472 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3473 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3474 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3475 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3476 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3477 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3478 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3479 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3484 * Other matching rules in X.520 that we do not use (yet):
3486 * 2.5.13.25 uTCTimeMatch
3487 * 2.5.13.26 uTCTimeOrderingMatch
3488 * 2.5.13.31* directoryStringFirstComponentMatch
3489 * 2.5.13.32* wordMatch
3490 * 2.5.13.33* keywordMatch
3491 * 2.5.13.36 certificatePairExactMatch
3492 * 2.5.13.37 certificatePairMatch
3493 * 2.5.13.38 certificateListExactMatch
3494 * 2.5.13.39 certificateListMatch
3495 * 2.5.13.40 algorithmIdentifierMatch
3496 * 2.5.13.41* storedPrefixMatch
3497 * 2.5.13.42 attributeCertificateMatch
3498 * 2.5.13.43 readerAndKeyIDMatch
3499 * 2.5.13.44 attributeIntegrityMatch
3501 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3503 static slap_mrule_defs_rec mrule_defs[] = {
3505 * EQUALITY matching rules must be listed after associated APPROX
3506 * matching rules. So, we list all APPROX matching rules first.
3508 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3510 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3511 NULL, NULL, directoryStringApproxMatch,
3512 directoryStringApproxIndexer, directoryStringApproxFilter,
3515 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3517 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3518 NULL, NULL, IA5StringApproxMatch,
3519 IA5StringApproxIndexer, IA5StringApproxFilter,
3523 * Other matching rules
3526 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3527 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3528 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3529 NULL, NULL, octetStringMatch,
3530 octetStringIndexer, octetStringFilter,
3533 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3535 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3536 NULL, dnNormalize, dnMatch,
3537 octetStringIndexer, octetStringFilter,
3540 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3541 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3542 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3543 NULL, dnNormalize, dnRelativeMatch,
3547 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3548 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3549 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3550 NULL, dnNormalize, dnRelativeMatch,
3554 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3556 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3557 NULL, dnNormalize, dnRelativeMatch,
3561 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3563 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3564 NULL, dnNormalize, dnRelativeMatch,
3568 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3569 "SYNTAX 1.2.36.79672281.1.5.0 )",
3570 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3571 NULL, rdnNormalize, rdnMatch,
3572 octetStringIndexer, octetStringFilter,
3575 #ifdef LDAP_COMP_MATCH
3576 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3577 "SYNTAX 1.2.36.79672281.1.5.2 )",
3578 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3579 NULL, NULL , componentFilterMatch,
3580 octetStringIndexer, octetStringFilter,
3583 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3584 "SYNTAX 1.2.36.79672281.1.5.3 )",
3585 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3586 NULL, NULL , allComponentsMatch,
3587 octetStringIndexer, octetStringFilter,
3590 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3591 "SYNTAX 1.2.36.79672281.1.5.3 )",
3592 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3593 NULL, NULL , directoryComponentsMatch,
3594 octetStringIndexer, octetStringFilter,
3598 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3600 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3601 NULL, UTF8StringNormalize, octetStringMatch,
3602 octetStringIndexer, octetStringFilter,
3603 directoryStringApproxMatchOID },
3605 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3607 SLAP_MR_ORDERING, directoryStringSyntaxes,
3608 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3610 "caseIgnoreMatch" },
3612 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3614 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3615 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3616 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3617 "caseIgnoreMatch" },
3619 {"( 2.5.13.5 NAME 'caseExactMatch' "
3620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3621 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3622 NULL, UTF8StringNormalize, octetStringMatch,
3623 octetStringIndexer, octetStringFilter,
3624 directoryStringApproxMatchOID },
3626 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3628 SLAP_MR_ORDERING, directoryStringSyntaxes,
3629 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3633 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3635 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3636 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3637 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3640 {"( 2.5.13.8 NAME 'numericStringMatch' "
3641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3642 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3643 NULL, numericStringNormalize, octetStringMatch,
3644 octetStringIndexer, octetStringFilter,
3647 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3649 SLAP_MR_ORDERING, NULL,
3650 NULL, numericStringNormalize, octetStringOrderingMatch,
3652 "numericStringMatch" },
3654 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3656 SLAP_MR_SUBSTR, NULL,
3657 NULL, numericStringNormalize, octetStringSubstringsMatch,
3658 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3659 "numericStringMatch" },
3661 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3663 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3664 NULL, NULL, NULL, NULL, NULL, NULL },
3666 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3668 SLAP_MR_SUBSTR, NULL,
3669 NULL, NULL, NULL, NULL, NULL,
3670 "caseIgnoreListMatch" },
3672 {"( 2.5.13.13 NAME 'booleanMatch' "
3673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3674 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3675 NULL, NULL, booleanMatch,
3676 octetStringIndexer, octetStringFilter,
3679 {"( 2.5.13.14 NAME 'integerMatch' "
3680 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3681 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3682 NULL, NULL, integerMatch,
3683 octetStringIndexer, octetStringFilter,
3686 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3688 SLAP_MR_ORDERING, NULL,
3689 NULL, NULL, integerMatch,
3693 {"( 2.5.13.16 NAME 'bitStringMatch' "
3694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3695 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3696 NULL, NULL, octetStringMatch,
3697 octetStringIndexer, octetStringFilter,
3700 {"( 2.5.13.17 NAME 'octetStringMatch' "
3701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3702 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3703 NULL, NULL, octetStringMatch,
3704 octetStringIndexer, octetStringFilter,
3707 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3709 SLAP_MR_ORDERING, NULL,
3710 NULL, NULL, octetStringOrderingMatch,
3712 "octetStringMatch" },
3714 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3716 SLAP_MR_SUBSTR, NULL,
3717 NULL, NULL, octetStringSubstringsMatch,
3718 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3719 "octetStringMatch" },
3721 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3723 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3725 telephoneNumberNormalize, octetStringMatch,
3726 octetStringIndexer, octetStringFilter,
3729 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3730 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3731 SLAP_MR_SUBSTR, NULL,
3732 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3733 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3734 "telephoneNumberMatch" },
3736 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3738 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3739 NULL, NULL, NULL, NULL, NULL, NULL },
3741 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3742 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3743 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3744 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3745 uniqueMemberIndexer, uniqueMemberFilter,
3748 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3750 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3751 NULL, NULL, NULL, NULL, NULL, NULL },
3753 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3755 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3756 NULL, generalizedTimeNormalize, octetStringMatch,
3757 generalizedTimeIndexer, generalizedTimeFilter,
3760 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3762 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3763 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3765 "generalizedTimeMatch" },
3767 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3768 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3769 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3770 integerFirstComponentMatchSyntaxes,
3771 NULL, firstComponentNormalize, integerMatch,
3772 octetStringIndexer, octetStringFilter,
3775 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3776 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3777 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3778 objectIdentifierFirstComponentMatchSyntaxes,
3779 NULL, firstComponentNormalize, octetStringMatch,
3780 octetStringIndexer, octetStringFilter,
3783 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3784 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3785 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3787 NULL, certificateExactNormalize, octetStringMatch,
3788 octetStringIndexer, octetStringFilter,
3790 NULL, NULL, NULL, NULL, NULL,
3794 {"( 2.5.13.35 NAME 'certificateMatch' "
3795 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3796 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3798 NULL, NULL, octetStringMatch,
3799 octetStringIndexer, octetStringFilter,
3801 NULL, NULL, NULL, NULL, NULL,
3805 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3806 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3807 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3808 NULL, IA5StringNormalize, octetStringMatch,
3809 octetStringIndexer, octetStringFilter,
3810 IA5StringApproxMatchOID },
3812 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3813 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3814 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3815 NULL, IA5StringNormalize, octetStringMatch,
3816 octetStringIndexer, octetStringFilter,
3817 IA5StringApproxMatchOID },
3819 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3821 SLAP_MR_SUBSTR, NULL,
3822 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3823 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3824 "caseIgnoreIA5Match" },
3826 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3827 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3828 SLAP_MR_SUBSTR, NULL,
3829 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3830 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3831 "caseExactIA5Match" },
3833 #ifdef SLAPD_AUTHPASSWD
3834 /* needs updating */
3835 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3837 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3838 NULL, NULL, authPasswordMatch,
3843 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3846 NULL, NULL, integerBitAndMatch,
3850 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3853 NULL, NULL, integerBitOrMatch,
3857 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3858 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3859 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3860 NULL, UUIDNormalize, octetStringMatch,
3861 octetStringIndexer, octetStringFilter,
3864 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3865 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3866 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3867 NULL, UUIDNormalize, octetStringOrderingMatch,
3868 octetStringIndexer, octetStringFilter,
3871 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3872 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3873 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3874 NULL, NULL, csnMatch,
3875 csnIndexer, csnFilter,
3878 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3879 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3880 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3881 NULL, NULL, csnOrderingMatch,
3885 #ifdef SLAP_AUTHZ_SYNTAX
3886 /* FIXME: OID is unused, but not registered yet */
3887 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3888 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3889 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3890 NULL, authzNormalize, authzMatch,
3893 #endif /* SLAP_AUTHZ_SYNTAX */
3895 {NULL, SLAP_MR_NONE, NULL,
3896 NULL, NULL, NULL, NULL, NULL,
3901 slap_schema_init( void )
3906 /* we should only be called once (from main) */
3907 assert( schema_init_done == 0 );
3909 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3910 res = register_syntax( &syntax_defs[i] );
3913 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3914 syntax_defs[i].sd_desc );
3919 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3920 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3921 mrule_defs[i].mrd_compat_syntaxes == NULL )
3924 "slap_schema_init: Ignoring unusable matching rule %s\n",
3925 mrule_defs[i].mrd_desc );
3929 res = register_matching_rule( &mrule_defs[i] );
3933 "slap_schema_init: Error registering matching rule %s\n",
3934 mrule_defs[i].mrd_desc );
3939 res = slap_schema_load();
3940 schema_init_done = 1;
3945 schema_destroy( void )
3954 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
3955 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );