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 #ifdef SLAP_AUTHZ_SYNTAX
73 /* FIXME: temporary */
74 #define authzMatch octetStringMatch
75 #endif /* SLAP_AUTHZ_SYNTAX */
77 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
78 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
79 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
80 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
87 /* no value allowed */
88 return LDAP_INVALID_SYNTAX;
96 /* any value allowed */
100 #define berValidate blobValidate
107 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
108 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
115 static int certificateValidate( Syntax *syntax, struct berval *in )
118 unsigned char *p = (unsigned char *)in->bv_val;
120 xcert = d2i_X509(NULL, &p, in->bv_len);
121 if ( !xcert ) return LDAP_INVALID_SYNTAX;
126 #define certificateValidate sequenceValidate
135 struct berval *value,
136 void *assertedValue )
138 struct berval *asserted = (struct berval *) assertedValue;
139 int match = value->bv_len - asserted->bv_len;
142 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
150 octetStringOrderingMatch(
155 struct berval *value,
156 void *assertedValue )
158 struct berval *asserted = (struct berval *) assertedValue;
159 ber_len_t v_len = value->bv_len;
160 ber_len_t av_len = asserted->bv_len;
162 int match = memcmp( value->bv_val, asserted->bv_val,
163 (v_len < av_len ? v_len : av_len) );
165 if( match == 0 ) match = v_len - av_len;
173 HASH_CONTEXT *HASHcontext,
174 unsigned char *HASHdigest,
175 struct berval *prefix,
179 unsigned char *value,
182 HASH_Init(HASHcontext);
183 if(prefix && prefix->bv_len > 0) {
184 HASH_Update(HASHcontext,
185 (unsigned char *)prefix->bv_val, prefix->bv_len);
187 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
188 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
189 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
190 HASH_Update(HASHcontext, value, value_len);
191 HASH_Final(HASHdigest, HASHcontext);
195 /* Index generation function */
196 int octetStringIndexer(
201 struct berval *prefix,
209 HASH_CONTEXT HASHcontext;
210 unsigned char HASHdigest[HASH_BYTES];
211 struct berval digest;
212 digest.bv_val = (char *)HASHdigest;
213 digest.bv_len = sizeof(HASHdigest);
215 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
216 /* just count them */
219 /* we should have at least one value at this point */
222 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
224 slen = syntax->ssyn_oidlen;
225 mlen = mr->smr_oidlen;
227 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
228 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
229 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
230 ber_dupbv_x( &keys[i], &digest, ctx );
233 BER_BVZERO( &keys[i] );
240 /* Index generation function */
241 int octetStringFilter(
246 struct berval *prefix,
247 void * assertedValue,
253 HASH_CONTEXT HASHcontext;
254 unsigned char HASHdigest[HASH_BYTES];
255 struct berval *value = (struct berval *) assertedValue;
256 struct berval digest;
257 digest.bv_val = (char *)HASHdigest;
258 digest.bv_len = sizeof(HASHdigest);
260 slen = syntax->ssyn_oidlen;
261 mlen = mr->smr_oidlen;
263 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
265 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
266 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
268 ber_dupbv_x( keys, &digest, ctx );
269 BER_BVZERO( &keys[1] );
277 octetStringSubstringsMatch(
282 struct berval *value,
283 void *assertedValue )
286 SubstringsAssertion *sub = assertedValue;
287 struct berval left = *value;
291 /* Add up asserted input length */
292 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
293 inlen += sub->sa_initial.bv_len;
296 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
297 inlen += sub->sa_any[i].bv_len;
300 if ( !BER_BVISNULL( &sub->sa_final ) ) {
301 inlen += sub->sa_final.bv_len;
304 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
305 if ( inlen > left.bv_len ) {
310 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
311 sub->sa_initial.bv_len );
317 left.bv_val += sub->sa_initial.bv_len;
318 left.bv_len -= sub->sa_initial.bv_len;
319 inlen -= sub->sa_initial.bv_len;
322 if ( !BER_BVISNULL( &sub->sa_final ) ) {
323 if ( inlen > left.bv_len ) {
328 match = memcmp( sub->sa_final.bv_val,
329 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
330 sub->sa_final.bv_len );
336 left.bv_len -= sub->sa_final.bv_len;
337 inlen -= sub->sa_final.bv_len;
341 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
346 if ( inlen > left.bv_len ) {
347 /* not enough length */
352 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
356 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
363 idx = p - left.bv_val;
365 if ( idx >= left.bv_len ) {
366 /* this shouldn't happen */
373 if ( sub->sa_any[i].bv_len > left.bv_len ) {
374 /* not enough left */
379 match = memcmp( left.bv_val,
380 sub->sa_any[i].bv_val,
381 sub->sa_any[i].bv_len );
389 left.bv_val += sub->sa_any[i].bv_len;
390 left.bv_len -= sub->sa_any[i].bv_len;
391 inlen -= sub->sa_any[i].bv_len;
400 /* Substrings Index generation function */
402 octetStringSubstringsIndexer(
407 struct berval *prefix,
416 HASH_CONTEXT HASHcontext;
417 unsigned char HASHdigest[HASH_BYTES];
418 struct berval digest;
419 digest.bv_val = (char *)HASHdigest;
420 digest.bv_len = sizeof(HASHdigest);
424 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
425 /* count number of indices to generate */
426 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
427 if( values[i].bv_len >= index_substr_if_maxlen ) {
428 nkeys += index_substr_if_maxlen -
429 (index_substr_if_minlen - 1);
430 } else if( values[i].bv_len >= index_substr_if_minlen ) {
431 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
435 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
436 if( values[i].bv_len >= index_substr_any_len ) {
437 nkeys += values[i].bv_len - (index_substr_any_len - 1);
441 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
442 if( values[i].bv_len >= index_substr_if_maxlen ) {
443 nkeys += index_substr_if_maxlen -
444 (index_substr_if_minlen - 1);
445 } else if( values[i].bv_len >= index_substr_if_minlen ) {
446 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
452 /* no keys to generate */
457 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
459 slen = syntax->ssyn_oidlen;
460 mlen = mr->smr_oidlen;
463 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
466 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
467 ( values[i].bv_len >= index_substr_any_len ) )
469 char pre = SLAP_INDEX_SUBSTR_PREFIX;
470 max = values[i].bv_len - (index_substr_any_len - 1);
472 for( j=0; j<max; j++ ) {
473 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
474 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
475 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
479 /* skip if too short */
480 if( values[i].bv_len < index_substr_if_minlen ) continue;
482 max = index_substr_if_maxlen < values[i].bv_len
483 ? index_substr_if_maxlen : values[i].bv_len;
485 for( j=index_substr_if_minlen; j<=max; j++ ) {
488 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
489 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
490 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
491 syntax, mr, (unsigned char *)values[i].bv_val, j );
492 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
495 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
496 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
497 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
498 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
499 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
506 BER_BVZERO( &keys[nkeys] );
517 octetStringSubstringsFilter (
522 struct berval *prefix,
523 void * assertedValue,
527 SubstringsAssertion *sa;
530 size_t slen, mlen, klen;
532 HASH_CONTEXT HASHcontext;
533 unsigned char HASHdigest[HASH_BYTES];
534 struct berval *value;
535 struct berval digest;
537 sa = (SubstringsAssertion *) assertedValue;
539 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
540 !BER_BVISNULL( &sa->sa_initial ) &&
541 sa->sa_initial.bv_len >= index_substr_if_minlen )
544 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
545 ( flags & SLAP_INDEX_SUBSTR_ANY ))
547 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
551 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
553 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
554 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
555 /* don't bother accounting with stepping */
556 nkeys += sa->sa_any[i].bv_len -
557 ( index_substr_any_len - 1 );
562 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
563 !BER_BVISNULL( &sa->sa_final ) &&
564 sa->sa_final.bv_len >= index_substr_if_minlen )
567 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
568 ( flags & SLAP_INDEX_SUBSTR_ANY ))
570 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
579 digest.bv_val = (char *)HASHdigest;
580 digest.bv_len = sizeof(HASHdigest);
582 slen = syntax->ssyn_oidlen;
583 mlen = mr->smr_oidlen;
585 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
588 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
589 !BER_BVISNULL( &sa->sa_initial ) &&
590 sa->sa_initial.bv_len >= index_substr_if_minlen )
592 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
593 value = &sa->sa_initial;
595 klen = index_substr_if_maxlen < value->bv_len
596 ? index_substr_if_maxlen : value->bv_len;
598 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
599 syntax, mr, (unsigned char *)value->bv_val, klen );
600 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
602 /* If initial is too long and we have subany indexed, use it
603 * to match the excess...
605 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
608 pre = SLAP_INDEX_SUBSTR_PREFIX;
609 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
611 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
612 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
613 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
618 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
620 pre = SLAP_INDEX_SUBSTR_PREFIX;
621 klen = index_substr_any_len;
623 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
624 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
628 value = &sa->sa_any[i];
631 j <= value->bv_len - index_substr_any_len;
632 j += index_substr_any_step )
634 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
635 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
636 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
641 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
642 !BER_BVISNULL( &sa->sa_final ) &&
643 sa->sa_final.bv_len >= index_substr_if_minlen )
645 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
646 value = &sa->sa_final;
648 klen = index_substr_if_maxlen < value->bv_len
649 ? index_substr_if_maxlen : value->bv_len;
651 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
652 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
655 /* If final is too long and we have subany indexed, use it
656 * to match the excess...
658 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
661 pre = SLAP_INDEX_SUBSTR_PREFIX;
662 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
664 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
665 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
666 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
672 BER_BVZERO( &keys[nkeys] );
689 /* very unforgiving validation, requires no normalization
690 * before simplistic matching
692 if( in->bv_len < 3 ) {
693 return LDAP_INVALID_SYNTAX;
697 * RFC 2252 section 6.3 Bit String
698 * bitstring = "'" *binary-digit "'B"
699 * binary-digit = "0" / "1"
700 * example: '0101111101'B
703 if( in->bv_val[0] != '\'' ||
704 in->bv_val[in->bv_len - 2] != '\'' ||
705 in->bv_val[in->bv_len - 1] != 'B' )
707 return LDAP_INVALID_SYNTAX;
710 for( i = in->bv_len - 3; i > 0; i-- ) {
711 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
712 return LDAP_INVALID_SYNTAX;
720 * Syntax is [RFC2252]:
725 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
727 Values in this syntax are encoded according to the following BNF:
729 bitstring = "'" *binary-digit "'B"
731 binary-digit = "0" / "1"
735 6.21. Name And Optional UID
737 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
739 Values in this syntax are encoded according to the following BNF:
741 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
743 Although the '#' character may occur in a string representation of a
744 distinguished name, no additional special quoting is done. This
745 syntax has been added subsequent to RFC 1778.
749 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
752 * draft-ietf-ldapbis-syntaxes-xx.txt says:
757 A value of the Bit String syntax is a sequence of binary digits. The
758 LDAP-specific encoding of a value of this syntax is defined by the
761 BitString = SQUOTE *binary-digit SQUOTE "B"
763 binary-digit = "0" / "1"
765 The <SQUOTE> rule is defined in [MODELS].
770 The LDAP definition for the Bit String syntax is:
772 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
774 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
778 3.3.21. Name and Optional UID
780 A value of the Name and Optional UID syntax is the distinguished name
781 [MODELS] of an entity optionally accompanied by a unique identifier
782 that serves to differentiate the entity from others with an identical
785 The LDAP-specific encoding of a value of this syntax is defined by
788 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
790 The <BitString> rule is defined in Section 3.3.2. The
791 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
794 Note that although the '#' character may occur in the string
795 representation of a distinguished name, no additional escaping of
796 this character is performed when a <distinguishedName> is encoded in
797 a <NameAndOptionalUID>.
800 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
802 The LDAP definition for the Name and Optional UID syntax is:
804 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
806 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
810 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
813 1.4. Common ABNF Productions
816 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
818 SQUOTE = %x27 ; single quote ("'")
822 * Note: normalization strips any leading "0"s, unless the
823 * bit string is exactly "'0'B", so the normalized example,
824 * in slapd, would result in
826 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
828 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
829 * i.e. "#", doesn't have to be escaped except when at the
830 * beginning of a value, the definition of Name and Optional
831 * UID appears to be flawed, because there is no clear means
832 * to determine whether the UID part is present or not.
836 * cn=Someone,dc=example,dc=com#'1'B
838 * could be either a NameAndOptionalUID with trailing UID, i.e.
840 * DN = "cn=Someone,dc=example,dc=com"
843 * or a NameAndOptionalUID with no trailing UID, and the AVA
844 * in the last RDN made of
847 * attributeValue = com#'1'B
849 * in fact "com#'1'B" is a valid IA5 string.
851 * As a consequence, current slapd code assumes that the
852 * presence of portions of a BitString at the end of the string
853 * representation of a NameAndOptionalUID means a BitString
854 * is expected, and cause an error otherwise. This is quite
855 * arbitrary, and might change in the future.
865 struct berval dn, uid;
867 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
869 ber_dupbv( &dn, in );
870 if( !dn.bv_val ) return LDAP_OTHER;
872 /* if there's a "#", try bitStringValidate()... */
873 uid.bv_val = strrchr( dn.bv_val, '#' );
874 if ( !BER_BVISNULL( &uid ) ) {
876 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
878 rc = bitStringValidate( NULL, &uid );
879 if ( rc == LDAP_SUCCESS ) {
880 /* in case of success, trim the UID,
881 * otherwise treat it as part of the DN */
882 dn.bv_len -= uid.bv_len + 1;
883 uid.bv_val[-1] = '\0';
887 rc = dnValidate( NULL, &dn );
889 ber_memfree( dn.bv_val );
900 assert( val != NULL );
901 assert( out != NULL );
904 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
906 if( BER_BVISEMPTY( val ) ) {
907 ber_dupbv_x( out, val, ctx );
909 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
910 return LDAP_INVALID_SYNTAX;
914 struct berval dnval = *val;
915 struct berval uidval = BER_BVNULL;
917 uidval.bv_val = strrchr( val->bv_val, '#' );
918 if ( !BER_BVISNULL( &uidval ) ) {
920 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
922 rc = bitStringValidate( NULL, &uidval );
924 if ( rc == LDAP_SUCCESS ) {
925 ber_dupbv_x( &dnval, val, ctx );
926 dnval.bv_len -= uidval.bv_len + 1;
927 dnval.bv_val[dnval.bv_len] = '\0';
930 BER_BVZERO( &uidval );
934 rc = dnPretty( syntax, &dnval, out, ctx );
935 if ( dnval.bv_val != val->bv_val ) {
936 slap_sl_free( dnval.bv_val, ctx );
938 if( rc != LDAP_SUCCESS ) {
942 if( !BER_BVISNULL( &uidval ) ) {
946 tmp = slap_sl_realloc( out->bv_val, out->bv_len
947 + STRLENOF( "#" ) + uidval.bv_len + 1,
950 ber_memfree_x( out->bv_val, ctx );
954 out->bv_val[out->bv_len++] = '#';
955 out->bv_val[out->bv_len++] = '\'';
957 got1 = uidval.bv_len < sizeof("'0'B");
958 for( i = 1; i < uidval.bv_len - 2; i++ ) {
959 c = uidval.bv_val[i];
962 if( got1 ) out->bv_val[out->bv_len++] = c;
966 out->bv_val[out->bv_len++] = c;
971 out->bv_val[out->bv_len++] = '\'';
972 out->bv_val[out->bv_len++] = 'B';
973 out->bv_val[out->bv_len] = '\0';
977 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
983 uniqueMemberNormalize(
988 struct berval *normalized,
994 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
996 ber_dupbv_x( &out, val, ctx );
997 if ( BER_BVISEMPTY( &out ) ) {
1001 struct berval uid = BER_BVNULL;
1003 uid.bv_val = strrchr( out.bv_val, '#' );
1004 if ( !BER_BVISNULL( &uid ) ) {
1006 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1008 rc = bitStringValidate( NULL, &uid );
1009 if ( rc == LDAP_SUCCESS ) {
1010 uid.bv_val[-1] = '\0';
1011 out.bv_len -= uid.bv_len + 1;
1017 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1019 if( rc != LDAP_SUCCESS ) {
1020 slap_sl_free( out.bv_val, ctx );
1021 return LDAP_INVALID_SYNTAX;
1024 if( !BER_BVISNULL( &uid ) ) {
1027 tmp = ch_realloc( normalized->bv_val,
1028 normalized->bv_len + uid.bv_len
1029 + STRLENOF("#") + 1 );
1030 if ( tmp == NULL ) {
1031 ber_memfree_x( normalized->bv_val, ctx );
1035 normalized->bv_val = tmp;
1037 /* insert the separator */
1038 normalized->bv_val[normalized->bv_len++] = '#';
1040 /* append the UID */
1041 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1042 uid.bv_val, uid.bv_len );
1043 normalized->bv_len += uid.bv_len;
1046 normalized->bv_val[normalized->bv_len] = '\0';
1049 slap_sl_free( out.bv_val, ctx );
1052 return LDAP_SUCCESS;
1061 struct berval *value,
1062 void *assertedValue )
1065 struct berval *asserted = (struct berval *) assertedValue;
1066 struct berval assertedDN = *asserted;
1067 struct berval assertedUID = BER_BVNULL;
1068 struct berval valueDN = BER_BVNULL;
1069 struct berval valueUID = BER_BVNULL;
1070 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1072 if ( !BER_BVISEMPTY( asserted ) ) {
1073 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1074 if ( !BER_BVISNULL( &assertedUID ) ) {
1075 assertedUID.bv_val++;
1076 assertedUID.bv_len = assertedDN.bv_len
1077 - ( assertedUID.bv_val - assertedDN.bv_val );
1079 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1080 assertedDN.bv_len -= assertedUID.bv_len + 1;
1083 BER_BVZERO( &assertedUID );
1088 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_ACI_ENABLED
3427 /* OpenLDAP Experimental Syntaxes */
3428 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3430 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3434 #ifdef SLAPD_AUTHPASSWD
3435 /* needs updating */
3436 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3437 SLAP_SYNTAX_HIDE, NULL, NULL},
3440 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3441 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3443 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3444 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3446 /* OpenLDAP Void Syntax */
3447 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3448 SLAP_SYNTAX_HIDE, inValidate, NULL},
3450 #ifdef SLAP_AUTHZ_SYNTAX
3451 /* FIXME: OID is unused, but not registered yet */
3452 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3453 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3454 #endif /* SLAP_AUTHZ_SYNTAX */
3456 {NULL, 0, NULL, NULL}
3459 char *certificateExactMatchSyntaxes[] = {
3460 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3463 #ifdef LDAP_COMP_MATCH
3464 char *componentFilterMatchSyntaxes[] = {
3465 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3469 char *directoryStringSyntaxes[] = {
3470 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3473 char *integerFirstComponentMatchSyntaxes[] = {
3474 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3475 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3478 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3479 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3480 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3481 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3482 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3483 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3484 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3485 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3486 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3491 * Other matching rules in X.520 that we do not use (yet):
3493 * 2.5.13.25 uTCTimeMatch
3494 * 2.5.13.26 uTCTimeOrderingMatch
3495 * 2.5.13.31* directoryStringFirstComponentMatch
3496 * 2.5.13.32* wordMatch
3497 * 2.5.13.33* keywordMatch
3498 * 2.5.13.36 certificatePairExactMatch
3499 * 2.5.13.37 certificatePairMatch
3500 * 2.5.13.38 certificateListExactMatch
3501 * 2.5.13.39 certificateListMatch
3502 * 2.5.13.40 algorithmIdentifierMatch
3503 * 2.5.13.41* storedPrefixMatch
3504 * 2.5.13.42 attributeCertificateMatch
3505 * 2.5.13.43 readerAndKeyIDMatch
3506 * 2.5.13.44 attributeIntegrityMatch
3508 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3510 static slap_mrule_defs_rec mrule_defs[] = {
3512 * EQUALITY matching rules must be listed after associated APPROX
3513 * matching rules. So, we list all APPROX matching rules first.
3515 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3517 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3518 NULL, NULL, directoryStringApproxMatch,
3519 directoryStringApproxIndexer, directoryStringApproxFilter,
3522 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3524 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3525 NULL, NULL, IA5StringApproxMatch,
3526 IA5StringApproxIndexer, IA5StringApproxFilter,
3530 * Other matching rules
3533 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3535 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3536 NULL, NULL, octetStringMatch,
3537 octetStringIndexer, octetStringFilter,
3540 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3541 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3542 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3543 NULL, dnNormalize, dnMatch,
3544 octetStringIndexer, octetStringFilter,
3547 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3548 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3549 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3550 NULL, dnNormalize, dnRelativeMatch,
3554 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3556 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3557 NULL, dnNormalize, dnRelativeMatch,
3561 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3563 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3564 NULL, dnNormalize, dnRelativeMatch,
3568 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3570 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3571 NULL, dnNormalize, dnRelativeMatch,
3575 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3576 "SYNTAX 1.2.36.79672281.1.5.0 )",
3577 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3578 NULL, rdnNormalize, rdnMatch,
3579 octetStringIndexer, octetStringFilter,
3582 #ifdef LDAP_COMP_MATCH
3583 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3584 "SYNTAX 1.2.36.79672281.1.5.2 )",
3585 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3586 NULL, NULL , componentFilterMatch,
3587 octetStringIndexer, octetStringFilter,
3590 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3591 "SYNTAX 1.2.36.79672281.1.5.3 )",
3592 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3593 NULL, NULL , allComponentsMatch,
3594 octetStringIndexer, octetStringFilter,
3597 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3598 "SYNTAX 1.2.36.79672281.1.5.3 )",
3599 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3600 NULL, NULL , directoryComponentsMatch,
3601 octetStringIndexer, octetStringFilter,
3605 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3607 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3608 NULL, UTF8StringNormalize, octetStringMatch,
3609 octetStringIndexer, octetStringFilter,
3610 directoryStringApproxMatchOID },
3612 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3614 SLAP_MR_ORDERING, directoryStringSyntaxes,
3615 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3617 "caseIgnoreMatch" },
3619 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3621 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3622 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3623 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3624 "caseIgnoreMatch" },
3626 {"( 2.5.13.5 NAME 'caseExactMatch' "
3627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3628 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3629 NULL, UTF8StringNormalize, octetStringMatch,
3630 octetStringIndexer, octetStringFilter,
3631 directoryStringApproxMatchOID },
3633 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3635 SLAP_MR_ORDERING, directoryStringSyntaxes,
3636 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3640 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3642 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3643 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3644 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3647 {"( 2.5.13.8 NAME 'numericStringMatch' "
3648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3649 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3650 NULL, numericStringNormalize, octetStringMatch,
3651 octetStringIndexer, octetStringFilter,
3654 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3656 SLAP_MR_ORDERING, NULL,
3657 NULL, numericStringNormalize, octetStringOrderingMatch,
3659 "numericStringMatch" },
3661 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3663 SLAP_MR_SUBSTR, NULL,
3664 NULL, numericStringNormalize, octetStringSubstringsMatch,
3665 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3666 "numericStringMatch" },
3668 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3670 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3671 NULL, NULL, NULL, NULL, NULL, NULL },
3673 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3674 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3675 SLAP_MR_SUBSTR, NULL,
3676 NULL, NULL, NULL, NULL, NULL,
3677 "caseIgnoreListMatch" },
3679 {"( 2.5.13.13 NAME 'booleanMatch' "
3680 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3681 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3682 NULL, NULL, booleanMatch,
3683 octetStringIndexer, octetStringFilter,
3686 {"( 2.5.13.14 NAME 'integerMatch' "
3687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3688 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3689 NULL, NULL, integerMatch,
3690 octetStringIndexer, octetStringFilter,
3693 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3695 SLAP_MR_ORDERING, NULL,
3696 NULL, NULL, integerMatch,
3700 {"( 2.5.13.16 NAME 'bitStringMatch' "
3701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3702 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3703 NULL, NULL, octetStringMatch,
3704 octetStringIndexer, octetStringFilter,
3707 {"( 2.5.13.17 NAME 'octetStringMatch' "
3708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3709 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3710 NULL, NULL, octetStringMatch,
3711 octetStringIndexer, octetStringFilter,
3714 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3716 SLAP_MR_ORDERING, NULL,
3717 NULL, NULL, octetStringOrderingMatch,
3719 "octetStringMatch" },
3721 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3723 SLAP_MR_SUBSTR, NULL,
3724 NULL, NULL, octetStringSubstringsMatch,
3725 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3726 "octetStringMatch" },
3728 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3730 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3732 telephoneNumberNormalize, octetStringMatch,
3733 octetStringIndexer, octetStringFilter,
3736 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3738 SLAP_MR_SUBSTR, NULL,
3739 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3740 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3741 "telephoneNumberMatch" },
3743 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3745 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3746 NULL, NULL, NULL, NULL, NULL, NULL },
3748 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3750 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3751 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3752 uniqueMemberIndexer, uniqueMemberFilter,
3755 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3757 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3758 NULL, NULL, NULL, NULL, NULL, NULL },
3760 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3762 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3763 NULL, generalizedTimeNormalize, octetStringMatch,
3764 generalizedTimeIndexer, generalizedTimeFilter,
3767 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3768 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3769 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3770 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3772 "generalizedTimeMatch" },
3774 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3776 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3777 integerFirstComponentMatchSyntaxes,
3778 NULL, firstComponentNormalize, integerMatch,
3779 octetStringIndexer, octetStringFilter,
3782 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3783 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3784 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3785 objectIdentifierFirstComponentMatchSyntaxes,
3786 NULL, firstComponentNormalize, octetStringMatch,
3787 octetStringIndexer, octetStringFilter,
3790 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3791 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3792 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3794 NULL, certificateExactNormalize, octetStringMatch,
3795 octetStringIndexer, octetStringFilter,
3797 NULL, NULL, NULL, NULL, NULL,
3801 {"( 2.5.13.35 NAME 'certificateMatch' "
3802 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3803 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3805 NULL, NULL, octetStringMatch,
3806 octetStringIndexer, octetStringFilter,
3808 NULL, NULL, NULL, NULL, NULL,
3812 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3813 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3814 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3815 NULL, IA5StringNormalize, octetStringMatch,
3816 octetStringIndexer, octetStringFilter,
3817 IA5StringApproxMatchOID },
3819 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3821 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3822 NULL, IA5StringNormalize, octetStringMatch,
3823 octetStringIndexer, octetStringFilter,
3824 IA5StringApproxMatchOID },
3826 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3827 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3828 SLAP_MR_SUBSTR, NULL,
3829 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3830 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3831 "caseIgnoreIA5Match" },
3833 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3834 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3835 SLAP_MR_SUBSTR, NULL,
3836 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3837 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3838 "caseExactIA5Match" },
3840 #ifdef SLAPD_AUTHPASSWD
3841 /* needs updating */
3842 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3844 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3845 NULL, NULL, authPasswordMatch,
3850 #ifdef SLAPD_ACI_ENABLED
3851 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3852 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3853 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3854 NULL, NULL, OpenLDAPaciMatch,
3859 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3860 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3862 NULL, NULL, integerBitAndMatch,
3866 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3867 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3869 NULL, NULL, integerBitOrMatch,
3873 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3874 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3875 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3876 NULL, UUIDNormalize, octetStringMatch,
3877 octetStringIndexer, octetStringFilter,
3880 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3881 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3882 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3883 NULL, UUIDNormalize, octetStringOrderingMatch,
3884 octetStringIndexer, octetStringFilter,
3887 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3888 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3889 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3890 NULL, NULL, csnMatch,
3891 csnIndexer, csnFilter,
3894 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3895 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3896 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3897 NULL, NULL, csnOrderingMatch,
3901 #ifdef SLAP_AUTHZ_SYNTAX
3902 /* FIXME: OID is unused, but not registered yet */
3903 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3904 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3905 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3906 NULL, authzNormalize, authzMatch,
3909 #endif /* SLAP_AUTHZ_SYNTAX */
3911 {NULL, SLAP_MR_NONE, NULL,
3912 NULL, NULL, NULL, NULL, NULL,
3917 slap_schema_init( void )
3922 /* we should only be called once (from main) */
3923 assert( schema_init_done == 0 );
3925 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3926 res = register_syntax( &syntax_defs[i] );
3929 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3930 syntax_defs[i].sd_desc );
3935 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3936 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3937 mrule_defs[i].mrd_compat_syntaxes == NULL )
3940 "slap_schema_init: Ignoring unusable matching rule %s\n",
3941 mrule_defs[i].mrd_desc );
3945 res = register_matching_rule( &mrule_defs[i] );
3949 "slap_schema_init: Error registering matching rule %s\n",
3950 mrule_defs[i].mrd_desc );
3955 res = slap_schema_load();
3956 schema_init_done = 1;
3961 schema_destroy( void )