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 = *value;
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 );
1089 if ( !BER_BVISEMPTY( value ) ) {
1091 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1092 if ( !BER_BVISNULL( &valueUID ) ) {
1094 valueUID.bv_len = valueDN.bv_len
1095 - ( valueUID.bv_val - valueDN.bv_val );
1097 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1098 valueDN.bv_len -= valueUID.bv_len + 1;
1101 BER_BVZERO( &valueUID );
1106 if( valueUID.bv_len && assertedUID.bv_len ) {
1107 match = valueUID.bv_len - assertedUID.bv_len;
1110 return LDAP_SUCCESS;
1113 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1116 return LDAP_SUCCESS;
1119 } else if ( !approx && valueUID.bv_len ) {
1122 return LDAP_SUCCESS;
1124 } else if ( !approx && assertedUID.bv_len ) {
1127 return LDAP_SUCCESS;
1130 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1134 uniqueMemberIndexer(
1139 struct berval *prefix,
1147 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1148 /* just count them */
1152 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1154 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1155 struct berval assertedDN = values[i];
1156 struct berval assertedUID = BER_BVNULL;
1158 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1159 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1160 if ( !BER_BVISNULL( &assertedUID ) ) {
1161 assertedUID.bv_val++;
1162 assertedUID.bv_len = assertedDN.bv_len
1163 - ( assertedUID.bv_val - assertedDN.bv_val );
1165 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1166 assertedDN.bv_len -= assertedUID.bv_len + 1;
1169 BER_BVZERO( &assertedUID );
1174 dnvalues[i] = assertedDN;
1176 BER_BVZERO( &dnvalues[i] );
1178 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1179 dnvalues, keysp, ctx );
1181 slap_sl_free( dnvalues, ctx );
1191 struct berval *prefix,
1192 void * assertedValue,
1196 struct berval *asserted = (struct berval *) assertedValue;
1197 struct berval assertedDN = *asserted;
1198 struct berval assertedUID = BER_BVNULL;
1200 if ( !BER_BVISEMPTY( asserted ) ) {
1201 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1202 if ( !BER_BVISNULL( &assertedUID ) ) {
1203 assertedUID.bv_val++;
1204 assertedUID.bv_len = assertedDN.bv_len
1205 - ( assertedUID.bv_val - assertedDN.bv_val );
1207 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1208 assertedDN.bv_len -= assertedUID.bv_len + 1;
1211 BER_BVZERO( &assertedUID );
1216 return octetStringFilter( use, flags, syntax, mr, prefix,
1217 &assertedDN, keysp, ctx );
1222 * Handling boolean syntax and matching is quite rigid.
1223 * A more flexible approach would be to allow a variety
1224 * of strings to be normalized and prettied into TRUE
1232 /* very unforgiving validation, requires no normalization
1233 * before simplistic matching
1236 if( in->bv_len == 4 ) {
1237 if( bvmatch( in, &slap_true_bv ) ) {
1238 return LDAP_SUCCESS;
1240 } else if( in->bv_len == 5 ) {
1241 if( bvmatch( in, &slap_false_bv ) ) {
1242 return LDAP_SUCCESS;
1246 return LDAP_INVALID_SYNTAX;
1255 struct berval *value,
1256 void *assertedValue )
1258 /* simplistic matching allowed by rigid validation */
1259 struct berval *asserted = (struct berval *) assertedValue;
1260 *matchp = value->bv_len != asserted->bv_len;
1261 return LDAP_SUCCESS;
1264 /*-------------------------------------------------------------------
1265 LDAP/X.500 string syntax / matching rules have a few oddities. This
1266 comment attempts to detail how slapd(8) treats them.
1269 StringSyntax X.500 LDAP Matching/Comments
1270 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1271 PrintableString subset subset i/e + ignore insignificant spaces
1272 PrintableString subset subset i/e + ignore insignificant spaces
1273 NumericString subset subset ignore all spaces
1274 IA5String ASCII ASCII i/e + ignore insignificant spaces
1275 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1277 TelephoneNumber subset subset i + ignore all spaces and "-"
1279 See draft-ietf-ldapbis-strpro for details (once published).
1283 In X.500(93), a directory string can be either a PrintableString,
1284 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1285 In later versions, more CHOICEs were added. In all cases the string
1288 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1289 A directory string cannot be zero length.
1291 For matching, there are both case ignore and exact rules. Both
1292 also require that "insignificant" spaces be ignored.
1293 spaces before the first non-space are ignored;
1294 spaces after the last non-space are ignored;
1295 spaces after a space are ignored.
1296 Note: by these rules (and as clarified in X.520), a string of only
1297 spaces is to be treated as if held one space, not empty (which
1298 would be a syntax error).
1301 In ASN.1, numeric string is just a string of digits and spaces
1302 and could be empty. However, in X.500, all attribute values of
1303 numeric string carry a non-empty constraint. For example:
1305 internationalISDNNumber ATTRIBUTE ::= {
1306 WITH SYNTAX InternationalISDNNumber
1307 EQUALITY MATCHING RULE numericStringMatch
1308 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1309 ID id-at-internationalISDNNumber }
1310 InternationalISDNNumber ::=
1311 NumericString (SIZE(1..ub-international-isdn-number))
1313 Unforunately, some assertion values are don't carry the same
1314 constraint (but its unclear how such an assertion could ever
1315 be true). In LDAP, there is one syntax (numericString) not two
1316 (numericString with constraint, numericString without constraint).
1317 This should be treated as numericString with non-empty constraint.
1318 Note that while someone may have no ISDN number, there are no ISDN
1319 numbers which are zero length.
1321 In matching, spaces are ignored.
1324 In ASN.1, Printable string is just a string of printable characters
1325 and can be empty. In X.500, semantics much like NumericString (see
1326 serialNumber for a like example) excepting uses insignificant space
1327 handling instead of ignore all spaces.
1330 Basically same as PrintableString. There are no examples in X.500,
1331 but same logic applies. So we require them to be non-empty as
1334 -------------------------------------------------------------------*/
1343 unsigned char *u = (unsigned char *)in->bv_val;
1345 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1346 /* directory strings cannot be empty */
1347 return LDAP_INVALID_SYNTAX;
1350 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1351 /* get the length indicated by the first byte */
1352 len = LDAP_UTF8_CHARLEN2( u, len );
1354 /* very basic checks */
1357 if( (u[5] & 0xC0) != 0x80 ) {
1358 return LDAP_INVALID_SYNTAX;
1361 if( (u[4] & 0xC0) != 0x80 ) {
1362 return LDAP_INVALID_SYNTAX;
1365 if( (u[3] & 0xC0) != 0x80 ) {
1366 return LDAP_INVALID_SYNTAX;
1369 if( (u[2] & 0xC0 )!= 0x80 ) {
1370 return LDAP_INVALID_SYNTAX;
1373 if( (u[1] & 0xC0) != 0x80 ) {
1374 return LDAP_INVALID_SYNTAX;
1377 /* CHARLEN already validated it */
1380 return LDAP_INVALID_SYNTAX;
1383 /* make sure len corresponds with the offset
1384 to the next character */
1385 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1389 return LDAP_INVALID_SYNTAX;
1392 return LDAP_SUCCESS;
1396 UTF8StringNormalize(
1401 struct berval *normalized,
1404 struct berval tmp, nvalue;
1408 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1410 if( BER_BVISNULL( val ) ) {
1411 /* assume we're dealing with a syntax (e.g., UTF8String)
1412 * which allows empty strings
1414 BER_BVZERO( normalized );
1415 return LDAP_SUCCESS;
1418 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1419 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1420 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1421 ? LDAP_UTF8_APPROX : 0;
1423 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1428 /* collapse spaces (in place) */
1430 nvalue.bv_val = tmp.bv_val;
1432 /* trim leading spaces? */
1433 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1434 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1436 for( i = 0; i < tmp.bv_len; i++) {
1437 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1438 if( wasspace++ == 0 ) {
1439 /* trim repeated spaces */
1440 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1444 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1448 if( !BER_BVISEMPTY( &nvalue ) ) {
1449 /* trim trailing space? */
1451 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1452 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1456 nvalue.bv_val[nvalue.bv_len] = '\0';
1459 /* string of all spaces is treated as one space */
1460 nvalue.bv_val[0] = ' ';
1461 nvalue.bv_val[1] = '\0';
1465 *normalized = nvalue;
1466 return LDAP_SUCCESS;
1470 directoryStringSubstringsMatch(
1475 struct berval *value,
1476 void *assertedValue )
1479 SubstringsAssertion *sub = assertedValue;
1480 struct berval left = *value;
1484 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1485 if ( sub->sa_initial.bv_len > left.bv_len ) {
1486 /* not enough left */
1491 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1492 sub->sa_initial.bv_len );
1498 left.bv_val += sub->sa_initial.bv_len;
1499 left.bv_len -= sub->sa_initial.bv_len;
1501 priorspace = ASCII_SPACE(
1502 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1505 if ( sub->sa_any ) {
1506 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1510 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1511 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1513 /* allow next space to match */
1520 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1524 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1525 /* not enough left */
1530 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1537 idx = p - left.bv_val;
1539 if ( idx >= left.bv_len ) {
1540 /* this shouldn't happen */
1547 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1548 /* not enough left */
1553 match = memcmp( left.bv_val,
1554 sub->sa_any[i].bv_val,
1555 sub->sa_any[i].bv_len );
1563 left.bv_val += sub->sa_any[i].bv_len;
1564 left.bv_len -= sub->sa_any[i].bv_len;
1566 priorspace = ASCII_SPACE(
1567 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1571 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1572 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1573 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1575 /* allow next space to match */
1580 if ( sub->sa_final.bv_len > left.bv_len ) {
1581 /* not enough left */
1586 match = memcmp( sub->sa_final.bv_val,
1587 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1588 sub->sa_final.bv_len );
1597 return LDAP_SUCCESS;
1600 #if defined(SLAPD_APPROX_INITIALS)
1601 # define SLAPD_APPROX_DELIMITER "._ "
1602 # define SLAPD_APPROX_WORDLEN 2
1604 # define SLAPD_APPROX_DELIMITER " "
1605 # define SLAPD_APPROX_WORDLEN 1
1614 struct berval *value,
1615 void *assertedValue )
1617 struct berval *nval, *assertv;
1618 char *val, **values, **words, *c;
1619 int i, count, len, nextchunk=0, nextavail=0;
1621 /* Yes, this is necessary */
1622 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1623 if( nval == NULL ) {
1625 return LDAP_SUCCESS;
1628 /* Yes, this is necessary */
1629 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1630 NULL, LDAP_UTF8_APPROX, NULL );
1631 if( assertv == NULL ) {
1634 return LDAP_SUCCESS;
1637 /* Isolate how many words there are */
1638 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1639 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1640 if ( c == NULL ) break;
1645 /* Get a phonetic copy of each word */
1646 words = (char **)ch_malloc( count * sizeof(char *) );
1647 values = (char **)ch_malloc( count * sizeof(char *) );
1648 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1650 values[i] = phonetic(c);
1653 /* Work through the asserted value's words, to see if at least some
1654 of the words are there, in the same order. */
1656 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1657 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1662 #if defined(SLAPD_APPROX_INITIALS)
1663 else if( len == 1 ) {
1664 /* Single letter words need to at least match one word's initial */
1665 for( i=nextavail; i<count; i++ )
1666 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1673 /* Isolate the next word in the asserted value and phonetic it */
1674 assertv->bv_val[nextchunk+len] = '\0';
1675 val = phonetic( assertv->bv_val + nextchunk );
1677 /* See if this phonetic chunk is in the remaining words of *value */
1678 for( i=nextavail; i<count; i++ ){
1679 if( !strcmp( val, values[i] ) ){
1687 /* This chunk in the asserted value was NOT within the *value. */
1693 /* Go on to the next word in the asserted value */
1697 /* If some of the words were seen, call it a match */
1698 if( nextavail > 0 ) {
1705 /* Cleanup allocs */
1706 ber_bvfree( assertv );
1707 for( i=0; i<count; i++ ) {
1708 ch_free( values[i] );
1714 return LDAP_SUCCESS;
1723 struct berval *prefix,
1729 int i,j, len, wordcount, keycount=0;
1730 struct berval *newkeys;
1731 BerVarray keys=NULL;
1733 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1734 struct berval val = BER_BVNULL;
1735 /* Yes, this is necessary */
1736 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1737 assert( !BER_BVISNULL( &val ) );
1739 /* Isolate how many words there are. There will be a key for each */
1740 for( wordcount = 0, c = val.bv_val; *c; c++) {
1741 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1742 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1744 if (*c == '\0') break;
1748 /* Allocate/increase storage to account for new keys */
1749 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1750 * sizeof(struct berval) );
1751 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1752 if( keys ) ch_free( keys );
1755 /* Get a phonetic copy of each word */
1756 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1758 if( len < SLAPD_APPROX_WORDLEN ) continue;
1759 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1764 ber_memfree( val.bv_val );
1766 BER_BVZERO( &keys[keycount] );
1769 return LDAP_SUCCESS;
1778 struct berval *prefix,
1779 void * assertedValue,
1788 /* Yes, this is necessary */
1789 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1790 NULL, LDAP_UTF8_APPROX, NULL );
1791 if( val == NULL || BER_BVISNULL( val ) ) {
1792 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1793 BER_BVZERO( &keys[0] );
1796 return LDAP_SUCCESS;
1799 /* Isolate how many words there are. There will be a key for each */
1800 for( count = 0,c = val->bv_val; *c; c++) {
1801 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1802 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1804 if (*c == '\0') break;
1808 /* Allocate storage for new keys */
1809 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1811 /* Get a phonetic copy of each word */
1812 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1814 if( len < SLAPD_APPROX_WORDLEN ) continue;
1815 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1821 BER_BVZERO( &keys[count] );
1824 return LDAP_SUCCESS;
1827 /* Remove all spaces and '-' characters */
1829 telephoneNumberNormalize(
1834 struct berval *normalized,
1839 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1841 /* validator should have refused an empty string */
1842 assert( !BER_BVISEMPTY( val ) );
1844 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1846 for( p = val->bv_val; *p; p++ ) {
1847 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1853 normalized->bv_len = q - normalized->bv_val;
1855 if( BER_BVISEMPTY( normalized ) ) {
1856 slap_sl_free( normalized->bv_val, ctx );
1857 BER_BVZERO( normalized );
1858 return LDAP_INVALID_SYNTAX;
1861 return LDAP_SUCCESS;
1869 struct berval val = *in;
1871 if( BER_BVISEMPTY( &val ) ) {
1872 /* disallow empty strings */
1873 return LDAP_INVALID_SYNTAX;
1876 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1877 if ( val.bv_len == 1 ) {
1878 return LDAP_SUCCESS;
1881 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1888 while ( OID_LEADCHAR( val.bv_val[0] )) {
1892 if ( val.bv_len == 0 ) {
1893 return LDAP_SUCCESS;
1897 if( !OID_SEPARATOR( val.bv_val[0] )) {
1905 return LDAP_INVALID_SYNTAX;
1914 struct berval val = *in;
1916 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1918 if ( val.bv_val[0] == '-' ) {
1922 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1923 return LDAP_INVALID_SYNTAX;
1926 if( val.bv_val[0] == '0' ) { /* "-0" */
1927 return LDAP_INVALID_SYNTAX;
1930 } else if ( val.bv_val[0] == '0' ) {
1931 if( val.bv_len > 1 ) { /* "0<more>" */
1932 return LDAP_INVALID_SYNTAX;
1935 return LDAP_SUCCESS;
1938 for( i=0; i < val.bv_len; i++ ) {
1939 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1940 return LDAP_INVALID_SYNTAX;
1944 return LDAP_SUCCESS;
1953 struct berval *value,
1954 void *assertedValue )
1956 struct berval *asserted = (struct berval *) assertedValue;
1957 int vsign = 1, asign = 1; /* default sign = '+' */
1962 if( v.bv_val[0] == '-' ) {
1968 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1971 if( a.bv_val[0] == '-' ) {
1977 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1979 match = vsign - asign;
1981 match = ( v.bv_len != a.bv_len
1982 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1983 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1984 if( vsign < 0 ) match = -match;
1988 return LDAP_SUCCESS;
1992 countryStringValidate(
1994 struct berval *val )
1996 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1998 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1999 return LDAP_INVALID_SYNTAX;
2001 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2002 return LDAP_INVALID_SYNTAX;
2005 return LDAP_SUCCESS;
2009 printableStringValidate(
2011 struct berval *val )
2015 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2017 for(i=0; i < val->bv_len; i++) {
2018 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2019 return LDAP_INVALID_SYNTAX;
2023 return LDAP_SUCCESS;
2027 printablesStringValidate(
2029 struct berval *val )
2033 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2035 for(i=0,len=0; i < val->bv_len; i++) {
2036 int c = val->bv_val[i];
2040 return LDAP_INVALID_SYNTAX;
2044 } else if ( SLAP_PRINTABLE(c) ) {
2047 return LDAP_INVALID_SYNTAX;
2052 return LDAP_INVALID_SYNTAX;
2055 return LDAP_SUCCESS;
2061 struct berval *val )
2065 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2067 for(i=0; i < val->bv_len; i++) {
2068 if( !LDAP_ASCII(val->bv_val[i]) ) {
2069 return LDAP_INVALID_SYNTAX;
2073 return LDAP_SUCCESS;
2082 struct berval *normalized,
2086 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2088 assert( !BER_BVISEMPTY( val ) );
2090 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2094 /* Ignore initial whitespace */
2095 while ( ASCII_SPACE( *p ) ) p++;
2097 normalized->bv_val = ber_strdup_x( p, ctx );
2098 p = q = normalized->bv_val;
2101 if ( ASCII_SPACE( *p ) ) {
2104 /* Ignore the extra whitespace */
2105 while ( ASCII_SPACE( *p ) ) {
2109 } else if ( casefold ) {
2110 /* Most IA5 rules require casefolding */
2111 *q++ = TOLOWER(*p); p++;
2118 assert( normalized->bv_val <= p );
2122 * If the string ended in space, backup the pointer one
2123 * position. One is enough because the above loop collapsed
2124 * all whitespace to a single space.
2126 if ( ASCII_SPACE( q[-1] ) ) --q;
2128 /* null terminate */
2131 normalized->bv_len = q - normalized->bv_val;
2132 if( BER_BVISEMPTY( normalized ) ) {
2133 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2134 normalized->bv_val[0] = ' ';
2135 normalized->bv_val[1] = '\0';
2136 normalized->bv_len = 1;
2139 return LDAP_SUCCESS;
2148 if( in->bv_len != 36 ) {
2149 return LDAP_INVALID_SYNTAX;
2152 for( i=0; i<36; i++ ) {
2158 if( in->bv_val[i] != '-' ) {
2159 return LDAP_INVALID_SYNTAX;
2163 if( !ASCII_HEX( in->bv_val[i]) ) {
2164 return LDAP_INVALID_SYNTAX;
2169 return LDAP_SUCCESS;
2178 struct berval *normalized,
2181 unsigned char octet = '\0';
2184 normalized->bv_len = 16;
2185 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2187 for( i=0, j=0; i<36; i++ ) {
2188 unsigned char nibble;
2189 if( val->bv_val[i] == '-' ) {
2192 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2193 nibble = val->bv_val[i] - '0';
2195 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2196 nibble = val->bv_val[i] - ('a'-10);
2198 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2199 nibble = val->bv_val[i] - ('A'-10);
2202 slap_sl_free( normalized->bv_val, ctx );
2203 return LDAP_INVALID_SYNTAX;
2208 normalized->bv_val[j>>1] = octet;
2210 octet = nibble << 4;
2215 normalized->bv_val[normalized->bv_len] = 0;
2216 return LDAP_SUCCESS;
2222 numericStringValidate(
2228 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2230 for(i=0; i < in->bv_len; i++) {
2231 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2232 return LDAP_INVALID_SYNTAX;
2236 return LDAP_SUCCESS;
2240 numericStringNormalize(
2245 struct berval *normalized,
2248 /* removal all spaces */
2251 assert( !BER_BVISEMPTY( val ) );
2253 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2256 q = normalized->bv_val;
2259 if ( ASCII_SPACE( *p ) ) {
2260 /* Ignore whitespace */
2267 /* we should have copied no more then is in val */
2268 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2270 /* null terminate */
2273 normalized->bv_len = q - normalized->bv_val;
2275 if( BER_BVISEMPTY( normalized ) ) {
2276 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2277 normalized->bv_val[0] = ' ';
2278 normalized->bv_val[1] = '\0';
2279 normalized->bv_len = 1;
2282 return LDAP_SUCCESS;
2286 * Integer conversion macros that will use the largest available
2289 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2290 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2291 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2292 # define SLAP_LONG_MAX LLONG_MAX
2293 # define SLAP_LONG_MIN LLONG_MIN
2294 # define SLAP_LONG long long
2296 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2297 # define SLAP_LONG_MAX LONG_MAX
2298 # define SLAP_LONG_MIN LONG_MIN
2299 # define SLAP_LONG long
2300 #endif /* HAVE_STRTOLL ... */
2308 struct berval *value,
2309 void *assertedValue )
2311 SLAP_LONG lValue, lAssertedValue;
2313 /* safe to assume integers are NUL terminated? */
2314 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2315 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2318 return LDAP_CONSTRAINT_VIOLATION;
2321 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2323 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2326 return LDAP_CONSTRAINT_VIOLATION;
2329 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2330 return LDAP_SUCCESS;
2339 struct berval *value,
2340 void *assertedValue )
2342 SLAP_LONG lValue, lAssertedValue;
2344 /* safe to assume integers are NUL terminated? */
2345 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2346 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2349 return LDAP_CONSTRAINT_VIOLATION;
2352 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2354 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2357 return LDAP_CONSTRAINT_VIOLATION;
2360 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2361 return LDAP_SUCCESS;
2365 serialNumberAndIssuerValidate(
2371 struct berval sn, i;
2372 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2374 i.bv_val = strchr( in->bv_val, '$' );
2375 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2377 sn.bv_val = in->bv_val;
2378 sn.bv_len = i.bv_val - in->bv_val;
2381 i.bv_len = in->bv_len - (sn.bv_len + 1);
2383 /* validate serial number (strict for now) */
2384 for( n=0; n < sn.bv_len; n++ ) {
2385 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2389 rc = dnValidate( NULL, &i );
2390 if( rc ) return LDAP_INVALID_SYNTAX;
2392 return LDAP_SUCCESS;
2396 serialNumberAndIssuerPretty(
2404 struct berval sn, i, newi;
2406 assert( val != NULL );
2407 assert( out != NULL );
2409 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2410 val->bv_val, 0, 0 );
2412 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2414 i.bv_val = strchr( val->bv_val, '$' );
2415 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2417 sn.bv_val = val->bv_val;
2418 sn.bv_len = i.bv_val - val->bv_val;
2421 i.bv_len = val->bv_len - (sn.bv_len + 1);
2423 /* eat leading zeros */
2424 for( n=0; n < (sn.bv_len-1); n++ ) {
2425 if( sn.bv_val[n] != '0' ) break;
2430 for( n=0; n < sn.bv_len; n++ ) {
2431 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2435 rc = dnPretty( syntax, &i, &newi, ctx );
2436 if( rc ) return LDAP_INVALID_SYNTAX;
2438 /* make room from sn + "$" */
2439 out->bv_len = sn.bv_len + newi.bv_len + 1;
2440 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2442 if( out->bv_val == NULL ) {
2444 slap_sl_free( newi.bv_val, ctx );
2448 /* push issuer over */
2449 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2450 /* insert sn and "$" */
2451 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2452 out->bv_val[sn.bv_len] = '$';
2454 out->bv_val[out->bv_len] = '\0';
2456 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2457 out->bv_val, 0, 0 );
2459 return LDAP_SUCCESS;
2463 * This routine is called by certificateExactNormalize when
2464 * certificateExactNormalize receives a search string instead of
2465 * a certificate. This routine checks if the search value is valid
2466 * and then returns the normalized value
2469 serialNumberAndIssuerNormalize(
2479 struct berval sn, i, newi;
2481 assert( val != NULL );
2482 assert( out != NULL );
2484 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2485 val->bv_val, 0, 0 );
2487 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2489 i.bv_val = strchr( val->bv_val, '$' );
2490 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2492 sn.bv_val = val->bv_val;
2493 sn.bv_len = i.bv_val - val->bv_val;
2496 i.bv_len = val->bv_len - (sn.bv_len + 1);
2498 /* eat leading zeros */
2499 for( n=0; n < (sn.bv_len-1); n++ ) {
2500 if( sn.bv_val[n] != '0' ) break;
2505 for( n=0; n < sn.bv_len; n++ ) {
2506 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2507 return LDAP_INVALID_SYNTAX;
2512 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2513 if( rc ) return LDAP_INVALID_SYNTAX;
2515 /* make room from sn + "$" */
2516 out->bv_len = sn.bv_len + newi.bv_len + 1;
2517 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2519 if( out->bv_val == NULL ) {
2521 slap_sl_free( newi.bv_val, ctx );
2525 /* push issuer over */
2526 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2527 /* insert sn and "$" */
2528 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2529 out->bv_val[sn.bv_len] = '$';
2531 out->bv_val[out->bv_len] = '\0';
2533 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2534 out->bv_val, 0, 0 );
2541 certificateExactNormalize(
2546 struct berval *normalized,
2549 int rc = LDAP_INVALID_SYNTAX;
2551 char *serial = NULL;
2552 ber_len_t seriallen;
2553 struct berval issuer_dn = BER_BVNULL;
2554 X509_NAME *name = NULL;
2555 ASN1_INTEGER *sn = NULL;
2558 if( BER_BVISEMPTY( val ) ) goto done;
2560 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2561 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2564 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2566 p = (unsigned char *)val->bv_val;
2567 xcert = d2i_X509( NULL, &p, val->bv_len);
2568 if( xcert == NULL ) goto done;
2570 sn=X509_get_serialNumber(xcert);
2571 if ( sn == NULL ) goto done;
2572 serial=i2s_ASN1_INTEGER(0, sn );
2573 if( serial == NULL ) goto done;
2574 seriallen=strlen(serial);
2576 name=X509_get_issuer_name(xcert);
2577 if( name == NULL ) goto done;
2578 rc = dnX509normalize( name, &issuer_dn );
2579 if( rc != LDAP_SUCCESS ) goto done;
2581 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2582 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2583 p = (unsigned char *)normalized->bv_val;
2584 AC_MEMCPY(p, serial, seriallen);
2587 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2588 p += issuer_dn.bv_len;
2591 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2592 normalized->bv_val, NULL, NULL );
2595 if (xcert) X509_free(xcert);
2596 if (serial) ch_free(serial);
2597 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2601 #endif /* HAVE_TLS */
2604 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2605 /* slight optimization - does not need the start parameter */
2606 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2611 check_time_syntax (struct berval *val,
2614 struct berval *fraction)
2617 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2618 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2619 * GeneralizedTime supports leap seconds, UTCTime does not.
2621 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2622 static const int mdays[2][12] = {
2623 /* non-leap years */
2624 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2626 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2629 int part, c, c1, c2, tzoffset, leapyear = 0;
2632 e = p + val->bv_len;
2634 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2635 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2637 for (part = start; part < 7 && p < e; part++) {
2639 if (!ASCII_DIGIT(c1)) {
2644 return LDAP_INVALID_SYNTAX;
2647 if (!ASCII_DIGIT(c)) {
2648 return LDAP_INVALID_SYNTAX;
2650 c += c1 * 10 - '0' * 11;
2651 if ((part | 1) == 3) {
2654 return LDAP_INVALID_SYNTAX;
2657 if (c >= ceiling[part]) {
2658 if (! (c == 60 && part == 6 && start == 0))
2659 return LDAP_INVALID_SYNTAX;
2663 if (part < 5 + start) {
2664 return LDAP_INVALID_SYNTAX;
2666 for (; part < 9; part++) {
2670 /* leapyear check for the Gregorian calendar (year>1581) */
2671 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2675 if (parts[3] >= mdays[leapyear][parts[2]]) {
2676 return LDAP_INVALID_SYNTAX;
2680 fraction->bv_val = p;
2681 fraction->bv_len = 0;
2682 if (p < e && (*p == '.' || *p == ',')) {
2684 while (++p < e && ASCII_DIGIT(*p)) {
2687 if (p - fraction->bv_val == 1) {
2688 return LDAP_INVALID_SYNTAX;
2690 for (end_num = p; end_num[-1] == '0'; --end_num) {
2693 c = end_num - fraction->bv_val;
2694 if (c != 1) fraction->bv_len = c;
2700 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2706 return LDAP_INVALID_SYNTAX;
2712 for (part = 7; part < 9 && p < e; part++) {
2714 if (!ASCII_DIGIT(c1)) {
2719 return LDAP_INVALID_SYNTAX;
2722 if (!ASCII_DIGIT(c2)) {
2723 return LDAP_INVALID_SYNTAX;
2725 parts[part] = c1 * 10 + c2 - '0' * 11;
2726 if (parts[part] >= ceiling[part]) {
2727 return LDAP_INVALID_SYNTAX;
2730 if (part < 8 + start) {
2731 return LDAP_INVALID_SYNTAX;
2734 if (tzoffset == '-') {
2735 /* negative offset to UTC, ie west of Greenwich */
2736 parts[4] += parts[7];
2737 parts[5] += parts[8];
2738 /* offset is just hhmm, no seconds */
2739 for (part = 6; --part >= 0; ) {
2743 c = mdays[leapyear][parts[2]];
2745 if (parts[part] >= c) {
2747 return LDAP_INVALID_SYNTAX;
2752 } else if (part != 5) {
2757 /* positive offset to UTC, ie east of Greenwich */
2758 parts[4] -= parts[7];
2759 parts[5] -= parts[8];
2760 for (part = 6; --part >= 0; ) {
2761 if (parts[part] < 0) {
2763 return LDAP_INVALID_SYNTAX;
2768 /* make first arg to % non-negative */
2769 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2774 } else if (part != 5) {
2781 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2784 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2791 struct berval *normalized )
2795 rc = check_time_syntax(val, 1, parts, NULL);
2796 if (rc != LDAP_SUCCESS) {
2800 normalized->bv_val = ch_malloc( 14 );
2801 if ( normalized->bv_val == NULL ) {
2802 return LBER_ERROR_MEMORY;
2805 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2806 parts[1], parts[2] + 1, parts[3] + 1,
2807 parts[4], parts[5], parts[6] );
2808 normalized->bv_len = 13;
2810 return LDAP_SUCCESS;
2820 return check_time_syntax(in, 1, parts, NULL);
2823 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2826 generalizedTimeValidate(
2831 struct berval fraction;
2832 return check_time_syntax(in, 0, parts, &fraction);
2836 generalizedTimeNormalize(
2841 struct berval *normalized,
2846 struct berval fraction;
2848 rc = check_time_syntax(val, 0, parts, &fraction);
2849 if (rc != LDAP_SUCCESS) {
2853 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2854 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2855 if ( BER_BVISNULL( normalized ) ) {
2856 return LBER_ERROR_MEMORY;
2859 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2860 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2861 parts[4], parts[5], parts[6] );
2862 if ( !BER_BVISEMPTY( &fraction ) ) {
2863 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2864 fraction.bv_val, fraction.bv_len );
2865 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2867 strcpy( normalized->bv_val + len-1, "Z" );
2868 normalized->bv_len = len;
2870 return LDAP_SUCCESS;
2874 generalizedTimeOrderingMatch(
2879 struct berval *value,
2880 void *assertedValue )
2882 struct berval *asserted = (struct berval *) assertedValue;
2883 ber_len_t v_len = value->bv_len;
2884 ber_len_t av_len = asserted->bv_len;
2886 /* ignore trailing 'Z' when comparing */
2887 int match = memcmp( value->bv_val, asserted->bv_val,
2888 (v_len < av_len ? v_len : av_len) - 1 );
2889 if ( match == 0 ) match = v_len - av_len;
2892 return LDAP_SUCCESS;
2895 /* Index generation function */
2896 int generalizedTimeIndexer(
2901 struct berval *prefix,
2909 BerValue bvtmp; /* 40 bit index */
2911 struct lutil_timet tt;
2913 bvtmp.bv_len = sizeof(tmp);
2915 for( i=0; values[i].bv_val != NULL; i++ ) {
2916 /* just count them */
2919 /* we should have at least one value at this point */
2922 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2924 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2925 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2926 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2927 /* Use 40 bits of time for key */
2928 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2929 lutil_tm2time( &tm, &tt );
2930 tmp[0] = tt.tt_gsec & 0xff;
2931 tmp[4] = tt.tt_sec & 0xff;
2933 tmp[3] = tt.tt_sec & 0xff;
2935 tmp[2] = tt.tt_sec & 0xff;
2937 tmp[1] = tt.tt_sec & 0xff;
2939 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2943 keys[j].bv_val = NULL;
2948 return LDAP_SUCCESS;
2951 /* Index generation function */
2952 int generalizedTimeFilter(
2957 struct berval *prefix,
2958 void * assertedValue,
2964 BerValue bvtmp; /* 40 bit index */
2965 BerValue *value = (BerValue *) assertedValue;
2967 struct lutil_timet tt;
2969 bvtmp.bv_len = sizeof(tmp);
2971 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2972 /* Use 40 bits of time for key */
2973 if ( value->bv_val && value->bv_len >= 10 &&
2974 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2976 lutil_tm2time( &tm, &tt );
2977 tmp[0] = tt.tt_gsec & 0xff;
2978 tmp[4] = tt.tt_sec & 0xff;
2980 tmp[3] = tt.tt_sec & 0xff;
2982 tmp[2] = tt.tt_sec & 0xff;
2984 tmp[1] = tt.tt_sec & 0xff;
2986 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2987 ber_dupbv_x(keys, &bvtmp, ctx );
2988 keys[1].bv_val = NULL;
2996 return LDAP_SUCCESS;
3000 deliveryMethodValidate(
3002 struct berval *val )
3005 #define LENOF(s) (sizeof(s)-1)
3006 struct berval tmp = *val;
3008 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3009 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3010 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3013 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3015 switch( tmp.bv_val[0] ) {
3018 if(( tmp.bv_len >= LENOF("any") ) &&
3019 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3021 tmp.bv_len -= LENOF("any");
3022 tmp.bv_val += LENOF("any");
3025 return LDAP_INVALID_SYNTAX;
3029 if(( tmp.bv_len >= LENOF("mhs") ) &&
3030 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3032 tmp.bv_len -= LENOF("mhs");
3033 tmp.bv_val += LENOF("mhs");
3036 return LDAP_INVALID_SYNTAX;
3040 if(( tmp.bv_len >= LENOF("physical") ) &&
3041 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3043 tmp.bv_len -= LENOF("physical");
3044 tmp.bv_val += LENOF("physical");
3047 return LDAP_INVALID_SYNTAX;
3050 case 'T': /* telex or teletex or telephone */
3051 if(( tmp.bv_len >= LENOF("telex") ) &&
3052 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3054 tmp.bv_len -= LENOF("telex");
3055 tmp.bv_val += LENOF("telex");
3058 if(( tmp.bv_len >= LENOF("teletex") ) &&
3059 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3061 tmp.bv_len -= LENOF("teletex");
3062 tmp.bv_val += LENOF("teletex");
3065 if(( tmp.bv_len >= LENOF("telephone") ) &&
3066 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3068 tmp.bv_len -= LENOF("telephone");
3069 tmp.bv_val += LENOF("telephone");
3072 return LDAP_INVALID_SYNTAX;
3075 case 'G': /* g3fax or g4fax */
3076 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3077 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3078 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3080 tmp.bv_len -= LENOF("g3fax");
3081 tmp.bv_val += LENOF("g3fax");
3084 return LDAP_INVALID_SYNTAX;
3088 if(( tmp.bv_len >= LENOF("ia5") ) &&
3089 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3091 tmp.bv_len -= LENOF("ia5");
3092 tmp.bv_val += LENOF("ia5");
3095 return LDAP_INVALID_SYNTAX;
3099 if(( tmp.bv_len >= LENOF("videotex") ) &&
3100 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3102 tmp.bv_len -= LENOF("videotex");
3103 tmp.bv_val += LENOF("videotex");
3106 return LDAP_INVALID_SYNTAX;
3109 return LDAP_INVALID_SYNTAX;
3112 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3114 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3118 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3122 return LDAP_INVALID_SYNTAX;
3124 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3133 nisNetgroupTripleValidate(
3135 struct berval *val )
3140 if ( BER_BVISEMPTY( val ) ) {
3141 return LDAP_INVALID_SYNTAX;
3144 p = (char *)val->bv_val;
3145 e = p + val->bv_len;
3147 if ( *p != '(' /*')'*/ ) {
3148 return LDAP_INVALID_SYNTAX;
3151 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3155 return LDAP_INVALID_SYNTAX;
3158 } else if ( !AD_CHAR( *p ) ) {
3159 return LDAP_INVALID_SYNTAX;
3163 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3164 return LDAP_INVALID_SYNTAX;
3170 return LDAP_INVALID_SYNTAX;
3173 return LDAP_SUCCESS;
3177 bootParameterValidate(
3179 struct berval *val )
3183 if ( BER_BVISEMPTY( val ) ) {
3184 return LDAP_INVALID_SYNTAX;
3187 p = (char *)val->bv_val;
3188 e = p + val->bv_len;
3191 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3192 if ( !AD_CHAR( *p ) ) {
3193 return LDAP_INVALID_SYNTAX;
3198 return LDAP_INVALID_SYNTAX;
3202 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3203 if ( !AD_CHAR( *p ) ) {
3204 return LDAP_INVALID_SYNTAX;
3209 return LDAP_INVALID_SYNTAX;
3213 for ( p++; p < e; p++ ) {
3214 if ( !SLAP_PRINTABLE( *p ) ) {
3215 return LDAP_INVALID_SYNTAX;
3219 return LDAP_SUCCESS;
3223 firstComponentNormalize(
3228 struct berval *normalized,
3235 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3236 ber_dupbv_x( normalized, val, ctx );
3237 return LDAP_SUCCESS;
3240 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3242 if( val->bv_val[0] != '(' /*')'*/ &&
3243 val->bv_val[0] != '{' /*'}'*/ )
3245 return LDAP_INVALID_SYNTAX;
3248 /* trim leading white space */
3250 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3256 /* grab next word */
3257 comp.bv_val = &val->bv_val[len];
3258 len = val->bv_len - len;
3259 for( comp.bv_len = 0;
3260 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3266 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3267 rc = numericoidValidate( NULL, &comp );
3268 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3269 rc = integerValidate( NULL, &comp );
3271 rc = LDAP_INVALID_SYNTAX;
3275 if( rc == LDAP_SUCCESS ) {
3276 ber_dupbv_x( normalized, &comp, ctx );
3283 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3284 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3286 static slap_syntax_defs_rec syntax_defs[] = {
3287 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3288 X_BINARY X_NOT_H_R ")",
3289 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3290 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3292 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3294 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3296 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3297 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3299 SLAP_SYNTAX_BER, berValidate, NULL},
3300 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3301 0, bitStringValidate, NULL },
3302 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3303 0, booleanValidate, NULL},
3304 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3305 X_BINARY X_NOT_H_R ")",
3306 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3307 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3308 X_BINARY X_NOT_H_R ")",
3309 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3310 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3311 X_BINARY X_NOT_H_R ")",
3312 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3313 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3314 0, countryStringValidate, NULL},
3315 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3316 0, dnValidate, dnPretty},
3317 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3318 0, rdnValidate, rdnPretty},
3319 #ifdef LDAP_COMP_MATCH
3320 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3321 0, allComponentsValidate, NULL},
3322 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3323 0, componentFilterValidate, NULL},
3325 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3327 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3328 0, deliveryMethodValidate, NULL},
3329 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3330 0, UTF8StringValidate, NULL},
3331 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3333 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3335 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3337 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3339 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3341 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3342 0, printablesStringValidate, NULL},
3343 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3344 SLAP_SYNTAX_BLOB, NULL, NULL},
3345 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3346 0, generalizedTimeValidate, NULL},
3347 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3349 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3350 0, IA5StringValidate, NULL},
3351 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3352 0, integerValidate, NULL},
3353 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3354 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3355 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3357 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3359 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3361 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3363 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3365 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3366 0, nameUIDValidate, nameUIDPretty },
3367 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3369 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3370 0, numericStringValidate, NULL},
3371 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3373 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3374 0, numericoidValidate, NULL},
3375 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3376 0, IA5StringValidate, NULL},
3377 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3378 0, blobValidate, NULL},
3379 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3380 0, UTF8StringValidate, NULL},
3381 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3383 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3385 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3386 0, printableStringValidate, NULL},
3387 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3388 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3389 0, subtreeSpecificationValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3391 X_BINARY X_NOT_H_R ")",
3392 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3393 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3394 0, printableStringValidate, NULL},
3395 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3397 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3398 0, printablesStringValidate, NULL},
3399 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3400 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3401 0, utcTimeValidate, NULL},
3403 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3405 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3407 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3409 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3411 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3414 /* RFC 2307 NIS Syntaxes */
3415 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3416 0, nisNetgroupTripleValidate, NULL},
3417 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3418 0, bootParameterValidate, NULL},
3420 /* From PKIX *//* This OID is not published yet. */
3421 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3423 serialNumberAndIssuerValidate,
3424 serialNumberAndIssuerPretty},
3426 #ifdef SLAPD_AUTHPASSWD
3427 /* needs updating */
3428 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3429 SLAP_SYNTAX_HIDE, NULL, NULL},
3432 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
3433 0, UUIDValidate, NULL},
3435 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3436 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3438 /* OpenLDAP Void Syntax */
3439 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3440 SLAP_SYNTAX_HIDE, inValidate, NULL},
3442 #ifdef SLAP_AUTHZ_SYNTAX
3443 /* FIXME: OID is unused, but not registered yet */
3444 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3445 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3446 #endif /* SLAP_AUTHZ_SYNTAX */
3448 {NULL, 0, NULL, NULL}
3451 char *certificateExactMatchSyntaxes[] = {
3452 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3455 #ifdef LDAP_COMP_MATCH
3456 char *componentFilterMatchSyntaxes[] = {
3457 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3461 char *directoryStringSyntaxes[] = {
3462 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3465 char *integerFirstComponentMatchSyntaxes[] = {
3466 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3467 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3470 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3471 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3472 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3473 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3474 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3475 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3476 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3477 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3478 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3483 * Other matching rules in X.520 that we do not use (yet):
3485 * 2.5.13.25 uTCTimeMatch
3486 * 2.5.13.26 uTCTimeOrderingMatch
3487 * 2.5.13.31* directoryStringFirstComponentMatch
3488 * 2.5.13.32* wordMatch
3489 * 2.5.13.33* keywordMatch
3490 * 2.5.13.36 certificatePairExactMatch
3491 * 2.5.13.37 certificatePairMatch
3492 * 2.5.13.38 certificateListExactMatch
3493 * 2.5.13.39 certificateListMatch
3494 * 2.5.13.40 algorithmIdentifierMatch
3495 * 2.5.13.41* storedPrefixMatch
3496 * 2.5.13.42 attributeCertificateMatch
3497 * 2.5.13.43 readerAndKeyIDMatch
3498 * 2.5.13.44 attributeIntegrityMatch
3500 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3502 static slap_mrule_defs_rec mrule_defs[] = {
3504 * EQUALITY matching rules must be listed after associated APPROX
3505 * matching rules. So, we list all APPROX matching rules first.
3507 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3509 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3510 NULL, NULL, directoryStringApproxMatch,
3511 directoryStringApproxIndexer, directoryStringApproxFilter,
3514 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3515 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3516 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3517 NULL, NULL, IA5StringApproxMatch,
3518 IA5StringApproxIndexer, IA5StringApproxFilter,
3522 * Other matching rules
3525 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3527 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3528 NULL, NULL, octetStringMatch,
3529 octetStringIndexer, octetStringFilter,
3532 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3534 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3535 NULL, dnNormalize, dnMatch,
3536 octetStringIndexer, octetStringFilter,
3539 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3541 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3542 NULL, dnNormalize, dnRelativeMatch,
3546 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3548 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3549 NULL, dnNormalize, dnRelativeMatch,
3553 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3555 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3556 NULL, dnNormalize, dnRelativeMatch,
3560 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3562 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3563 NULL, dnNormalize, dnRelativeMatch,
3567 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3568 "SYNTAX 1.2.36.79672281.1.5.0 )",
3569 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3570 NULL, rdnNormalize, rdnMatch,
3571 octetStringIndexer, octetStringFilter,
3574 #ifdef LDAP_COMP_MATCH
3575 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3576 "SYNTAX 1.2.36.79672281.1.5.2 )",
3577 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3578 NULL, NULL , componentFilterMatch,
3579 octetStringIndexer, octetStringFilter,
3582 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3583 "SYNTAX 1.2.36.79672281.1.5.3 )",
3584 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3585 NULL, NULL , allComponentsMatch,
3586 octetStringIndexer, octetStringFilter,
3589 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3590 "SYNTAX 1.2.36.79672281.1.5.3 )",
3591 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3592 NULL, NULL , directoryComponentsMatch,
3593 octetStringIndexer, octetStringFilter,
3597 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3598 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3599 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3600 NULL, UTF8StringNormalize, octetStringMatch,
3601 octetStringIndexer, octetStringFilter,
3602 directoryStringApproxMatchOID },
3604 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3605 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3606 SLAP_MR_ORDERING, directoryStringSyntaxes,
3607 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3609 "caseIgnoreMatch" },
3611 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3613 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3614 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3615 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3616 "caseIgnoreMatch" },
3618 {"( 2.5.13.5 NAME 'caseExactMatch' "
3619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3620 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3621 NULL, UTF8StringNormalize, octetStringMatch,
3622 octetStringIndexer, octetStringFilter,
3623 directoryStringApproxMatchOID },
3625 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3626 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3627 SLAP_MR_ORDERING, directoryStringSyntaxes,
3628 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3632 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3633 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3634 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3635 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3636 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3639 {"( 2.5.13.8 NAME 'numericStringMatch' "
3640 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3641 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3642 NULL, numericStringNormalize, octetStringMatch,
3643 octetStringIndexer, octetStringFilter,
3646 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3647 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3648 SLAP_MR_ORDERING, NULL,
3649 NULL, numericStringNormalize, octetStringOrderingMatch,
3651 "numericStringMatch" },
3653 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3654 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3655 SLAP_MR_SUBSTR, NULL,
3656 NULL, numericStringNormalize, octetStringSubstringsMatch,
3657 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3658 "numericStringMatch" },
3660 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3661 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3662 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3663 NULL, NULL, NULL, NULL, NULL, NULL },
3665 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3667 SLAP_MR_SUBSTR, NULL,
3668 NULL, NULL, NULL, NULL, NULL,
3669 "caseIgnoreListMatch" },
3671 {"( 2.5.13.13 NAME 'booleanMatch' "
3672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3673 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3674 NULL, NULL, booleanMatch,
3675 octetStringIndexer, octetStringFilter,
3678 {"( 2.5.13.14 NAME 'integerMatch' "
3679 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3681 NULL, NULL, integerMatch,
3682 octetStringIndexer, octetStringFilter,
3685 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3686 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3687 SLAP_MR_ORDERING, NULL,
3688 NULL, NULL, integerMatch,
3692 {"( 2.5.13.16 NAME 'bitStringMatch' "
3693 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3694 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3695 NULL, NULL, octetStringMatch,
3696 octetStringIndexer, octetStringFilter,
3699 {"( 2.5.13.17 NAME 'octetStringMatch' "
3700 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3701 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3702 NULL, NULL, octetStringMatch,
3703 octetStringIndexer, octetStringFilter,
3706 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3707 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3708 SLAP_MR_ORDERING, NULL,
3709 NULL, NULL, octetStringOrderingMatch,
3711 "octetStringMatch" },
3713 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3714 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3715 SLAP_MR_SUBSTR, NULL,
3716 NULL, NULL, octetStringSubstringsMatch,
3717 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3718 "octetStringMatch" },
3720 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3721 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3722 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3724 telephoneNumberNormalize, octetStringMatch,
3725 octetStringIndexer, octetStringFilter,
3728 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3730 SLAP_MR_SUBSTR, NULL,
3731 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3732 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3733 "telephoneNumberMatch" },
3735 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3737 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3738 NULL, NULL, NULL, NULL, NULL, NULL },
3740 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3741 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3742 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3743 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3744 uniqueMemberIndexer, uniqueMemberFilter,
3747 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3748 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3749 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3750 NULL, NULL, NULL, NULL, NULL, NULL },
3752 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3753 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3754 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3755 NULL, generalizedTimeNormalize, octetStringMatch,
3756 generalizedTimeIndexer, generalizedTimeFilter,
3759 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3760 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3761 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3762 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3764 "generalizedTimeMatch" },
3766 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3767 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3768 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3769 integerFirstComponentMatchSyntaxes,
3770 NULL, firstComponentNormalize, integerMatch,
3771 octetStringIndexer, octetStringFilter,
3774 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3776 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3777 objectIdentifierFirstComponentMatchSyntaxes,
3778 NULL, firstComponentNormalize, octetStringMatch,
3779 octetStringIndexer, octetStringFilter,
3782 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3783 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3784 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3786 NULL, certificateExactNormalize, octetStringMatch,
3787 octetStringIndexer, octetStringFilter,
3789 NULL, NULL, NULL, NULL, NULL,
3793 {"( 2.5.13.35 NAME 'certificateMatch' "
3794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3795 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3797 NULL, NULL, octetStringMatch,
3798 octetStringIndexer, octetStringFilter,
3800 NULL, NULL, NULL, NULL, NULL,
3804 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3805 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3806 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3807 NULL, IA5StringNormalize, octetStringMatch,
3808 octetStringIndexer, octetStringFilter,
3809 IA5StringApproxMatchOID },
3811 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3812 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3813 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3814 NULL, IA5StringNormalize, octetStringMatch,
3815 octetStringIndexer, octetStringFilter,
3816 IA5StringApproxMatchOID },
3818 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3819 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3820 SLAP_MR_SUBSTR, NULL,
3821 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3822 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3823 "caseIgnoreIA5Match" },
3825 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3827 SLAP_MR_SUBSTR, NULL,
3828 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3829 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3830 "caseExactIA5Match" },
3832 #ifdef SLAPD_AUTHPASSWD
3833 /* needs updating */
3834 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3835 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3836 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3837 NULL, NULL, authPasswordMatch,
3842 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3845 NULL, NULL, integerBitAndMatch,
3849 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3850 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3852 NULL, NULL, integerBitOrMatch,
3856 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
3857 "SYNTAX 1.3.6.1.1.16.1 )",
3858 SLAP_MR_EQUALITY, NULL,
3859 NULL, UUIDNormalize, octetStringMatch,
3860 octetStringIndexer, octetStringFilter,
3863 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
3864 "SYNTAX 1.3.6.1.1.16.1 )",
3865 SLAP_MR_ORDERING, NULL,
3866 NULL, UUIDNormalize, octetStringOrderingMatch,
3867 octetStringIndexer, octetStringFilter,
3870 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3871 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3872 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3873 NULL, NULL, csnMatch,
3874 csnIndexer, csnFilter,
3877 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3878 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3879 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3880 NULL, NULL, csnOrderingMatch,
3884 #ifdef SLAP_AUTHZ_SYNTAX
3885 /* FIXME: OID is unused, but not registered yet */
3886 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3887 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3888 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3889 NULL, authzNormalize, authzMatch,
3892 #endif /* SLAP_AUTHZ_SYNTAX */
3894 {NULL, SLAP_MR_NONE, NULL,
3895 NULL, NULL, NULL, NULL, NULL,
3900 slap_schema_init( void )
3905 /* we should only be called once (from main) */
3906 assert( schema_init_done == 0 );
3908 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3909 res = register_syntax( &syntax_defs[i] );
3912 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3913 syntax_defs[i].sd_desc );
3918 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3919 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3920 mrule_defs[i].mrd_compat_syntaxes == NULL )
3923 "slap_schema_init: Ignoring unusable matching rule %s\n",
3924 mrule_defs[i].mrd_desc );
3928 res = register_matching_rule( &mrule_defs[i] );
3932 "slap_schema_init: Error registering matching rule %s\n",
3933 mrule_defs[i].mrd_desc );
3938 res = slap_schema_load();
3939 schema_init_done = 1;
3944 schema_destroy( void )
3953 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
3954 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );