1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
46 #include "lutil_hash.h"
47 #define HASH_BYTES LUTIL_HASH_BYTES
48 #define HASH_CONTEXT lutil_HASH_CTX
49 #define HASH_Init(c) lutil_HASHInit(c)
50 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
51 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
53 #define OpenLDAPaciMatch NULL
55 /* approx matching rules */
56 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
57 #define directoryStringApproxMatch approxMatch
58 #define directoryStringApproxIndexer approxIndexer
59 #define directoryStringApproxFilter approxFilter
60 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
61 #define IA5StringApproxMatch approxMatch
62 #define IA5StringApproxIndexer approxIndexer
63 #define IA5StringApproxFilter approxFilter
65 /* Change Sequence Number (CSN) - much of this will change */
66 #define csnValidate blobValidate
67 #define csnMatch octetStringMatch
68 #define csnOrderingMatch octetStringOrderingMatch
69 #define csnIndexer generalizedTimeIndexer
70 #define csnFilter generalizedTimeFilter
72 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
73 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
74 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
75 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
110 static int certificateValidate( Syntax *syntax, struct berval *in )
113 unsigned char *p = (unsigned char *)in->bv_val;
115 xcert = d2i_X509(NULL, &p, in->bv_len);
116 if ( !xcert ) return LDAP_INVALID_SYNTAX;
121 #define certificateValidate sequenceValidate
130 struct berval *value,
131 void *assertedValue )
133 struct berval *asserted = (struct berval *) assertedValue;
134 int match = value->bv_len - asserted->bv_len;
137 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
145 octetStringOrderingMatch(
150 struct berval *value,
151 void *assertedValue )
153 struct berval *asserted = (struct berval *) assertedValue;
154 ber_len_t v_len = value->bv_len;
155 ber_len_t av_len = asserted->bv_len;
157 int match = memcmp( value->bv_val, asserted->bv_val,
158 (v_len < av_len ? v_len : av_len) );
160 if( match == 0 ) match = v_len - av_len;
168 HASH_CONTEXT *HASHcontext,
169 unsigned char *HASHdigest,
170 struct berval *prefix,
174 unsigned char *value,
177 HASH_Init(HASHcontext);
178 if(prefix && prefix->bv_len > 0) {
179 HASH_Update(HASHcontext,
180 (unsigned char *)prefix->bv_val, prefix->bv_len);
182 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
183 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
184 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
185 HASH_Update(HASHcontext, value, value_len);
186 HASH_Final(HASHdigest, HASHcontext);
190 /* Index generation function */
191 int octetStringIndexer(
196 struct berval *prefix,
204 HASH_CONTEXT HASHcontext;
205 unsigned char HASHdigest[HASH_BYTES];
206 struct berval digest;
207 digest.bv_val = (char *)HASHdigest;
208 digest.bv_len = sizeof(HASHdigest);
210 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
211 /* just count them */
214 /* we should have at least one value at this point */
217 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
219 slen = syntax->ssyn_oidlen;
220 mlen = mr->smr_oidlen;
222 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
223 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
224 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
225 ber_dupbv_x( &keys[i], &digest, ctx );
228 BER_BVZERO( &keys[i] );
235 /* Index generation function */
236 int octetStringFilter(
241 struct berval *prefix,
242 void * assertedValue,
248 HASH_CONTEXT HASHcontext;
249 unsigned char HASHdigest[HASH_BYTES];
250 struct berval *value = (struct berval *) assertedValue;
251 struct berval digest;
252 digest.bv_val = (char *)HASHdigest;
253 digest.bv_len = sizeof(HASHdigest);
255 slen = syntax->ssyn_oidlen;
256 mlen = mr->smr_oidlen;
258 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
260 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
261 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
263 ber_dupbv_x( keys, &digest, ctx );
264 BER_BVZERO( &keys[1] );
272 octetStringSubstringsMatch(
277 struct berval *value,
278 void *assertedValue )
281 SubstringsAssertion *sub = assertedValue;
282 struct berval left = *value;
286 /* Add up asserted input length */
287 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
288 inlen += sub->sa_initial.bv_len;
291 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
292 inlen += sub->sa_any[i].bv_len;
295 if ( !BER_BVISNULL( &sub->sa_final ) ) {
296 inlen += sub->sa_final.bv_len;
299 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
300 if ( inlen > left.bv_len ) {
305 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
306 sub->sa_initial.bv_len );
312 left.bv_val += sub->sa_initial.bv_len;
313 left.bv_len -= sub->sa_initial.bv_len;
314 inlen -= sub->sa_initial.bv_len;
317 if ( !BER_BVISNULL( &sub->sa_final ) ) {
318 if ( inlen > left.bv_len ) {
323 match = memcmp( sub->sa_final.bv_val,
324 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
325 sub->sa_final.bv_len );
331 left.bv_len -= sub->sa_final.bv_len;
332 inlen -= sub->sa_final.bv_len;
336 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
341 if ( inlen > left.bv_len ) {
342 /* not enough length */
347 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
351 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
358 idx = p - left.bv_val;
360 if ( idx >= left.bv_len ) {
361 /* this shouldn't happen */
368 if ( sub->sa_any[i].bv_len > left.bv_len ) {
369 /* not enough left */
374 match = memcmp( left.bv_val,
375 sub->sa_any[i].bv_val,
376 sub->sa_any[i].bv_len );
384 left.bv_val += sub->sa_any[i].bv_len;
385 left.bv_len -= sub->sa_any[i].bv_len;
386 inlen -= sub->sa_any[i].bv_len;
395 /* Substrings Index generation function */
397 octetStringSubstringsIndexer(
402 struct berval *prefix,
411 HASH_CONTEXT HASHcontext;
412 unsigned char HASHdigest[HASH_BYTES];
413 struct berval digest;
414 digest.bv_val = (char *)HASHdigest;
415 digest.bv_len = sizeof(HASHdigest);
419 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
420 /* count number of indices to generate */
421 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
422 if( values[i].bv_len >= index_substr_if_maxlen ) {
423 nkeys += index_substr_if_maxlen -
424 (index_substr_if_minlen - 1);
425 } else if( values[i].bv_len >= index_substr_if_minlen ) {
426 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
430 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
431 if( values[i].bv_len >= index_substr_any_len ) {
432 nkeys += values[i].bv_len - (index_substr_any_len - 1);
436 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
437 if( values[i].bv_len >= index_substr_if_maxlen ) {
438 nkeys += index_substr_if_maxlen -
439 (index_substr_if_minlen - 1);
440 } else if( values[i].bv_len >= index_substr_if_minlen ) {
441 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
447 /* no keys to generate */
452 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
454 slen = syntax->ssyn_oidlen;
455 mlen = mr->smr_oidlen;
458 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
461 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
462 ( values[i].bv_len >= index_substr_any_len ) )
464 char pre = SLAP_INDEX_SUBSTR_PREFIX;
465 max = values[i].bv_len - (index_substr_any_len - 1);
467 for( j=0; j<max; j++ ) {
468 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
469 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
470 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
474 /* skip if too short */
475 if( values[i].bv_len < index_substr_if_minlen ) continue;
477 max = index_substr_if_maxlen < values[i].bv_len
478 ? index_substr_if_maxlen : values[i].bv_len;
480 for( j=index_substr_if_minlen; j<=max; j++ ) {
483 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
484 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
485 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
486 syntax, mr, (unsigned char *)values[i].bv_val, j );
487 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
490 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
491 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
492 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
493 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
494 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
501 BER_BVZERO( &keys[nkeys] );
512 octetStringSubstringsFilter (
517 struct berval *prefix,
518 void * assertedValue,
522 SubstringsAssertion *sa;
525 size_t slen, mlen, klen;
527 HASH_CONTEXT HASHcontext;
528 unsigned char HASHdigest[HASH_BYTES];
529 struct berval *value;
530 struct berval digest;
532 sa = (SubstringsAssertion *) assertedValue;
534 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
535 !BER_BVISNULL( &sa->sa_initial ) &&
536 sa->sa_initial.bv_len >= index_substr_if_minlen )
539 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
540 ( flags & SLAP_INDEX_SUBSTR_ANY ))
542 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
546 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
548 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
549 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
550 /* don't bother accounting with stepping */
551 nkeys += sa->sa_any[i].bv_len -
552 ( index_substr_any_len - 1 );
557 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
558 !BER_BVISNULL( &sa->sa_final ) &&
559 sa->sa_final.bv_len >= index_substr_if_minlen )
562 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
563 ( flags & SLAP_INDEX_SUBSTR_ANY ))
565 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
574 digest.bv_val = (char *)HASHdigest;
575 digest.bv_len = sizeof(HASHdigest);
577 slen = syntax->ssyn_oidlen;
578 mlen = mr->smr_oidlen;
580 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
583 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
584 !BER_BVISNULL( &sa->sa_initial ) &&
585 sa->sa_initial.bv_len >= index_substr_if_minlen )
587 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
588 value = &sa->sa_initial;
590 klen = index_substr_if_maxlen < value->bv_len
591 ? index_substr_if_maxlen : value->bv_len;
593 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
594 syntax, mr, (unsigned char *)value->bv_val, klen );
595 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
597 /* If initial is too long and we have subany indexed, use it
598 * to match the excess...
600 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
603 pre = SLAP_INDEX_SUBSTR_PREFIX;
604 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
606 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
607 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
608 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
613 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
615 pre = SLAP_INDEX_SUBSTR_PREFIX;
616 klen = index_substr_any_len;
618 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
619 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
623 value = &sa->sa_any[i];
626 j <= value->bv_len - index_substr_any_len;
627 j += index_substr_any_step )
629 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
630 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
631 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
636 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
637 !BER_BVISNULL( &sa->sa_final ) &&
638 sa->sa_final.bv_len >= index_substr_if_minlen )
640 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
641 value = &sa->sa_final;
643 klen = index_substr_if_maxlen < value->bv_len
644 ? index_substr_if_maxlen : value->bv_len;
646 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
647 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
648 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
650 /* If final is too long and we have subany indexed, use it
651 * to match the excess...
653 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
656 pre = SLAP_INDEX_SUBSTR_PREFIX;
657 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
659 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
660 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
661 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
667 BER_BVZERO( &keys[nkeys] );
684 /* very unforgiving validation, requires no normalization
685 * before simplistic matching
687 if( in->bv_len < 3 ) {
688 return LDAP_INVALID_SYNTAX;
692 * RFC 2252 section 6.3 Bit String
693 * bitstring = "'" *binary-digit "'B"
694 * binary-digit = "0" / "1"
695 * example: '0101111101'B
698 if( in->bv_val[0] != '\'' ||
699 in->bv_val[in->bv_len - 2] != '\'' ||
700 in->bv_val[in->bv_len - 1] != 'B' )
702 return LDAP_INVALID_SYNTAX;
705 for( i = in->bv_len - 3; i > 0; i-- ) {
706 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
707 return LDAP_INVALID_SYNTAX;
715 * Syntax is [RFC2252]:
720 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
722 Values in this syntax are encoded according to the following BNF:
724 bitstring = "'" *binary-digit "'B"
726 binary-digit = "0" / "1"
730 6.21. Name And Optional UID
732 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
734 Values in this syntax are encoded according to the following BNF:
736 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
738 Although the '#' character may occur in a string representation of a
739 distinguished name, no additional special quoting is done. This
740 syntax has been added subsequent to RFC 1778.
744 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
747 * draft-ietf-ldapbis-syntaxes-xx.txt says:
752 A value of the Bit String syntax is a sequence of binary digits. The
753 LDAP-specific encoding of a value of this syntax is defined by the
756 BitString = SQUOTE *binary-digit SQUOTE "B"
758 binary-digit = "0" / "1"
760 The <SQUOTE> rule is defined in [MODELS].
765 The LDAP definition for the Bit String syntax is:
767 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
769 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
773 3.3.21. Name and Optional UID
775 A value of the Name and Optional UID syntax is the distinguished name
776 [MODELS] of an entity optionally accompanied by a unique identifier
777 that serves to differentiate the entity from others with an identical
780 The LDAP-specific encoding of a value of this syntax is defined by
783 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
785 The <BitString> rule is defined in Section 3.3.2. The
786 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
789 Note that although the '#' character may occur in the string
790 representation of a distinguished name, no additional escaping of
791 this character is performed when a <distinguishedName> is encoded in
792 a <NameAndOptionalUID>.
795 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
797 The LDAP definition for the Name and Optional UID syntax is:
799 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
801 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
805 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
808 1.4. Common ABNF Productions
811 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
813 SQUOTE = %x27 ; single quote ("'")
817 * Note: normalization strips any leading "0"s, unless the
818 * bit string is exactly "'0'B", so the normalized example,
819 * in slapd, would result in
821 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
823 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
824 * i.e. "#", doesn't have to be escaped except when at the
825 * beginning of a value, the definition of Name and Optional
826 * UID appears to be flawed, because there is no clear means
827 * to determine whether the UID part is present or not.
831 * cn=Someone,dc=example,dc=com#'1'B
833 * could be either a NameAndOptionalUID with trailing UID, i.e.
835 * DN = "cn=Someone,dc=example,dc=com"
838 * or a NameAndOptionalUID with no trailing UID, and the AVA
839 * in the last RDN made of
842 * attributeValue = com#'1'B
844 * in fact "com#'1'B" is a valid IA5 string.
846 * As a consequence, current slapd code assumes that the
847 * presence of portions of a BitString at the end of the string
848 * representation of a NameAndOptionalUID means a BitString
849 * is expected, and cause an error otherwise. This is quite
850 * arbitrary, and might change in the future.
860 struct berval dn, uid;
862 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
864 ber_dupbv( &dn, in );
865 if( !dn.bv_val ) return LDAP_OTHER;
867 /* if there's a "#", try bitStringValidate()... */
868 uid.bv_val = strrchr( dn.bv_val, '#' );
869 if ( !BER_BVISNULL( &uid ) ) {
871 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
873 rc = bitStringValidate( NULL, &uid );
874 if ( rc == LDAP_SUCCESS ) {
875 /* in case of success, trim the UID,
876 * otherwise treat it as part of the DN */
877 dn.bv_len -= uid.bv_len + 1;
878 uid.bv_val[-1] = '\0';
882 rc = dnValidate( NULL, &dn );
884 ber_memfree( dn.bv_val );
899 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
901 if( BER_BVISEMPTY( val ) ) {
902 ber_dupbv_x( out, val, ctx );
904 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
905 return LDAP_INVALID_SYNTAX;
909 struct berval dnval = *val;
910 struct berval uidval = BER_BVNULL;
912 uidval.bv_val = strrchr( val->bv_val, '#' );
913 if ( !BER_BVISNULL( &uidval ) ) {
915 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
917 rc = bitStringValidate( NULL, &uidval );
919 if ( rc == LDAP_SUCCESS ) {
920 ber_dupbv_x( &dnval, val, ctx );
921 dnval.bv_len -= uidval.bv_len + 1;
922 dnval.bv_val[dnval.bv_len] = '\0';
925 BER_BVZERO( &uidval );
929 rc = dnPretty( syntax, &dnval, out, ctx );
930 if ( dnval.bv_val != val->bv_val ) {
931 slap_sl_free( dnval.bv_val, ctx );
933 if( rc != LDAP_SUCCESS ) {
937 if( !BER_BVISNULL( &uidval ) ) {
941 tmp = slap_sl_realloc( out->bv_val, out->bv_len
942 + STRLENOF( "#" ) + uidval.bv_len + 1,
945 ber_memfree_x( out->bv_val, ctx );
949 out->bv_val[out->bv_len++] = '#';
950 out->bv_val[out->bv_len++] = '\'';
952 got1 = uidval.bv_len < sizeof("'0'B");
953 for( i = 1; i < uidval.bv_len - 2; i++ ) {
954 c = uidval.bv_val[i];
957 if( got1 ) out->bv_val[out->bv_len++] = c;
961 out->bv_val[out->bv_len++] = c;
966 out->bv_val[out->bv_len++] = '\'';
967 out->bv_val[out->bv_len++] = 'B';
968 out->bv_val[out->bv_len] = '\0';
972 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
978 uniqueMemberNormalize(
983 struct berval *normalized,
989 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
991 ber_dupbv_x( &out, val, ctx );
992 if ( BER_BVISEMPTY( &out ) ) {
996 struct berval uid = BER_BVNULL;
998 uid.bv_val = strrchr( out.bv_val, '#' );
999 if ( !BER_BVISNULL( &uid ) ) {
1001 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1003 rc = bitStringValidate( NULL, &uid );
1004 if ( rc == LDAP_SUCCESS ) {
1005 uid.bv_val[-1] = '\0';
1006 out.bv_len -= uid.bv_len + 1;
1012 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1014 if( rc != LDAP_SUCCESS ) {
1015 slap_sl_free( out.bv_val, ctx );
1016 return LDAP_INVALID_SYNTAX;
1019 if( !BER_BVISNULL( &uid ) ) {
1022 tmp = ch_realloc( normalized->bv_val,
1023 normalized->bv_len + uid.bv_len
1024 + STRLENOF("#") + 1 );
1025 if ( tmp == NULL ) {
1026 ber_memfree_x( normalized->bv_val, ctx );
1030 normalized->bv_val = tmp;
1032 /* insert the separator */
1033 normalized->bv_val[normalized->bv_len++] = '#';
1035 /* append the UID */
1036 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1037 uid.bv_val, uid.bv_len );
1038 normalized->bv_len += uid.bv_len;
1041 normalized->bv_val[normalized->bv_len] = '\0';
1044 slap_sl_free( out.bv_val, ctx );
1047 return LDAP_SUCCESS;
1056 struct berval *value,
1057 void *assertedValue )
1060 struct berval *asserted = (struct berval *) assertedValue;
1061 struct berval assertedDN = *asserted;
1062 struct berval assertedUID = BER_BVNULL;
1063 struct berval valueDN = BER_BVNULL;
1064 struct berval valueUID = BER_BVNULL;
1065 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1067 if ( !BER_BVISEMPTY( asserted ) ) {
1068 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1069 if ( !BER_BVISNULL( &assertedUID ) ) {
1070 assertedUID.bv_val++;
1071 assertedUID.bv_len = assertedDN.bv_len
1072 - ( assertedUID.bv_val - assertedDN.bv_val );
1074 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1075 assertedDN.bv_len -= assertedUID.bv_len + 1;
1078 BER_BVZERO( &assertedUID );
1083 if ( !BER_BVISEMPTY( value ) ) {
1086 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1087 if ( !BER_BVISNULL( &valueUID ) ) {
1089 valueUID.bv_len = valueDN.bv_len
1090 - ( valueUID.bv_val - valueDN.bv_val );
1092 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1093 valueDN.bv_len -= valueUID.bv_len + 1;
1096 BER_BVZERO( &valueUID );
1101 if( valueUID.bv_len && assertedUID.bv_len ) {
1102 match = valueUID.bv_len - assertedUID.bv_len;
1105 return LDAP_SUCCESS;
1108 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1111 return LDAP_SUCCESS;
1114 } else if ( !approx && valueUID.bv_len ) {
1117 return LDAP_SUCCESS;
1119 } else if ( !approx && assertedUID.bv_len ) {
1122 return LDAP_SUCCESS;
1125 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1129 uniqueMemberIndexer(
1134 struct berval *prefix,
1142 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1143 /* just count them */
1147 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1149 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1150 struct berval assertedDN = values[i];
1151 struct berval assertedUID = BER_BVNULL;
1153 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1154 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1155 if ( !BER_BVISNULL( &assertedUID ) ) {
1156 assertedUID.bv_val++;
1157 assertedUID.bv_len = assertedDN.bv_len
1158 - ( assertedUID.bv_val - assertedDN.bv_val );
1160 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1161 assertedDN.bv_len -= assertedUID.bv_len + 1;
1164 BER_BVZERO( &assertedUID );
1169 dnvalues[i] = assertedDN;
1171 BER_BVZERO( &dnvalues[i] );
1173 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1174 dnvalues, keysp, ctx );
1176 slap_sl_free( dnvalues, ctx );
1186 struct berval *prefix,
1187 void * assertedValue,
1191 struct berval *asserted = (struct berval *) assertedValue;
1192 struct berval assertedDN = *asserted;
1193 struct berval assertedUID = BER_BVNULL;
1195 if ( !BER_BVISEMPTY( asserted ) ) {
1196 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1197 if ( !BER_BVISNULL( &assertedUID ) ) {
1198 assertedUID.bv_val++;
1199 assertedUID.bv_len = assertedDN.bv_len
1200 - ( assertedUID.bv_val - assertedDN.bv_val );
1202 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1203 assertedDN.bv_len -= assertedUID.bv_len + 1;
1206 BER_BVZERO( &assertedUID );
1211 return octetStringFilter( use, flags, syntax, mr, prefix,
1212 &assertedDN, keysp, ctx );
1217 * Handling boolean syntax and matching is quite rigid.
1218 * A more flexible approach would be to allow a variety
1219 * of strings to be normalized and prettied into TRUE
1227 /* very unforgiving validation, requires no normalization
1228 * before simplistic matching
1231 if( in->bv_len == 4 ) {
1232 if( bvmatch( in, &slap_true_bv ) ) {
1233 return LDAP_SUCCESS;
1235 } else if( in->bv_len == 5 ) {
1236 if( bvmatch( in, &slap_false_bv ) ) {
1237 return LDAP_SUCCESS;
1241 return LDAP_INVALID_SYNTAX;
1250 struct berval *value,
1251 void *assertedValue )
1253 /* simplistic matching allowed by rigid validation */
1254 struct berval *asserted = (struct berval *) assertedValue;
1255 *matchp = value->bv_len != asserted->bv_len;
1256 return LDAP_SUCCESS;
1259 /*-------------------------------------------------------------------
1260 LDAP/X.500 string syntax / matching rules have a few oddities. This
1261 comment attempts to detail how slapd(8) treats them.
1264 StringSyntax X.500 LDAP Matching/Comments
1265 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1266 PrintableString subset subset i/e + ignore insignificant spaces
1267 PrintableString subset subset i/e + ignore insignificant spaces
1268 NumericString subset subset ignore all spaces
1269 IA5String ASCII ASCII i/e + ignore insignificant spaces
1270 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1272 TelephoneNumber subset subset i + ignore all spaces and "-"
1274 See draft-ietf-ldapbis-strpro for details (once published).
1278 In X.500(93), a directory string can be either a PrintableString,
1279 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1280 In later versions, more CHOICEs were added. In all cases the string
1283 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1284 A directory string cannot be zero length.
1286 For matching, there are both case ignore and exact rules. Both
1287 also require that "insignificant" spaces be ignored.
1288 spaces before the first non-space are ignored;
1289 spaces after the last non-space are ignored;
1290 spaces after a space are ignored.
1291 Note: by these rules (and as clarified in X.520), a string of only
1292 spaces is to be treated as if held one space, not empty (which
1293 would be a syntax error).
1296 In ASN.1, numeric string is just a string of digits and spaces
1297 and could be empty. However, in X.500, all attribute values of
1298 numeric string carry a non-empty constraint. For example:
1300 internationalISDNNumber ATTRIBUTE ::= {
1301 WITH SYNTAX InternationalISDNNumber
1302 EQUALITY MATCHING RULE numericStringMatch
1303 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1304 ID id-at-internationalISDNNumber }
1305 InternationalISDNNumber ::=
1306 NumericString (SIZE(1..ub-international-isdn-number))
1308 Unforunately, some assertion values are don't carry the same
1309 constraint (but its unclear how such an assertion could ever
1310 be true). In LDAP, there is one syntax (numericString) not two
1311 (numericString with constraint, numericString without constraint).
1312 This should be treated as numericString with non-empty constraint.
1313 Note that while someone may have no ISDN number, there are no ISDN
1314 numbers which are zero length.
1316 In matching, spaces are ignored.
1319 In ASN.1, Printable string is just a string of printable characters
1320 and can be empty. In X.500, semantics much like NumericString (see
1321 serialNumber for a like example) excepting uses insignificant space
1322 handling instead of ignore all spaces.
1325 Basically same as PrintableString. There are no examples in X.500,
1326 but same logic applies. So we require them to be non-empty as
1329 -------------------------------------------------------------------*/
1338 unsigned char *u = (unsigned char *)in->bv_val;
1340 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1341 /* directory strings cannot be empty */
1342 return LDAP_INVALID_SYNTAX;
1345 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1346 /* get the length indicated by the first byte */
1347 len = LDAP_UTF8_CHARLEN2( u, len );
1349 /* very basic checks */
1352 if( (u[5] & 0xC0) != 0x80 ) {
1353 return LDAP_INVALID_SYNTAX;
1356 if( (u[4] & 0xC0) != 0x80 ) {
1357 return LDAP_INVALID_SYNTAX;
1360 if( (u[3] & 0xC0) != 0x80 ) {
1361 return LDAP_INVALID_SYNTAX;
1364 if( (u[2] & 0xC0 )!= 0x80 ) {
1365 return LDAP_INVALID_SYNTAX;
1368 if( (u[1] & 0xC0) != 0x80 ) {
1369 return LDAP_INVALID_SYNTAX;
1372 /* CHARLEN already validated it */
1375 return LDAP_INVALID_SYNTAX;
1378 /* make sure len corresponds with the offset
1379 to the next character */
1380 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1384 return LDAP_INVALID_SYNTAX;
1387 return LDAP_SUCCESS;
1391 UTF8StringNormalize(
1396 struct berval *normalized,
1399 struct berval tmp, nvalue;
1403 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1405 if( BER_BVISNULL( val ) ) {
1406 /* assume we're dealing with a syntax (e.g., UTF8String)
1407 * which allows empty strings
1409 BER_BVZERO( normalized );
1410 return LDAP_SUCCESS;
1413 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1414 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1415 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1416 ? LDAP_UTF8_APPROX : 0;
1418 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1423 /* collapse spaces (in place) */
1425 nvalue.bv_val = tmp.bv_val;
1427 /* trim leading spaces? */
1428 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1429 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1431 for( i = 0; i < tmp.bv_len; i++) {
1432 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1433 if( wasspace++ == 0 ) {
1434 /* trim repeated spaces */
1435 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1439 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1443 if( !BER_BVISEMPTY( &nvalue ) ) {
1444 /* trim trailing space? */
1446 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1447 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1451 nvalue.bv_val[nvalue.bv_len] = '\0';
1454 /* string of all spaces is treated as one space */
1455 nvalue.bv_val[0] = ' ';
1456 nvalue.bv_val[1] = '\0';
1460 *normalized = nvalue;
1461 return LDAP_SUCCESS;
1465 directoryStringSubstringsMatch(
1470 struct berval *value,
1471 void *assertedValue )
1474 SubstringsAssertion *sub = assertedValue;
1475 struct berval left = *value;
1479 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1480 if ( sub->sa_initial.bv_len > left.bv_len ) {
1481 /* not enough left */
1486 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1487 sub->sa_initial.bv_len );
1493 left.bv_val += sub->sa_initial.bv_len;
1494 left.bv_len -= sub->sa_initial.bv_len;
1496 priorspace = ASCII_SPACE(
1497 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1500 if ( sub->sa_any ) {
1501 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1505 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1506 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1508 /* allow next space to match */
1515 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1519 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1520 /* not enough left */
1525 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1532 idx = p - left.bv_val;
1534 if ( idx >= left.bv_len ) {
1535 /* this shouldn't happen */
1542 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1543 /* not enough left */
1548 match = memcmp( left.bv_val,
1549 sub->sa_any[i].bv_val,
1550 sub->sa_any[i].bv_len );
1558 left.bv_val += sub->sa_any[i].bv_len;
1559 left.bv_len -= sub->sa_any[i].bv_len;
1561 priorspace = ASCII_SPACE(
1562 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1566 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1567 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1568 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1570 /* allow next space to match */
1575 if ( sub->sa_final.bv_len > left.bv_len ) {
1576 /* not enough left */
1581 match = memcmp( sub->sa_final.bv_val,
1582 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1583 sub->sa_final.bv_len );
1592 return LDAP_SUCCESS;
1595 #if defined(SLAPD_APPROX_INITIALS)
1596 # define SLAPD_APPROX_DELIMITER "._ "
1597 # define SLAPD_APPROX_WORDLEN 2
1599 # define SLAPD_APPROX_DELIMITER " "
1600 # define SLAPD_APPROX_WORDLEN 1
1609 struct berval *value,
1610 void *assertedValue )
1612 struct berval *nval, *assertv;
1613 char *val, **values, **words, *c;
1614 int i, count, len, nextchunk=0, nextavail=0;
1616 /* Yes, this is necessary */
1617 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1618 if( nval == NULL ) {
1620 return LDAP_SUCCESS;
1623 /* Yes, this is necessary */
1624 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1625 NULL, LDAP_UTF8_APPROX, NULL );
1626 if( assertv == NULL ) {
1629 return LDAP_SUCCESS;
1632 /* Isolate how many words there are */
1633 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1634 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1635 if ( c == NULL ) break;
1640 /* Get a phonetic copy of each word */
1641 words = (char **)ch_malloc( count * sizeof(char *) );
1642 values = (char **)ch_malloc( count * sizeof(char *) );
1643 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1645 values[i] = phonetic(c);
1648 /* Work through the asserted value's words, to see if at least some
1649 of the words are there, in the same order. */
1651 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1652 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1657 #if defined(SLAPD_APPROX_INITIALS)
1658 else if( len == 1 ) {
1659 /* Single letter words need to at least match one word's initial */
1660 for( i=nextavail; i<count; i++ )
1661 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1668 /* Isolate the next word in the asserted value and phonetic it */
1669 assertv->bv_val[nextchunk+len] = '\0';
1670 val = phonetic( assertv->bv_val + nextchunk );
1672 /* See if this phonetic chunk is in the remaining words of *value */
1673 for( i=nextavail; i<count; i++ ){
1674 if( !strcmp( val, values[i] ) ){
1682 /* This chunk in the asserted value was NOT within the *value. */
1688 /* Go on to the next word in the asserted value */
1692 /* If some of the words were seen, call it a match */
1693 if( nextavail > 0 ) {
1700 /* Cleanup allocs */
1701 ber_bvfree( assertv );
1702 for( i=0; i<count; i++ ) {
1703 ch_free( values[i] );
1709 return LDAP_SUCCESS;
1718 struct berval *prefix,
1724 int i,j, len, wordcount, keycount=0;
1725 struct berval *newkeys;
1726 BerVarray keys=NULL;
1728 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1729 struct berval val = BER_BVNULL;
1730 /* Yes, this is necessary */
1731 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1732 assert( !BER_BVISNULL( &val ) );
1734 /* Isolate how many words there are. There will be a key for each */
1735 for( wordcount = 0, c = val.bv_val; *c; c++) {
1736 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1737 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1739 if (*c == '\0') break;
1743 /* Allocate/increase storage to account for new keys */
1744 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1745 * sizeof(struct berval) );
1746 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1747 if( keys ) ch_free( keys );
1750 /* Get a phonetic copy of each word */
1751 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1753 if( len < SLAPD_APPROX_WORDLEN ) continue;
1754 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1759 ber_memfree( val.bv_val );
1761 BER_BVZERO( &keys[keycount] );
1764 return LDAP_SUCCESS;
1773 struct berval *prefix,
1774 void * assertedValue,
1783 /* Yes, this is necessary */
1784 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1785 NULL, LDAP_UTF8_APPROX, NULL );
1786 if( val == NULL || BER_BVISNULL( val ) ) {
1787 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1788 BER_BVZERO( &keys[0] );
1791 return LDAP_SUCCESS;
1794 /* Isolate how many words there are. There will be a key for each */
1795 for( count = 0,c = val->bv_val; *c; c++) {
1796 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1797 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1799 if (*c == '\0') break;
1803 /* Allocate storage for new keys */
1804 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1806 /* Get a phonetic copy of each word */
1807 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1809 if( len < SLAPD_APPROX_WORDLEN ) continue;
1810 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1816 BER_BVZERO( &keys[count] );
1819 return LDAP_SUCCESS;
1822 /* Remove all spaces and '-' characters */
1824 telephoneNumberNormalize(
1829 struct berval *normalized,
1834 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1836 /* validator should have refused an empty string */
1837 assert( !BER_BVISEMPTY( val ) );
1839 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1841 for( p = val->bv_val; *p; p++ ) {
1842 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1848 normalized->bv_len = q - normalized->bv_val;
1850 if( BER_BVISEMPTY( normalized ) ) {
1851 slap_sl_free( normalized->bv_val, ctx );
1852 BER_BVZERO( normalized );
1853 return LDAP_INVALID_SYNTAX;
1856 return LDAP_SUCCESS;
1864 struct berval val = *in;
1866 if( BER_BVISEMPTY( &val ) ) {
1867 /* disallow empty strings */
1868 return LDAP_INVALID_SYNTAX;
1871 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1872 if ( val.bv_len == 1 ) {
1873 return LDAP_SUCCESS;
1876 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1883 while ( OID_LEADCHAR( val.bv_val[0] )) {
1887 if ( val.bv_len == 0 ) {
1888 return LDAP_SUCCESS;
1892 if( !OID_SEPARATOR( val.bv_val[0] )) {
1900 return LDAP_INVALID_SYNTAX;
1909 struct berval val = *in;
1911 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1913 if ( val.bv_val[0] == '-' ) {
1917 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1918 return LDAP_INVALID_SYNTAX;
1921 if( val.bv_val[0] == '0' ) { /* "-0" */
1922 return LDAP_INVALID_SYNTAX;
1925 } else if ( val.bv_val[0] == '0' ) {
1926 if( val.bv_len > 1 ) { /* "0<more>" */
1927 return LDAP_INVALID_SYNTAX;
1930 return LDAP_SUCCESS;
1933 for( i=0; i < val.bv_len; i++ ) {
1934 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1935 return LDAP_INVALID_SYNTAX;
1939 return LDAP_SUCCESS;
1948 struct berval *value,
1949 void *assertedValue )
1951 struct berval *asserted = (struct berval *) assertedValue;
1952 int vsign = 1, asign = 1; /* default sign = '+' */
1957 if( v.bv_val[0] == '-' ) {
1963 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1966 if( a.bv_val[0] == '-' ) {
1972 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1974 match = vsign - asign;
1976 match = ( v.bv_len != a.bv_len
1977 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1978 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1979 if( vsign < 0 ) match = -match;
1983 return LDAP_SUCCESS;
1987 countryStringValidate(
1989 struct berval *val )
1991 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1993 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1994 return LDAP_INVALID_SYNTAX;
1996 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1997 return LDAP_INVALID_SYNTAX;
2000 return LDAP_SUCCESS;
2004 printableStringValidate(
2006 struct berval *val )
2010 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2012 for(i=0; i < val->bv_len; i++) {
2013 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2014 return LDAP_INVALID_SYNTAX;
2018 return LDAP_SUCCESS;
2022 printablesStringValidate(
2024 struct berval *val )
2028 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2030 for(i=0,len=0; i < val->bv_len; i++) {
2031 int c = val->bv_val[i];
2035 return LDAP_INVALID_SYNTAX;
2039 } else if ( SLAP_PRINTABLE(c) ) {
2042 return LDAP_INVALID_SYNTAX;
2047 return LDAP_INVALID_SYNTAX;
2050 return LDAP_SUCCESS;
2056 struct berval *val )
2060 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2062 for(i=0; i < val->bv_len; i++) {
2063 if( !LDAP_ASCII(val->bv_val[i]) ) {
2064 return LDAP_INVALID_SYNTAX;
2068 return LDAP_SUCCESS;
2077 struct berval *normalized,
2081 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2083 assert( !BER_BVISEMPTY( val ) );
2085 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2089 /* Ignore initial whitespace */
2090 while ( ASCII_SPACE( *p ) ) p++;
2092 normalized->bv_val = ber_strdup_x( p, ctx );
2093 p = q = normalized->bv_val;
2096 if ( ASCII_SPACE( *p ) ) {
2099 /* Ignore the extra whitespace */
2100 while ( ASCII_SPACE( *p ) ) {
2104 } else if ( casefold ) {
2105 /* Most IA5 rules require casefolding */
2106 *q++ = TOLOWER(*p); p++;
2113 assert( normalized->bv_val <= p );
2117 * If the string ended in space, backup the pointer one
2118 * position. One is enough because the above loop collapsed
2119 * all whitespace to a single space.
2121 if ( ASCII_SPACE( q[-1] ) ) --q;
2123 /* null terminate */
2126 normalized->bv_len = q - normalized->bv_val;
2127 if( BER_BVISEMPTY( normalized ) ) {
2128 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2129 normalized->bv_val[0] = ' ';
2130 normalized->bv_val[1] = '\0';
2131 normalized->bv_len = 1;
2134 return LDAP_SUCCESS;
2143 if( in->bv_len != 36 ) {
2144 return LDAP_INVALID_SYNTAX;
2147 for( i=0; i<36; i++ ) {
2153 if( in->bv_val[i] != '-' ) {
2154 return LDAP_INVALID_SYNTAX;
2158 if( !ASCII_HEX( in->bv_val[i]) ) {
2159 return LDAP_INVALID_SYNTAX;
2164 return LDAP_SUCCESS;
2173 struct berval *normalized,
2176 unsigned char octet = '\0';
2179 normalized->bv_len = 16;
2180 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2182 for( i=0, j=0; i<36; i++ ) {
2183 unsigned char nibble;
2184 if( val->bv_val[i] == '-' ) {
2187 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2188 nibble = val->bv_val[i] - '0';
2190 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2191 nibble = val->bv_val[i] - ('a'-10);
2193 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2194 nibble = val->bv_val[i] - ('A'-10);
2197 slap_sl_free( normalized->bv_val, ctx );
2198 return LDAP_INVALID_SYNTAX;
2203 normalized->bv_val[j>>1] = octet;
2205 octet = nibble << 4;
2210 normalized->bv_val[normalized->bv_len] = 0;
2211 return LDAP_SUCCESS;
2217 numericStringValidate(
2223 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2225 for(i=0; i < in->bv_len; i++) {
2226 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2227 return LDAP_INVALID_SYNTAX;
2231 return LDAP_SUCCESS;
2235 numericStringNormalize(
2240 struct berval *normalized,
2243 /* removal all spaces */
2246 assert( !BER_BVISEMPTY( val ) );
2248 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2251 q = normalized->bv_val;
2254 if ( ASCII_SPACE( *p ) ) {
2255 /* Ignore whitespace */
2262 /* we should have copied no more then is in val */
2263 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2265 /* null terminate */
2268 normalized->bv_len = q - normalized->bv_val;
2270 if( BER_BVISEMPTY( normalized ) ) {
2271 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2272 normalized->bv_val[0] = ' ';
2273 normalized->bv_val[1] = '\0';
2274 normalized->bv_len = 1;
2277 return LDAP_SUCCESS;
2281 * Integer conversion macros that will use the largest available
2284 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2285 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2286 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2287 # define SLAP_LONG_MAX LLONG_MAX
2288 # define SLAP_LONG_MIN LLONG_MIN
2289 # define SLAP_LONG long long
2291 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2292 # define SLAP_LONG_MAX LONG_MAX
2293 # define SLAP_LONG_MIN LONG_MIN
2294 # define SLAP_LONG long
2295 #endif /* HAVE_STRTOLL ... */
2303 struct berval *value,
2304 void *assertedValue )
2306 SLAP_LONG lValue, lAssertedValue;
2308 /* safe to assume integers are NUL terminated? */
2309 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2310 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2313 return LDAP_CONSTRAINT_VIOLATION;
2316 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2318 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2321 return LDAP_CONSTRAINT_VIOLATION;
2324 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2325 return LDAP_SUCCESS;
2334 struct berval *value,
2335 void *assertedValue )
2337 SLAP_LONG lValue, lAssertedValue;
2339 /* safe to assume integers are NUL terminated? */
2340 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2341 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2344 return LDAP_CONSTRAINT_VIOLATION;
2347 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2349 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2352 return LDAP_CONSTRAINT_VIOLATION;
2355 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2356 return LDAP_SUCCESS;
2360 serialNumberAndIssuerValidate(
2366 struct berval sn, i;
2367 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2369 i.bv_val = strchr( in->bv_val, '$' );
2370 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2372 sn.bv_val = in->bv_val;
2373 sn.bv_len = i.bv_val - in->bv_val;
2376 i.bv_len = in->bv_len - (sn.bv_len + 1);
2378 /* validate serial number (strict for now) */
2379 for( n=0; n < sn.bv_len; n++ ) {
2380 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2384 rc = dnValidate( NULL, &i );
2385 if( rc ) return LDAP_INVALID_SYNTAX;
2387 return LDAP_SUCCESS;
2391 serialNumberAndIssuerPretty(
2399 struct berval sn, i, newi;
2404 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2405 val->bv_val, 0, 0 );
2407 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2409 i.bv_val = strchr( val->bv_val, '$' );
2410 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2412 sn.bv_val = val->bv_val;
2413 sn.bv_len = i.bv_val - val->bv_val;
2416 i.bv_len = val->bv_len - (sn.bv_len + 1);
2418 /* eat leading zeros */
2419 for( n=0; n < (sn.bv_len-1); n++ ) {
2420 if( sn.bv_val[n] != '0' ) break;
2425 for( n=0; n < sn.bv_len; n++ ) {
2426 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2430 rc = dnPretty( syntax, &i, &newi, ctx );
2431 if( rc ) return LDAP_INVALID_SYNTAX;
2433 /* make room from sn + "$" */
2434 out->bv_len = sn.bv_len + newi.bv_len + 1;
2435 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2437 if( BER_BVISNULL( out ) ) {
2438 slap_sl_free( newi.bv_val, ctx );
2442 /* push issuer over */
2443 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2444 /* insert sn and "$" */
2445 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2446 out->bv_val[sn.bv_len] = '$';
2448 out->bv_val[out->bv_len] = '\0';
2450 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2451 out->bv_val, 0, 0 );
2453 return LDAP_SUCCESS;
2457 * This routine is called by certificateExactNormalize when
2458 * certificateExactNormalize receives a search string instead of
2459 * a certificate. This routine checks if the search value is valid
2460 * and then returns the normalized value
2463 serialNumberAndIssuerNormalize(
2473 struct berval sn, i, newi;
2478 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2479 val->bv_val, 0, 0 );
2481 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2483 i.bv_val = strchr( val->bv_val, '$' );
2484 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2486 sn.bv_val = val->bv_val;
2487 sn.bv_len = i.bv_val - val->bv_val;
2490 i.bv_len = val->bv_len - (sn.bv_len + 1);
2492 /* eat leading zeros */
2493 for( n=0; n < (sn.bv_len-1); n++ ) {
2494 if( sn.bv_val[n] != '0' ) break;
2499 for( n=0; n < sn.bv_len; n++ ) {
2500 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2501 return LDAP_INVALID_SYNTAX;
2506 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2507 if( rc ) return LDAP_INVALID_SYNTAX;
2509 /* make room from sn + "$" */
2510 out->bv_len = sn.bv_len + newi.bv_len + 1;
2511 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2513 if( BER_BVISNULL( out ) ) {
2514 slap_sl_free( newi.bv_val, ctx );
2518 /* push issuer over */
2519 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2520 /* insert sn and "$" */
2521 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2522 out->bv_val[sn.bv_len] = '$';
2524 out->bv_val[out->bv_len] = '\0';
2526 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2527 out->bv_val, 0, 0 );
2534 certificateExactNormalize(
2539 struct berval *normalized,
2542 int rc = LDAP_INVALID_SYNTAX;
2544 char *serial = NULL;
2545 ber_len_t seriallen;
2546 struct berval issuer_dn = BER_BVNULL;
2547 X509_NAME *name = NULL;
2548 ASN1_INTEGER *sn = NULL;
2551 if( BER_BVISEMPTY( val ) ) goto done;
2553 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2554 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2557 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2559 p = (unsigned char *)val->bv_val;
2560 xcert = d2i_X509( NULL, &p, val->bv_len);
2561 if( xcert == NULL ) goto done;
2563 sn=X509_get_serialNumber(xcert);
2564 if ( sn == NULL ) goto done;
2565 serial=i2s_ASN1_INTEGER(0, sn );
2566 if( serial == NULL ) goto done;
2567 seriallen=strlen(serial);
2569 name=X509_get_issuer_name(xcert);
2570 if( name == NULL ) goto done;
2571 rc = dnX509normalize( name, &issuer_dn );
2572 if( rc != LDAP_SUCCESS ) goto done;
2574 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2575 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2576 p = (unsigned char *)normalized->bv_val;
2577 AC_MEMCPY(p, serial, seriallen);
2580 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2581 p += issuer_dn.bv_len;
2584 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2585 normalized->bv_val, NULL, NULL );
2588 if (xcert) X509_free(xcert);
2589 if (serial) ch_free(serial);
2590 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2594 #endif /* HAVE_TLS */
2597 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2598 /* slight optimization - does not need the start parameter */
2599 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2604 check_time_syntax (struct berval *val,
2607 struct berval *fraction)
2610 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2611 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2612 * GeneralizedTime supports leap seconds, UTCTime does not.
2614 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2615 static const int mdays[2][12] = {
2616 /* non-leap years */
2617 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2619 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2622 int part, c, c1, c2, tzoffset, leapyear = 0;
2625 e = p + val->bv_len;
2627 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2628 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2630 for (part = start; part < 7 && p < e; part++) {
2632 if (!ASCII_DIGIT(c1)) {
2637 return LDAP_INVALID_SYNTAX;
2640 if (!ASCII_DIGIT(c)) {
2641 return LDAP_INVALID_SYNTAX;
2643 c += c1 * 10 - '0' * 11;
2644 if ((part | 1) == 3) {
2647 return LDAP_INVALID_SYNTAX;
2650 if (c >= ceiling[part]) {
2651 if (! (c == 60 && part == 6 && start == 0))
2652 return LDAP_INVALID_SYNTAX;
2656 if (part < 5 + start) {
2657 return LDAP_INVALID_SYNTAX;
2659 for (; part < 9; part++) {
2663 /* leapyear check for the Gregorian calendar (year>1581) */
2664 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2668 if (parts[3] >= mdays[leapyear][parts[2]]) {
2669 return LDAP_INVALID_SYNTAX;
2673 fraction->bv_val = p;
2674 fraction->bv_len = 0;
2675 if (p < e && (*p == '.' || *p == ',')) {
2677 while (++p < e && ASCII_DIGIT(*p)) {
2680 if (p - fraction->bv_val == 1) {
2681 return LDAP_INVALID_SYNTAX;
2683 for (end_num = p; end_num[-1] == '0'; --end_num) {
2686 c = end_num - fraction->bv_val;
2687 if (c != 1) fraction->bv_len = c;
2693 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2699 return LDAP_INVALID_SYNTAX;
2705 for (part = 7; part < 9 && p < e; part++) {
2707 if (!ASCII_DIGIT(c1)) {
2712 return LDAP_INVALID_SYNTAX;
2715 if (!ASCII_DIGIT(c2)) {
2716 return LDAP_INVALID_SYNTAX;
2718 parts[part] = c1 * 10 + c2 - '0' * 11;
2719 if (parts[part] >= ceiling[part]) {
2720 return LDAP_INVALID_SYNTAX;
2723 if (part < 8 + start) {
2724 return LDAP_INVALID_SYNTAX;
2727 if (tzoffset == '-') {
2728 /* negative offset to UTC, ie west of Greenwich */
2729 parts[4] += parts[7];
2730 parts[5] += parts[8];
2731 /* offset is just hhmm, no seconds */
2732 for (part = 6; --part >= 0; ) {
2736 c = mdays[leapyear][parts[2]];
2738 if (parts[part] >= c) {
2740 return LDAP_INVALID_SYNTAX;
2745 } else if (part != 5) {
2750 /* positive offset to UTC, ie east of Greenwich */
2751 parts[4] -= parts[7];
2752 parts[5] -= parts[8];
2753 for (part = 6; --part >= 0; ) {
2754 if (parts[part] < 0) {
2756 return LDAP_INVALID_SYNTAX;
2761 /* make first arg to % non-negative */
2762 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2767 } else if (part != 5) {
2774 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2777 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2784 struct berval *normalized )
2788 rc = check_time_syntax(val, 1, parts, NULL);
2789 if (rc != LDAP_SUCCESS) {
2793 normalized->bv_val = ch_malloc( 14 );
2794 if ( normalized->bv_val == NULL ) {
2795 return LBER_ERROR_MEMORY;
2798 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2799 parts[1], parts[2] + 1, parts[3] + 1,
2800 parts[4], parts[5], parts[6] );
2801 normalized->bv_len = 13;
2803 return LDAP_SUCCESS;
2813 return check_time_syntax(in, 1, parts, NULL);
2816 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2819 generalizedTimeValidate(
2824 struct berval fraction;
2825 return check_time_syntax(in, 0, parts, &fraction);
2829 generalizedTimeNormalize(
2834 struct berval *normalized,
2839 struct berval fraction;
2841 rc = check_time_syntax(val, 0, parts, &fraction);
2842 if (rc != LDAP_SUCCESS) {
2846 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2847 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2848 if ( BER_BVISNULL( normalized ) ) {
2849 return LBER_ERROR_MEMORY;
2852 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2853 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2854 parts[4], parts[5], parts[6] );
2855 if ( !BER_BVISEMPTY( &fraction ) ) {
2856 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2857 fraction.bv_val, fraction.bv_len );
2858 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2860 strcpy( normalized->bv_val + len-1, "Z" );
2861 normalized->bv_len = len;
2863 return LDAP_SUCCESS;
2867 generalizedTimeOrderingMatch(
2872 struct berval *value,
2873 void *assertedValue )
2875 struct berval *asserted = (struct berval *) assertedValue;
2876 ber_len_t v_len = value->bv_len;
2877 ber_len_t av_len = asserted->bv_len;
2879 /* ignore trailing 'Z' when comparing */
2880 int match = memcmp( value->bv_val, asserted->bv_val,
2881 (v_len < av_len ? v_len : av_len) - 1 );
2882 if ( match == 0 ) match = v_len - av_len;
2885 return LDAP_SUCCESS;
2888 /* Index generation function */
2889 int generalizedTimeIndexer(
2894 struct berval *prefix,
2902 BerValue bvtmp; /* 40 bit index */
2904 struct lutil_timet tt;
2906 bvtmp.bv_len = sizeof(tmp);
2908 for( i=0; values[i].bv_val != NULL; i++ ) {
2909 /* just count them */
2912 /* we should have at least one value at this point */
2915 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2917 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2918 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2919 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2920 /* Use 40 bits of time for key */
2921 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2922 lutil_tm2time( &tm, &tt );
2923 tmp[0] = tt.tt_gsec & 0xff;
2924 tmp[4] = tt.tt_sec & 0xff;
2926 tmp[3] = tt.tt_sec & 0xff;
2928 tmp[2] = tt.tt_sec & 0xff;
2930 tmp[1] = tt.tt_sec & 0xff;
2932 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2936 keys[j].bv_val = NULL;
2941 return LDAP_SUCCESS;
2944 /* Index generation function */
2945 int generalizedTimeFilter(
2950 struct berval *prefix,
2951 void * assertedValue,
2957 BerValue bvtmp; /* 40 bit index */
2958 BerValue *value = (BerValue *) assertedValue;
2960 struct lutil_timet tt;
2962 bvtmp.bv_len = sizeof(tmp);
2964 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2965 /* Use 40 bits of time for key */
2966 if ( value->bv_val && value->bv_len >= 10 &&
2967 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2969 lutil_tm2time( &tm, &tt );
2970 tmp[0] = tt.tt_gsec & 0xff;
2971 tmp[4] = tt.tt_sec & 0xff;
2973 tmp[3] = tt.tt_sec & 0xff;
2975 tmp[2] = tt.tt_sec & 0xff;
2977 tmp[1] = tt.tt_sec & 0xff;
2979 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2980 ber_dupbv_x(keys, &bvtmp, ctx );
2981 keys[1].bv_val = NULL;
2989 return LDAP_SUCCESS;
2993 deliveryMethodValidate(
2995 struct berval *val )
2998 #define LENOF(s) (sizeof(s)-1)
2999 struct berval tmp = *val;
3001 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3002 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3003 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3006 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3008 switch( tmp.bv_val[0] ) {
3011 if(( tmp.bv_len >= LENOF("any") ) &&
3012 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3014 tmp.bv_len -= LENOF("any");
3015 tmp.bv_val += LENOF("any");
3018 return LDAP_INVALID_SYNTAX;
3022 if(( tmp.bv_len >= LENOF("mhs") ) &&
3023 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3025 tmp.bv_len -= LENOF("mhs");
3026 tmp.bv_val += LENOF("mhs");
3029 return LDAP_INVALID_SYNTAX;
3033 if(( tmp.bv_len >= LENOF("physical") ) &&
3034 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3036 tmp.bv_len -= LENOF("physical");
3037 tmp.bv_val += LENOF("physical");
3040 return LDAP_INVALID_SYNTAX;
3043 case 'T': /* telex or teletex or telephone */
3044 if(( tmp.bv_len >= LENOF("telex") ) &&
3045 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3047 tmp.bv_len -= LENOF("telex");
3048 tmp.bv_val += LENOF("telex");
3051 if(( tmp.bv_len >= LENOF("teletex") ) &&
3052 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3054 tmp.bv_len -= LENOF("teletex");
3055 tmp.bv_val += LENOF("teletex");
3058 if(( tmp.bv_len >= LENOF("telephone") ) &&
3059 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3061 tmp.bv_len -= LENOF("telephone");
3062 tmp.bv_val += LENOF("telephone");
3065 return LDAP_INVALID_SYNTAX;
3068 case 'G': /* g3fax or g4fax */
3069 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3070 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3071 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3073 tmp.bv_len -= LENOF("g3fax");
3074 tmp.bv_val += LENOF("g3fax");
3077 return LDAP_INVALID_SYNTAX;
3081 if(( tmp.bv_len >= LENOF("ia5") ) &&
3082 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3084 tmp.bv_len -= LENOF("ia5");
3085 tmp.bv_val += LENOF("ia5");
3088 return LDAP_INVALID_SYNTAX;
3092 if(( tmp.bv_len >= LENOF("videotex") ) &&
3093 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3095 tmp.bv_len -= LENOF("videotex");
3096 tmp.bv_val += LENOF("videotex");
3099 return LDAP_INVALID_SYNTAX;
3102 return LDAP_INVALID_SYNTAX;
3105 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3107 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3111 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3115 return LDAP_INVALID_SYNTAX;
3117 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3126 nisNetgroupTripleValidate(
3128 struct berval *val )
3133 if ( BER_BVISEMPTY( val ) ) {
3134 return LDAP_INVALID_SYNTAX;
3137 p = (char *)val->bv_val;
3138 e = p + val->bv_len;
3140 if ( *p != '(' /*')'*/ ) {
3141 return LDAP_INVALID_SYNTAX;
3144 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3148 return LDAP_INVALID_SYNTAX;
3151 } else if ( !AD_CHAR( *p ) ) {
3152 return LDAP_INVALID_SYNTAX;
3156 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3157 return LDAP_INVALID_SYNTAX;
3163 return LDAP_INVALID_SYNTAX;
3166 return LDAP_SUCCESS;
3170 bootParameterValidate(
3172 struct berval *val )
3176 if ( BER_BVISEMPTY( val ) ) {
3177 return LDAP_INVALID_SYNTAX;
3180 p = (char *)val->bv_val;
3181 e = p + val->bv_len;
3184 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3185 if ( !AD_CHAR( *p ) ) {
3186 return LDAP_INVALID_SYNTAX;
3191 return LDAP_INVALID_SYNTAX;
3195 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3196 if ( !AD_CHAR( *p ) ) {
3197 return LDAP_INVALID_SYNTAX;
3202 return LDAP_INVALID_SYNTAX;
3206 for ( p++; p < e; p++ ) {
3207 if ( !SLAP_PRINTABLE( *p ) ) {
3208 return LDAP_INVALID_SYNTAX;
3212 return LDAP_SUCCESS;
3216 firstComponentNormalize(
3221 struct berval *normalized,
3228 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3229 ber_dupbv_x( normalized, val, ctx );
3230 return LDAP_SUCCESS;
3233 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3235 if( val->bv_val[0] != '(' /*')'*/ &&
3236 val->bv_val[0] != '{' /*'}'*/ )
3238 return LDAP_INVALID_SYNTAX;
3241 /* trim leading white space */
3243 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3249 /* grab next word */
3250 comp.bv_val = &val->bv_val[len];
3251 len = val->bv_len - len;
3252 for( comp.bv_len = 0;
3253 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3259 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3260 rc = numericoidValidate( NULL, &comp );
3261 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3262 rc = integerValidate( NULL, &comp );
3264 rc = LDAP_INVALID_SYNTAX;
3268 if( rc == LDAP_SUCCESS ) {
3269 ber_dupbv_x( normalized, &comp, ctx );
3276 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3277 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3279 static slap_syntax_defs_rec syntax_defs[] = {
3280 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3281 X_BINARY X_NOT_H_R ")",
3282 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3283 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3285 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3287 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3289 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3290 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3292 SLAP_SYNTAX_BER, berValidate, NULL},
3293 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3294 0, bitStringValidate, NULL },
3295 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3296 0, booleanValidate, NULL},
3297 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3298 X_BINARY X_NOT_H_R ")",
3299 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3300 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3301 X_BINARY X_NOT_H_R ")",
3302 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3303 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3304 X_BINARY X_NOT_H_R ")",
3305 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3306 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3307 0, countryStringValidate, NULL},
3308 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3309 0, dnValidate, dnPretty},
3310 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3311 0, rdnValidate, rdnPretty},
3312 #ifdef LDAP_COMP_MATCH
3313 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3314 0, allComponentsValidate, NULL},
3315 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3316 0, componentFilterValidate, NULL},
3318 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3320 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3321 0, deliveryMethodValidate, NULL},
3322 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3323 0, UTF8StringValidate, NULL},
3324 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3326 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3328 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3330 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3332 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3334 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3335 0, printablesStringValidate, NULL},
3336 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3337 SLAP_SYNTAX_BLOB, NULL, NULL},
3338 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3339 0, generalizedTimeValidate, NULL},
3340 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3342 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3343 0, IA5StringValidate, NULL},
3344 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3345 0, integerValidate, NULL},
3346 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3347 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3350 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3352 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3354 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3356 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3358 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3359 0, nameUIDValidate, nameUIDPretty },
3360 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3362 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3363 0, numericStringValidate, NULL},
3364 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3366 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3367 0, numericoidValidate, NULL},
3368 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3369 0, IA5StringValidate, NULL},
3370 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3371 0, blobValidate, NULL},
3372 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3373 0, UTF8StringValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3376 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3378 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3379 0, printableStringValidate, NULL},
3380 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3381 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3382 0, subtreeSpecificationValidate, NULL},
3383 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3384 X_BINARY X_NOT_H_R ")",
3385 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3386 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3387 0, printableStringValidate, NULL},
3388 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3390 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3391 0, printablesStringValidate, NULL},
3392 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3393 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3394 0, utcTimeValidate, NULL},
3396 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3398 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3402 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3404 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3407 /* RFC 2307 NIS Syntaxes */
3408 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3409 0, nisNetgroupTripleValidate, NULL},
3410 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3411 0, bootParameterValidate, NULL},
3413 /* From PKIX *//* This OID is not published yet. */
3414 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3416 serialNumberAndIssuerValidate,
3417 serialNumberAndIssuerPretty},
3419 #ifdef SLAPD_ACI_ENABLED
3420 /* OpenLDAP Experimental Syntaxes */
3421 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3423 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3427 #ifdef SLAPD_AUTHPASSWD
3428 /* needs updating */
3429 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3430 SLAP_SYNTAX_HIDE, NULL, NULL},
3433 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3434 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3436 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3437 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3439 /* OpenLDAP Void Syntax */
3440 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3441 SLAP_SYNTAX_HIDE, inValidate, NULL},
3442 {NULL, 0, NULL, NULL}
3445 char *certificateExactMatchSyntaxes[] = {
3446 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3449 #ifdef LDAP_COMP_MATCH
3450 char *componentFilterMatchSyntaxes[] = {
3451 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3455 char *directoryStringSyntaxes[] = {
3456 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3459 char *integerFirstComponentMatchSyntaxes[] = {
3460 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3461 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3464 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3465 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3466 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3467 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3468 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3469 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3470 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3471 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3472 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3477 * Other matching rules in X.520 that we do not use (yet):
3479 * 2.5.13.25 uTCTimeMatch
3480 * 2.5.13.26 uTCTimeOrderingMatch
3481 * 2.5.13.31* directoryStringFirstComponentMatch
3482 * 2.5.13.32* wordMatch
3483 * 2.5.13.33* keywordMatch
3484 * 2.5.13.36 certificatePairExactMatch
3485 * 2.5.13.37 certificatePairMatch
3486 * 2.5.13.38 certificateListExactMatch
3487 * 2.5.13.39 certificateListMatch
3488 * 2.5.13.40 algorithmIdentifierMatch
3489 * 2.5.13.41* storedPrefixMatch
3490 * 2.5.13.42 attributeCertificateMatch
3491 * 2.5.13.43 readerAndKeyIDMatch
3492 * 2.5.13.44 attributeIntegrityMatch
3494 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3496 static slap_mrule_defs_rec mrule_defs[] = {
3498 * EQUALITY matching rules must be listed after associated APPROX
3499 * matching rules. So, we list all APPROX matching rules first.
3501 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3503 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3504 NULL, NULL, directoryStringApproxMatch,
3505 directoryStringApproxIndexer, directoryStringApproxFilter,
3508 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3510 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3511 NULL, NULL, IA5StringApproxMatch,
3512 IA5StringApproxIndexer, IA5StringApproxFilter,
3516 * Other matching rules
3519 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3521 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3522 NULL, NULL, octetStringMatch,
3523 octetStringIndexer, octetStringFilter,
3526 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3527 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3528 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3529 NULL, dnNormalize, dnMatch,
3530 octetStringIndexer, octetStringFilter,
3533 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3535 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3536 NULL, dnNormalize, dnRelativeMatch,
3540 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3541 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3542 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3543 NULL, dnNormalize, dnRelativeMatch,
3547 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
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.11 NAME 'dnSuperiorMatch' "
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.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3562 "SYNTAX 1.2.36.79672281.1.5.0 )",
3563 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3564 NULL, rdnNormalize, rdnMatch,
3565 octetStringIndexer, octetStringFilter,
3568 #ifdef LDAP_COMP_MATCH
3569 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3570 "SYNTAX 1.2.36.79672281.1.5.2 )",
3571 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3572 NULL, NULL , componentFilterMatch,
3573 octetStringIndexer, octetStringFilter,
3576 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3577 "SYNTAX 1.2.36.79672281.1.5.3 )",
3578 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3579 NULL, NULL , allComponentsMatch,
3580 octetStringIndexer, octetStringFilter,
3583 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3584 "SYNTAX 1.2.36.79672281.1.5.3 )",
3585 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3586 NULL, NULL , directoryComponentsMatch,
3587 octetStringIndexer, octetStringFilter,
3591 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3593 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3594 NULL, UTF8StringNormalize, octetStringMatch,
3595 octetStringIndexer, octetStringFilter,
3596 directoryStringApproxMatchOID },
3598 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3600 SLAP_MR_ORDERING, directoryStringSyntaxes,
3601 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3603 "caseIgnoreMatch" },
3605 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3607 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3608 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3609 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3610 "caseIgnoreMatch" },
3612 {"( 2.5.13.5 NAME 'caseExactMatch' "
3613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3614 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3615 NULL, UTF8StringNormalize, octetStringMatch,
3616 octetStringIndexer, octetStringFilter,
3617 directoryStringApproxMatchOID },
3619 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3621 SLAP_MR_ORDERING, directoryStringSyntaxes,
3622 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3626 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3628 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3629 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3630 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3633 {"( 2.5.13.8 NAME 'numericStringMatch' "
3634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3635 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3636 NULL, numericStringNormalize, octetStringMatch,
3637 octetStringIndexer, octetStringFilter,
3640 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3642 SLAP_MR_ORDERING, NULL,
3643 NULL, numericStringNormalize, octetStringOrderingMatch,
3645 "numericStringMatch" },
3647 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3649 SLAP_MR_SUBSTR, NULL,
3650 NULL, numericStringNormalize, octetStringSubstringsMatch,
3651 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3652 "numericStringMatch" },
3654 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3656 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3657 NULL, NULL, NULL, NULL, NULL, NULL },
3659 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3660 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3661 SLAP_MR_SUBSTR, NULL,
3662 NULL, NULL, NULL, NULL, NULL,
3663 "caseIgnoreListMatch" },
3665 {"( 2.5.13.13 NAME 'booleanMatch' "
3666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3667 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3668 NULL, NULL, booleanMatch,
3669 octetStringIndexer, octetStringFilter,
3672 {"( 2.5.13.14 NAME 'integerMatch' "
3673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3674 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3675 NULL, NULL, integerMatch,
3676 octetStringIndexer, octetStringFilter,
3679 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3680 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3681 SLAP_MR_ORDERING, NULL,
3682 NULL, NULL, integerMatch,
3686 {"( 2.5.13.16 NAME 'bitStringMatch' "
3687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3688 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3689 NULL, NULL, octetStringMatch,
3690 octetStringIndexer, octetStringFilter,
3693 {"( 2.5.13.17 NAME 'octetStringMatch' "
3694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3695 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3696 NULL, NULL, octetStringMatch,
3697 octetStringIndexer, octetStringFilter,
3700 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3702 SLAP_MR_ORDERING, NULL,
3703 NULL, NULL, octetStringOrderingMatch,
3705 "octetStringMatch" },
3707 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3709 SLAP_MR_SUBSTR, NULL,
3710 NULL, NULL, octetStringSubstringsMatch,
3711 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3712 "octetStringMatch" },
3714 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3716 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3718 telephoneNumberNormalize, octetStringMatch,
3719 octetStringIndexer, octetStringFilter,
3722 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3724 SLAP_MR_SUBSTR, NULL,
3725 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3726 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3727 "telephoneNumberMatch" },
3729 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3730 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3731 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3732 NULL, NULL, NULL, NULL, NULL, NULL },
3734 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3735 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3736 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3737 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3738 uniqueMemberIndexer, uniqueMemberFilter,
3741 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3742 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3743 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3744 NULL, NULL, NULL, NULL, NULL, NULL },
3746 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3747 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3748 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3749 NULL, generalizedTimeNormalize, octetStringMatch,
3750 generalizedTimeIndexer, generalizedTimeFilter,
3753 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3755 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3756 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3758 "generalizedTimeMatch" },
3760 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3762 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3763 integerFirstComponentMatchSyntaxes,
3764 NULL, firstComponentNormalize, integerMatch,
3765 octetStringIndexer, octetStringFilter,
3768 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3769 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3770 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3771 objectIdentifierFirstComponentMatchSyntaxes,
3772 NULL, firstComponentNormalize, octetStringMatch,
3773 octetStringIndexer, octetStringFilter,
3776 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3777 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3778 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3780 NULL, certificateExactNormalize, octetStringMatch,
3781 octetStringIndexer, octetStringFilter,
3783 NULL, NULL, NULL, NULL, NULL,
3787 {"( 2.5.13.35 NAME 'certificateMatch' "
3788 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3789 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3791 NULL, NULL, octetStringMatch,
3792 octetStringIndexer, octetStringFilter,
3794 NULL, NULL, NULL, NULL, NULL,
3798 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3799 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3800 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3801 NULL, IA5StringNormalize, octetStringMatch,
3802 octetStringIndexer, octetStringFilter,
3803 IA5StringApproxMatchOID },
3805 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3806 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3807 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3808 NULL, IA5StringNormalize, octetStringMatch,
3809 octetStringIndexer, octetStringFilter,
3810 IA5StringApproxMatchOID },
3812 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3813 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3814 SLAP_MR_SUBSTR, NULL,
3815 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3816 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3817 "caseIgnoreIA5Match" },
3819 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3821 SLAP_MR_SUBSTR, NULL,
3822 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3823 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3824 "caseExactIA5Match" },
3826 #ifdef SLAPD_AUTHPASSWD
3827 /* needs updating */
3828 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3830 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3831 NULL, NULL, authPasswordMatch,
3836 #ifdef SLAPD_ACI_ENABLED
3837 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3838 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3839 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3840 NULL, NULL, OpenLDAPaciMatch,
3845 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3848 NULL, NULL, integerBitAndMatch,
3852 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3853 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3855 NULL, NULL, integerBitOrMatch,
3859 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3860 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3861 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3862 NULL, UUIDNormalize, octetStringMatch,
3863 octetStringIndexer, octetStringFilter,
3866 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3867 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3868 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3869 NULL, UUIDNormalize, octetStringOrderingMatch,
3870 octetStringIndexer, octetStringFilter,
3873 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3874 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3875 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3876 NULL, NULL, csnMatch,
3877 csnIndexer, csnFilter,
3880 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3881 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3882 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3883 NULL, NULL, csnOrderingMatch,
3887 {NULL, SLAP_MR_NONE, NULL,
3888 NULL, NULL, NULL, NULL, NULL,
3893 slap_schema_init( void )
3898 /* we should only be called once (from main) */
3899 assert( schema_init_done == 0 );
3901 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3902 res = register_syntax( &syntax_defs[i] );
3905 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3906 syntax_defs[i].sd_desc );
3911 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3912 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3913 mrule_defs[i].mrd_compat_syntaxes == NULL )
3916 "slap_schema_init: Ignoring unusable matching rule %s\n",
3917 mrule_defs[i].mrd_desc );
3921 res = register_matching_rule( &mrule_defs[i] );
3925 "slap_schema_init: Error registering matching rule %s\n",
3926 mrule_defs[i].mrd_desc );
3931 res = slap_schema_load();
3932 schema_init_done = 1;
3937 schema_destroy( void )