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,
407 ber_len_t i, j, len, nkeys;
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;
524 ber_len_t len, max, nkeys = 0;
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 );
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) ? 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 : -1;
2356 return LDAP_SUCCESS;
2360 serialNumberAndIssuerValidate(
2367 struct berval sn, i;
2368 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2370 i.bv_val = strchr( in->bv_val, '$' );
2371 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2373 sn.bv_val = in->bv_val;
2374 sn.bv_len = i.bv_val - in->bv_val;
2377 i.bv_len = in->bv_len - (sn.bv_len + 1);
2379 /* validate serial number (strict for now) */
2380 for( n=0; n < sn.bv_len; n++ ) {
2381 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2385 rc = dnValidate( NULL, &i );
2386 if( rc ) return LDAP_INVALID_SYNTAX;
2388 return LDAP_SUCCESS;
2392 serialNumberAndIssuerPretty(
2401 struct berval sn, i, newi;
2406 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2407 val->bv_val, 0, 0 );
2409 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2411 i.bv_val = strchr( val->bv_val, '$' );
2412 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2414 sn.bv_val = val->bv_val;
2415 sn.bv_len = i.bv_val - val->bv_val;
2418 i.bv_len = val->bv_len - (sn.bv_len + 1);
2420 /* eat leading zeros */
2421 for( n=0; n < (sn.bv_len-1); n++ ) {
2422 if( sn.bv_val[n] != '0' ) break;
2427 for( n=0; n < sn.bv_len; n++ ) {
2428 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2432 rc = dnPretty( syntax, &i, &newi, ctx );
2433 if( rc ) return LDAP_INVALID_SYNTAX;
2435 /* make room from sn + "$" */
2436 out->bv_len = sn.bv_len + newi.bv_len + 1;
2437 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2439 if( BER_BVISNULL( out ) ) {
2440 slap_sl_free( newi.bv_val, ctx );
2444 /* push issuer over */
2445 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2446 /* insert sn and "$" */
2447 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2448 out->bv_val[sn.bv_len] = '$';
2450 out->bv_val[out->bv_len] = '\0';
2452 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2453 out->bv_val, 0, 0 );
2455 return LDAP_SUCCESS;
2459 * This routine is called by certificateExactNormalize when
2460 * certificateExactNormalize receives a search string instead of
2461 * a certificate. This routine checks if the search value is valid
2462 * and then returns the normalized value
2465 serialNumberAndIssuerNormalize(
2476 struct berval sn, i, newi;
2481 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2482 val->bv_val, 0, 0 );
2484 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2486 i.bv_val = strchr( val->bv_val, '$' );
2487 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2489 sn.bv_val = val->bv_val;
2490 sn.bv_len = i.bv_val - val->bv_val;
2493 i.bv_len = val->bv_len - (sn.bv_len + 1);
2495 /* eat leading zeros */
2496 for( n=0; n < (sn.bv_len-1); n++ ) {
2497 if( sn.bv_val[n] != '0' ) break;
2502 for( n=0; n < sn.bv_len; n++ ) {
2503 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2504 return LDAP_INVALID_SYNTAX;
2509 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2510 if( rc ) return LDAP_INVALID_SYNTAX;
2512 /* make room from sn + "$" */
2513 out->bv_len = sn.bv_len + newi.bv_len + 1;
2514 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2516 if( BER_BVISNULL( out ) ) {
2517 slap_sl_free( newi.bv_val, ctx );
2521 /* push issuer over */
2522 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2523 /* insert sn and "$" */
2524 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2525 out->bv_val[sn.bv_len] = '$';
2527 out->bv_val[out->bv_len] = '\0';
2529 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2530 out->bv_val, 0, 0 );
2537 certificateExactNormalize(
2542 struct berval *normalized,
2545 int rc = LDAP_INVALID_SYNTAX;
2547 char *serial = NULL;
2548 ber_len_t seriallen;
2549 struct berval issuer_dn = BER_BVNULL;
2550 X509_NAME *name = NULL;
2551 ASN1_INTEGER *sn = NULL;
2554 if( BER_BVISEMPTY( val ) ) goto done;
2556 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2557 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2560 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2562 p = (unsigned char *)val->bv_val;
2563 xcert = d2i_X509( NULL, &p, val->bv_len);
2564 if( xcert == NULL ) goto done;
2566 sn=X509_get_serialNumber(xcert);
2567 if ( sn == NULL ) goto done;
2568 serial=i2s_ASN1_INTEGER(0, sn );
2569 if( serial == NULL ) goto done;
2570 seriallen=strlen(serial);
2572 name=X509_get_issuer_name(xcert);
2573 if( name == NULL ) goto done;
2574 rc = dnX509normalize( name, &issuer_dn );
2575 if( rc != LDAP_SUCCESS ) goto done;
2577 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2578 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2579 p = (unsigned char *)normalized->bv_val;
2580 AC_MEMCPY(p, serial, seriallen);
2583 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2584 p += issuer_dn.bv_len;
2587 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2588 normalized->bv_val, NULL, NULL );
2591 if (xcert) X509_free(xcert);
2592 if (serial) ch_free(serial);
2593 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2597 #endif /* HAVE_TLS */
2600 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2601 /* slight optimization - does not need the start parameter */
2602 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2607 check_time_syntax (struct berval *val,
2610 struct berval *fraction)
2613 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2614 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2615 * GeneralizedTime supports leap seconds, UTCTime does not.
2617 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2618 static const int mdays[2][12] = {
2619 /* non-leap years */
2620 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2622 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2625 int part, c, c1, c2, tzoffset, leapyear = 0;
2628 e = p + val->bv_len;
2630 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2631 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2633 for (part = start; part < 7 && p < e; part++) {
2635 if (!ASCII_DIGIT(c1)) {
2640 return LDAP_INVALID_SYNTAX;
2643 if (!ASCII_DIGIT(c)) {
2644 return LDAP_INVALID_SYNTAX;
2646 c += c1 * 10 - '0' * 11;
2647 if ((part | 1) == 3) {
2650 return LDAP_INVALID_SYNTAX;
2653 if (c >= ceiling[part]) {
2654 if (! (c == 60 && part == 6 && start == 0))
2655 return LDAP_INVALID_SYNTAX;
2659 if (part < 5 + start) {
2660 return LDAP_INVALID_SYNTAX;
2662 for (; part < 9; part++) {
2666 /* leapyear check for the Gregorian calendar (year>1581) */
2667 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2671 if (parts[3] >= mdays[leapyear][parts[2]]) {
2672 return LDAP_INVALID_SYNTAX;
2676 fraction->bv_val = p;
2677 fraction->bv_len = 0;
2678 if (p < e && (*p == '.' || *p == ',')) {
2680 while (++p < e && ASCII_DIGIT(*p)) {
2683 if (p - fraction->bv_val == 1) {
2684 return LDAP_INVALID_SYNTAX;
2686 for (end_num = p; end_num[-1] == '0'; --end_num) {
2689 c = end_num - fraction->bv_val;
2690 if (c != 1) fraction->bv_len = c;
2696 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2702 return LDAP_INVALID_SYNTAX;
2708 for (part = 7; part < 9 && p < e; part++) {
2710 if (!ASCII_DIGIT(c1)) {
2715 return LDAP_INVALID_SYNTAX;
2718 if (!ASCII_DIGIT(c2)) {
2719 return LDAP_INVALID_SYNTAX;
2721 parts[part] = c1 * 10 + c2 - '0' * 11;
2722 if (parts[part] >= ceiling[part]) {
2723 return LDAP_INVALID_SYNTAX;
2726 if (part < 8 + start) {
2727 return LDAP_INVALID_SYNTAX;
2730 if (tzoffset == '-') {
2731 /* negative offset to UTC, ie west of Greenwich */
2732 parts[4] += parts[7];
2733 parts[5] += parts[8];
2734 /* offset is just hhmm, no seconds */
2735 for (part = 6; --part >= 0; ) {
2739 c = mdays[leapyear][parts[2]];
2741 if (parts[part] >= c) {
2743 return LDAP_INVALID_SYNTAX;
2748 } else if (part != 5) {
2753 /* positive offset to UTC, ie east of Greenwich */
2754 parts[4] -= parts[7];
2755 parts[5] -= parts[8];
2756 for (part = 6; --part >= 0; ) {
2757 if (parts[part] < 0) {
2759 return LDAP_INVALID_SYNTAX;
2764 /* make first arg to % non-negative */
2765 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2770 } else if (part != 5) {
2777 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2780 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2787 struct berval *normalized )
2791 rc = check_time_syntax(val, 1, parts, NULL);
2792 if (rc != LDAP_SUCCESS) {
2796 normalized->bv_val = ch_malloc( 14 );
2797 if ( normalized->bv_val == NULL ) {
2798 return LBER_ERROR_MEMORY;
2801 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2802 parts[1], parts[2] + 1, parts[3] + 1,
2803 parts[4], parts[5], parts[6] );
2804 normalized->bv_len = 13;
2806 return LDAP_SUCCESS;
2816 return check_time_syntax(in, 1, parts, NULL);
2819 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2822 generalizedTimeValidate(
2827 struct berval fraction;
2828 return check_time_syntax(in, 0, parts, &fraction);
2832 generalizedTimeNormalize(
2837 struct berval *normalized,
2842 struct berval fraction;
2844 rc = check_time_syntax(val, 0, parts, &fraction);
2845 if (rc != LDAP_SUCCESS) {
2849 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2850 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2851 if ( BER_BVISNULL( normalized ) ) {
2852 return LBER_ERROR_MEMORY;
2855 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2856 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2857 parts[4], parts[5], parts[6] );
2858 if ( !BER_BVISEMPTY( &fraction ) ) {
2859 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2860 fraction.bv_val, fraction.bv_len );
2861 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2863 strcpy( normalized->bv_val + len-1, "Z" );
2864 normalized->bv_len = len;
2866 return LDAP_SUCCESS;
2870 generalizedTimeOrderingMatch(
2875 struct berval *value,
2876 void *assertedValue )
2878 struct berval *asserted = (struct berval *) assertedValue;
2879 ber_len_t v_len = value->bv_len;
2880 ber_len_t av_len = asserted->bv_len;
2882 /* ignore trailing 'Z' when comparing */
2883 int match = memcmp( value->bv_val, asserted->bv_val,
2884 (v_len < av_len ? v_len : av_len) - 1 );
2885 if ( match == 0 ) match = v_len - av_len;
2888 return LDAP_SUCCESS;
2891 /* Index generation function */
2892 int generalizedTimeIndexer(
2897 struct berval *prefix,
2906 BerValue bvtmp; /* 40 bit index */
2908 struct lutil_timet tt;
2910 bvtmp.bv_len = sizeof(tmp);
2912 for( i=0; values[i].bv_val != NULL; i++ ) {
2913 /* just count them */
2916 /* we should have at least one value at this point */
2919 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2921 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2922 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2923 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2924 /* Use 40 bits of time for key */
2925 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2926 lutil_tm2time( &tm, &tt );
2927 tmp[0] = tt.tt_gsec & 0xff;
2928 tmp[4] = tt.tt_sec & 0xff;
2930 tmp[3] = tt.tt_sec & 0xff;
2932 tmp[2] = tt.tt_sec & 0xff;
2934 tmp[1] = tt.tt_sec & 0xff;
2936 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2940 keys[j].bv_val = NULL;
2945 return LDAP_SUCCESS;
2948 /* Index generation function */
2949 int generalizedTimeFilter(
2954 struct berval *prefix,
2955 void * assertedValue,
2961 BerValue bvtmp; /* 40 bit index */
2962 BerValue *value = (BerValue *) assertedValue;
2964 struct lutil_timet tt;
2966 bvtmp.bv_len = sizeof(tmp);
2968 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2969 /* Use 40 bits of time for key */
2970 if ( value->bv_val && value->bv_len >= 10 &&
2971 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2973 lutil_tm2time( &tm, &tt );
2974 tmp[0] = tt.tt_gsec & 0xff;
2975 tmp[4] = tt.tt_sec & 0xff;
2977 tmp[3] = tt.tt_sec & 0xff;
2979 tmp[2] = tt.tt_sec & 0xff;
2981 tmp[1] = tt.tt_sec & 0xff;
2983 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2984 ber_dupbv_x(keys, &bvtmp, ctx );
2985 keys[1].bv_val = NULL;
2993 return LDAP_SUCCESS;
2997 deliveryMethodValidate(
2999 struct berval *val )
3002 #define LENOF(s) (sizeof(s)-1)
3003 struct berval tmp = *val;
3005 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3006 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3007 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3010 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3012 switch( tmp.bv_val[0] ) {
3015 if(( tmp.bv_len >= LENOF("any") ) &&
3016 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3018 tmp.bv_len -= LENOF("any");
3019 tmp.bv_val += LENOF("any");
3022 return LDAP_INVALID_SYNTAX;
3026 if(( tmp.bv_len >= LENOF("mhs") ) &&
3027 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3029 tmp.bv_len -= LENOF("mhs");
3030 tmp.bv_val += LENOF("mhs");
3033 return LDAP_INVALID_SYNTAX;
3037 if(( tmp.bv_len >= LENOF("physical") ) &&
3038 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3040 tmp.bv_len -= LENOF("physical");
3041 tmp.bv_val += LENOF("physical");
3044 return LDAP_INVALID_SYNTAX;
3047 case 'T': /* telex or teletex or telephone */
3048 if(( tmp.bv_len >= LENOF("telex") ) &&
3049 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3051 tmp.bv_len -= LENOF("telex");
3052 tmp.bv_val += LENOF("telex");
3055 if(( tmp.bv_len >= LENOF("teletex") ) &&
3056 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3058 tmp.bv_len -= LENOF("teletex");
3059 tmp.bv_val += LENOF("teletex");
3062 if(( tmp.bv_len >= LENOF("telephone") ) &&
3063 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3065 tmp.bv_len -= LENOF("telephone");
3066 tmp.bv_val += LENOF("telephone");
3069 return LDAP_INVALID_SYNTAX;
3072 case 'G': /* g3fax or g4fax */
3073 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3074 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3075 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3077 tmp.bv_len -= LENOF("g3fax");
3078 tmp.bv_val += LENOF("g3fax");
3081 return LDAP_INVALID_SYNTAX;
3085 if(( tmp.bv_len >= LENOF("ia5") ) &&
3086 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3088 tmp.bv_len -= LENOF("ia5");
3089 tmp.bv_val += LENOF("ia5");
3092 return LDAP_INVALID_SYNTAX;
3096 if(( tmp.bv_len >= LENOF("videotex") ) &&
3097 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3099 tmp.bv_len -= LENOF("videotex");
3100 tmp.bv_val += LENOF("videotex");
3103 return LDAP_INVALID_SYNTAX;
3106 return LDAP_INVALID_SYNTAX;
3109 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3111 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3115 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3119 return LDAP_INVALID_SYNTAX;
3121 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3130 nisNetgroupTripleValidate(
3132 struct berval *val )
3137 if ( BER_BVISEMPTY( val ) ) {
3138 return LDAP_INVALID_SYNTAX;
3141 p = (char *)val->bv_val;
3142 e = p + val->bv_len;
3144 if ( *p != '(' /*')'*/ ) {
3145 return LDAP_INVALID_SYNTAX;
3148 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3152 return LDAP_INVALID_SYNTAX;
3155 } else if ( !AD_CHAR( *p ) ) {
3156 return LDAP_INVALID_SYNTAX;
3160 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3161 return LDAP_INVALID_SYNTAX;
3167 return LDAP_INVALID_SYNTAX;
3170 return LDAP_SUCCESS;
3174 bootParameterValidate(
3176 struct berval *val )
3180 if ( BER_BVISEMPTY( val ) ) {
3181 return LDAP_INVALID_SYNTAX;
3184 p = (char *)val->bv_val;
3185 e = p + val->bv_len;
3188 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3189 if ( !AD_CHAR( *p ) ) {
3190 return LDAP_INVALID_SYNTAX;
3195 return LDAP_INVALID_SYNTAX;
3199 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3200 if ( !AD_CHAR( *p ) ) {
3201 return LDAP_INVALID_SYNTAX;
3206 return LDAP_INVALID_SYNTAX;
3210 for ( p++; p < e; p++ ) {
3211 if ( !SLAP_PRINTABLE( *p ) ) {
3212 return LDAP_INVALID_SYNTAX;
3216 return LDAP_SUCCESS;
3220 firstComponentNormalize(
3225 struct berval *normalized,
3232 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3233 ber_dupbv_x( normalized, val, ctx );
3234 return LDAP_SUCCESS;
3237 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3239 if( val->bv_val[0] != '(' /*')'*/ &&
3240 val->bv_val[0] != '{' /*'}'*/ )
3242 return LDAP_INVALID_SYNTAX;
3245 /* trim leading white space */
3247 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3253 /* grab next word */
3254 comp.bv_val = &val->bv_val[len];
3255 len = val->bv_len - len;
3256 for( comp.bv_len = 0;
3257 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3263 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3264 rc = numericoidValidate( NULL, &comp );
3265 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3266 rc = integerValidate( NULL, &comp );
3268 rc = LDAP_INVALID_SYNTAX;
3272 if( rc == LDAP_SUCCESS ) {
3273 ber_dupbv_x( normalized, &comp, ctx );
3280 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3281 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3283 static slap_syntax_defs_rec syntax_defs[] = {
3284 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3285 X_BINARY X_NOT_H_R ")",
3286 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3287 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3289 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3291 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3293 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3294 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3296 SLAP_SYNTAX_BER, berValidate, NULL},
3297 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3298 0, bitStringValidate, NULL },
3299 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3300 0, booleanValidate, NULL},
3301 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3302 X_BINARY X_NOT_H_R ")",
3303 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3304 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3305 X_BINARY X_NOT_H_R ")",
3306 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3307 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
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.11 DESC 'Country String' )",
3311 0, countryStringValidate, NULL},
3312 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3313 0, dnValidate, dnPretty},
3314 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3315 0, rdnValidate, rdnPretty},
3316 #ifdef LDAP_COMP_MATCH
3317 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3318 0, allComponentsValidate, NULL},
3319 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3320 0, componentFilterValidate, NULL},
3322 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3324 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3325 0, deliveryMethodValidate, NULL},
3326 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3327 0, UTF8StringValidate, NULL},
3328 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3330 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3332 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3334 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3336 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3338 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3339 0, printablesStringValidate, NULL},
3340 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3341 SLAP_SYNTAX_BLOB, NULL, NULL},
3342 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3343 0, generalizedTimeValidate, NULL},
3344 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3346 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3347 0, IA5StringValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3349 0, integerValidate, NULL},
3350 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3351 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3352 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3354 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3356 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3358 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3360 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3362 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3363 0, nameUIDValidate, nameUIDPretty },
3364 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3366 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3367 0, numericStringValidate, NULL},
3368 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3370 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3371 0, numericoidValidate, NULL},
3372 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3373 0, IA5StringValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3375 0, blobValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3377 0, UTF8StringValidate, NULL},
3378 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3380 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3382 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3383 0, printableStringValidate, NULL},
3384 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3385 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3386 0, subtreeSpecificationValidate, NULL},
3387 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3388 X_BINARY X_NOT_H_R ")",
3389 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3391 0, printableStringValidate, NULL},
3392 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3394 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3395 0, printablesStringValidate, NULL},
3396 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3397 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3398 0, utcTimeValidate, NULL},
3400 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3402 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3404 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3406 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3408 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3411 /* RFC 2307 NIS Syntaxes */
3412 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3413 0, nisNetgroupTripleValidate, NULL},
3414 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3415 0, bootParameterValidate, NULL},
3417 /* From PKIX *//* This OID is not published yet. */
3418 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3420 serialNumberAndIssuerValidate,
3421 serialNumberAndIssuerPretty},
3423 #ifdef SLAPD_ACI_ENABLED
3424 /* OpenLDAP Experimental Syntaxes */
3425 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3427 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3431 #ifdef SLAPD_AUTHPASSWD
3432 /* needs updating */
3433 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3434 SLAP_SYNTAX_HIDE, NULL, NULL},
3437 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3438 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3440 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3441 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3443 /* OpenLDAP Void Syntax */
3444 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3445 SLAP_SYNTAX_HIDE, inValidate, NULL},
3446 {NULL, 0, NULL, NULL}
3449 char *certificateExactMatchSyntaxes[] = {
3450 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3453 #ifdef LDAP_COMP_MATCH
3454 char *componentFilterMatchSyntaxes[] = {
3455 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3459 char *directoryStringSyntaxes[] = {
3460 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3463 char *integerFirstComponentMatchSyntaxes[] = {
3464 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3465 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3468 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3469 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3470 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3471 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3472 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3473 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3474 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3475 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3476 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3481 * Other matching rules in X.520 that we do not use (yet):
3483 * 2.5.13.25 uTCTimeMatch
3484 * 2.5.13.26 uTCTimeOrderingMatch
3485 * 2.5.13.31* directoryStringFirstComponentMatch
3486 * 2.5.13.32* wordMatch
3487 * 2.5.13.33* keywordMatch
3488 * 2.5.13.36 certificatePairExactMatch
3489 * 2.5.13.37 certificatePairMatch
3490 * 2.5.13.38 certificateListExactMatch
3491 * 2.5.13.39 certificateListMatch
3492 * 2.5.13.40 algorithmIdentifierMatch
3493 * 2.5.13.41* storedPrefixMatch
3494 * 2.5.13.42 attributeCertificateMatch
3495 * 2.5.13.43 readerAndKeyIDMatch
3496 * 2.5.13.44 attributeIntegrityMatch
3498 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3500 static slap_mrule_defs_rec mrule_defs[] = {
3502 * EQUALITY matching rules must be listed after associated APPROX
3503 * matching rules. So, we list all APPROX matching rules first.
3505 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3507 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3508 NULL, NULL, directoryStringApproxMatch,
3509 directoryStringApproxIndexer, directoryStringApproxFilter,
3512 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3514 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3515 NULL, NULL, IA5StringApproxMatch,
3516 IA5StringApproxIndexer, IA5StringApproxFilter,
3520 * Other matching rules
3523 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3524 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3525 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3526 NULL, NULL, octetStringMatch,
3527 octetStringIndexer, octetStringFilter,
3530 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3531 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3532 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3533 NULL, dnNormalize, dnMatch,
3534 octetStringIndexer, octetStringFilter,
3537 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3539 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3540 NULL, dnNormalize, dnRelativeMatch,
3544 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3546 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3547 NULL, dnNormalize, dnRelativeMatch,
3551 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3553 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3554 NULL, dnNormalize, dnRelativeMatch,
3558 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3560 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3561 NULL, dnNormalize, dnRelativeMatch,
3565 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3566 "SYNTAX 1.2.36.79672281.1.5.0 )",
3567 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3568 NULL, rdnNormalize, rdnMatch,
3569 octetStringIndexer, octetStringFilter,
3572 #ifdef LDAP_COMP_MATCH
3573 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3574 "SYNTAX 1.2.36.79672281.1.5.2 )",
3575 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3576 NULL, NULL , componentFilterMatch,
3577 octetStringIndexer, octetStringFilter,
3580 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3581 "SYNTAX 1.2.36.79672281.1.5.3 )",
3582 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3583 NULL, NULL , allComponentsMatch,
3584 octetStringIndexer, octetStringFilter,
3587 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3588 "SYNTAX 1.2.36.79672281.1.5.3 )",
3589 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3590 NULL, NULL , directoryComponentsMatch,
3591 octetStringIndexer, octetStringFilter,
3595 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3596 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3597 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3598 NULL, UTF8StringNormalize, octetStringMatch,
3599 octetStringIndexer, octetStringFilter,
3600 directoryStringApproxMatchOID },
3602 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3603 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3604 SLAP_MR_ORDERING, directoryStringSyntaxes,
3605 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3607 "caseIgnoreMatch" },
3609 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3610 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3611 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3612 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3613 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3614 "caseIgnoreMatch" },
3616 {"( 2.5.13.5 NAME 'caseExactMatch' "
3617 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3618 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3619 NULL, UTF8StringNormalize, octetStringMatch,
3620 octetStringIndexer, octetStringFilter,
3621 directoryStringApproxMatchOID },
3623 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3624 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3625 SLAP_MR_ORDERING, directoryStringSyntaxes,
3626 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3630 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3631 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3632 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3633 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3634 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3637 {"( 2.5.13.8 NAME 'numericStringMatch' "
3638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3639 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3640 NULL, numericStringNormalize, octetStringMatch,
3641 octetStringIndexer, octetStringFilter,
3644 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3645 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3646 SLAP_MR_ORDERING, NULL,
3647 NULL, numericStringNormalize, octetStringOrderingMatch,
3649 "numericStringMatch" },
3651 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3652 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3653 SLAP_MR_SUBSTR, NULL,
3654 NULL, numericStringNormalize, octetStringSubstringsMatch,
3655 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3656 "numericStringMatch" },
3658 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3660 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3661 NULL, NULL, NULL, NULL, NULL, NULL },
3663 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3665 SLAP_MR_SUBSTR, NULL,
3666 NULL, NULL, NULL, NULL, NULL,
3667 "caseIgnoreListMatch" },
3669 {"( 2.5.13.13 NAME 'booleanMatch' "
3670 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3671 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3672 NULL, NULL, booleanMatch,
3673 octetStringIndexer, octetStringFilter,
3676 {"( 2.5.13.14 NAME 'integerMatch' "
3677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3678 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3679 NULL, NULL, integerMatch,
3680 octetStringIndexer, octetStringFilter,
3683 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3685 SLAP_MR_ORDERING, NULL,
3686 NULL, NULL, integerMatch,
3690 {"( 2.5.13.16 NAME 'bitStringMatch' "
3691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3692 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3693 NULL, NULL, octetStringMatch,
3694 octetStringIndexer, octetStringFilter,
3697 {"( 2.5.13.17 NAME 'octetStringMatch' "
3698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3699 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3700 NULL, NULL, octetStringMatch,
3701 octetStringIndexer, octetStringFilter,
3704 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3706 SLAP_MR_ORDERING, NULL,
3707 NULL, NULL, octetStringOrderingMatch,
3709 "octetStringMatch" },
3711 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3713 SLAP_MR_SUBSTR, NULL,
3714 NULL, NULL, octetStringSubstringsMatch,
3715 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3716 "octetStringMatch" },
3718 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3719 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3720 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3722 telephoneNumberNormalize, octetStringMatch,
3723 octetStringIndexer, octetStringFilter,
3726 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3728 SLAP_MR_SUBSTR, NULL,
3729 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3730 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3731 "telephoneNumberMatch" },
3733 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3734 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3735 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3736 NULL, NULL, NULL, NULL, NULL, NULL },
3738 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3739 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3740 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3741 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3742 uniqueMemberIndexer, uniqueMemberFilter,
3745 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3746 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3747 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3748 NULL, NULL, NULL, NULL, NULL, NULL },
3750 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3752 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3753 NULL, generalizedTimeNormalize, octetStringMatch,
3754 generalizedTimeIndexer, generalizedTimeFilter,
3757 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3759 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3760 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3762 "generalizedTimeMatch" },
3764 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3766 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3767 integerFirstComponentMatchSyntaxes,
3768 NULL, firstComponentNormalize, integerMatch,
3769 octetStringIndexer, octetStringFilter,
3772 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3773 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3774 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3775 objectIdentifierFirstComponentMatchSyntaxes,
3776 NULL, firstComponentNormalize, octetStringMatch,
3777 octetStringIndexer, octetStringFilter,
3780 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3781 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3782 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3784 NULL, certificateExactNormalize, octetStringMatch,
3785 octetStringIndexer, octetStringFilter,
3787 NULL, NULL, NULL, NULL, NULL,
3791 {"( 2.5.13.35 NAME 'certificateMatch' "
3792 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3793 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3795 NULL, NULL, octetStringMatch,
3796 octetStringIndexer, octetStringFilter,
3798 NULL, NULL, NULL, NULL, NULL,
3802 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3804 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3805 NULL, IA5StringNormalize, octetStringMatch,
3806 octetStringIndexer, octetStringFilter,
3807 IA5StringApproxMatchOID },
3809 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3811 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3812 NULL, IA5StringNormalize, octetStringMatch,
3813 octetStringIndexer, octetStringFilter,
3814 IA5StringApproxMatchOID },
3816 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3818 SLAP_MR_SUBSTR, NULL,
3819 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3820 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3821 "caseIgnoreIA5Match" },
3823 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3825 SLAP_MR_SUBSTR, NULL,
3826 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3827 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3828 "caseExactIA5Match" },
3830 #ifdef SLAPD_AUTHPASSWD
3831 /* needs updating */
3832 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3833 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3834 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3835 NULL, NULL, authPasswordMatch,
3840 #ifdef SLAPD_ACI_ENABLED
3841 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3842 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3843 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3844 NULL, NULL, OpenLDAPaciMatch,
3849 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3850 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3852 NULL, NULL, integerBitAndMatch,
3856 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3857 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3859 NULL, NULL, integerBitOrMatch,
3863 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3864 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3865 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3866 NULL, UUIDNormalize, octetStringMatch,
3867 octetStringIndexer, octetStringFilter,
3870 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3871 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3872 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3873 NULL, UUIDNormalize, octetStringOrderingMatch,
3874 octetStringIndexer, octetStringFilter,
3877 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3878 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3879 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3880 NULL, NULL, csnMatch,
3881 csnIndexer, csnFilter,
3884 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3885 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3886 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3887 NULL, NULL, csnOrderingMatch,
3891 {NULL, SLAP_MR_NONE, NULL,
3892 NULL, NULL, NULL, NULL, NULL,
3897 slap_schema_init( void )
3902 /* we should only be called once (from main) */
3903 assert( schema_init_done == 0 );
3905 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3906 res = register_syntax( &syntax_defs[i] );
3909 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3910 syntax_defs[i].sd_desc );
3915 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3916 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3917 mrule_defs[i].mrd_compat_syntaxes == NULL )
3920 "slap_schema_init: Ignoring unusable matching rule %s\n",
3921 mrule_defs[i].mrd_desc );
3925 res = register_matching_rule( &mrule_defs[i] );
3929 "slap_schema_init: Error registering matching rule %s\n",
3930 mrule_defs[i].mrd_desc );
3935 res = slap_schema_load();
3936 schema_init_done = 1;
3941 schema_destroy( void )