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 octetStringMatch
55 /* approx matching rules */
56 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
57 #define directoryStringApproxMatch approxMatch
58 #define directoryStringApproxIndexer approxIndexer
59 #define directoryStringApproxFilter approxFilter
60 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
61 #define IA5StringApproxMatch approxMatch
62 #define IA5StringApproxIndexer approxIndexer
63 #define IA5StringApproxFilter approxFilter
65 /* Change Sequence Number (CSN) - much of this will change */
66 #define csnValidate blobValidate
67 #define csnMatch octetStringMatch
68 #define csnOrderingMatch octetStringOrderingMatch
69 #define csnIndexer generalizedTimeIndexer
70 #define csnFilter generalizedTimeFilter
72 #ifdef SLAP_AUTHZ_SYNTAX
73 /* FIXME: temporary */
74 #define authzMatch octetStringMatch
75 #endif /* SLAP_AUTHZ_SYNTAX */
77 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
78 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
79 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
80 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
82 ldap_pvt_thread_mutex_t ad_undef_mutex;
83 ldap_pvt_thread_mutex_t oc_undef_mutex;
90 /* no value allowed */
91 return LDAP_INVALID_SYNTAX;
99 /* any value allowed */
103 #define berValidate blobValidate
110 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
111 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
118 static int certificateValidate( Syntax *syntax, struct berval *in )
121 unsigned char *p = (unsigned char *)in->bv_val;
123 xcert = d2i_X509(NULL, &p, in->bv_len);
124 if ( !xcert ) return LDAP_INVALID_SYNTAX;
129 #define certificateValidate sequenceValidate
138 struct berval *value,
139 void *assertedValue )
141 struct berval *asserted = (struct berval *) assertedValue;
142 int match = value->bv_len - asserted->bv_len;
145 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
153 octetStringOrderingMatch(
158 struct berval *value,
159 void *assertedValue )
161 struct berval *asserted = (struct berval *) assertedValue;
162 ber_len_t v_len = value->bv_len;
163 ber_len_t av_len = asserted->bv_len;
165 int match = memcmp( value->bv_val, asserted->bv_val,
166 (v_len < av_len ? v_len : av_len) );
168 if( match == 0 ) match = v_len - av_len;
176 HASH_CONTEXT *HASHcontext,
177 unsigned char *HASHdigest,
178 struct berval *prefix,
182 unsigned char *value,
185 HASH_Init(HASHcontext);
186 if(prefix && prefix->bv_len > 0) {
187 HASH_Update(HASHcontext,
188 (unsigned char *)prefix->bv_val, prefix->bv_len);
190 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
191 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
192 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
193 HASH_Update(HASHcontext, value, value_len);
194 HASH_Final(HASHdigest, HASHcontext);
198 /* Index generation function */
199 int octetStringIndexer(
204 struct berval *prefix,
212 HASH_CONTEXT HASHcontext;
213 unsigned char HASHdigest[HASH_BYTES];
214 struct berval digest;
215 digest.bv_val = (char *)HASHdigest;
216 digest.bv_len = sizeof(HASHdigest);
218 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
219 /* just count them */
222 /* we should have at least one value at this point */
225 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
227 slen = syntax->ssyn_oidlen;
228 mlen = mr->smr_oidlen;
230 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
231 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
232 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
233 ber_dupbv_x( &keys[i], &digest, ctx );
236 BER_BVZERO( &keys[i] );
243 /* Index generation function */
244 int octetStringFilter(
249 struct berval *prefix,
250 void * assertedValue,
256 HASH_CONTEXT HASHcontext;
257 unsigned char HASHdigest[HASH_BYTES];
258 struct berval *value = (struct berval *) assertedValue;
259 struct berval digest;
260 digest.bv_val = (char *)HASHdigest;
261 digest.bv_len = sizeof(HASHdigest);
263 slen = syntax->ssyn_oidlen;
264 mlen = mr->smr_oidlen;
266 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
268 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
269 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
271 ber_dupbv_x( keys, &digest, ctx );
272 BER_BVZERO( &keys[1] );
280 octetStringSubstringsMatch(
285 struct berval *value,
286 void *assertedValue )
289 SubstringsAssertion *sub = assertedValue;
290 struct berval left = *value;
294 /* Add up asserted input length */
295 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
296 inlen += sub->sa_initial.bv_len;
299 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
300 inlen += sub->sa_any[i].bv_len;
303 if ( !BER_BVISNULL( &sub->sa_final ) ) {
304 inlen += sub->sa_final.bv_len;
307 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
308 if ( inlen > left.bv_len ) {
313 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
314 sub->sa_initial.bv_len );
320 left.bv_val += sub->sa_initial.bv_len;
321 left.bv_len -= sub->sa_initial.bv_len;
322 inlen -= sub->sa_initial.bv_len;
325 if ( !BER_BVISNULL( &sub->sa_final ) ) {
326 if ( inlen > left.bv_len ) {
331 match = memcmp( sub->sa_final.bv_val,
332 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
333 sub->sa_final.bv_len );
339 left.bv_len -= sub->sa_final.bv_len;
340 inlen -= sub->sa_final.bv_len;
344 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
349 if ( inlen > left.bv_len ) {
350 /* not enough length */
355 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
359 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
366 idx = p - left.bv_val;
368 if ( idx >= left.bv_len ) {
369 /* this shouldn't happen */
376 if ( sub->sa_any[i].bv_len > left.bv_len ) {
377 /* not enough left */
382 match = memcmp( left.bv_val,
383 sub->sa_any[i].bv_val,
384 sub->sa_any[i].bv_len );
392 left.bv_val += sub->sa_any[i].bv_len;
393 left.bv_len -= sub->sa_any[i].bv_len;
394 inlen -= sub->sa_any[i].bv_len;
403 /* Substrings Index generation function */
405 octetStringSubstringsIndexer(
410 struct berval *prefix,
419 HASH_CONTEXT HASHcontext;
420 unsigned char HASHdigest[HASH_BYTES];
421 struct berval digest;
422 digest.bv_val = (char *)HASHdigest;
423 digest.bv_len = sizeof(HASHdigest);
427 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
428 /* count number of indices to generate */
429 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
430 if( values[i].bv_len >= index_substr_if_maxlen ) {
431 nkeys += index_substr_if_maxlen -
432 (index_substr_if_minlen - 1);
433 } else if( values[i].bv_len >= index_substr_if_minlen ) {
434 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
438 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
439 if( values[i].bv_len >= index_substr_any_len ) {
440 nkeys += values[i].bv_len - (index_substr_any_len - 1);
444 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
445 if( values[i].bv_len >= index_substr_if_maxlen ) {
446 nkeys += index_substr_if_maxlen -
447 (index_substr_if_minlen - 1);
448 } else if( values[i].bv_len >= index_substr_if_minlen ) {
449 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
455 /* no keys to generate */
460 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
462 slen = syntax->ssyn_oidlen;
463 mlen = mr->smr_oidlen;
466 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
469 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
470 ( values[i].bv_len >= index_substr_any_len ) )
472 char pre = SLAP_INDEX_SUBSTR_PREFIX;
473 max = values[i].bv_len - (index_substr_any_len - 1);
475 for( j=0; j<max; j++ ) {
476 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
477 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
478 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
482 /* skip if too short */
483 if( values[i].bv_len < index_substr_if_minlen ) continue;
485 max = index_substr_if_maxlen < values[i].bv_len
486 ? index_substr_if_maxlen : values[i].bv_len;
488 for( j=index_substr_if_minlen; j<=max; j++ ) {
491 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
492 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
493 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
494 syntax, mr, (unsigned char *)values[i].bv_val, j );
495 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
498 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
499 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
500 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
501 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
502 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
509 BER_BVZERO( &keys[nkeys] );
520 octetStringSubstringsFilter (
525 struct berval *prefix,
526 void * assertedValue,
530 SubstringsAssertion *sa;
533 size_t slen, mlen, klen;
535 HASH_CONTEXT HASHcontext;
536 unsigned char HASHdigest[HASH_BYTES];
537 struct berval *value;
538 struct berval digest;
540 sa = (SubstringsAssertion *) assertedValue;
542 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
543 !BER_BVISNULL( &sa->sa_initial ) &&
544 sa->sa_initial.bv_len >= index_substr_if_minlen )
547 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
548 ( flags & SLAP_INDEX_SUBSTR_ANY ))
550 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
554 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
556 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
557 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
558 /* don't bother accounting with stepping */
559 nkeys += sa->sa_any[i].bv_len -
560 ( index_substr_any_len - 1 );
565 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
566 !BER_BVISNULL( &sa->sa_final ) &&
567 sa->sa_final.bv_len >= index_substr_if_minlen )
570 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
571 ( flags & SLAP_INDEX_SUBSTR_ANY ))
573 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
582 digest.bv_val = (char *)HASHdigest;
583 digest.bv_len = sizeof(HASHdigest);
585 slen = syntax->ssyn_oidlen;
586 mlen = mr->smr_oidlen;
588 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
591 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
592 !BER_BVISNULL( &sa->sa_initial ) &&
593 sa->sa_initial.bv_len >= index_substr_if_minlen )
595 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
596 value = &sa->sa_initial;
598 klen = index_substr_if_maxlen < value->bv_len
599 ? index_substr_if_maxlen : value->bv_len;
601 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
602 syntax, mr, (unsigned char *)value->bv_val, klen );
603 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
605 /* If initial is too long and we have subany indexed, use it
606 * to match the excess...
608 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
611 pre = SLAP_INDEX_SUBSTR_PREFIX;
612 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
614 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
615 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
616 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
621 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
623 pre = SLAP_INDEX_SUBSTR_PREFIX;
624 klen = index_substr_any_len;
626 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
627 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
631 value = &sa->sa_any[i];
634 j <= value->bv_len - index_substr_any_len;
635 j += index_substr_any_step )
637 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
638 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
639 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
644 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
645 !BER_BVISNULL( &sa->sa_final ) &&
646 sa->sa_final.bv_len >= index_substr_if_minlen )
648 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
649 value = &sa->sa_final;
651 klen = index_substr_if_maxlen < value->bv_len
652 ? index_substr_if_maxlen : value->bv_len;
654 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
655 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
656 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 /* If final is too long and we have subany indexed, use it
659 * to match the excess...
661 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
664 pre = SLAP_INDEX_SUBSTR_PREFIX;
665 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
667 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
668 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
669 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
675 BER_BVZERO( &keys[nkeys] );
692 /* very unforgiving validation, requires no normalization
693 * before simplistic matching
695 if( in->bv_len < 3 ) {
696 return LDAP_INVALID_SYNTAX;
700 * RFC 2252 section 6.3 Bit String
701 * bitstring = "'" *binary-digit "'B"
702 * binary-digit = "0" / "1"
703 * example: '0101111101'B
706 if( in->bv_val[0] != '\'' ||
707 in->bv_val[in->bv_len - 2] != '\'' ||
708 in->bv_val[in->bv_len - 1] != 'B' )
710 return LDAP_INVALID_SYNTAX;
713 for( i = in->bv_len - 3; i > 0; i-- ) {
714 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
715 return LDAP_INVALID_SYNTAX;
723 * Syntax is [RFC2252]:
728 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
730 Values in this syntax are encoded according to the following BNF:
732 bitstring = "'" *binary-digit "'B"
734 binary-digit = "0" / "1"
738 6.21. Name And Optional UID
740 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
742 Values in this syntax are encoded according to the following BNF:
744 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
746 Although the '#' character may occur in a string representation of a
747 distinguished name, no additional special quoting is done. This
748 syntax has been added subsequent to RFC 1778.
752 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
755 * draft-ietf-ldapbis-syntaxes-xx.txt says:
760 A value of the Bit String syntax is a sequence of binary digits. The
761 LDAP-specific encoding of a value of this syntax is defined by the
764 BitString = SQUOTE *binary-digit SQUOTE "B"
766 binary-digit = "0" / "1"
768 The <SQUOTE> rule is defined in [MODELS].
773 The LDAP definition for the Bit String syntax is:
775 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
777 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
781 3.3.21. Name and Optional UID
783 A value of the Name and Optional UID syntax is the distinguished name
784 [MODELS] of an entity optionally accompanied by a unique identifier
785 that serves to differentiate the entity from others with an identical
788 The LDAP-specific encoding of a value of this syntax is defined by
791 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
793 The <BitString> rule is defined in Section 3.3.2. The
794 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
797 Note that although the '#' character may occur in the string
798 representation of a distinguished name, no additional escaping of
799 this character is performed when a <distinguishedName> is encoded in
800 a <NameAndOptionalUID>.
803 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
805 The LDAP definition for the Name and Optional UID syntax is:
807 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
809 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
813 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
816 1.4. Common ABNF Productions
819 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
821 SQUOTE = %x27 ; single quote ("'")
825 * Note: normalization strips any leading "0"s, unless the
826 * bit string is exactly "'0'B", so the normalized example,
827 * in slapd, would result in
829 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
831 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
832 * i.e. "#", doesn't have to be escaped except when at the
833 * beginning of a value, the definition of Name and Optional
834 * UID appears to be flawed, because there is no clear means
835 * to determine whether the UID part is present or not.
839 * cn=Someone,dc=example,dc=com#'1'B
841 * could be either a NameAndOptionalUID with trailing UID, i.e.
843 * DN = "cn=Someone,dc=example,dc=com"
846 * or a NameAndOptionalUID with no trailing UID, and the AVA
847 * in the last RDN made of
850 * attributeValue = com#'1'B
852 * in fact "com#'1'B" is a valid IA5 string.
854 * As a consequence, current slapd code assumes that the
855 * presence of portions of a BitString at the end of the string
856 * representation of a NameAndOptionalUID means a BitString
857 * is expected, and cause an error otherwise. This is quite
858 * arbitrary, and might change in the future.
868 struct berval dn, uid;
870 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
872 ber_dupbv( &dn, in );
873 if( !dn.bv_val ) return LDAP_OTHER;
875 /* if there's a "#", try bitStringValidate()... */
876 uid.bv_val = strrchr( dn.bv_val, '#' );
877 if ( !BER_BVISNULL( &uid ) ) {
879 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
881 rc = bitStringValidate( NULL, &uid );
882 if ( rc == LDAP_SUCCESS ) {
883 /* in case of success, trim the UID,
884 * otherwise treat it as part of the DN */
885 dn.bv_len -= uid.bv_len + 1;
886 uid.bv_val[-1] = '\0';
890 rc = dnValidate( NULL, &dn );
892 ber_memfree( dn.bv_val );
903 assert( val != NULL );
904 assert( out != NULL );
907 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
909 if( BER_BVISEMPTY( val ) ) {
910 ber_dupbv_x( out, val, ctx );
912 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
913 return LDAP_INVALID_SYNTAX;
917 struct berval dnval = *val;
918 struct berval uidval = BER_BVNULL;
920 uidval.bv_val = strrchr( val->bv_val, '#' );
921 if ( !BER_BVISNULL( &uidval ) ) {
923 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
925 rc = bitStringValidate( NULL, &uidval );
927 if ( rc == LDAP_SUCCESS ) {
928 ber_dupbv_x( &dnval, val, ctx );
929 dnval.bv_len -= uidval.bv_len + 1;
930 dnval.bv_val[dnval.bv_len] = '\0';
933 BER_BVZERO( &uidval );
937 rc = dnPretty( syntax, &dnval, out, ctx );
938 if ( dnval.bv_val != val->bv_val ) {
939 slap_sl_free( dnval.bv_val, ctx );
941 if( rc != LDAP_SUCCESS ) {
945 if( !BER_BVISNULL( &uidval ) ) {
949 tmp = slap_sl_realloc( out->bv_val, out->bv_len
950 + STRLENOF( "#" ) + uidval.bv_len + 1,
953 ber_memfree_x( out->bv_val, ctx );
957 out->bv_val[out->bv_len++] = '#';
958 out->bv_val[out->bv_len++] = '\'';
960 got1 = uidval.bv_len < sizeof("'0'B");
961 for( i = 1; i < uidval.bv_len - 2; i++ ) {
962 c = uidval.bv_val[i];
965 if( got1 ) out->bv_val[out->bv_len++] = c;
969 out->bv_val[out->bv_len++] = c;
974 out->bv_val[out->bv_len++] = '\'';
975 out->bv_val[out->bv_len++] = 'B';
976 out->bv_val[out->bv_len] = '\0';
980 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
986 uniqueMemberNormalize(
991 struct berval *normalized,
997 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
999 ber_dupbv_x( &out, val, ctx );
1000 if ( BER_BVISEMPTY( &out ) ) {
1004 struct berval uid = BER_BVNULL;
1006 uid.bv_val = strrchr( out.bv_val, '#' );
1007 if ( !BER_BVISNULL( &uid ) ) {
1009 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1011 rc = bitStringValidate( NULL, &uid );
1012 if ( rc == LDAP_SUCCESS ) {
1013 uid.bv_val[-1] = '\0';
1014 out.bv_len -= uid.bv_len + 1;
1020 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1022 if( rc != LDAP_SUCCESS ) {
1023 slap_sl_free( out.bv_val, ctx );
1024 return LDAP_INVALID_SYNTAX;
1027 if( !BER_BVISNULL( &uid ) ) {
1030 tmp = ch_realloc( normalized->bv_val,
1031 normalized->bv_len + uid.bv_len
1032 + STRLENOF("#") + 1 );
1033 if ( tmp == NULL ) {
1034 ber_memfree_x( normalized->bv_val, ctx );
1038 normalized->bv_val = tmp;
1040 /* insert the separator */
1041 normalized->bv_val[normalized->bv_len++] = '#';
1043 /* append the UID */
1044 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1045 uid.bv_val, uid.bv_len );
1046 normalized->bv_len += uid.bv_len;
1049 normalized->bv_val[normalized->bv_len] = '\0';
1052 slap_sl_free( out.bv_val, ctx );
1055 return LDAP_SUCCESS;
1064 struct berval *value,
1065 void *assertedValue )
1068 struct berval *asserted = (struct berval *) assertedValue;
1069 struct berval assertedDN = *asserted;
1070 struct berval assertedUID = BER_BVNULL;
1071 struct berval valueDN = BER_BVNULL;
1072 struct berval valueUID = BER_BVNULL;
1073 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1075 if ( !BER_BVISEMPTY( asserted ) ) {
1076 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1077 if ( !BER_BVISNULL( &assertedUID ) ) {
1078 assertedUID.bv_val++;
1079 assertedUID.bv_len = assertedDN.bv_len
1080 - ( assertedUID.bv_val - assertedDN.bv_val );
1082 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1083 assertedDN.bv_len -= assertedUID.bv_len + 1;
1086 BER_BVZERO( &assertedUID );
1091 if ( !BER_BVISEMPTY( value ) ) {
1094 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1095 if ( !BER_BVISNULL( &valueUID ) ) {
1097 valueUID.bv_len = valueDN.bv_len
1098 - ( valueUID.bv_val - valueDN.bv_val );
1100 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1101 valueDN.bv_len -= valueUID.bv_len + 1;
1104 BER_BVZERO( &valueUID );
1109 if( valueUID.bv_len && assertedUID.bv_len ) {
1110 match = valueUID.bv_len - assertedUID.bv_len;
1113 return LDAP_SUCCESS;
1116 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1119 return LDAP_SUCCESS;
1122 } else if ( !approx && valueUID.bv_len ) {
1125 return LDAP_SUCCESS;
1127 } else if ( !approx && assertedUID.bv_len ) {
1130 return LDAP_SUCCESS;
1133 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1137 uniqueMemberIndexer(
1142 struct berval *prefix,
1150 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1151 /* just count them */
1155 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1157 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1158 struct berval assertedDN = values[i];
1159 struct berval assertedUID = BER_BVNULL;
1161 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1162 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1163 if ( !BER_BVISNULL( &assertedUID ) ) {
1164 assertedUID.bv_val++;
1165 assertedUID.bv_len = assertedDN.bv_len
1166 - ( assertedUID.bv_val - assertedDN.bv_val );
1168 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1169 assertedDN.bv_len -= assertedUID.bv_len + 1;
1172 BER_BVZERO( &assertedUID );
1177 dnvalues[i] = assertedDN;
1179 BER_BVZERO( &dnvalues[i] );
1181 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1182 dnvalues, keysp, ctx );
1184 slap_sl_free( dnvalues, ctx );
1194 struct berval *prefix,
1195 void * assertedValue,
1199 struct berval *asserted = (struct berval *) assertedValue;
1200 struct berval assertedDN = *asserted;
1201 struct berval assertedUID = BER_BVNULL;
1203 if ( !BER_BVISEMPTY( asserted ) ) {
1204 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1205 if ( !BER_BVISNULL( &assertedUID ) ) {
1206 assertedUID.bv_val++;
1207 assertedUID.bv_len = assertedDN.bv_len
1208 - ( assertedUID.bv_val - assertedDN.bv_val );
1210 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1211 assertedDN.bv_len -= assertedUID.bv_len + 1;
1214 BER_BVZERO( &assertedUID );
1219 return octetStringFilter( use, flags, syntax, mr, prefix,
1220 &assertedDN, keysp, ctx );
1225 * Handling boolean syntax and matching is quite rigid.
1226 * A more flexible approach would be to allow a variety
1227 * of strings to be normalized and prettied into TRUE
1235 /* very unforgiving validation, requires no normalization
1236 * before simplistic matching
1239 if( in->bv_len == 4 ) {
1240 if( bvmatch( in, &slap_true_bv ) ) {
1241 return LDAP_SUCCESS;
1243 } else if( in->bv_len == 5 ) {
1244 if( bvmatch( in, &slap_false_bv ) ) {
1245 return LDAP_SUCCESS;
1249 return LDAP_INVALID_SYNTAX;
1258 struct berval *value,
1259 void *assertedValue )
1261 /* simplistic matching allowed by rigid validation */
1262 struct berval *asserted = (struct berval *) assertedValue;
1263 *matchp = value->bv_len != asserted->bv_len;
1264 return LDAP_SUCCESS;
1267 /*-------------------------------------------------------------------
1268 LDAP/X.500 string syntax / matching rules have a few oddities. This
1269 comment attempts to detail how slapd(8) treats them.
1272 StringSyntax X.500 LDAP Matching/Comments
1273 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1274 PrintableString subset subset i/e + ignore insignificant spaces
1275 PrintableString subset subset i/e + ignore insignificant spaces
1276 NumericString subset subset ignore all spaces
1277 IA5String ASCII ASCII i/e + ignore insignificant spaces
1278 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1280 TelephoneNumber subset subset i + ignore all spaces and "-"
1282 See draft-ietf-ldapbis-strpro for details (once published).
1286 In X.500(93), a directory string can be either a PrintableString,
1287 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1288 In later versions, more CHOICEs were added. In all cases the string
1291 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1292 A directory string cannot be zero length.
1294 For matching, there are both case ignore and exact rules. Both
1295 also require that "insignificant" spaces be ignored.
1296 spaces before the first non-space are ignored;
1297 spaces after the last non-space are ignored;
1298 spaces after a space are ignored.
1299 Note: by these rules (and as clarified in X.520), a string of only
1300 spaces is to be treated as if held one space, not empty (which
1301 would be a syntax error).
1304 In ASN.1, numeric string is just a string of digits and spaces
1305 and could be empty. However, in X.500, all attribute values of
1306 numeric string carry a non-empty constraint. For example:
1308 internationalISDNNumber ATTRIBUTE ::= {
1309 WITH SYNTAX InternationalISDNNumber
1310 EQUALITY MATCHING RULE numericStringMatch
1311 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1312 ID id-at-internationalISDNNumber }
1313 InternationalISDNNumber ::=
1314 NumericString (SIZE(1..ub-international-isdn-number))
1316 Unforunately, some assertion values are don't carry the same
1317 constraint (but its unclear how such an assertion could ever
1318 be true). In LDAP, there is one syntax (numericString) not two
1319 (numericString with constraint, numericString without constraint).
1320 This should be treated as numericString with non-empty constraint.
1321 Note that while someone may have no ISDN number, there are no ISDN
1322 numbers which are zero length.
1324 In matching, spaces are ignored.
1327 In ASN.1, Printable string is just a string of printable characters
1328 and can be empty. In X.500, semantics much like NumericString (see
1329 serialNumber for a like example) excepting uses insignificant space
1330 handling instead of ignore all spaces.
1333 Basically same as PrintableString. There are no examples in X.500,
1334 but same logic applies. So we require them to be non-empty as
1337 -------------------------------------------------------------------*/
1346 unsigned char *u = (unsigned char *)in->bv_val;
1348 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1349 /* directory strings cannot be empty */
1350 return LDAP_INVALID_SYNTAX;
1353 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1354 /* get the length indicated by the first byte */
1355 len = LDAP_UTF8_CHARLEN2( u, len );
1357 /* very basic checks */
1360 if( (u[5] & 0xC0) != 0x80 ) {
1361 return LDAP_INVALID_SYNTAX;
1364 if( (u[4] & 0xC0) != 0x80 ) {
1365 return LDAP_INVALID_SYNTAX;
1368 if( (u[3] & 0xC0) != 0x80 ) {
1369 return LDAP_INVALID_SYNTAX;
1372 if( (u[2] & 0xC0 )!= 0x80 ) {
1373 return LDAP_INVALID_SYNTAX;
1376 if( (u[1] & 0xC0) != 0x80 ) {
1377 return LDAP_INVALID_SYNTAX;
1380 /* CHARLEN already validated it */
1383 return LDAP_INVALID_SYNTAX;
1386 /* make sure len corresponds with the offset
1387 to the next character */
1388 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1392 return LDAP_INVALID_SYNTAX;
1395 return LDAP_SUCCESS;
1399 UTF8StringNormalize(
1404 struct berval *normalized,
1407 struct berval tmp, nvalue;
1411 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1413 if( BER_BVISNULL( val ) ) {
1414 /* assume we're dealing with a syntax (e.g., UTF8String)
1415 * which allows empty strings
1417 BER_BVZERO( normalized );
1418 return LDAP_SUCCESS;
1421 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1422 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1423 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1424 ? LDAP_UTF8_APPROX : 0;
1426 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1431 /* collapse spaces (in place) */
1433 nvalue.bv_val = tmp.bv_val;
1435 /* trim leading spaces? */
1436 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1437 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1439 for( i = 0; i < tmp.bv_len; i++) {
1440 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1441 if( wasspace++ == 0 ) {
1442 /* trim repeated spaces */
1443 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1447 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1451 if( !BER_BVISEMPTY( &nvalue ) ) {
1452 /* trim trailing space? */
1454 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1455 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1459 nvalue.bv_val[nvalue.bv_len] = '\0';
1462 /* string of all spaces is treated as one space */
1463 nvalue.bv_val[0] = ' ';
1464 nvalue.bv_val[1] = '\0';
1468 *normalized = nvalue;
1469 return LDAP_SUCCESS;
1473 directoryStringSubstringsMatch(
1478 struct berval *value,
1479 void *assertedValue )
1482 SubstringsAssertion *sub = assertedValue;
1483 struct berval left = *value;
1487 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1488 if ( sub->sa_initial.bv_len > left.bv_len ) {
1489 /* not enough left */
1494 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1495 sub->sa_initial.bv_len );
1501 left.bv_val += sub->sa_initial.bv_len;
1502 left.bv_len -= sub->sa_initial.bv_len;
1504 priorspace = ASCII_SPACE(
1505 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1508 if ( sub->sa_any ) {
1509 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1513 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1514 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1516 /* allow next space to match */
1523 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1527 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1528 /* not enough left */
1533 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1540 idx = p - left.bv_val;
1542 if ( idx >= left.bv_len ) {
1543 /* this shouldn't happen */
1550 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1551 /* not enough left */
1556 match = memcmp( left.bv_val,
1557 sub->sa_any[i].bv_val,
1558 sub->sa_any[i].bv_len );
1566 left.bv_val += sub->sa_any[i].bv_len;
1567 left.bv_len -= sub->sa_any[i].bv_len;
1569 priorspace = ASCII_SPACE(
1570 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1574 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1575 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1576 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1578 /* allow next space to match */
1583 if ( sub->sa_final.bv_len > left.bv_len ) {
1584 /* not enough left */
1589 match = memcmp( sub->sa_final.bv_val,
1590 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1591 sub->sa_final.bv_len );
1600 return LDAP_SUCCESS;
1603 #if defined(SLAPD_APPROX_INITIALS)
1604 # define SLAPD_APPROX_DELIMITER "._ "
1605 # define SLAPD_APPROX_WORDLEN 2
1607 # define SLAPD_APPROX_DELIMITER " "
1608 # define SLAPD_APPROX_WORDLEN 1
1617 struct berval *value,
1618 void *assertedValue )
1620 struct berval *nval, *assertv;
1621 char *val, **values, **words, *c;
1622 int i, count, len, nextchunk=0, nextavail=0;
1624 /* Yes, this is necessary */
1625 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1626 if( nval == NULL ) {
1628 return LDAP_SUCCESS;
1631 /* Yes, this is necessary */
1632 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1633 NULL, LDAP_UTF8_APPROX, NULL );
1634 if( assertv == NULL ) {
1637 return LDAP_SUCCESS;
1640 /* Isolate how many words there are */
1641 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1642 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1643 if ( c == NULL ) break;
1648 /* Get a phonetic copy of each word */
1649 words = (char **)ch_malloc( count * sizeof(char *) );
1650 values = (char **)ch_malloc( count * sizeof(char *) );
1651 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1653 values[i] = phonetic(c);
1656 /* Work through the asserted value's words, to see if at least some
1657 of the words are there, in the same order. */
1659 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1660 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1665 #if defined(SLAPD_APPROX_INITIALS)
1666 else if( len == 1 ) {
1667 /* Single letter words need to at least match one word's initial */
1668 for( i=nextavail; i<count; i++ )
1669 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1676 /* Isolate the next word in the asserted value and phonetic it */
1677 assertv->bv_val[nextchunk+len] = '\0';
1678 val = phonetic( assertv->bv_val + nextchunk );
1680 /* See if this phonetic chunk is in the remaining words of *value */
1681 for( i=nextavail; i<count; i++ ){
1682 if( !strcmp( val, values[i] ) ){
1690 /* This chunk in the asserted value was NOT within the *value. */
1696 /* Go on to the next word in the asserted value */
1700 /* If some of the words were seen, call it a match */
1701 if( nextavail > 0 ) {
1708 /* Cleanup allocs */
1709 ber_bvfree( assertv );
1710 for( i=0; i<count; i++ ) {
1711 ch_free( values[i] );
1717 return LDAP_SUCCESS;
1726 struct berval *prefix,
1732 int i,j, len, wordcount, keycount=0;
1733 struct berval *newkeys;
1734 BerVarray keys=NULL;
1736 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1737 struct berval val = BER_BVNULL;
1738 /* Yes, this is necessary */
1739 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1740 assert( !BER_BVISNULL( &val ) );
1742 /* Isolate how many words there are. There will be a key for each */
1743 for( wordcount = 0, c = val.bv_val; *c; c++) {
1744 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1745 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1747 if (*c == '\0') break;
1751 /* Allocate/increase storage to account for new keys */
1752 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1753 * sizeof(struct berval) );
1754 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1755 if( keys ) ch_free( keys );
1758 /* Get a phonetic copy of each word */
1759 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1761 if( len < SLAPD_APPROX_WORDLEN ) continue;
1762 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1767 ber_memfree( val.bv_val );
1769 BER_BVZERO( &keys[keycount] );
1772 return LDAP_SUCCESS;
1781 struct berval *prefix,
1782 void * assertedValue,
1791 /* Yes, this is necessary */
1792 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1793 NULL, LDAP_UTF8_APPROX, NULL );
1794 if( val == NULL || BER_BVISNULL( val ) ) {
1795 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1796 BER_BVZERO( &keys[0] );
1799 return LDAP_SUCCESS;
1802 /* Isolate how many words there are. There will be a key for each */
1803 for( count = 0,c = val->bv_val; *c; c++) {
1804 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1805 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1807 if (*c == '\0') break;
1811 /* Allocate storage for new keys */
1812 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1814 /* Get a phonetic copy of each word */
1815 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1817 if( len < SLAPD_APPROX_WORDLEN ) continue;
1818 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1824 BER_BVZERO( &keys[count] );
1827 return LDAP_SUCCESS;
1830 /* Remove all spaces and '-' characters */
1832 telephoneNumberNormalize(
1837 struct berval *normalized,
1842 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1844 /* validator should have refused an empty string */
1845 assert( !BER_BVISEMPTY( val ) );
1847 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1849 for( p = val->bv_val; *p; p++ ) {
1850 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1856 normalized->bv_len = q - normalized->bv_val;
1858 if( BER_BVISEMPTY( normalized ) ) {
1859 slap_sl_free( normalized->bv_val, ctx );
1860 BER_BVZERO( normalized );
1861 return LDAP_INVALID_SYNTAX;
1864 return LDAP_SUCCESS;
1872 struct berval val = *in;
1874 if( BER_BVISEMPTY( &val ) ) {
1875 /* disallow empty strings */
1876 return LDAP_INVALID_SYNTAX;
1879 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1880 if ( val.bv_len == 1 ) {
1881 return LDAP_SUCCESS;
1884 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1891 while ( OID_LEADCHAR( val.bv_val[0] )) {
1895 if ( val.bv_len == 0 ) {
1896 return LDAP_SUCCESS;
1900 if( !OID_SEPARATOR( val.bv_val[0] )) {
1908 return LDAP_INVALID_SYNTAX;
1917 struct berval val = *in;
1919 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1921 if ( val.bv_val[0] == '-' ) {
1925 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1926 return LDAP_INVALID_SYNTAX;
1929 if( val.bv_val[0] == '0' ) { /* "-0" */
1930 return LDAP_INVALID_SYNTAX;
1933 } else if ( val.bv_val[0] == '0' ) {
1934 if( val.bv_len > 1 ) { /* "0<more>" */
1935 return LDAP_INVALID_SYNTAX;
1938 return LDAP_SUCCESS;
1941 for( i=0; i < val.bv_len; i++ ) {
1942 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1943 return LDAP_INVALID_SYNTAX;
1947 return LDAP_SUCCESS;
1956 struct berval *value,
1957 void *assertedValue )
1959 struct berval *asserted = (struct berval *) assertedValue;
1960 int vsign = 1, asign = 1; /* default sign = '+' */
1965 if( v.bv_val[0] == '-' ) {
1971 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1974 if( a.bv_val[0] == '-' ) {
1980 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1982 match = vsign - asign;
1984 match = ( v.bv_len != a.bv_len
1985 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1986 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1987 if( vsign < 0 ) match = -match;
1991 return LDAP_SUCCESS;
1995 countryStringValidate(
1997 struct berval *val )
1999 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2001 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2002 return LDAP_INVALID_SYNTAX;
2004 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2005 return LDAP_INVALID_SYNTAX;
2008 return LDAP_SUCCESS;
2012 printableStringValidate(
2014 struct berval *val )
2018 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2020 for(i=0; i < val->bv_len; i++) {
2021 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2022 return LDAP_INVALID_SYNTAX;
2026 return LDAP_SUCCESS;
2030 printablesStringValidate(
2032 struct berval *val )
2036 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2038 for(i=0,len=0; i < val->bv_len; i++) {
2039 int c = val->bv_val[i];
2043 return LDAP_INVALID_SYNTAX;
2047 } else if ( SLAP_PRINTABLE(c) ) {
2050 return LDAP_INVALID_SYNTAX;
2055 return LDAP_INVALID_SYNTAX;
2058 return LDAP_SUCCESS;
2064 struct berval *val )
2068 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2070 for(i=0; i < val->bv_len; i++) {
2071 if( !LDAP_ASCII(val->bv_val[i]) ) {
2072 return LDAP_INVALID_SYNTAX;
2076 return LDAP_SUCCESS;
2085 struct berval *normalized,
2089 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2091 assert( !BER_BVISEMPTY( val ) );
2093 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2097 /* Ignore initial whitespace */
2098 while ( ASCII_SPACE( *p ) ) p++;
2100 normalized->bv_val = ber_strdup_x( p, ctx );
2101 p = q = normalized->bv_val;
2104 if ( ASCII_SPACE( *p ) ) {
2107 /* Ignore the extra whitespace */
2108 while ( ASCII_SPACE( *p ) ) {
2112 } else if ( casefold ) {
2113 /* Most IA5 rules require casefolding */
2114 *q++ = TOLOWER(*p); p++;
2121 assert( normalized->bv_val <= p );
2125 * If the string ended in space, backup the pointer one
2126 * position. One is enough because the above loop collapsed
2127 * all whitespace to a single space.
2129 if ( ASCII_SPACE( q[-1] ) ) --q;
2131 /* null terminate */
2134 normalized->bv_len = q - normalized->bv_val;
2135 if( BER_BVISEMPTY( normalized ) ) {
2136 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2137 normalized->bv_val[0] = ' ';
2138 normalized->bv_val[1] = '\0';
2139 normalized->bv_len = 1;
2142 return LDAP_SUCCESS;
2151 if( in->bv_len != 36 ) {
2152 return LDAP_INVALID_SYNTAX;
2155 for( i=0; i<36; i++ ) {
2161 if( in->bv_val[i] != '-' ) {
2162 return LDAP_INVALID_SYNTAX;
2166 if( !ASCII_HEX( in->bv_val[i]) ) {
2167 return LDAP_INVALID_SYNTAX;
2172 return LDAP_SUCCESS;
2181 struct berval *normalized,
2184 unsigned char octet = '\0';
2187 normalized->bv_len = 16;
2188 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2190 for( i=0, j=0; i<36; i++ ) {
2191 unsigned char nibble;
2192 if( val->bv_val[i] == '-' ) {
2195 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2196 nibble = val->bv_val[i] - '0';
2198 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2199 nibble = val->bv_val[i] - ('a'-10);
2201 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2202 nibble = val->bv_val[i] - ('A'-10);
2205 slap_sl_free( normalized->bv_val, ctx );
2206 return LDAP_INVALID_SYNTAX;
2211 normalized->bv_val[j>>1] = octet;
2213 octet = nibble << 4;
2218 normalized->bv_val[normalized->bv_len] = 0;
2219 return LDAP_SUCCESS;
2225 numericStringValidate(
2231 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2233 for(i=0; i < in->bv_len; i++) {
2234 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2235 return LDAP_INVALID_SYNTAX;
2239 return LDAP_SUCCESS;
2243 numericStringNormalize(
2248 struct berval *normalized,
2251 /* removal all spaces */
2254 assert( !BER_BVISEMPTY( val ) );
2256 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2259 q = normalized->bv_val;
2262 if ( ASCII_SPACE( *p ) ) {
2263 /* Ignore whitespace */
2270 /* we should have copied no more then is in val */
2271 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2273 /* null terminate */
2276 normalized->bv_len = q - normalized->bv_val;
2278 if( BER_BVISEMPTY( normalized ) ) {
2279 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2280 normalized->bv_val[0] = ' ';
2281 normalized->bv_val[1] = '\0';
2282 normalized->bv_len = 1;
2285 return LDAP_SUCCESS;
2289 * Integer conversion macros that will use the largest available
2292 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2293 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2294 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2295 # define SLAP_LONG_MAX LLONG_MAX
2296 # define SLAP_LONG_MIN LLONG_MIN
2297 # define SLAP_LONG long long
2299 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2300 # define SLAP_LONG_MAX LONG_MAX
2301 # define SLAP_LONG_MIN LONG_MIN
2302 # define SLAP_LONG long
2303 #endif /* HAVE_STRTOLL ... */
2311 struct berval *value,
2312 void *assertedValue )
2314 SLAP_LONG lValue, lAssertedValue;
2316 /* safe to assume integers are NUL terminated? */
2317 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2318 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2321 return LDAP_CONSTRAINT_VIOLATION;
2324 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2326 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2329 return LDAP_CONSTRAINT_VIOLATION;
2332 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2333 return LDAP_SUCCESS;
2342 struct berval *value,
2343 void *assertedValue )
2345 SLAP_LONG lValue, lAssertedValue;
2347 /* safe to assume integers are NUL terminated? */
2348 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2349 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2352 return LDAP_CONSTRAINT_VIOLATION;
2355 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2357 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2360 return LDAP_CONSTRAINT_VIOLATION;
2363 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2364 return LDAP_SUCCESS;
2368 serialNumberAndIssuerValidate(
2374 struct berval sn, i;
2375 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2377 i.bv_val = strchr( in->bv_val, '$' );
2378 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2380 sn.bv_val = in->bv_val;
2381 sn.bv_len = i.bv_val - in->bv_val;
2384 i.bv_len = in->bv_len - (sn.bv_len + 1);
2386 /* validate serial number (strict for now) */
2387 for( n=0; n < sn.bv_len; n++ ) {
2388 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2392 rc = dnValidate( NULL, &i );
2393 if( rc ) return LDAP_INVALID_SYNTAX;
2395 return LDAP_SUCCESS;
2399 serialNumberAndIssuerPretty(
2407 struct berval sn, i, newi;
2409 assert( val != NULL );
2410 assert( out != NULL );
2412 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2413 val->bv_val, 0, 0 );
2415 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2417 i.bv_val = strchr( val->bv_val, '$' );
2418 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2420 sn.bv_val = val->bv_val;
2421 sn.bv_len = i.bv_val - val->bv_val;
2424 i.bv_len = val->bv_len - (sn.bv_len + 1);
2426 /* eat leading zeros */
2427 for( n=0; n < (sn.bv_len-1); n++ ) {
2428 if( sn.bv_val[n] != '0' ) break;
2433 for( n=0; n < sn.bv_len; n++ ) {
2434 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2438 rc = dnPretty( syntax, &i, &newi, ctx );
2439 if( rc ) return LDAP_INVALID_SYNTAX;
2441 /* make room from sn + "$" */
2442 out->bv_len = sn.bv_len + newi.bv_len + 1;
2443 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2445 if( out->bv_val == NULL ) {
2447 slap_sl_free( newi.bv_val, ctx );
2451 /* push issuer over */
2452 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2453 /* insert sn and "$" */
2454 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2455 out->bv_val[sn.bv_len] = '$';
2457 out->bv_val[out->bv_len] = '\0';
2459 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2460 out->bv_val, 0, 0 );
2462 return LDAP_SUCCESS;
2466 * This routine is called by certificateExactNormalize when
2467 * certificateExactNormalize receives a search string instead of
2468 * a certificate. This routine checks if the search value is valid
2469 * and then returns the normalized value
2472 serialNumberAndIssuerNormalize(
2482 struct berval sn, i, newi;
2484 assert( val != NULL );
2485 assert( out != NULL );
2487 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2488 val->bv_val, 0, 0 );
2490 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2492 i.bv_val = strchr( val->bv_val, '$' );
2493 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2495 sn.bv_val = val->bv_val;
2496 sn.bv_len = i.bv_val - val->bv_val;
2499 i.bv_len = val->bv_len - (sn.bv_len + 1);
2501 /* eat leading zeros */
2502 for( n=0; n < (sn.bv_len-1); n++ ) {
2503 if( sn.bv_val[n] != '0' ) break;
2508 for( n=0; n < sn.bv_len; n++ ) {
2509 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2510 return LDAP_INVALID_SYNTAX;
2515 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2516 if( rc ) return LDAP_INVALID_SYNTAX;
2518 /* make room from sn + "$" */
2519 out->bv_len = sn.bv_len + newi.bv_len + 1;
2520 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2522 if( out->bv_val == NULL ) {
2524 slap_sl_free( newi.bv_val, ctx );
2528 /* push issuer over */
2529 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2530 /* insert sn and "$" */
2531 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2532 out->bv_val[sn.bv_len] = '$';
2534 out->bv_val[out->bv_len] = '\0';
2536 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2537 out->bv_val, 0, 0 );
2544 certificateExactNormalize(
2549 struct berval *normalized,
2552 int rc = LDAP_INVALID_SYNTAX;
2554 char *serial = NULL;
2555 ber_len_t seriallen;
2556 struct berval issuer_dn = BER_BVNULL;
2557 X509_NAME *name = NULL;
2558 ASN1_INTEGER *sn = NULL;
2561 if( BER_BVISEMPTY( val ) ) goto done;
2563 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2564 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2567 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2569 p = (unsigned char *)val->bv_val;
2570 xcert = d2i_X509( NULL, &p, val->bv_len);
2571 if( xcert == NULL ) goto done;
2573 sn=X509_get_serialNumber(xcert);
2574 if ( sn == NULL ) goto done;
2575 serial=i2s_ASN1_INTEGER(0, sn );
2576 if( serial == NULL ) goto done;
2577 seriallen=strlen(serial);
2579 name=X509_get_issuer_name(xcert);
2580 if( name == NULL ) goto done;
2581 rc = dnX509normalize( name, &issuer_dn );
2582 if( rc != LDAP_SUCCESS ) goto done;
2584 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2585 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2586 p = (unsigned char *)normalized->bv_val;
2587 AC_MEMCPY(p, serial, seriallen);
2590 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2591 p += issuer_dn.bv_len;
2594 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2595 normalized->bv_val, NULL, NULL );
2598 if (xcert) X509_free(xcert);
2599 if (serial) ch_free(serial);
2600 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2604 #endif /* HAVE_TLS */
2607 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2608 /* slight optimization - does not need the start parameter */
2609 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2614 check_time_syntax (struct berval *val,
2617 struct berval *fraction)
2620 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2621 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2622 * GeneralizedTime supports leap seconds, UTCTime does not.
2624 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2625 static const int mdays[2][12] = {
2626 /* non-leap years */
2627 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2629 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2632 int part, c, c1, c2, tzoffset, leapyear = 0;
2635 e = p + val->bv_len;
2637 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2638 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2640 for (part = start; part < 7 && p < e; part++) {
2642 if (!ASCII_DIGIT(c1)) {
2647 return LDAP_INVALID_SYNTAX;
2650 if (!ASCII_DIGIT(c)) {
2651 return LDAP_INVALID_SYNTAX;
2653 c += c1 * 10 - '0' * 11;
2654 if ((part | 1) == 3) {
2657 return LDAP_INVALID_SYNTAX;
2660 if (c >= ceiling[part]) {
2661 if (! (c == 60 && part == 6 && start == 0))
2662 return LDAP_INVALID_SYNTAX;
2666 if (part < 5 + start) {
2667 return LDAP_INVALID_SYNTAX;
2669 for (; part < 9; part++) {
2673 /* leapyear check for the Gregorian calendar (year>1581) */
2674 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2678 if (parts[3] >= mdays[leapyear][parts[2]]) {
2679 return LDAP_INVALID_SYNTAX;
2683 fraction->bv_val = p;
2684 fraction->bv_len = 0;
2685 if (p < e && (*p == '.' || *p == ',')) {
2687 while (++p < e && ASCII_DIGIT(*p)) {
2690 if (p - fraction->bv_val == 1) {
2691 return LDAP_INVALID_SYNTAX;
2693 for (end_num = p; end_num[-1] == '0'; --end_num) {
2696 c = end_num - fraction->bv_val;
2697 if (c != 1) fraction->bv_len = c;
2703 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2709 return LDAP_INVALID_SYNTAX;
2715 for (part = 7; part < 9 && p < e; part++) {
2717 if (!ASCII_DIGIT(c1)) {
2722 return LDAP_INVALID_SYNTAX;
2725 if (!ASCII_DIGIT(c2)) {
2726 return LDAP_INVALID_SYNTAX;
2728 parts[part] = c1 * 10 + c2 - '0' * 11;
2729 if (parts[part] >= ceiling[part]) {
2730 return LDAP_INVALID_SYNTAX;
2733 if (part < 8 + start) {
2734 return LDAP_INVALID_SYNTAX;
2737 if (tzoffset == '-') {
2738 /* negative offset to UTC, ie west of Greenwich */
2739 parts[4] += parts[7];
2740 parts[5] += parts[8];
2741 /* offset is just hhmm, no seconds */
2742 for (part = 6; --part >= 0; ) {
2746 c = mdays[leapyear][parts[2]];
2748 if (parts[part] >= c) {
2750 return LDAP_INVALID_SYNTAX;
2755 } else if (part != 5) {
2760 /* positive offset to UTC, ie east of Greenwich */
2761 parts[4] -= parts[7];
2762 parts[5] -= parts[8];
2763 for (part = 6; --part >= 0; ) {
2764 if (parts[part] < 0) {
2766 return LDAP_INVALID_SYNTAX;
2771 /* make first arg to % non-negative */
2772 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2777 } else if (part != 5) {
2784 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2787 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2794 struct berval *normalized )
2798 rc = check_time_syntax(val, 1, parts, NULL);
2799 if (rc != LDAP_SUCCESS) {
2803 normalized->bv_val = ch_malloc( 14 );
2804 if ( normalized->bv_val == NULL ) {
2805 return LBER_ERROR_MEMORY;
2808 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2809 parts[1], parts[2] + 1, parts[3] + 1,
2810 parts[4], parts[5], parts[6] );
2811 normalized->bv_len = 13;
2813 return LDAP_SUCCESS;
2823 return check_time_syntax(in, 1, parts, NULL);
2826 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2829 generalizedTimeValidate(
2834 struct berval fraction;
2835 return check_time_syntax(in, 0, parts, &fraction);
2839 generalizedTimeNormalize(
2844 struct berval *normalized,
2849 struct berval fraction;
2851 rc = check_time_syntax(val, 0, parts, &fraction);
2852 if (rc != LDAP_SUCCESS) {
2856 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2857 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2858 if ( BER_BVISNULL( normalized ) ) {
2859 return LBER_ERROR_MEMORY;
2862 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2863 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2864 parts[4], parts[5], parts[6] );
2865 if ( !BER_BVISEMPTY( &fraction ) ) {
2866 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2867 fraction.bv_val, fraction.bv_len );
2868 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2870 strcpy( normalized->bv_val + len-1, "Z" );
2871 normalized->bv_len = len;
2873 return LDAP_SUCCESS;
2877 generalizedTimeOrderingMatch(
2882 struct berval *value,
2883 void *assertedValue )
2885 struct berval *asserted = (struct berval *) assertedValue;
2886 ber_len_t v_len = value->bv_len;
2887 ber_len_t av_len = asserted->bv_len;
2889 /* ignore trailing 'Z' when comparing */
2890 int match = memcmp( value->bv_val, asserted->bv_val,
2891 (v_len < av_len ? v_len : av_len) - 1 );
2892 if ( match == 0 ) match = v_len - av_len;
2895 return LDAP_SUCCESS;
2898 /* Index generation function */
2899 int generalizedTimeIndexer(
2904 struct berval *prefix,
2912 BerValue bvtmp; /* 40 bit index */
2914 struct lutil_timet tt;
2916 bvtmp.bv_len = sizeof(tmp);
2918 for( i=0; values[i].bv_val != NULL; i++ ) {
2919 /* just count them */
2922 /* we should have at least one value at this point */
2925 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2927 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2928 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2929 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2930 /* Use 40 bits of time for key */
2931 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2932 lutil_tm2time( &tm, &tt );
2933 tmp[0] = tt.tt_gsec & 0xff;
2934 tmp[4] = tt.tt_sec & 0xff;
2936 tmp[3] = tt.tt_sec & 0xff;
2938 tmp[2] = tt.tt_sec & 0xff;
2940 tmp[1] = tt.tt_sec & 0xff;
2942 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2946 keys[j].bv_val = NULL;
2951 return LDAP_SUCCESS;
2954 /* Index generation function */
2955 int generalizedTimeFilter(
2960 struct berval *prefix,
2961 void * assertedValue,
2967 BerValue bvtmp; /* 40 bit index */
2968 BerValue *value = (BerValue *) assertedValue;
2970 struct lutil_timet tt;
2972 bvtmp.bv_len = sizeof(tmp);
2974 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2975 /* Use 40 bits of time for key */
2976 if ( value->bv_val && value->bv_len >= 10 &&
2977 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2979 lutil_tm2time( &tm, &tt );
2980 tmp[0] = tt.tt_gsec & 0xff;
2981 tmp[4] = tt.tt_sec & 0xff;
2983 tmp[3] = tt.tt_sec & 0xff;
2985 tmp[2] = tt.tt_sec & 0xff;
2987 tmp[1] = tt.tt_sec & 0xff;
2989 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2990 ber_dupbv_x(keys, &bvtmp, ctx );
2991 keys[1].bv_val = NULL;
2999 return LDAP_SUCCESS;
3003 deliveryMethodValidate(
3005 struct berval *val )
3008 #define LENOF(s) (sizeof(s)-1)
3009 struct berval tmp = *val;
3011 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3012 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3013 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3016 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3018 switch( tmp.bv_val[0] ) {
3021 if(( tmp.bv_len >= LENOF("any") ) &&
3022 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3024 tmp.bv_len -= LENOF("any");
3025 tmp.bv_val += LENOF("any");
3028 return LDAP_INVALID_SYNTAX;
3032 if(( tmp.bv_len >= LENOF("mhs") ) &&
3033 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3035 tmp.bv_len -= LENOF("mhs");
3036 tmp.bv_val += LENOF("mhs");
3039 return LDAP_INVALID_SYNTAX;
3043 if(( tmp.bv_len >= LENOF("physical") ) &&
3044 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3046 tmp.bv_len -= LENOF("physical");
3047 tmp.bv_val += LENOF("physical");
3050 return LDAP_INVALID_SYNTAX;
3053 case 'T': /* telex or teletex or telephone */
3054 if(( tmp.bv_len >= LENOF("telex") ) &&
3055 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3057 tmp.bv_len -= LENOF("telex");
3058 tmp.bv_val += LENOF("telex");
3061 if(( tmp.bv_len >= LENOF("teletex") ) &&
3062 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3064 tmp.bv_len -= LENOF("teletex");
3065 tmp.bv_val += LENOF("teletex");
3068 if(( tmp.bv_len >= LENOF("telephone") ) &&
3069 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3071 tmp.bv_len -= LENOF("telephone");
3072 tmp.bv_val += LENOF("telephone");
3075 return LDAP_INVALID_SYNTAX;
3078 case 'G': /* g3fax or g4fax */
3079 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3080 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3081 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3083 tmp.bv_len -= LENOF("g3fax");
3084 tmp.bv_val += LENOF("g3fax");
3087 return LDAP_INVALID_SYNTAX;
3091 if(( tmp.bv_len >= LENOF("ia5") ) &&
3092 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3094 tmp.bv_len -= LENOF("ia5");
3095 tmp.bv_val += LENOF("ia5");
3098 return LDAP_INVALID_SYNTAX;
3102 if(( tmp.bv_len >= LENOF("videotex") ) &&
3103 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3105 tmp.bv_len -= LENOF("videotex");
3106 tmp.bv_val += LENOF("videotex");
3109 return LDAP_INVALID_SYNTAX;
3112 return LDAP_INVALID_SYNTAX;
3115 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3117 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3121 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3125 return LDAP_INVALID_SYNTAX;
3127 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3136 nisNetgroupTripleValidate(
3138 struct berval *val )
3143 if ( BER_BVISEMPTY( val ) ) {
3144 return LDAP_INVALID_SYNTAX;
3147 p = (char *)val->bv_val;
3148 e = p + val->bv_len;
3150 if ( *p != '(' /*')'*/ ) {
3151 return LDAP_INVALID_SYNTAX;
3154 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3158 return LDAP_INVALID_SYNTAX;
3161 } else if ( !AD_CHAR( *p ) ) {
3162 return LDAP_INVALID_SYNTAX;
3166 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3167 return LDAP_INVALID_SYNTAX;
3173 return LDAP_INVALID_SYNTAX;
3176 return LDAP_SUCCESS;
3180 bootParameterValidate(
3182 struct berval *val )
3186 if ( BER_BVISEMPTY( val ) ) {
3187 return LDAP_INVALID_SYNTAX;
3190 p = (char *)val->bv_val;
3191 e = p + val->bv_len;
3194 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3195 if ( !AD_CHAR( *p ) ) {
3196 return LDAP_INVALID_SYNTAX;
3201 return LDAP_INVALID_SYNTAX;
3205 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3206 if ( !AD_CHAR( *p ) ) {
3207 return LDAP_INVALID_SYNTAX;
3212 return LDAP_INVALID_SYNTAX;
3216 for ( p++; p < e; p++ ) {
3217 if ( !SLAP_PRINTABLE( *p ) ) {
3218 return LDAP_INVALID_SYNTAX;
3222 return LDAP_SUCCESS;
3226 firstComponentNormalize(
3231 struct berval *normalized,
3238 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3239 ber_dupbv_x( normalized, val, ctx );
3240 return LDAP_SUCCESS;
3243 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3245 if( val->bv_val[0] != '(' /*')'*/ &&
3246 val->bv_val[0] != '{' /*'}'*/ )
3248 return LDAP_INVALID_SYNTAX;
3251 /* trim leading white space */
3253 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3259 /* grab next word */
3260 comp.bv_val = &val->bv_val[len];
3261 len = val->bv_len - len;
3262 for( comp.bv_len = 0;
3263 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3269 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3270 rc = numericoidValidate( NULL, &comp );
3271 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3272 rc = integerValidate( NULL, &comp );
3274 rc = LDAP_INVALID_SYNTAX;
3278 if( rc == LDAP_SUCCESS ) {
3279 ber_dupbv_x( normalized, &comp, ctx );
3286 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3287 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3289 static slap_syntax_defs_rec syntax_defs[] = {
3290 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3291 X_BINARY X_NOT_H_R ")",
3292 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3293 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3295 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3297 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3299 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3300 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3302 SLAP_SYNTAX_BER, berValidate, NULL},
3303 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3304 0, bitStringValidate, NULL },
3305 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3306 0, booleanValidate, NULL},
3307 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3308 X_BINARY X_NOT_H_R ")",
3309 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3310 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3311 X_BINARY X_NOT_H_R ")",
3312 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3313 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3314 X_BINARY X_NOT_H_R ")",
3315 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3316 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3317 0, countryStringValidate, NULL},
3318 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3319 0, dnValidate, dnPretty},
3320 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3321 0, rdnValidate, rdnPretty},
3322 #ifdef LDAP_COMP_MATCH
3323 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3324 0, allComponentsValidate, NULL},
3325 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3326 0, componentFilterValidate, NULL},
3328 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3330 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3331 0, deliveryMethodValidate, NULL},
3332 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3333 0, UTF8StringValidate, NULL},
3334 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3336 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3338 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3340 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3342 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3344 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3345 0, printablesStringValidate, NULL},
3346 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3347 SLAP_SYNTAX_BLOB, NULL, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3349 0, generalizedTimeValidate, NULL},
3350 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3352 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3353 0, IA5StringValidate, NULL},
3354 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3355 0, integerValidate, NULL},
3356 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3357 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3358 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3360 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3362 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3364 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3366 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3368 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3369 0, nameUIDValidate, nameUIDPretty },
3370 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3372 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3373 0, numericStringValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3376 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3377 0, numericoidValidate, NULL},
3378 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3379 0, IA5StringValidate, NULL},
3380 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3381 0, blobValidate, NULL},
3382 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3383 0, UTF8StringValidate, NULL},
3384 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3386 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3388 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3389 0, printableStringValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3391 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3392 0, subtreeSpecificationValidate, NULL},
3393 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3394 X_BINARY X_NOT_H_R ")",
3395 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3396 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3397 0, printableStringValidate, NULL},
3398 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3401 0, printablesStringValidate, NULL},
3402 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3403 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3404 0, utcTimeValidate, NULL},
3406 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3408 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3410 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3412 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3414 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3417 /* RFC 2307 NIS Syntaxes */
3418 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3419 0, nisNetgroupTripleValidate, NULL},
3420 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3421 0, bootParameterValidate, NULL},
3423 /* From PKIX *//* This OID is not published yet. */
3424 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3426 serialNumberAndIssuerValidate,
3427 serialNumberAndIssuerPretty},
3429 #ifdef SLAPD_ACI_ENABLED
3430 /* OpenLDAP Experimental Syntaxes */
3431 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3433 OpenLDAPaciValidate,
3437 #ifdef SLAPD_AUTHPASSWD
3438 /* needs updating */
3439 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3440 SLAP_SYNTAX_HIDE, NULL, NULL},
3443 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3444 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3446 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3447 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3449 /* OpenLDAP Void Syntax */
3450 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3451 SLAP_SYNTAX_HIDE, inValidate, NULL},
3453 #ifdef SLAP_AUTHZ_SYNTAX
3454 /* FIXME: OID is unused, but not registered yet */
3455 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3456 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3457 #endif /* SLAP_AUTHZ_SYNTAX */
3459 {NULL, 0, NULL, NULL}
3462 char *certificateExactMatchSyntaxes[] = {
3463 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3466 #ifdef LDAP_COMP_MATCH
3467 char *componentFilterMatchSyntaxes[] = {
3468 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3472 char *directoryStringSyntaxes[] = {
3473 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3476 char *integerFirstComponentMatchSyntaxes[] = {
3477 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3478 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3481 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3482 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3483 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3484 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3485 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3486 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3487 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3488 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3489 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3494 * Other matching rules in X.520 that we do not use (yet):
3496 * 2.5.13.25 uTCTimeMatch
3497 * 2.5.13.26 uTCTimeOrderingMatch
3498 * 2.5.13.31* directoryStringFirstComponentMatch
3499 * 2.5.13.32* wordMatch
3500 * 2.5.13.33* keywordMatch
3501 * 2.5.13.36 certificatePairExactMatch
3502 * 2.5.13.37 certificatePairMatch
3503 * 2.5.13.38 certificateListExactMatch
3504 * 2.5.13.39 certificateListMatch
3505 * 2.5.13.40 algorithmIdentifierMatch
3506 * 2.5.13.41* storedPrefixMatch
3507 * 2.5.13.42 attributeCertificateMatch
3508 * 2.5.13.43 readerAndKeyIDMatch
3509 * 2.5.13.44 attributeIntegrityMatch
3511 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3513 static slap_mrule_defs_rec mrule_defs[] = {
3515 * EQUALITY matching rules must be listed after associated APPROX
3516 * matching rules. So, we list all APPROX matching rules first.
3518 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3520 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3521 NULL, NULL, directoryStringApproxMatch,
3522 directoryStringApproxIndexer, directoryStringApproxFilter,
3525 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3527 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3528 NULL, NULL, IA5StringApproxMatch,
3529 IA5StringApproxIndexer, IA5StringApproxFilter,
3533 * Other matching rules
3536 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3538 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3539 NULL, NULL, octetStringMatch,
3540 octetStringIndexer, octetStringFilter,
3543 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3545 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3546 NULL, dnNormalize, dnMatch,
3547 octetStringIndexer, octetStringFilter,
3550 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3552 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3553 NULL, dnNormalize, dnRelativeMatch,
3557 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3559 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3560 NULL, dnNormalize, dnRelativeMatch,
3564 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3566 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3567 NULL, dnNormalize, dnRelativeMatch,
3571 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3573 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3574 NULL, dnNormalize, dnRelativeMatch,
3578 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3579 "SYNTAX 1.2.36.79672281.1.5.0 )",
3580 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3581 NULL, rdnNormalize, rdnMatch,
3582 octetStringIndexer, octetStringFilter,
3585 #ifdef LDAP_COMP_MATCH
3586 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3587 "SYNTAX 1.2.36.79672281.1.5.2 )",
3588 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3589 NULL, NULL , componentFilterMatch,
3590 octetStringIndexer, octetStringFilter,
3593 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3594 "SYNTAX 1.2.36.79672281.1.5.3 )",
3595 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3596 NULL, NULL , allComponentsMatch,
3597 octetStringIndexer, octetStringFilter,
3600 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3601 "SYNTAX 1.2.36.79672281.1.5.3 )",
3602 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3603 NULL, NULL , directoryComponentsMatch,
3604 octetStringIndexer, octetStringFilter,
3608 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3610 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3611 NULL, UTF8StringNormalize, octetStringMatch,
3612 octetStringIndexer, octetStringFilter,
3613 directoryStringApproxMatchOID },
3615 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3617 SLAP_MR_ORDERING, directoryStringSyntaxes,
3618 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3620 "caseIgnoreMatch" },
3622 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3624 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3625 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3626 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3627 "caseIgnoreMatch" },
3629 {"( 2.5.13.5 NAME 'caseExactMatch' "
3630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3631 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3632 NULL, UTF8StringNormalize, octetStringMatch,
3633 octetStringIndexer, octetStringFilter,
3634 directoryStringApproxMatchOID },
3636 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3638 SLAP_MR_ORDERING, directoryStringSyntaxes,
3639 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3643 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3645 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3646 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3647 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3650 {"( 2.5.13.8 NAME 'numericStringMatch' "
3651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3652 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3653 NULL, numericStringNormalize, octetStringMatch,
3654 octetStringIndexer, octetStringFilter,
3657 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3659 SLAP_MR_ORDERING, NULL,
3660 NULL, numericStringNormalize, octetStringOrderingMatch,
3662 "numericStringMatch" },
3664 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3665 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3666 SLAP_MR_SUBSTR, NULL,
3667 NULL, numericStringNormalize, octetStringSubstringsMatch,
3668 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3669 "numericStringMatch" },
3671 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3673 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3674 NULL, NULL, NULL, NULL, NULL, NULL },
3676 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3678 SLAP_MR_SUBSTR, NULL,
3679 NULL, NULL, NULL, NULL, NULL,
3680 "caseIgnoreListMatch" },
3682 {"( 2.5.13.13 NAME 'booleanMatch' "
3683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3684 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3685 NULL, NULL, booleanMatch,
3686 octetStringIndexer, octetStringFilter,
3689 {"( 2.5.13.14 NAME 'integerMatch' "
3690 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3691 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3692 NULL, NULL, integerMatch,
3693 octetStringIndexer, octetStringFilter,
3696 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3697 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3698 SLAP_MR_ORDERING, NULL,
3699 NULL, NULL, integerMatch,
3703 {"( 2.5.13.16 NAME 'bitStringMatch' "
3704 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3705 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3706 NULL, NULL, octetStringMatch,
3707 octetStringIndexer, octetStringFilter,
3710 {"( 2.5.13.17 NAME 'octetStringMatch' "
3711 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3712 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3713 NULL, NULL, octetStringMatch,
3714 octetStringIndexer, octetStringFilter,
3717 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3718 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3719 SLAP_MR_ORDERING, NULL,
3720 NULL, NULL, octetStringOrderingMatch,
3722 "octetStringMatch" },
3724 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3725 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3726 SLAP_MR_SUBSTR, NULL,
3727 NULL, NULL, octetStringSubstringsMatch,
3728 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3729 "octetStringMatch" },
3731 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3732 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3733 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3735 telephoneNumberNormalize, octetStringMatch,
3736 octetStringIndexer, octetStringFilter,
3739 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3740 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3741 SLAP_MR_SUBSTR, NULL,
3742 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3743 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3744 "telephoneNumberMatch" },
3746 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3747 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3748 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3749 NULL, NULL, NULL, NULL, NULL, NULL },
3751 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3752 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3753 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3754 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3755 uniqueMemberIndexer, uniqueMemberFilter,
3758 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3760 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3761 NULL, NULL, NULL, NULL, NULL, NULL },
3763 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3764 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3765 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3766 NULL, generalizedTimeNormalize, octetStringMatch,
3767 generalizedTimeIndexer, generalizedTimeFilter,
3770 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3772 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3773 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3775 "generalizedTimeMatch" },
3777 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3778 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3779 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3780 integerFirstComponentMatchSyntaxes,
3781 NULL, firstComponentNormalize, integerMatch,
3782 octetStringIndexer, octetStringFilter,
3785 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3786 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3787 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3788 objectIdentifierFirstComponentMatchSyntaxes,
3789 NULL, firstComponentNormalize, octetStringMatch,
3790 octetStringIndexer, octetStringFilter,
3793 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3794 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3795 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3797 NULL, certificateExactNormalize, octetStringMatch,
3798 octetStringIndexer, octetStringFilter,
3800 NULL, NULL, NULL, NULL, NULL,
3804 {"( 2.5.13.35 NAME 'certificateMatch' "
3805 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3806 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3808 NULL, NULL, octetStringMatch,
3809 octetStringIndexer, octetStringFilter,
3811 NULL, NULL, NULL, NULL, NULL,
3815 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3816 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3817 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3818 NULL, IA5StringNormalize, octetStringMatch,
3819 octetStringIndexer, octetStringFilter,
3820 IA5StringApproxMatchOID },
3822 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3823 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3824 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3825 NULL, IA5StringNormalize, octetStringMatch,
3826 octetStringIndexer, octetStringFilter,
3827 IA5StringApproxMatchOID },
3829 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3830 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3831 SLAP_MR_SUBSTR, NULL,
3832 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3833 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3834 "caseIgnoreIA5Match" },
3836 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3838 SLAP_MR_SUBSTR, NULL,
3839 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3840 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3841 "caseExactIA5Match" },
3843 #ifdef SLAPD_AUTHPASSWD
3844 /* needs updating */
3845 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3847 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3848 NULL, NULL, authPasswordMatch,
3853 #ifdef SLAPD_ACI_ENABLED
3854 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3855 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3856 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3857 NULL, OpenLDAPaciNormalize, OpenLDAPaciMatch,
3862 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3865 NULL, NULL, integerBitAndMatch,
3869 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3872 NULL, NULL, integerBitOrMatch,
3876 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3877 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3878 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3879 NULL, UUIDNormalize, octetStringMatch,
3880 octetStringIndexer, octetStringFilter,
3883 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3884 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3885 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3886 NULL, UUIDNormalize, octetStringOrderingMatch,
3887 octetStringIndexer, octetStringFilter,
3890 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3891 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3892 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3893 NULL, NULL, csnMatch,
3894 csnIndexer, csnFilter,
3897 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3898 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3899 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3900 NULL, NULL, csnOrderingMatch,
3904 #ifdef SLAP_AUTHZ_SYNTAX
3905 /* FIXME: OID is unused, but not registered yet */
3906 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3907 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3908 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3909 NULL, authzNormalize, authzMatch,
3912 #endif /* SLAP_AUTHZ_SYNTAX */
3914 {NULL, SLAP_MR_NONE, NULL,
3915 NULL, NULL, NULL, NULL, NULL,
3920 slap_schema_init( void )
3925 /* we should only be called once (from main) */
3926 assert( schema_init_done == 0 );
3928 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3929 res = register_syntax( &syntax_defs[i] );
3932 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3933 syntax_defs[i].sd_desc );
3938 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3939 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3940 mrule_defs[i].mrd_compat_syntaxes == NULL )
3943 "slap_schema_init: Ignoring unusable matching rule %s\n",
3944 mrule_defs[i].mrd_desc );
3948 res = register_matching_rule( &mrule_defs[i] );
3952 "slap_schema_init: Error registering matching rule %s\n",
3953 mrule_defs[i].mrd_desc );
3958 res = slap_schema_load();
3959 schema_init_done = 1;
3964 schema_destroy( void )
3973 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
3974 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );