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 #define OpenLDAPaciMatch NULL
55 /* approx matching rules */
56 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
57 #define directoryStringApproxMatch approxMatch
58 #define directoryStringApproxIndexer approxIndexer
59 #define directoryStringApproxFilter approxFilter
60 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
61 #define IA5StringApproxMatch approxMatch
62 #define IA5StringApproxIndexer approxIndexer
63 #define IA5StringApproxFilter approxFilter
65 /* Change Sequence Number (CSN) - much of this will change */
66 #define csnValidate blobValidate
67 #define csnMatch octetStringMatch
68 #define csnOrderingMatch octetStringOrderingMatch
69 #define csnIndexer generalizedTimeIndexer
70 #define csnFilter generalizedTimeFilter
72 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
73 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
74 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
75 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
110 static int certificateValidate( Syntax *syntax, struct berval *in )
113 unsigned char *p = (unsigned char *)in->bv_val;
115 xcert = d2i_X509(NULL, &p, in->bv_len);
116 if ( !xcert ) return LDAP_INVALID_SYNTAX;
121 #define certificateValidate sequenceValidate
130 struct berval *value,
131 void *assertedValue )
133 struct berval *asserted = (struct berval *) assertedValue;
134 int match = value->bv_len - asserted->bv_len;
137 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
145 octetStringOrderingMatch(
150 struct berval *value,
151 void *assertedValue )
153 struct berval *asserted = (struct berval *) assertedValue;
154 ber_len_t v_len = value->bv_len;
155 ber_len_t av_len = asserted->bv_len;
157 int match = memcmp( value->bv_val, asserted->bv_val,
158 (v_len < av_len ? v_len : av_len) );
160 if( match == 0 ) match = v_len - av_len;
168 HASH_CONTEXT *HASHcontext,
169 unsigned char *HASHdigest,
170 struct berval *prefix,
174 unsigned char *value,
177 HASH_Init(HASHcontext);
178 if(prefix && prefix->bv_len > 0) {
179 HASH_Update(HASHcontext,
180 (unsigned char *)prefix->bv_val, prefix->bv_len);
182 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
183 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
184 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
185 HASH_Update(HASHcontext, value, value_len);
186 HASH_Final(HASHdigest, HASHcontext);
190 /* Index generation function */
191 int octetStringIndexer(
196 struct berval *prefix,
204 HASH_CONTEXT HASHcontext;
205 unsigned char HASHdigest[HASH_BYTES];
206 struct berval digest;
207 digest.bv_val = (char *)HASHdigest;
208 digest.bv_len = sizeof(HASHdigest);
210 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
211 /* just count them */
214 /* we should have at least one value at this point */
217 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
219 slen = syntax->ssyn_oidlen;
220 mlen = mr->smr_oidlen;
222 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
223 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
224 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
225 ber_dupbv_x( &keys[i], &digest, ctx );
228 BER_BVZERO( &keys[i] );
235 /* Index generation function */
236 int octetStringFilter(
241 struct berval *prefix,
242 void * assertedValue,
248 HASH_CONTEXT HASHcontext;
249 unsigned char HASHdigest[HASH_BYTES];
250 struct berval *value = (struct berval *) assertedValue;
251 struct berval digest;
252 digest.bv_val = (char *)HASHdigest;
253 digest.bv_len = sizeof(HASHdigest);
255 slen = syntax->ssyn_oidlen;
256 mlen = mr->smr_oidlen;
258 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
260 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
261 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
263 ber_dupbv_x( keys, &digest, ctx );
264 BER_BVZERO( &keys[1] );
272 octetStringSubstringsMatch(
277 struct berval *value,
278 void *assertedValue )
281 SubstringsAssertion *sub = assertedValue;
282 struct berval left = *value;
286 /* Add up asserted input length */
287 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
288 inlen += sub->sa_initial.bv_len;
291 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
292 inlen += sub->sa_any[i].bv_len;
295 if ( !BER_BVISNULL( &sub->sa_final ) ) {
296 inlen += sub->sa_final.bv_len;
299 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
300 if ( inlen > left.bv_len ) {
305 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
306 sub->sa_initial.bv_len );
312 left.bv_val += sub->sa_initial.bv_len;
313 left.bv_len -= sub->sa_initial.bv_len;
314 inlen -= sub->sa_initial.bv_len;
317 if ( !BER_BVISNULL( &sub->sa_final ) ) {
318 if ( inlen > left.bv_len ) {
323 match = memcmp( sub->sa_final.bv_val,
324 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
325 sub->sa_final.bv_len );
331 left.bv_len -= sub->sa_final.bv_len;
332 inlen -= sub->sa_final.bv_len;
336 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
341 if ( inlen > left.bv_len ) {
342 /* not enough length */
347 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
351 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
358 idx = p - left.bv_val;
360 if ( idx >= left.bv_len ) {
361 /* this shouldn't happen */
368 if ( sub->sa_any[i].bv_len > left.bv_len ) {
369 /* not enough left */
374 match = memcmp( left.bv_val,
375 sub->sa_any[i].bv_val,
376 sub->sa_any[i].bv_len );
384 left.bv_val += sub->sa_any[i].bv_len;
385 left.bv_len -= sub->sa_any[i].bv_len;
386 inlen -= sub->sa_any[i].bv_len;
395 /* Substrings Index generation function */
397 octetStringSubstringsIndexer(
402 struct berval *prefix,
411 HASH_CONTEXT HASHcontext;
412 unsigned char HASHdigest[HASH_BYTES];
413 struct berval digest;
414 digest.bv_val = (char *)HASHdigest;
415 digest.bv_len = sizeof(HASHdigest);
419 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
420 /* count number of indices to generate */
421 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
422 if( values[i].bv_len >= index_substr_if_maxlen ) {
423 nkeys += index_substr_if_maxlen -
424 (index_substr_if_minlen - 1);
425 } else if( values[i].bv_len >= index_substr_if_minlen ) {
426 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
430 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
431 if( values[i].bv_len >= index_substr_any_len ) {
432 nkeys += values[i].bv_len - (index_substr_any_len - 1);
436 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
437 if( values[i].bv_len >= index_substr_if_maxlen ) {
438 nkeys += index_substr_if_maxlen -
439 (index_substr_if_minlen - 1);
440 } else if( values[i].bv_len >= index_substr_if_minlen ) {
441 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
447 /* no keys to generate */
452 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
454 slen = syntax->ssyn_oidlen;
455 mlen = mr->smr_oidlen;
458 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
461 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
462 ( values[i].bv_len >= index_substr_any_len ) )
464 char pre = SLAP_INDEX_SUBSTR_PREFIX;
465 max = values[i].bv_len - (index_substr_any_len - 1);
467 for( j=0; j<max; j++ ) {
468 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
469 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
470 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
474 /* skip if too short */
475 if( values[i].bv_len < index_substr_if_minlen ) continue;
477 max = index_substr_if_maxlen < values[i].bv_len
478 ? index_substr_if_maxlen : values[i].bv_len;
480 for( j=index_substr_if_minlen; j<=max; j++ ) {
483 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
484 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
485 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
486 syntax, mr, (unsigned char *)values[i].bv_val, j );
487 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
490 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
491 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
492 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
493 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
494 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
501 BER_BVZERO( &keys[nkeys] );
512 octetStringSubstringsFilter (
517 struct berval *prefix,
518 void * assertedValue,
522 SubstringsAssertion *sa;
525 size_t slen, mlen, klen;
527 HASH_CONTEXT HASHcontext;
528 unsigned char HASHdigest[HASH_BYTES];
529 struct berval *value;
530 struct berval digest;
532 sa = (SubstringsAssertion *) assertedValue;
534 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
535 !BER_BVISNULL( &sa->sa_initial ) &&
536 sa->sa_initial.bv_len >= index_substr_if_minlen )
539 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
540 ( flags & SLAP_INDEX_SUBSTR_ANY ))
542 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
546 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
548 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
549 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
550 /* don't bother accounting with stepping */
551 nkeys += sa->sa_any[i].bv_len -
552 ( index_substr_any_len - 1 );
557 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
558 !BER_BVISNULL( &sa->sa_final ) &&
559 sa->sa_final.bv_len >= index_substr_if_minlen )
562 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
563 ( flags & SLAP_INDEX_SUBSTR_ANY ))
565 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
574 digest.bv_val = (char *)HASHdigest;
575 digest.bv_len = sizeof(HASHdigest);
577 slen = syntax->ssyn_oidlen;
578 mlen = mr->smr_oidlen;
580 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
583 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
584 !BER_BVISNULL( &sa->sa_initial ) &&
585 sa->sa_initial.bv_len >= index_substr_if_minlen )
587 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
588 value = &sa->sa_initial;
590 klen = index_substr_if_maxlen < value->bv_len
591 ? index_substr_if_maxlen : value->bv_len;
593 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
594 syntax, mr, (unsigned char *)value->bv_val, klen );
595 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
597 /* If initial is too long and we have subany indexed, use it
598 * to match the excess...
600 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
603 pre = SLAP_INDEX_SUBSTR_PREFIX;
604 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
606 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
607 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
608 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
613 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
615 pre = SLAP_INDEX_SUBSTR_PREFIX;
616 klen = index_substr_any_len;
618 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
619 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
623 value = &sa->sa_any[i];
626 j <= value->bv_len - index_substr_any_len;
627 j += index_substr_any_step )
629 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
630 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
631 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
636 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
637 !BER_BVISNULL( &sa->sa_final ) &&
638 sa->sa_final.bv_len >= index_substr_if_minlen )
640 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
641 value = &sa->sa_final;
643 klen = index_substr_if_maxlen < value->bv_len
644 ? index_substr_if_maxlen : value->bv_len;
646 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
647 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
648 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
650 /* If final is too long and we have subany indexed, use it
651 * to match the excess...
653 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
656 pre = SLAP_INDEX_SUBSTR_PREFIX;
657 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
659 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
660 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
661 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
667 BER_BVZERO( &keys[nkeys] );
684 /* very unforgiving validation, requires no normalization
685 * before simplistic matching
687 if( in->bv_len < 3 ) {
688 return LDAP_INVALID_SYNTAX;
692 * RFC 2252 section 6.3 Bit String
693 * bitstring = "'" *binary-digit "'B"
694 * binary-digit = "0" / "1"
695 * example: '0101111101'B
698 if( in->bv_val[0] != '\'' ||
699 in->bv_val[in->bv_len - 2] != '\'' ||
700 in->bv_val[in->bv_len - 1] != 'B' )
702 return LDAP_INVALID_SYNTAX;
705 for( i = in->bv_len - 3; i > 0; i-- ) {
706 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
707 return LDAP_INVALID_SYNTAX;
715 * Syntax is [RFC2252]:
720 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
722 Values in this syntax are encoded according to the following BNF:
724 bitstring = "'" *binary-digit "'B"
726 binary-digit = "0" / "1"
730 6.21. Name And Optional UID
732 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
734 Values in this syntax are encoded according to the following BNF:
736 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
738 Although the '#' character may occur in a string representation of a
739 distinguished name, no additional special quoting is done. This
740 syntax has been added subsequent to RFC 1778.
744 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
747 * draft-ietf-ldapbis-syntaxes-xx.txt says:
752 A value of the Bit String syntax is a sequence of binary digits. The
753 LDAP-specific encoding of a value of this syntax is defined by the
756 BitString = SQUOTE *binary-digit SQUOTE "B"
758 binary-digit = "0" / "1"
760 The <SQUOTE> rule is defined in [MODELS].
765 The LDAP definition for the Bit String syntax is:
767 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
769 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
773 3.3.21. Name and Optional UID
775 A value of the Name and Optional UID syntax is the distinguished name
776 [MODELS] of an entity optionally accompanied by a unique identifier
777 that serves to differentiate the entity from others with an identical
780 The LDAP-specific encoding of a value of this syntax is defined by
783 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
785 The <BitString> rule is defined in Section 3.3.2. The
786 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
789 Note that although the '#' character may occur in the string
790 representation of a distinguished name, no additional escaping of
791 this character is performed when a <distinguishedName> is encoded in
792 a <NameAndOptionalUID>.
795 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
797 The LDAP definition for the Name and Optional UID syntax is:
799 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
801 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
805 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
808 1.4. Common ABNF Productions
811 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
813 SQUOTE = %x27 ; single quote ("'")
817 * Note: normalization strips any leading "0"s, unless the
818 * bit string is exactly "'0'B", so the normalized example,
819 * in slapd, would result in
821 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
823 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
824 * i.e. "#", doesn't have to be escaped except when at the
825 * beginning of a value, the definition of Name and Optional
826 * UID appears to be flawed, because there is no clear means
827 * to determine whether the UID part is present or not.
831 * cn=Someone,dc=example,dc=com#'1'B
833 * could be either a NameAndOptionalUID with trailing UID, i.e.
835 * DN = "cn=Someone,dc=example,dc=com"
838 * or a NameAndOptionalUID with no trailing UID, and the AVA
839 * in the last RDN made of
842 * attributeValue = com#'1'B
844 * in fact "com#'1'B" is a valid IA5 string.
846 * As a consequence, current slapd code assumes that the
847 * presence of portions of a BitString at the end of the string
848 * representation of a NameAndOptionalUID means a BitString
849 * is expected, and cause an error otherwise. This is quite
850 * arbitrary, and might change in the future.
860 struct berval dn, uid;
862 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
864 ber_dupbv( &dn, in );
865 if( !dn.bv_val ) return LDAP_OTHER;
867 /* if there's a "#", try bitStringValidate()... */
868 uid.bv_val = strrchr( dn.bv_val, '#' );
869 if ( !BER_BVISNULL( &uid ) ) {
871 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
873 rc = bitStringValidate( NULL, &uid );
874 if ( rc == LDAP_SUCCESS ) {
875 /* in case of success, trim the UID,
876 * otherwise treat it as part of the DN */
877 dn.bv_len -= uid.bv_len + 1;
878 uid.bv_val[-1] = '\0';
882 rc = dnValidate( NULL, &dn );
884 ber_memfree( dn.bv_val );
895 assert( val != NULL );
896 assert( out != NULL );
899 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
901 if( BER_BVISEMPTY( val ) ) {
902 ber_dupbv_x( out, val, ctx );
904 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
905 return LDAP_INVALID_SYNTAX;
909 struct berval dnval = *val;
910 struct berval uidval = BER_BVNULL;
912 uidval.bv_val = strrchr( val->bv_val, '#' );
913 if ( !BER_BVISNULL( &uidval ) ) {
915 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
917 rc = bitStringValidate( NULL, &uidval );
919 if ( rc == LDAP_SUCCESS ) {
920 ber_dupbv_x( &dnval, val, ctx );
921 dnval.bv_len -= uidval.bv_len + 1;
922 dnval.bv_val[dnval.bv_len] = '\0';
925 BER_BVZERO( &uidval );
929 rc = dnPretty( syntax, &dnval, out, ctx );
930 if ( dnval.bv_val != val->bv_val ) {
931 slap_sl_free( dnval.bv_val, ctx );
933 if( rc != LDAP_SUCCESS ) {
937 if( !BER_BVISNULL( &uidval ) ) {
941 tmp = slap_sl_realloc( out->bv_val, out->bv_len
942 + STRLENOF( "#" ) + uidval.bv_len + 1,
945 ber_memfree_x( out->bv_val, ctx );
949 out->bv_val[out->bv_len++] = '#';
950 out->bv_val[out->bv_len++] = '\'';
952 got1 = uidval.bv_len < sizeof("'0'B");
953 for( i = 1; i < uidval.bv_len - 2; i++ ) {
954 c = uidval.bv_val[i];
957 if( got1 ) out->bv_val[out->bv_len++] = c;
961 out->bv_val[out->bv_len++] = c;
966 out->bv_val[out->bv_len++] = '\'';
967 out->bv_val[out->bv_len++] = 'B';
968 out->bv_val[out->bv_len] = '\0';
972 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
978 uniqueMemberNormalize(
983 struct berval *normalized,
989 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
991 ber_dupbv_x( &out, val, ctx );
992 if ( BER_BVISEMPTY( &out ) ) {
996 struct berval uid = BER_BVNULL;
998 uid.bv_val = strrchr( out.bv_val, '#' );
999 if ( !BER_BVISNULL( &uid ) ) {
1001 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1003 rc = bitStringValidate( NULL, &uid );
1004 if ( rc == LDAP_SUCCESS ) {
1005 uid.bv_val[-1] = '\0';
1006 out.bv_len -= uid.bv_len + 1;
1012 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1014 if( rc != LDAP_SUCCESS ) {
1015 slap_sl_free( out.bv_val, ctx );
1016 return LDAP_INVALID_SYNTAX;
1019 if( !BER_BVISNULL( &uid ) ) {
1022 tmp = ch_realloc( normalized->bv_val,
1023 normalized->bv_len + uid.bv_len
1024 + STRLENOF("#") + 1 );
1025 if ( tmp == NULL ) {
1026 ber_memfree_x( normalized->bv_val, ctx );
1030 normalized->bv_val = tmp;
1032 /* insert the separator */
1033 normalized->bv_val[normalized->bv_len++] = '#';
1035 /* append the UID */
1036 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1037 uid.bv_val, uid.bv_len );
1038 normalized->bv_len += uid.bv_len;
1041 normalized->bv_val[normalized->bv_len] = '\0';
1044 slap_sl_free( out.bv_val, ctx );
1047 return LDAP_SUCCESS;
1056 struct berval *value,
1057 void *assertedValue )
1060 struct berval *asserted = (struct berval *) assertedValue;
1061 struct berval assertedDN = *asserted;
1062 struct berval assertedUID = BER_BVNULL;
1063 struct berval valueDN = BER_BVNULL;
1064 struct berval valueUID = BER_BVNULL;
1065 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1067 if ( !BER_BVISEMPTY( asserted ) ) {
1068 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1069 if ( !BER_BVISNULL( &assertedUID ) ) {
1070 assertedUID.bv_val++;
1071 assertedUID.bv_len = assertedDN.bv_len
1072 - ( assertedUID.bv_val - assertedDN.bv_val );
1074 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1075 assertedDN.bv_len -= assertedUID.bv_len + 1;
1078 BER_BVZERO( &assertedUID );
1083 if ( !BER_BVISEMPTY( value ) ) {
1086 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1087 if ( !BER_BVISNULL( &valueUID ) ) {
1089 valueUID.bv_len = valueDN.bv_len
1090 - ( valueUID.bv_val - valueDN.bv_val );
1092 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1093 valueDN.bv_len -= valueUID.bv_len + 1;
1096 BER_BVZERO( &valueUID );
1101 if( valueUID.bv_len && assertedUID.bv_len ) {
1102 match = valueUID.bv_len - assertedUID.bv_len;
1105 return LDAP_SUCCESS;
1108 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1111 return LDAP_SUCCESS;
1114 } else if ( !approx && valueUID.bv_len ) {
1117 return LDAP_SUCCESS;
1119 } else if ( !approx && assertedUID.bv_len ) {
1122 return LDAP_SUCCESS;
1125 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1129 uniqueMemberIndexer(
1134 struct berval *prefix,
1142 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1143 /* just count them */
1147 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1149 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1150 struct berval assertedDN = values[i];
1151 struct berval assertedUID = BER_BVNULL;
1153 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1154 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1155 if ( !BER_BVISNULL( &assertedUID ) ) {
1156 assertedUID.bv_val++;
1157 assertedUID.bv_len = assertedDN.bv_len
1158 - ( assertedUID.bv_val - assertedDN.bv_val );
1160 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1161 assertedDN.bv_len -= assertedUID.bv_len + 1;
1164 BER_BVZERO( &assertedUID );
1169 dnvalues[i] = assertedDN;
1171 BER_BVZERO( &dnvalues[i] );
1173 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1174 dnvalues, keysp, ctx );
1176 slap_sl_free( dnvalues, ctx );
1186 struct berval *prefix,
1187 void * assertedValue,
1191 struct berval *asserted = (struct berval *) assertedValue;
1192 struct berval assertedDN = *asserted;
1193 struct berval assertedUID = BER_BVNULL;
1195 if ( !BER_BVISEMPTY( asserted ) ) {
1196 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1197 if ( !BER_BVISNULL( &assertedUID ) ) {
1198 assertedUID.bv_val++;
1199 assertedUID.bv_len = assertedDN.bv_len
1200 - ( assertedUID.bv_val - assertedDN.bv_val );
1202 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1203 assertedDN.bv_len -= assertedUID.bv_len + 1;
1206 BER_BVZERO( &assertedUID );
1211 return octetStringFilter( use, flags, syntax, mr, prefix,
1212 &assertedDN, keysp, ctx );
1217 * Handling boolean syntax and matching is quite rigid.
1218 * A more flexible approach would be to allow a variety
1219 * of strings to be normalized and prettied into TRUE
1227 /* very unforgiving validation, requires no normalization
1228 * before simplistic matching
1231 if( in->bv_len == 4 ) {
1232 if( bvmatch( in, &slap_true_bv ) ) {
1233 return LDAP_SUCCESS;
1235 } else if( in->bv_len == 5 ) {
1236 if( bvmatch( in, &slap_false_bv ) ) {
1237 return LDAP_SUCCESS;
1241 return LDAP_INVALID_SYNTAX;
1250 struct berval *value,
1251 void *assertedValue )
1253 /* simplistic matching allowed by rigid validation */
1254 struct berval *asserted = (struct berval *) assertedValue;
1255 *matchp = value->bv_len != asserted->bv_len;
1256 return LDAP_SUCCESS;
1259 /*-------------------------------------------------------------------
1260 LDAP/X.500 string syntax / matching rules have a few oddities. This
1261 comment attempts to detail how slapd(8) treats them.
1264 StringSyntax X.500 LDAP Matching/Comments
1265 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1266 PrintableString subset subset i/e + ignore insignificant spaces
1267 PrintableString subset subset i/e + ignore insignificant spaces
1268 NumericString subset subset ignore all spaces
1269 IA5String ASCII ASCII i/e + ignore insignificant spaces
1270 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1272 TelephoneNumber subset subset i + ignore all spaces and "-"
1274 See draft-ietf-ldapbis-strpro for details (once published).
1278 In X.500(93), a directory string can be either a PrintableString,
1279 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1280 In later versions, more CHOICEs were added. In all cases the string
1283 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1284 A directory string cannot be zero length.
1286 For matching, there are both case ignore and exact rules. Both
1287 also require that "insignificant" spaces be ignored.
1288 spaces before the first non-space are ignored;
1289 spaces after the last non-space are ignored;
1290 spaces after a space are ignored.
1291 Note: by these rules (and as clarified in X.520), a string of only
1292 spaces is to be treated as if held one space, not empty (which
1293 would be a syntax error).
1296 In ASN.1, numeric string is just a string of digits and spaces
1297 and could be empty. However, in X.500, all attribute values of
1298 numeric string carry a non-empty constraint. For example:
1300 internationalISDNNumber ATTRIBUTE ::= {
1301 WITH SYNTAX InternationalISDNNumber
1302 EQUALITY MATCHING RULE numericStringMatch
1303 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1304 ID id-at-internationalISDNNumber }
1305 InternationalISDNNumber ::=
1306 NumericString (SIZE(1..ub-international-isdn-number))
1308 Unforunately, some assertion values are don't carry the same
1309 constraint (but its unclear how such an assertion could ever
1310 be true). In LDAP, there is one syntax (numericString) not two
1311 (numericString with constraint, numericString without constraint).
1312 This should be treated as numericString with non-empty constraint.
1313 Note that while someone may have no ISDN number, there are no ISDN
1314 numbers which are zero length.
1316 In matching, spaces are ignored.
1319 In ASN.1, Printable string is just a string of printable characters
1320 and can be empty. In X.500, semantics much like NumericString (see
1321 serialNumber for a like example) excepting uses insignificant space
1322 handling instead of ignore all spaces.
1325 Basically same as PrintableString. There are no examples in X.500,
1326 but same logic applies. So we require them to be non-empty as
1329 -------------------------------------------------------------------*/
1338 unsigned char *u = (unsigned char *)in->bv_val;
1340 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1341 /* directory strings cannot be empty */
1342 return LDAP_INVALID_SYNTAX;
1345 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1346 /* get the length indicated by the first byte */
1347 len = LDAP_UTF8_CHARLEN2( u, len );
1349 /* very basic checks */
1352 if( (u[5] & 0xC0) != 0x80 ) {
1353 return LDAP_INVALID_SYNTAX;
1356 if( (u[4] & 0xC0) != 0x80 ) {
1357 return LDAP_INVALID_SYNTAX;
1360 if( (u[3] & 0xC0) != 0x80 ) {
1361 return LDAP_INVALID_SYNTAX;
1364 if( (u[2] & 0xC0 )!= 0x80 ) {
1365 return LDAP_INVALID_SYNTAX;
1368 if( (u[1] & 0xC0) != 0x80 ) {
1369 return LDAP_INVALID_SYNTAX;
1372 /* CHARLEN already validated it */
1375 return LDAP_INVALID_SYNTAX;
1378 /* make sure len corresponds with the offset
1379 to the next character */
1380 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1384 return LDAP_INVALID_SYNTAX;
1387 return LDAP_SUCCESS;
1391 UTF8StringNormalize(
1396 struct berval *normalized,
1399 struct berval tmp, nvalue;
1403 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1405 if( BER_BVISNULL( val ) ) {
1406 /* assume we're dealing with a syntax (e.g., UTF8String)
1407 * which allows empty strings
1409 BER_BVZERO( normalized );
1410 return LDAP_SUCCESS;
1413 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1414 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1415 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1416 ? LDAP_UTF8_APPROX : 0;
1418 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1423 /* collapse spaces (in place) */
1425 nvalue.bv_val = tmp.bv_val;
1427 /* trim leading spaces? */
1428 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1429 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1431 for( i = 0; i < tmp.bv_len; i++) {
1432 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1433 if( wasspace++ == 0 ) {
1434 /* trim repeated spaces */
1435 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1439 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1443 if( !BER_BVISEMPTY( &nvalue ) ) {
1444 /* trim trailing space? */
1446 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1447 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1451 nvalue.bv_val[nvalue.bv_len] = '\0';
1454 /* string of all spaces is treated as one space */
1455 nvalue.bv_val[0] = ' ';
1456 nvalue.bv_val[1] = '\0';
1460 *normalized = nvalue;
1461 return LDAP_SUCCESS;
1465 directoryStringSubstringsMatch(
1470 struct berval *value,
1471 void *assertedValue )
1474 SubstringsAssertion *sub = assertedValue;
1475 struct berval left = *value;
1479 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1480 if ( sub->sa_initial.bv_len > left.bv_len ) {
1481 /* not enough left */
1486 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1487 sub->sa_initial.bv_len );
1493 left.bv_val += sub->sa_initial.bv_len;
1494 left.bv_len -= sub->sa_initial.bv_len;
1496 priorspace = ASCII_SPACE(
1497 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1500 if ( sub->sa_any ) {
1501 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1505 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1506 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1508 /* allow next space to match */
1515 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1519 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1520 /* not enough left */
1525 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1532 idx = p - left.bv_val;
1534 if ( idx >= left.bv_len ) {
1535 /* this shouldn't happen */
1542 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1543 /* not enough left */
1548 match = memcmp( left.bv_val,
1549 sub->sa_any[i].bv_val,
1550 sub->sa_any[i].bv_len );
1558 left.bv_val += sub->sa_any[i].bv_len;
1559 left.bv_len -= sub->sa_any[i].bv_len;
1561 priorspace = ASCII_SPACE(
1562 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1566 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1567 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1568 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1570 /* allow next space to match */
1575 if ( sub->sa_final.bv_len > left.bv_len ) {
1576 /* not enough left */
1581 match = memcmp( sub->sa_final.bv_val,
1582 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1583 sub->sa_final.bv_len );
1592 return LDAP_SUCCESS;
1595 #if defined(SLAPD_APPROX_INITIALS)
1596 # define SLAPD_APPROX_DELIMITER "._ "
1597 # define SLAPD_APPROX_WORDLEN 2
1599 # define SLAPD_APPROX_DELIMITER " "
1600 # define SLAPD_APPROX_WORDLEN 1
1609 struct berval *value,
1610 void *assertedValue )
1612 struct berval *nval, *assertv;
1613 char *val, **values, **words, *c;
1614 int i, count, len, nextchunk=0, nextavail=0;
1616 /* Yes, this is necessary */
1617 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1618 if( nval == NULL ) {
1620 return LDAP_SUCCESS;
1623 /* Yes, this is necessary */
1624 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1625 NULL, LDAP_UTF8_APPROX, NULL );
1626 if( assertv == NULL ) {
1629 return LDAP_SUCCESS;
1632 /* Isolate how many words there are */
1633 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1634 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1635 if ( c == NULL ) break;
1640 /* Get a phonetic copy of each word */
1641 words = (char **)ch_malloc( count * sizeof(char *) );
1642 values = (char **)ch_malloc( count * sizeof(char *) );
1643 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1645 values[i] = phonetic(c);
1648 /* Work through the asserted value's words, to see if at least some
1649 of the words are there, in the same order. */
1651 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1652 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1657 #if defined(SLAPD_APPROX_INITIALS)
1658 else if( len == 1 ) {
1659 /* Single letter words need to at least match one word's initial */
1660 for( i=nextavail; i<count; i++ )
1661 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1668 /* Isolate the next word in the asserted value and phonetic it */
1669 assertv->bv_val[nextchunk+len] = '\0';
1670 val = phonetic( assertv->bv_val + nextchunk );
1672 /* See if this phonetic chunk is in the remaining words of *value */
1673 for( i=nextavail; i<count; i++ ){
1674 if( !strcmp( val, values[i] ) ){
1682 /* This chunk in the asserted value was NOT within the *value. */
1688 /* Go on to the next word in the asserted value */
1692 /* If some of the words were seen, call it a match */
1693 if( nextavail > 0 ) {
1700 /* Cleanup allocs */
1701 ber_bvfree( assertv );
1702 for( i=0; i<count; i++ ) {
1703 ch_free( values[i] );
1709 return LDAP_SUCCESS;
1718 struct berval *prefix,
1724 int i,j, len, wordcount, keycount=0;
1725 struct berval *newkeys;
1726 BerVarray keys=NULL;
1728 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1729 struct berval val = BER_BVNULL;
1730 /* Yes, this is necessary */
1731 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1732 assert( !BER_BVISNULL( &val ) );
1734 /* Isolate how many words there are. There will be a key for each */
1735 for( wordcount = 0, c = val.bv_val; *c; c++) {
1736 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1737 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1739 if (*c == '\0') break;
1743 /* Allocate/increase storage to account for new keys */
1744 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1745 * sizeof(struct berval) );
1746 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1747 if( keys ) ch_free( keys );
1750 /* Get a phonetic copy of each word */
1751 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1753 if( len < SLAPD_APPROX_WORDLEN ) continue;
1754 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1759 ber_memfree( val.bv_val );
1761 BER_BVZERO( &keys[keycount] );
1764 return LDAP_SUCCESS;
1773 struct berval *prefix,
1774 void * assertedValue,
1783 /* Yes, this is necessary */
1784 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1785 NULL, LDAP_UTF8_APPROX, NULL );
1786 if( val == NULL || BER_BVISNULL( val ) ) {
1787 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1788 BER_BVZERO( &keys[0] );
1791 return LDAP_SUCCESS;
1794 /* Isolate how many words there are. There will be a key for each */
1795 for( count = 0,c = val->bv_val; *c; c++) {
1796 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1797 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1799 if (*c == '\0') break;
1803 /* Allocate storage for new keys */
1804 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1806 /* Get a phonetic copy of each word */
1807 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1809 if( len < SLAPD_APPROX_WORDLEN ) continue;
1810 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1816 BER_BVZERO( &keys[count] );
1819 return LDAP_SUCCESS;
1822 /* Remove all spaces and '-' characters */
1824 telephoneNumberNormalize(
1829 struct berval *normalized,
1834 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1836 /* validator should have refused an empty string */
1837 assert( !BER_BVISEMPTY( val ) );
1839 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1841 for( p = val->bv_val; *p; p++ ) {
1842 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1848 normalized->bv_len = q - normalized->bv_val;
1850 if( BER_BVISEMPTY( normalized ) ) {
1851 slap_sl_free( normalized->bv_val, ctx );
1852 BER_BVZERO( normalized );
1853 return LDAP_INVALID_SYNTAX;
1856 return LDAP_SUCCESS;
1864 struct berval val = *in;
1866 if( BER_BVISEMPTY( &val ) ) {
1867 /* disallow empty strings */
1868 return LDAP_INVALID_SYNTAX;
1871 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1872 if ( val.bv_len == 1 ) {
1873 return LDAP_SUCCESS;
1876 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1883 while ( OID_LEADCHAR( val.bv_val[0] )) {
1887 if ( val.bv_len == 0 ) {
1888 return LDAP_SUCCESS;
1892 if( !OID_SEPARATOR( val.bv_val[0] )) {
1900 return LDAP_INVALID_SYNTAX;
1909 struct berval val = *in;
1911 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1913 if ( val.bv_val[0] == '-' ) {
1917 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1918 return LDAP_INVALID_SYNTAX;
1921 if( val.bv_val[0] == '0' ) { /* "-0" */
1922 return LDAP_INVALID_SYNTAX;
1925 } else if ( val.bv_val[0] == '0' ) {
1926 if( val.bv_len > 1 ) { /* "0<more>" */
1927 return LDAP_INVALID_SYNTAX;
1930 return LDAP_SUCCESS;
1933 for( i=0; i < val.bv_len; i++ ) {
1934 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1935 return LDAP_INVALID_SYNTAX;
1939 return LDAP_SUCCESS;
1948 struct berval *value,
1949 void *assertedValue )
1951 struct berval *asserted = (struct berval *) assertedValue;
1952 int vsign = 1, asign = 1; /* default sign = '+' */
1957 if( v.bv_val[0] == '-' ) {
1963 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1966 if( a.bv_val[0] == '-' ) {
1972 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1974 match = vsign - asign;
1976 match = ( v.bv_len != a.bv_len
1977 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1978 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1979 if( vsign < 0 ) match = -match;
1983 return LDAP_SUCCESS;
1987 countryStringValidate(
1989 struct berval *val )
1991 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1993 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1994 return LDAP_INVALID_SYNTAX;
1996 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1997 return LDAP_INVALID_SYNTAX;
2000 return LDAP_SUCCESS;
2004 printableStringValidate(
2006 struct berval *val )
2010 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2012 for(i=0; i < val->bv_len; i++) {
2013 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2014 return LDAP_INVALID_SYNTAX;
2018 return LDAP_SUCCESS;
2022 printablesStringValidate(
2024 struct berval *val )
2028 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2030 for(i=0,len=0; i < val->bv_len; i++) {
2031 int c = val->bv_val[i];
2035 return LDAP_INVALID_SYNTAX;
2039 } else if ( SLAP_PRINTABLE(c) ) {
2042 return LDAP_INVALID_SYNTAX;
2047 return LDAP_INVALID_SYNTAX;
2050 return LDAP_SUCCESS;
2056 struct berval *val )
2060 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2062 for(i=0; i < val->bv_len; i++) {
2063 if( !LDAP_ASCII(val->bv_val[i]) ) {
2064 return LDAP_INVALID_SYNTAX;
2068 return LDAP_SUCCESS;
2077 struct berval *normalized,
2081 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2083 assert( !BER_BVISEMPTY( val ) );
2085 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2089 /* Ignore initial whitespace */
2090 while ( ASCII_SPACE( *p ) ) p++;
2092 normalized->bv_val = ber_strdup_x( p, ctx );
2093 p = q = normalized->bv_val;
2096 if ( ASCII_SPACE( *p ) ) {
2099 /* Ignore the extra whitespace */
2100 while ( ASCII_SPACE( *p ) ) {
2104 } else if ( casefold ) {
2105 /* Most IA5 rules require casefolding */
2106 *q++ = TOLOWER(*p); p++;
2113 assert( normalized->bv_val <= p );
2117 * If the string ended in space, backup the pointer one
2118 * position. One is enough because the above loop collapsed
2119 * all whitespace to a single space.
2121 if ( ASCII_SPACE( q[-1] ) ) --q;
2123 /* null terminate */
2126 normalized->bv_len = q - normalized->bv_val;
2127 if( BER_BVISEMPTY( normalized ) ) {
2128 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2129 normalized->bv_val[0] = ' ';
2130 normalized->bv_val[1] = '\0';
2131 normalized->bv_len = 1;
2134 return LDAP_SUCCESS;
2143 if( in->bv_len != 36 ) {
2144 return LDAP_INVALID_SYNTAX;
2147 for( i=0; i<36; i++ ) {
2153 if( in->bv_val[i] != '-' ) {
2154 return LDAP_INVALID_SYNTAX;
2158 if( !ASCII_HEX( in->bv_val[i]) ) {
2159 return LDAP_INVALID_SYNTAX;
2164 return LDAP_SUCCESS;
2173 struct berval *normalized,
2176 unsigned char octet = '\0';
2179 normalized->bv_len = 16;
2180 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2182 for( i=0, j=0; i<36; i++ ) {
2183 unsigned char nibble;
2184 if( val->bv_val[i] == '-' ) {
2187 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2188 nibble = val->bv_val[i] - '0';
2190 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2191 nibble = val->bv_val[i] - ('a'-10);
2193 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2194 nibble = val->bv_val[i] - ('A'-10);
2197 slap_sl_free( normalized->bv_val, ctx );
2198 return LDAP_INVALID_SYNTAX;
2203 normalized->bv_val[j>>1] = octet;
2205 octet = nibble << 4;
2210 normalized->bv_val[normalized->bv_len] = 0;
2211 return LDAP_SUCCESS;
2217 numericStringValidate(
2223 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2225 for(i=0; i < in->bv_len; i++) {
2226 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2227 return LDAP_INVALID_SYNTAX;
2231 return LDAP_SUCCESS;
2235 numericStringNormalize(
2240 struct berval *normalized,
2243 /* removal all spaces */
2246 assert( !BER_BVISEMPTY( val ) );
2248 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2251 q = normalized->bv_val;
2254 if ( ASCII_SPACE( *p ) ) {
2255 /* Ignore whitespace */
2262 /* we should have copied no more then is in val */
2263 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2265 /* null terminate */
2268 normalized->bv_len = q - normalized->bv_val;
2270 if( BER_BVISEMPTY( normalized ) ) {
2271 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2272 normalized->bv_val[0] = ' ';
2273 normalized->bv_val[1] = '\0';
2274 normalized->bv_len = 1;
2277 return LDAP_SUCCESS;
2281 * Integer conversion macros that will use the largest available
2284 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2285 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2286 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2287 # define SLAP_LONG_MAX LLONG_MAX
2288 # define SLAP_LONG_MIN LLONG_MIN
2289 # define SLAP_LONG long long
2291 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2292 # define SLAP_LONG_MAX LONG_MAX
2293 # define SLAP_LONG_MIN LONG_MIN
2294 # define SLAP_LONG long
2295 #endif /* HAVE_STRTOLL ... */
2303 struct berval *value,
2304 void *assertedValue )
2306 SLAP_LONG lValue, lAssertedValue;
2308 /* safe to assume integers are NUL terminated? */
2309 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2310 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2313 return LDAP_CONSTRAINT_VIOLATION;
2316 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2318 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2321 return LDAP_CONSTRAINT_VIOLATION;
2324 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2325 return LDAP_SUCCESS;
2334 struct berval *value,
2335 void *assertedValue )
2337 SLAP_LONG lValue, lAssertedValue;
2339 /* safe to assume integers are NUL terminated? */
2340 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2341 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2344 return LDAP_CONSTRAINT_VIOLATION;
2347 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2349 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2352 return LDAP_CONSTRAINT_VIOLATION;
2355 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2356 return LDAP_SUCCESS;
2360 serialNumberAndIssuerValidate(
2366 struct berval sn, i;
2367 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2369 i.bv_val = strchr( in->bv_val, '$' );
2370 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2372 sn.bv_val = in->bv_val;
2373 sn.bv_len = i.bv_val - in->bv_val;
2376 i.bv_len = in->bv_len - (sn.bv_len + 1);
2378 /* validate serial number (strict for now) */
2379 for( n=0; n < sn.bv_len; n++ ) {
2380 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2384 rc = dnValidate( NULL, &i );
2385 if( rc ) return LDAP_INVALID_SYNTAX;
2387 return LDAP_SUCCESS;
2391 serialNumberAndIssuerPretty(
2399 struct berval sn, i, newi;
2401 assert( val != NULL );
2402 assert( out != NULL );
2404 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2405 val->bv_val, 0, 0 );
2407 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2409 i.bv_val = strchr( val->bv_val, '$' );
2410 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2412 sn.bv_val = val->bv_val;
2413 sn.bv_len = i.bv_val - val->bv_val;
2416 i.bv_len = val->bv_len - (sn.bv_len + 1);
2418 /* eat leading zeros */
2419 for( n=0; n < (sn.bv_len-1); n++ ) {
2420 if( sn.bv_val[n] != '0' ) break;
2425 for( n=0; n < sn.bv_len; n++ ) {
2426 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2430 rc = dnPretty( syntax, &i, &newi, ctx );
2431 if( rc ) return LDAP_INVALID_SYNTAX;
2433 /* make room from sn + "$" */
2434 out->bv_len = sn.bv_len + newi.bv_len + 1;
2435 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2437 if( out->bv_val == NULL ) {
2439 slap_sl_free( newi.bv_val, ctx );
2443 /* push issuer over */
2444 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2445 /* insert sn and "$" */
2446 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2447 out->bv_val[sn.bv_len] = '$';
2449 out->bv_val[out->bv_len] = '\0';
2451 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2452 out->bv_val, 0, 0 );
2454 return LDAP_SUCCESS;
2458 * This routine is called by certificateExactNormalize when
2459 * certificateExactNormalize receives a search string instead of
2460 * a certificate. This routine checks if the search value is valid
2461 * and then returns the normalized value
2464 serialNumberAndIssuerNormalize(
2474 struct berval sn, i, newi;
2476 assert( val != NULL );
2477 assert( out != NULL );
2479 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2480 val->bv_val, 0, 0 );
2482 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2484 i.bv_val = strchr( val->bv_val, '$' );
2485 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2487 sn.bv_val = val->bv_val;
2488 sn.bv_len = i.bv_val - val->bv_val;
2491 i.bv_len = val->bv_len - (sn.bv_len + 1);
2493 /* eat leading zeros */
2494 for( n=0; n < (sn.bv_len-1); n++ ) {
2495 if( sn.bv_val[n] != '0' ) break;
2500 for( n=0; n < sn.bv_len; n++ ) {
2501 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2502 return LDAP_INVALID_SYNTAX;
2507 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2508 if( rc ) return LDAP_INVALID_SYNTAX;
2510 /* make room from sn + "$" */
2511 out->bv_len = sn.bv_len + newi.bv_len + 1;
2512 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2514 if( out->bv_val == NULL ) {
2516 slap_sl_free( newi.bv_val, ctx );
2520 /* push issuer over */
2521 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2522 /* insert sn and "$" */
2523 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2524 out->bv_val[sn.bv_len] = '$';
2526 out->bv_val[out->bv_len] = '\0';
2528 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2529 out->bv_val, 0, 0 );
2536 certificateExactNormalize(
2541 struct berval *normalized,
2544 int rc = LDAP_INVALID_SYNTAX;
2546 char *serial = NULL;
2547 ber_len_t seriallen;
2548 struct berval issuer_dn = BER_BVNULL;
2549 X509_NAME *name = NULL;
2550 ASN1_INTEGER *sn = NULL;
2553 if( BER_BVISEMPTY( val ) ) goto done;
2555 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2556 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2559 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2561 p = (unsigned char *)val->bv_val;
2562 xcert = d2i_X509( NULL, &p, val->bv_len);
2563 if( xcert == NULL ) goto done;
2565 sn=X509_get_serialNumber(xcert);
2566 if ( sn == NULL ) goto done;
2567 serial=i2s_ASN1_INTEGER(0, sn );
2568 if( serial == NULL ) goto done;
2569 seriallen=strlen(serial);
2571 name=X509_get_issuer_name(xcert);
2572 if( name == NULL ) goto done;
2573 rc = dnX509normalize( name, &issuer_dn );
2574 if( rc != LDAP_SUCCESS ) goto done;
2576 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2577 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2578 p = (unsigned char *)normalized->bv_val;
2579 AC_MEMCPY(p, serial, seriallen);
2582 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2583 p += issuer_dn.bv_len;
2586 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2587 normalized->bv_val, NULL, NULL );
2590 if (xcert) X509_free(xcert);
2591 if (serial) ch_free(serial);
2592 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2596 #endif /* HAVE_TLS */
2599 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2600 /* slight optimization - does not need the start parameter */
2601 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2606 check_time_syntax (struct berval *val,
2609 struct berval *fraction)
2612 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2613 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2614 * GeneralizedTime supports leap seconds, UTCTime does not.
2616 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2617 static const int mdays[2][12] = {
2618 /* non-leap years */
2619 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2621 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2624 int part, c, c1, c2, tzoffset, leapyear = 0;
2627 e = p + val->bv_len;
2629 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2630 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2632 for (part = start; part < 7 && p < e; part++) {
2634 if (!ASCII_DIGIT(c1)) {
2639 return LDAP_INVALID_SYNTAX;
2642 if (!ASCII_DIGIT(c)) {
2643 return LDAP_INVALID_SYNTAX;
2645 c += c1 * 10 - '0' * 11;
2646 if ((part | 1) == 3) {
2649 return LDAP_INVALID_SYNTAX;
2652 if (c >= ceiling[part]) {
2653 if (! (c == 60 && part == 6 && start == 0))
2654 return LDAP_INVALID_SYNTAX;
2658 if (part < 5 + start) {
2659 return LDAP_INVALID_SYNTAX;
2661 for (; part < 9; part++) {
2665 /* leapyear check for the Gregorian calendar (year>1581) */
2666 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2670 if (parts[3] >= mdays[leapyear][parts[2]]) {
2671 return LDAP_INVALID_SYNTAX;
2675 fraction->bv_val = p;
2676 fraction->bv_len = 0;
2677 if (p < e && (*p == '.' || *p == ',')) {
2679 while (++p < e && ASCII_DIGIT(*p)) {
2682 if (p - fraction->bv_val == 1) {
2683 return LDAP_INVALID_SYNTAX;
2685 for (end_num = p; end_num[-1] == '0'; --end_num) {
2688 c = end_num - fraction->bv_val;
2689 if (c != 1) fraction->bv_len = c;
2695 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2701 return LDAP_INVALID_SYNTAX;
2707 for (part = 7; part < 9 && p < e; part++) {
2709 if (!ASCII_DIGIT(c1)) {
2714 return LDAP_INVALID_SYNTAX;
2717 if (!ASCII_DIGIT(c2)) {
2718 return LDAP_INVALID_SYNTAX;
2720 parts[part] = c1 * 10 + c2 - '0' * 11;
2721 if (parts[part] >= ceiling[part]) {
2722 return LDAP_INVALID_SYNTAX;
2725 if (part < 8 + start) {
2726 return LDAP_INVALID_SYNTAX;
2729 if (tzoffset == '-') {
2730 /* negative offset to UTC, ie west of Greenwich */
2731 parts[4] += parts[7];
2732 parts[5] += parts[8];
2733 /* offset is just hhmm, no seconds */
2734 for (part = 6; --part >= 0; ) {
2738 c = mdays[leapyear][parts[2]];
2740 if (parts[part] >= c) {
2742 return LDAP_INVALID_SYNTAX;
2747 } else if (part != 5) {
2752 /* positive offset to UTC, ie east of Greenwich */
2753 parts[4] -= parts[7];
2754 parts[5] -= parts[8];
2755 for (part = 6; --part >= 0; ) {
2756 if (parts[part] < 0) {
2758 return LDAP_INVALID_SYNTAX;
2763 /* make first arg to % non-negative */
2764 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2769 } else if (part != 5) {
2776 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2779 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2786 struct berval *normalized )
2790 rc = check_time_syntax(val, 1, parts, NULL);
2791 if (rc != LDAP_SUCCESS) {
2795 normalized->bv_val = ch_malloc( 14 );
2796 if ( normalized->bv_val == NULL ) {
2797 return LBER_ERROR_MEMORY;
2800 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2801 parts[1], parts[2] + 1, parts[3] + 1,
2802 parts[4], parts[5], parts[6] );
2803 normalized->bv_len = 13;
2805 return LDAP_SUCCESS;
2815 return check_time_syntax(in, 1, parts, NULL);
2818 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2821 generalizedTimeValidate(
2826 struct berval fraction;
2827 return check_time_syntax(in, 0, parts, &fraction);
2831 generalizedTimeNormalize(
2836 struct berval *normalized,
2841 struct berval fraction;
2843 rc = check_time_syntax(val, 0, parts, &fraction);
2844 if (rc != LDAP_SUCCESS) {
2848 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2849 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2850 if ( BER_BVISNULL( normalized ) ) {
2851 return LBER_ERROR_MEMORY;
2854 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2855 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2856 parts[4], parts[5], parts[6] );
2857 if ( !BER_BVISEMPTY( &fraction ) ) {
2858 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2859 fraction.bv_val, fraction.bv_len );
2860 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2862 strcpy( normalized->bv_val + len-1, "Z" );
2863 normalized->bv_len = len;
2865 return LDAP_SUCCESS;
2869 generalizedTimeOrderingMatch(
2874 struct berval *value,
2875 void *assertedValue )
2877 struct berval *asserted = (struct berval *) assertedValue;
2878 ber_len_t v_len = value->bv_len;
2879 ber_len_t av_len = asserted->bv_len;
2881 /* ignore trailing 'Z' when comparing */
2882 int match = memcmp( value->bv_val, asserted->bv_val,
2883 (v_len < av_len ? v_len : av_len) - 1 );
2884 if ( match == 0 ) match = v_len - av_len;
2887 return LDAP_SUCCESS;
2890 /* Index generation function */
2891 int generalizedTimeIndexer(
2896 struct berval *prefix,
2904 BerValue bvtmp; /* 40 bit index */
2906 struct lutil_timet tt;
2908 bvtmp.bv_len = sizeof(tmp);
2910 for( i=0; values[i].bv_val != NULL; i++ ) {
2911 /* just count them */
2914 /* we should have at least one value at this point */
2917 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2919 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2920 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2921 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2922 /* Use 40 bits of time for key */
2923 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2924 lutil_tm2time( &tm, &tt );
2925 tmp[0] = tt.tt_gsec & 0xff;
2926 tmp[4] = tt.tt_sec & 0xff;
2928 tmp[3] = tt.tt_sec & 0xff;
2930 tmp[2] = tt.tt_sec & 0xff;
2932 tmp[1] = tt.tt_sec & 0xff;
2934 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2938 keys[j].bv_val = NULL;
2943 return LDAP_SUCCESS;
2946 /* Index generation function */
2947 int generalizedTimeFilter(
2952 struct berval *prefix,
2953 void * assertedValue,
2959 BerValue bvtmp; /* 40 bit index */
2960 BerValue *value = (BerValue *) assertedValue;
2962 struct lutil_timet tt;
2964 bvtmp.bv_len = sizeof(tmp);
2966 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2967 /* Use 40 bits of time for key */
2968 if ( value->bv_val && value->bv_len >= 10 &&
2969 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2971 lutil_tm2time( &tm, &tt );
2972 tmp[0] = tt.tt_gsec & 0xff;
2973 tmp[4] = tt.tt_sec & 0xff;
2975 tmp[3] = tt.tt_sec & 0xff;
2977 tmp[2] = tt.tt_sec & 0xff;
2979 tmp[1] = tt.tt_sec & 0xff;
2981 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2982 ber_dupbv_x(keys, &bvtmp, ctx );
2983 keys[1].bv_val = NULL;
2991 return LDAP_SUCCESS;
2995 deliveryMethodValidate(
2997 struct berval *val )
3000 #define LENOF(s) (sizeof(s)-1)
3001 struct berval tmp = *val;
3003 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3004 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3005 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3008 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3010 switch( tmp.bv_val[0] ) {
3013 if(( tmp.bv_len >= LENOF("any") ) &&
3014 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3016 tmp.bv_len -= LENOF("any");
3017 tmp.bv_val += LENOF("any");
3020 return LDAP_INVALID_SYNTAX;
3024 if(( tmp.bv_len >= LENOF("mhs") ) &&
3025 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3027 tmp.bv_len -= LENOF("mhs");
3028 tmp.bv_val += LENOF("mhs");
3031 return LDAP_INVALID_SYNTAX;
3035 if(( tmp.bv_len >= LENOF("physical") ) &&
3036 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3038 tmp.bv_len -= LENOF("physical");
3039 tmp.bv_val += LENOF("physical");
3042 return LDAP_INVALID_SYNTAX;
3045 case 'T': /* telex or teletex or telephone */
3046 if(( tmp.bv_len >= LENOF("telex") ) &&
3047 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3049 tmp.bv_len -= LENOF("telex");
3050 tmp.bv_val += LENOF("telex");
3053 if(( tmp.bv_len >= LENOF("teletex") ) &&
3054 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3056 tmp.bv_len -= LENOF("teletex");
3057 tmp.bv_val += LENOF("teletex");
3060 if(( tmp.bv_len >= LENOF("telephone") ) &&
3061 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3063 tmp.bv_len -= LENOF("telephone");
3064 tmp.bv_val += LENOF("telephone");
3067 return LDAP_INVALID_SYNTAX;
3070 case 'G': /* g3fax or g4fax */
3071 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3072 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3073 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3075 tmp.bv_len -= LENOF("g3fax");
3076 tmp.bv_val += LENOF("g3fax");
3079 return LDAP_INVALID_SYNTAX;
3083 if(( tmp.bv_len >= LENOF("ia5") ) &&
3084 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3086 tmp.bv_len -= LENOF("ia5");
3087 tmp.bv_val += LENOF("ia5");
3090 return LDAP_INVALID_SYNTAX;
3094 if(( tmp.bv_len >= LENOF("videotex") ) &&
3095 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3097 tmp.bv_len -= LENOF("videotex");
3098 tmp.bv_val += LENOF("videotex");
3101 return LDAP_INVALID_SYNTAX;
3104 return LDAP_INVALID_SYNTAX;
3107 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3109 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3113 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3117 return LDAP_INVALID_SYNTAX;
3119 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3128 nisNetgroupTripleValidate(
3130 struct berval *val )
3135 if ( BER_BVISEMPTY( val ) ) {
3136 return LDAP_INVALID_SYNTAX;
3139 p = (char *)val->bv_val;
3140 e = p + val->bv_len;
3142 if ( *p != '(' /*')'*/ ) {
3143 return LDAP_INVALID_SYNTAX;
3146 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3150 return LDAP_INVALID_SYNTAX;
3153 } else if ( !AD_CHAR( *p ) ) {
3154 return LDAP_INVALID_SYNTAX;
3158 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3159 return LDAP_INVALID_SYNTAX;
3165 return LDAP_INVALID_SYNTAX;
3168 return LDAP_SUCCESS;
3172 bootParameterValidate(
3174 struct berval *val )
3178 if ( BER_BVISEMPTY( val ) ) {
3179 return LDAP_INVALID_SYNTAX;
3182 p = (char *)val->bv_val;
3183 e = p + val->bv_len;
3186 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3187 if ( !AD_CHAR( *p ) ) {
3188 return LDAP_INVALID_SYNTAX;
3193 return LDAP_INVALID_SYNTAX;
3197 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3198 if ( !AD_CHAR( *p ) ) {
3199 return LDAP_INVALID_SYNTAX;
3204 return LDAP_INVALID_SYNTAX;
3208 for ( p++; p < e; p++ ) {
3209 if ( !SLAP_PRINTABLE( *p ) ) {
3210 return LDAP_INVALID_SYNTAX;
3214 return LDAP_SUCCESS;
3218 firstComponentNormalize(
3223 struct berval *normalized,
3230 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3231 ber_dupbv_x( normalized, val, ctx );
3232 return LDAP_SUCCESS;
3235 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3237 if( val->bv_val[0] != '(' /*')'*/ &&
3238 val->bv_val[0] != '{' /*'}'*/ )
3240 return LDAP_INVALID_SYNTAX;
3243 /* trim leading white space */
3245 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3251 /* grab next word */
3252 comp.bv_val = &val->bv_val[len];
3253 len = val->bv_len - len;
3254 for( comp.bv_len = 0;
3255 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3261 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3262 rc = numericoidValidate( NULL, &comp );
3263 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3264 rc = integerValidate( NULL, &comp );
3266 rc = LDAP_INVALID_SYNTAX;
3270 if( rc == LDAP_SUCCESS ) {
3271 ber_dupbv_x( normalized, &comp, ctx );
3278 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3279 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3281 static slap_syntax_defs_rec syntax_defs[] = {
3282 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3283 X_BINARY X_NOT_H_R ")",
3284 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3285 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3287 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3289 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3291 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3292 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3294 SLAP_SYNTAX_BER, berValidate, NULL},
3295 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3296 0, bitStringValidate, NULL },
3297 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3298 0, booleanValidate, NULL},
3299 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3300 X_BINARY X_NOT_H_R ")",
3301 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3302 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3303 X_BINARY X_NOT_H_R ")",
3304 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3305 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3306 X_BINARY X_NOT_H_R ")",
3307 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3308 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3309 0, countryStringValidate, NULL},
3310 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3311 0, dnValidate, dnPretty},
3312 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3313 0, rdnValidate, rdnPretty},
3314 #ifdef LDAP_COMP_MATCH
3315 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3316 0, allComponentsValidate, NULL},
3317 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3318 0, componentFilterValidate, NULL},
3320 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3322 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3323 0, deliveryMethodValidate, NULL},
3324 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3325 0, UTF8StringValidate, NULL},
3326 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3328 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3330 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3332 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3334 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3336 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3337 0, printablesStringValidate, NULL},
3338 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3339 SLAP_SYNTAX_BLOB, NULL, NULL},
3340 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3341 0, generalizedTimeValidate, NULL},
3342 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3344 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3345 0, IA5StringValidate, NULL},
3346 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3347 0, integerValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3349 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3350 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3352 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3354 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3356 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3358 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3360 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3361 0, nameUIDValidate, nameUIDPretty },
3362 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3364 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3365 0, numericStringValidate, NULL},
3366 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3368 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3369 0, numericoidValidate, NULL},
3370 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3371 0, IA5StringValidate, NULL},
3372 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3373 0, blobValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3375 0, UTF8StringValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3378 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3380 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3381 0, printableStringValidate, NULL},
3382 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3383 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3384 0, subtreeSpecificationValidate, NULL},
3385 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3386 X_BINARY X_NOT_H_R ")",
3387 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3388 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3389 0, printableStringValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3392 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3393 0, printablesStringValidate, NULL},
3394 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3395 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3396 0, utcTimeValidate, NULL},
3398 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3402 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3404 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3406 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3409 /* RFC 2307 NIS Syntaxes */
3410 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3411 0, nisNetgroupTripleValidate, NULL},
3412 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3413 0, bootParameterValidate, NULL},
3415 /* From PKIX *//* This OID is not published yet. */
3416 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3418 serialNumberAndIssuerValidate,
3419 serialNumberAndIssuerPretty},
3421 #ifdef SLAPD_ACI_ENABLED
3422 /* OpenLDAP Experimental Syntaxes */
3423 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3425 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3429 #ifdef SLAPD_AUTHPASSWD
3430 /* needs updating */
3431 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3432 SLAP_SYNTAX_HIDE, NULL, NULL},
3435 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3436 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3438 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3439 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3441 /* OpenLDAP Void Syntax */
3442 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3443 SLAP_SYNTAX_HIDE, inValidate, NULL},
3444 {NULL, 0, NULL, NULL}
3447 char *certificateExactMatchSyntaxes[] = {
3448 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3451 #ifdef LDAP_COMP_MATCH
3452 char *componentFilterMatchSyntaxes[] = {
3453 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3457 char *directoryStringSyntaxes[] = {
3458 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3461 char *integerFirstComponentMatchSyntaxes[] = {
3462 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3463 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3466 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3467 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3468 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3469 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3470 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3471 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3472 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3473 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3474 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3479 * Other matching rules in X.520 that we do not use (yet):
3481 * 2.5.13.25 uTCTimeMatch
3482 * 2.5.13.26 uTCTimeOrderingMatch
3483 * 2.5.13.31* directoryStringFirstComponentMatch
3484 * 2.5.13.32* wordMatch
3485 * 2.5.13.33* keywordMatch
3486 * 2.5.13.36 certificatePairExactMatch
3487 * 2.5.13.37 certificatePairMatch
3488 * 2.5.13.38 certificateListExactMatch
3489 * 2.5.13.39 certificateListMatch
3490 * 2.5.13.40 algorithmIdentifierMatch
3491 * 2.5.13.41* storedPrefixMatch
3492 * 2.5.13.42 attributeCertificateMatch
3493 * 2.5.13.43 readerAndKeyIDMatch
3494 * 2.5.13.44 attributeIntegrityMatch
3496 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3498 static slap_mrule_defs_rec mrule_defs[] = {
3500 * EQUALITY matching rules must be listed after associated APPROX
3501 * matching rules. So, we list all APPROX matching rules first.
3503 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3504 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3505 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3506 NULL, NULL, directoryStringApproxMatch,
3507 directoryStringApproxIndexer, directoryStringApproxFilter,
3510 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3511 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3512 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3513 NULL, NULL, IA5StringApproxMatch,
3514 IA5StringApproxIndexer, IA5StringApproxFilter,
3518 * Other matching rules
3521 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3522 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3523 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3524 NULL, NULL, octetStringMatch,
3525 octetStringIndexer, octetStringFilter,
3528 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3529 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3530 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3531 NULL, dnNormalize, dnMatch,
3532 octetStringIndexer, octetStringFilter,
3535 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3536 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3537 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3538 NULL, dnNormalize, dnRelativeMatch,
3542 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3543 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3544 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3545 NULL, dnNormalize, dnRelativeMatch,
3549 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3550 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3551 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3552 NULL, dnNormalize, dnRelativeMatch,
3556 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3557 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3558 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3559 NULL, dnNormalize, dnRelativeMatch,
3563 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3564 "SYNTAX 1.2.36.79672281.1.5.0 )",
3565 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3566 NULL, rdnNormalize, rdnMatch,
3567 octetStringIndexer, octetStringFilter,
3570 #ifdef LDAP_COMP_MATCH
3571 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3572 "SYNTAX 1.2.36.79672281.1.5.2 )",
3573 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3574 NULL, NULL , componentFilterMatch,
3575 octetStringIndexer, octetStringFilter,
3578 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3579 "SYNTAX 1.2.36.79672281.1.5.3 )",
3580 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3581 NULL, NULL , allComponentsMatch,
3582 octetStringIndexer, octetStringFilter,
3585 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3586 "SYNTAX 1.2.36.79672281.1.5.3 )",
3587 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3588 NULL, NULL , directoryComponentsMatch,
3589 octetStringIndexer, octetStringFilter,
3593 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3595 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3596 NULL, UTF8StringNormalize, octetStringMatch,
3597 octetStringIndexer, octetStringFilter,
3598 directoryStringApproxMatchOID },
3600 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3602 SLAP_MR_ORDERING, directoryStringSyntaxes,
3603 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3605 "caseIgnoreMatch" },
3607 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3609 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3610 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3611 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3612 "caseIgnoreMatch" },
3614 {"( 2.5.13.5 NAME 'caseExactMatch' "
3615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3616 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3617 NULL, UTF8StringNormalize, octetStringMatch,
3618 octetStringIndexer, octetStringFilter,
3619 directoryStringApproxMatchOID },
3621 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3623 SLAP_MR_ORDERING, directoryStringSyntaxes,
3624 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3628 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3629 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3630 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3631 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3632 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3635 {"( 2.5.13.8 NAME 'numericStringMatch' "
3636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3637 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3638 NULL, numericStringNormalize, octetStringMatch,
3639 octetStringIndexer, octetStringFilter,
3642 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3644 SLAP_MR_ORDERING, NULL,
3645 NULL, numericStringNormalize, octetStringOrderingMatch,
3647 "numericStringMatch" },
3649 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3651 SLAP_MR_SUBSTR, NULL,
3652 NULL, numericStringNormalize, octetStringSubstringsMatch,
3653 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3654 "numericStringMatch" },
3656 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3658 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3659 NULL, NULL, NULL, NULL, NULL, NULL },
3661 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3663 SLAP_MR_SUBSTR, NULL,
3664 NULL, NULL, NULL, NULL, NULL,
3665 "caseIgnoreListMatch" },
3667 {"( 2.5.13.13 NAME 'booleanMatch' "
3668 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3669 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3670 NULL, NULL, booleanMatch,
3671 octetStringIndexer, octetStringFilter,
3674 {"( 2.5.13.14 NAME 'integerMatch' "
3675 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3676 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3677 NULL, NULL, integerMatch,
3678 octetStringIndexer, octetStringFilter,
3681 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3683 SLAP_MR_ORDERING, NULL,
3684 NULL, NULL, integerMatch,
3688 {"( 2.5.13.16 NAME 'bitStringMatch' "
3689 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3690 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3691 NULL, NULL, octetStringMatch,
3692 octetStringIndexer, octetStringFilter,
3695 {"( 2.5.13.17 NAME 'octetStringMatch' "
3696 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3697 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3698 NULL, NULL, octetStringMatch,
3699 octetStringIndexer, octetStringFilter,
3702 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3703 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3704 SLAP_MR_ORDERING, NULL,
3705 NULL, NULL, octetStringOrderingMatch,
3707 "octetStringMatch" },
3709 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3710 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3711 SLAP_MR_SUBSTR, NULL,
3712 NULL, NULL, octetStringSubstringsMatch,
3713 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3714 "octetStringMatch" },
3716 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3717 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3718 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3720 telephoneNumberNormalize, octetStringMatch,
3721 octetStringIndexer, octetStringFilter,
3724 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3725 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3726 SLAP_MR_SUBSTR, NULL,
3727 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3728 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3729 "telephoneNumberMatch" },
3731 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3732 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3733 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3734 NULL, NULL, NULL, NULL, NULL, NULL },
3736 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3738 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3739 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3740 uniqueMemberIndexer, uniqueMemberFilter,
3743 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3745 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3746 NULL, NULL, NULL, NULL, NULL, NULL },
3748 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3750 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3751 NULL, generalizedTimeNormalize, octetStringMatch,
3752 generalizedTimeIndexer, generalizedTimeFilter,
3755 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3757 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3758 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3760 "generalizedTimeMatch" },
3762 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3763 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3764 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3765 integerFirstComponentMatchSyntaxes,
3766 NULL, firstComponentNormalize, integerMatch,
3767 octetStringIndexer, octetStringFilter,
3770 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3772 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3773 objectIdentifierFirstComponentMatchSyntaxes,
3774 NULL, firstComponentNormalize, octetStringMatch,
3775 octetStringIndexer, octetStringFilter,
3778 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3779 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3780 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3782 NULL, certificateExactNormalize, octetStringMatch,
3783 octetStringIndexer, octetStringFilter,
3785 NULL, NULL, NULL, NULL, NULL,
3789 {"( 2.5.13.35 NAME 'certificateMatch' "
3790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3791 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3793 NULL, NULL, octetStringMatch,
3794 octetStringIndexer, octetStringFilter,
3796 NULL, NULL, NULL, NULL, NULL,
3800 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3802 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3803 NULL, IA5StringNormalize, octetStringMatch,
3804 octetStringIndexer, octetStringFilter,
3805 IA5StringApproxMatchOID },
3807 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3809 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3810 NULL, IA5StringNormalize, octetStringMatch,
3811 octetStringIndexer, octetStringFilter,
3812 IA5StringApproxMatchOID },
3814 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3816 SLAP_MR_SUBSTR, NULL,
3817 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3818 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3819 "caseIgnoreIA5Match" },
3821 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3823 SLAP_MR_SUBSTR, NULL,
3824 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3825 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3826 "caseExactIA5Match" },
3828 #ifdef SLAPD_AUTHPASSWD
3829 /* needs updating */
3830 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3832 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3833 NULL, NULL, authPasswordMatch,
3838 #ifdef SLAPD_ACI_ENABLED
3839 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3840 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3841 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3842 NULL, NULL, OpenLDAPaciMatch,
3847 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3848 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3850 NULL, NULL, integerBitAndMatch,
3854 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3855 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3857 NULL, NULL, integerBitOrMatch,
3861 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3862 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3863 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3864 NULL, UUIDNormalize, octetStringMatch,
3865 octetStringIndexer, octetStringFilter,
3868 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3869 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3870 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3871 NULL, UUIDNormalize, octetStringOrderingMatch,
3872 octetStringIndexer, octetStringFilter,
3875 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3876 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3877 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3878 NULL, NULL, csnMatch,
3879 csnIndexer, csnFilter,
3882 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3883 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3884 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3885 NULL, NULL, csnOrderingMatch,
3889 {NULL, SLAP_MR_NONE, NULL,
3890 NULL, NULL, NULL, NULL, NULL,
3895 slap_schema_init( void )
3900 /* we should only be called once (from main) */
3901 assert( schema_init_done == 0 );
3903 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3904 res = register_syntax( &syntax_defs[i] );
3907 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3908 syntax_defs[i].sd_desc );
3913 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3914 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3915 mrule_defs[i].mrd_compat_syntaxes == NULL )
3918 "slap_schema_init: Ignoring unusable matching rule %s\n",
3919 mrule_defs[i].mrd_desc );
3923 res = register_matching_rule( &mrule_defs[i] );
3927 "slap_schema_init: Error registering matching rule %s\n",
3928 mrule_defs[i].mrd_desc );
3933 res = slap_schema_load();
3934 schema_init_done = 1;
3939 schema_destroy( void )