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>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
44 #include "lutil_hash.h"
45 #define HASH_BYTES LUTIL_HASH_BYTES
46 #define HASH_CONTEXT lutil_HASH_CTX
47 #define HASH_Init(c) lutil_HASHInit(c)
48 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
49 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
51 #define OpenLDAPaciMatch NULL
53 /* approx matching rules */
54 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
55 #define directoryStringApproxMatch approxMatch
56 #define directoryStringApproxIndexer approxIndexer
57 #define directoryStringApproxFilter approxFilter
58 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch approxMatch
60 #define IA5StringApproxIndexer approxIndexer
61 #define IA5StringApproxFilter approxFilter
63 /* Change Sequence Number (CSN) - much of this will change */
64 #define csnValidate blobValidate
65 #define csnMatch octetStringMatch
66 #define csnOrderingMatch octetStringOrderingMatch
67 #define csnIndexer generalizedTimeIndexer
68 #define csnFilter generalizedTimeFilter
70 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
71 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
72 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
73 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
80 /* no value allowed */
81 return LDAP_INVALID_SYNTAX;
89 /* any value allowed */
93 #define berValidate blobValidate
100 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
101 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 static int certificateValidate( Syntax *syntax, struct berval *in )
111 unsigned char *p = (unsigned char *)in->bv_val;
113 xcert = d2i_X509(NULL, &p, in->bv_len);
114 if ( !xcert ) return LDAP_INVALID_SYNTAX;
119 #define certificateValidate sequenceValidate
128 struct berval *value,
129 void *assertedValue )
131 struct berval *asserted = (struct berval *) assertedValue;
132 int match = value->bv_len - asserted->bv_len;
135 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
143 octetStringOrderingMatch(
148 struct berval *value,
149 void *assertedValue )
151 struct berval *asserted = (struct berval *) assertedValue;
152 ber_len_t v_len = value->bv_len;
153 ber_len_t av_len = asserted->bv_len;
155 int match = memcmp( value->bv_val, asserted->bv_val,
156 (v_len < av_len ? v_len : av_len) );
158 if( match == 0 ) match = v_len - av_len;
166 HASH_CONTEXT *HASHcontext,
167 unsigned char *HASHdigest,
168 struct berval *prefix,
172 unsigned char *value,
175 HASH_Init(HASHcontext);
176 if(prefix && prefix->bv_len > 0) {
177 HASH_Update(HASHcontext,
178 (unsigned char *)prefix->bv_val, prefix->bv_len);
180 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
181 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
182 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
183 HASH_Update(HASHcontext, value, value_len);
184 HASH_Final(HASHdigest, HASHcontext);
188 /* Index generation function */
189 int octetStringIndexer(
194 struct berval *prefix,
202 HASH_CONTEXT HASHcontext;
203 unsigned char HASHdigest[HASH_BYTES];
204 struct berval digest;
205 digest.bv_val = (char *)HASHdigest;
206 digest.bv_len = sizeof(HASHdigest);
208 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
209 /* just count them */
212 /* we should have at least one value at this point */
215 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
217 slen = syntax->ssyn_oidlen;
218 mlen = mr->smr_oidlen;
220 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
221 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
222 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
223 ber_dupbv_x( &keys[i], &digest, ctx );
226 BER_BVZERO( &keys[i] );
233 /* Index generation function */
234 int octetStringFilter(
239 struct berval *prefix,
240 void * assertedValue,
246 HASH_CONTEXT HASHcontext;
247 unsigned char HASHdigest[HASH_BYTES];
248 struct berval *value = (struct berval *) assertedValue;
249 struct berval digest;
250 digest.bv_val = (char *)HASHdigest;
251 digest.bv_len = sizeof(HASHdigest);
253 slen = syntax->ssyn_oidlen;
254 mlen = mr->smr_oidlen;
256 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
258 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
259 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
261 ber_dupbv_x( keys, &digest, ctx );
262 BER_BVZERO( &keys[1] );
270 octetStringSubstringsMatch(
275 struct berval *value,
276 void *assertedValue )
279 SubstringsAssertion *sub = assertedValue;
280 struct berval left = *value;
284 /* Add up asserted input length */
285 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
286 inlen += sub->sa_initial.bv_len;
289 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
290 inlen += sub->sa_any[i].bv_len;
293 if ( !BER_BVISNULL( &sub->sa_final ) ) {
294 inlen += sub->sa_final.bv_len;
297 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
298 if ( inlen > left.bv_len ) {
303 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
304 sub->sa_initial.bv_len );
310 left.bv_val += sub->sa_initial.bv_len;
311 left.bv_len -= sub->sa_initial.bv_len;
312 inlen -= sub->sa_initial.bv_len;
315 if ( !BER_BVISNULL( &sub->sa_final ) ) {
316 if ( inlen > left.bv_len ) {
321 match = memcmp( sub->sa_final.bv_val,
322 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
323 sub->sa_final.bv_len );
329 left.bv_len -= sub->sa_final.bv_len;
330 inlen -= sub->sa_final.bv_len;
334 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
339 if ( inlen > left.bv_len ) {
340 /* not enough length */
345 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
349 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
356 idx = p - left.bv_val;
358 if ( idx >= left.bv_len ) {
359 /* this shouldn't happen */
366 if ( sub->sa_any[i].bv_len > left.bv_len ) {
367 /* not enough left */
372 match = memcmp( left.bv_val,
373 sub->sa_any[i].bv_val,
374 sub->sa_any[i].bv_len );
382 left.bv_val += sub->sa_any[i].bv_len;
383 left.bv_len -= sub->sa_any[i].bv_len;
384 inlen -= sub->sa_any[i].bv_len;
393 /* Substrings Index generation function */
395 octetStringSubstringsIndexer(
400 struct berval *prefix,
405 ber_len_t i, j, len, nkeys;
409 HASH_CONTEXT HASHcontext;
410 unsigned char HASHdigest[HASH_BYTES];
411 struct berval digest;
412 digest.bv_val = (char *)HASHdigest;
413 digest.bv_len = sizeof(HASHdigest);
417 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
418 /* count number of indices to generate */
419 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
420 if( values[i].bv_len >= index_substr_if_maxlen ) {
421 nkeys += index_substr_if_maxlen -
422 (index_substr_if_minlen - 1);
423 } else if( values[i].bv_len >= index_substr_if_minlen ) {
424 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
428 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
429 if( values[i].bv_len >= index_substr_any_len ) {
430 nkeys += values[i].bv_len - (index_substr_any_len - 1);
434 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
435 if( values[i].bv_len >= index_substr_if_maxlen ) {
436 nkeys += index_substr_if_maxlen -
437 (index_substr_if_minlen - 1);
438 } else if( values[i].bv_len >= index_substr_if_minlen ) {
439 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
445 /* no keys to generate */
450 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
452 slen = syntax->ssyn_oidlen;
453 mlen = mr->smr_oidlen;
456 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
459 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
460 ( values[i].bv_len >= index_substr_any_len ) )
462 char pre = SLAP_INDEX_SUBSTR_PREFIX;
463 max = values[i].bv_len - (index_substr_any_len - 1);
465 for( j=0; j<max; j++ ) {
466 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
467 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
468 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
472 /* skip if too short */
473 if( values[i].bv_len < index_substr_if_minlen ) continue;
475 max = index_substr_if_maxlen < values[i].bv_len
476 ? index_substr_if_maxlen : values[i].bv_len;
478 for( j=index_substr_if_minlen; j<=max; j++ ) {
481 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
482 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
483 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
484 syntax, mr, (unsigned char *)values[i].bv_val, j );
485 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
488 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
489 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
490 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
491 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
492 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
499 BER_BVZERO( &keys[nkeys] );
510 octetStringSubstringsFilter (
515 struct berval *prefix,
516 void * assertedValue,
520 SubstringsAssertion *sa;
522 ber_len_t len, max, nkeys = 0;
523 size_t slen, mlen, klen;
525 HASH_CONTEXT HASHcontext;
526 unsigned char HASHdigest[HASH_BYTES];
527 struct berval *value;
528 struct berval digest;
530 sa = (SubstringsAssertion *) assertedValue;
532 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
533 !BER_BVISNULL( &sa->sa_initial ) &&
534 sa->sa_initial.bv_len >= index_substr_if_minlen )
537 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
538 ( flags & SLAP_INDEX_SUBSTR_ANY ))
540 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
544 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
546 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
547 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
548 /* don't bother accounting with stepping */
549 nkeys += sa->sa_any[i].bv_len -
550 ( index_substr_any_len - 1 );
555 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
556 !BER_BVISNULL( &sa->sa_final ) &&
557 sa->sa_final.bv_len >= index_substr_if_minlen )
560 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
561 ( flags & SLAP_INDEX_SUBSTR_ANY ))
563 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
572 digest.bv_val = (char *)HASHdigest;
573 digest.bv_len = sizeof(HASHdigest);
575 slen = syntax->ssyn_oidlen;
576 mlen = mr->smr_oidlen;
578 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
581 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
582 !BER_BVISNULL( &sa->sa_initial ) &&
583 sa->sa_initial.bv_len >= index_substr_if_minlen )
585 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
586 value = &sa->sa_initial;
588 klen = index_substr_if_maxlen < value->bv_len
589 ? index_substr_if_maxlen : value->bv_len;
591 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
592 syntax, mr, (unsigned char *)value->bv_val, klen );
593 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
595 /* If initial is too long and we have subany indexed, use it
596 * to match the excess...
598 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
601 pre = SLAP_INDEX_SUBSTR_PREFIX;
602 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
604 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
605 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
606 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
611 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
613 pre = SLAP_INDEX_SUBSTR_PREFIX;
614 klen = index_substr_any_len;
616 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
617 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
621 value = &sa->sa_any[i];
624 j <= value->bv_len - index_substr_any_len;
625 j += index_substr_any_step )
627 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
628 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
629 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
635 !BER_BVISNULL( &sa->sa_final ) &&
636 sa->sa_final.bv_len >= index_substr_if_minlen )
638 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
639 value = &sa->sa_final;
641 klen = index_substr_if_maxlen < value->bv_len
642 ? index_substr_if_maxlen : value->bv_len;
644 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
645 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
646 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 /* If final is too long and we have subany indexed, use it
649 * to match the excess...
651 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
654 pre = SLAP_INDEX_SUBSTR_PREFIX;
655 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
657 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
658 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
659 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
665 BER_BVZERO( &keys[nkeys] );
682 /* very unforgiving validation, requires no normalization
683 * before simplistic matching
685 if( in->bv_len < 3 ) {
686 return LDAP_INVALID_SYNTAX;
690 * RFC 2252 section 6.3 Bit String
691 * bitstring = "'" *binary-digit "'B"
692 * binary-digit = "0" / "1"
693 * example: '0101111101'B
696 if( in->bv_val[0] != '\'' ||
697 in->bv_val[in->bv_len - 2] != '\'' ||
698 in->bv_val[in->bv_len - 1] != 'B' )
700 return LDAP_INVALID_SYNTAX;
703 for( i = in->bv_len - 3; i > 0; i-- ) {
704 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
705 return LDAP_INVALID_SYNTAX;
713 * Syntax is [RFC2252]:
718 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
720 Values in this syntax are encoded according to the following BNF:
722 bitstring = "'" *binary-digit "'B"
724 binary-digit = "0" / "1"
728 6.21. Name And Optional UID
730 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
732 Values in this syntax are encoded according to the following BNF:
734 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
736 Although the '#' character may occur in a string representation of a
737 distinguished name, no additional special quoting is done. This
738 syntax has been added subsequent to RFC 1778.
742 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
745 * draft-ietf-ldapbis-syntaxes-xx.txt says:
750 A value of the Bit String syntax is a sequence of binary digits. The
751 LDAP-specific encoding of a value of this syntax is defined by the
754 BitString = SQUOTE *binary-digit SQUOTE "B"
756 binary-digit = "0" / "1"
758 The <SQUOTE> rule is defined in [MODELS].
763 The LDAP definition for the Bit String syntax is:
765 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
767 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
771 3.3.21. Name and Optional UID
773 A value of the Name and Optional UID syntax is the distinguished name
774 [MODELS] of an entity optionally accompanied by a unique identifier
775 that serves to differentiate the entity from others with an identical
778 The LDAP-specific encoding of a value of this syntax is defined by
781 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
783 The <BitString> rule is defined in Section 3.3.2. The
784 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
787 Note that although the '#' character may occur in the string
788 representation of a distinguished name, no additional escaping of
789 this character is performed when a <distinguishedName> is encoded in
790 a <NameAndOptionalUID>.
793 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
795 The LDAP definition for the Name and Optional UID syntax is:
797 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
799 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
803 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
806 1.4. Common ABNF Productions
809 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
811 SQUOTE = %x27 ; single quote ("'")
815 * Note: normalization strips any leading "0"s, unless the
816 * bit string is exactly "'0'B", so the normalized example,
817 * in slapd, would result in
819 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
821 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
822 * i.e. "#", doesn't have to be escaped except when at the
823 * beginning of a value, the definition of Name and Optional
824 * UID appears to be flawed, because there is no clear means
825 * to determine whether the UID part is present or not.
829 * cn=Someone,dc=example,dc=com#'1'B
831 * could be either a NameAndOptionalUID with trailing UID, i.e.
833 * DN = "cn=Someone,dc=example,dc=com"
836 * or a NameAndOptionalUID with no trailing UID, and the AVA
837 * in the last RDN made of
840 * attributeValue = com#'1'B
842 * in fact "com#'1'B" is a valid IA5 string.
844 * As a consequence, current slapd code assumes that the
845 * presence of portions of a BitString at the end of the string
846 * representation of a NameAndOptionalUID means a BitString
847 * is expected, and cause an error otherwise. This is quite
848 * arbitrary, and might change in the future.
858 struct berval dn, uid;
860 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
862 ber_dupbv( &dn, in );
863 if( !dn.bv_val ) return LDAP_OTHER;
865 /* if there's a "#", try bitStringValidate()... */
866 uid.bv_val = strrchr( dn.bv_val, '#' );
867 if ( !BER_BVISNULL( &uid ) ) {
869 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
871 rc = bitStringValidate( NULL, &uid );
872 if ( rc == LDAP_SUCCESS ) {
873 /* in case of success, trim the UID,
874 * otherwise treat it as part of the DN */
875 dn.bv_len -= uid.bv_len + 1;
876 uid.bv_val[-1] = '\0';
880 rc = dnValidate( NULL, &dn );
882 ber_memfree( dn.bv_val );
897 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
899 if( BER_BVISEMPTY( val ) ) {
900 ber_dupbv_x( out, val, ctx );
902 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
903 return LDAP_INVALID_SYNTAX;
907 struct berval dnval = *val;
908 struct berval uidval = BER_BVNULL;
910 uidval.bv_val = strrchr( val->bv_val, '#' );
911 if ( !BER_BVISNULL( &uidval ) ) {
913 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
915 rc = bitStringValidate( NULL, &uidval );
917 if ( rc == LDAP_SUCCESS ) {
918 ber_dupbv_x( &dnval, val, ctx );
919 dnval.bv_len -= uidval.bv_len + 1;
920 dnval.bv_val[dnval.bv_len] = '\0';
923 BER_BVZERO( &uidval );
927 rc = dnPretty( syntax, &dnval, out, ctx );
928 if ( dnval.bv_val != val->bv_val ) {
929 slap_sl_free( dnval.bv_val, ctx );
931 if( rc != LDAP_SUCCESS ) {
935 if( !BER_BVISNULL( &uidval ) ) {
939 tmp = slap_sl_realloc( out->bv_val, out->bv_len
940 + STRLENOF( "#" ) + uidval.bv_len + 1,
943 ber_memfree_x( out->bv_val, ctx );
947 out->bv_val[out->bv_len++] = '#';
948 out->bv_val[out->bv_len++] = '\'';
950 got1 = uidval.bv_len < sizeof("'0'B");
951 for( i = 1; i < uidval.bv_len - 2; i++ ) {
952 c = uidval.bv_val[i];
955 if( got1 ) out->bv_val[out->bv_len++] = c;
959 out->bv_val[out->bv_len++] = c;
964 out->bv_val[out->bv_len++] = '\'';
965 out->bv_val[out->bv_len++] = 'B';
966 out->bv_val[out->bv_len] = '\0';
970 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
976 uniqueMemberNormalize(
981 struct berval *normalized,
987 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
989 ber_dupbv_x( &out, val, ctx );
990 if ( BER_BVISEMPTY( &out ) ) {
994 struct berval uid = BER_BVNULL;
996 uid.bv_val = strrchr( out.bv_val, '#' );
997 if ( !BER_BVISNULL( &uid ) ) {
999 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1001 rc = bitStringValidate( NULL, &uid );
1002 if ( rc == LDAP_SUCCESS ) {
1003 uid.bv_val[-1] = '\0';
1004 out.bv_len -= uid.bv_len + 1;
1010 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1012 if( rc != LDAP_SUCCESS ) {
1013 slap_sl_free( out.bv_val, ctx );
1014 return LDAP_INVALID_SYNTAX;
1017 if( !BER_BVISNULL( &uid ) ) {
1020 tmp = ch_realloc( normalized->bv_val,
1021 normalized->bv_len + uid.bv_len
1022 + STRLENOF("#") + 1 );
1023 if ( tmp == NULL ) {
1024 ber_memfree_x( normalized->bv_val, ctx );
1028 normalized->bv_val = tmp;
1030 /* insert the separator */
1031 normalized->bv_val[normalized->bv_len++] = '#';
1033 /* append the UID */
1034 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1035 uid.bv_val, uid.bv_len );
1036 normalized->bv_len += uid.bv_len;
1039 normalized->bv_val[normalized->bv_len] = '\0';
1042 slap_sl_free( out.bv_val, ctx );
1045 return LDAP_SUCCESS;
1054 struct berval *value,
1055 void *assertedValue )
1058 struct berval *asserted = (struct berval *) assertedValue;
1059 struct berval assertedDN = *asserted;
1060 struct berval assertedUID = BER_BVNULL;
1061 struct berval valueDN = BER_BVNULL;
1062 struct berval valueUID = BER_BVNULL;
1063 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1065 if ( !BER_BVISEMPTY( asserted ) ) {
1066 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1067 if ( !BER_BVISNULL( &assertedUID ) ) {
1068 assertedUID.bv_val++;
1069 assertedUID.bv_len = assertedDN.bv_len
1070 - ( assertedUID.bv_val - assertedDN.bv_val );
1072 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1073 assertedDN.bv_len -= assertedUID.bv_len + 1;
1076 BER_BVZERO( &assertedUID );
1081 if ( !BER_BVISEMPTY( value ) ) {
1084 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1085 if ( !BER_BVISNULL( &valueUID ) ) {
1087 valueUID.bv_len = valueDN.bv_len
1088 - ( valueUID.bv_val - valueDN.bv_val );
1090 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1091 valueDN.bv_len -= valueUID.bv_len + 1;
1094 BER_BVZERO( &valueUID );
1099 if( valueUID.bv_len && assertedUID.bv_len ) {
1100 match = valueUID.bv_len - assertedUID.bv_len;
1103 return LDAP_SUCCESS;
1106 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1109 return LDAP_SUCCESS;
1112 } else if ( !approx && valueUID.bv_len ) {
1115 return LDAP_SUCCESS;
1117 } else if ( !approx && assertedUID.bv_len ) {
1120 return LDAP_SUCCESS;
1123 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1127 uniqueMemberIndexer(
1132 struct berval *prefix,
1140 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1141 /* just count them */
1145 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1147 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1148 struct berval assertedDN = values[i];
1149 struct berval assertedUID = BER_BVNULL;
1151 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1152 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1153 if ( !BER_BVISNULL( &assertedUID ) ) {
1154 assertedUID.bv_val++;
1155 assertedUID.bv_len = assertedDN.bv_len
1156 - ( assertedUID.bv_val - assertedDN.bv_val );
1158 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1159 assertedDN.bv_len -= assertedUID.bv_len + 1;
1162 BER_BVZERO( &assertedUID );
1167 dnvalues[i] = assertedDN;
1169 BER_BVZERO( &dnvalues[i] );
1171 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1172 dnvalues, keysp, ctx );
1174 slap_sl_free( dnvalues, ctx );
1184 struct berval *prefix,
1185 void * assertedValue,
1189 struct berval *asserted = (struct berval *) assertedValue;
1190 struct berval assertedDN = *asserted;
1191 struct berval assertedUID = BER_BVNULL;
1193 if ( !BER_BVISEMPTY( asserted ) ) {
1194 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1195 if ( !BER_BVISNULL( &assertedUID ) ) {
1196 assertedUID.bv_val++;
1197 assertedUID.bv_len = assertedDN.bv_len
1198 - ( assertedUID.bv_val - assertedDN.bv_val );
1200 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1201 assertedDN.bv_len -= assertedUID.bv_len + 1;
1204 BER_BVZERO( &assertedUID );
1209 return octetStringFilter( use, flags, syntax, mr, prefix,
1210 &assertedDN, keysp, ctx );
1215 * Handling boolean syntax and matching is quite rigid.
1216 * A more flexible approach would be to allow a variety
1217 * of strings to be normalized and prettied into TRUE
1225 /* very unforgiving validation, requires no normalization
1226 * before simplistic matching
1229 if( in->bv_len == 4 ) {
1230 if( bvmatch( in, &slap_true_bv ) ) {
1231 return LDAP_SUCCESS;
1233 } else if( in->bv_len == 5 ) {
1234 if( bvmatch( in, &slap_false_bv ) ) {
1235 return LDAP_SUCCESS;
1239 return LDAP_INVALID_SYNTAX;
1248 struct berval *value,
1249 void *assertedValue )
1251 /* simplistic matching allowed by rigid validation */
1252 struct berval *asserted = (struct berval *) assertedValue;
1253 *matchp = value->bv_len != asserted->bv_len;
1254 return LDAP_SUCCESS;
1257 /*-------------------------------------------------------------------
1258 LDAP/X.500 string syntax / matching rules have a few oddities. This
1259 comment attempts to detail how slapd(8) treats them.
1262 StringSyntax X.500 LDAP Matching/Comments
1263 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1264 PrintableString subset subset i/e + ignore insignificant spaces
1265 PrintableString subset subset i/e + ignore insignificant spaces
1266 NumericString subset subset ignore all spaces
1267 IA5String ASCII ASCII i/e + ignore insignificant spaces
1268 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1270 TelephoneNumber subset subset i + ignore all spaces and "-"
1272 See draft-ietf-ldapbis-strpro for details (once published).
1276 In X.500(93), a directory string can be either a PrintableString,
1277 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1278 In later versions, more CHOICEs were added. In all cases the string
1281 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1282 A directory string cannot be zero length.
1284 For matching, there are both case ignore and exact rules. Both
1285 also require that "insignificant" spaces be ignored.
1286 spaces before the first non-space are ignored;
1287 spaces after the last non-space are ignored;
1288 spaces after a space are ignored.
1289 Note: by these rules (and as clarified in X.520), a string of only
1290 spaces is to be treated as if held one space, not empty (which
1291 would be a syntax error).
1294 In ASN.1, numeric string is just a string of digits and spaces
1295 and could be empty. However, in X.500, all attribute values of
1296 numeric string carry a non-empty constraint. For example:
1298 internationalISDNNumber ATTRIBUTE ::= {
1299 WITH SYNTAX InternationalISDNNumber
1300 EQUALITY MATCHING RULE numericStringMatch
1301 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1302 ID id-at-internationalISDNNumber }
1303 InternationalISDNNumber ::=
1304 NumericString (SIZE(1..ub-international-isdn-number))
1306 Unforunately, some assertion values are don't carry the same
1307 constraint (but its unclear how such an assertion could ever
1308 be true). In LDAP, there is one syntax (numericString) not two
1309 (numericString with constraint, numericString without constraint).
1310 This should be treated as numericString with non-empty constraint.
1311 Note that while someone may have no ISDN number, there are no ISDN
1312 numbers which are zero length.
1314 In matching, spaces are ignored.
1317 In ASN.1, Printable string is just a string of printable characters
1318 and can be empty. In X.500, semantics much like NumericString (see
1319 serialNumber for a like example) excepting uses insignificant space
1320 handling instead of ignore all spaces.
1323 Basically same as PrintableString. There are no examples in X.500,
1324 but same logic applies. So we require them to be non-empty as
1327 -------------------------------------------------------------------*/
1336 unsigned char *u = (unsigned char *)in->bv_val;
1338 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1339 /* directory strings cannot be empty */
1340 return LDAP_INVALID_SYNTAX;
1343 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1344 /* get the length indicated by the first byte */
1345 len = LDAP_UTF8_CHARLEN2( u, len );
1347 /* very basic checks */
1350 if( (u[5] & 0xC0) != 0x80 ) {
1351 return LDAP_INVALID_SYNTAX;
1354 if( (u[4] & 0xC0) != 0x80 ) {
1355 return LDAP_INVALID_SYNTAX;
1358 if( (u[3] & 0xC0) != 0x80 ) {
1359 return LDAP_INVALID_SYNTAX;
1362 if( (u[2] & 0xC0 )!= 0x80 ) {
1363 return LDAP_INVALID_SYNTAX;
1366 if( (u[1] & 0xC0) != 0x80 ) {
1367 return LDAP_INVALID_SYNTAX;
1370 /* CHARLEN already validated it */
1373 return LDAP_INVALID_SYNTAX;
1376 /* make sure len corresponds with the offset
1377 to the next character */
1378 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1382 return LDAP_INVALID_SYNTAX;
1385 return LDAP_SUCCESS;
1389 UTF8StringNormalize(
1394 struct berval *normalized,
1397 struct berval tmp, nvalue;
1401 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1403 if( BER_BVISNULL( val ) ) {
1404 /* assume we're dealing with a syntax (e.g., UTF8String)
1405 * which allows empty strings
1407 BER_BVZERO( normalized );
1408 return LDAP_SUCCESS;
1411 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1412 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1413 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1414 ? LDAP_UTF8_APPROX : 0;
1416 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1421 /* collapse spaces (in place) */
1423 nvalue.bv_val = tmp.bv_val;
1425 /* trim leading spaces? */
1426 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1427 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1429 for( i = 0; i < tmp.bv_len; i++) {
1430 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1431 if( wasspace++ == 0 ) {
1432 /* trim repeated spaces */
1433 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1437 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1441 if( !BER_BVISEMPTY( &nvalue ) ) {
1442 /* trim trailing space? */
1444 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1445 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1449 nvalue.bv_val[nvalue.bv_len] = '\0';
1452 /* string of all spaces is treated as one space */
1453 nvalue.bv_val[0] = ' ';
1454 nvalue.bv_val[1] = '\0';
1458 *normalized = nvalue;
1459 return LDAP_SUCCESS;
1463 directoryStringSubstringsMatch(
1468 struct berval *value,
1469 void *assertedValue )
1472 SubstringsAssertion *sub = assertedValue;
1473 struct berval left = *value;
1477 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1478 if ( sub->sa_initial.bv_len > left.bv_len ) {
1479 /* not enough left */
1484 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1485 sub->sa_initial.bv_len );
1491 left.bv_val += sub->sa_initial.bv_len;
1492 left.bv_len -= sub->sa_initial.bv_len;
1494 priorspace = ASCII_SPACE(
1495 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1498 if ( sub->sa_any ) {
1499 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1503 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1504 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1506 /* allow next space to match */
1513 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1517 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1518 /* not enough left */
1523 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1530 idx = p - left.bv_val;
1532 if ( idx >= left.bv_len ) {
1533 /* this shouldn't happen */
1540 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1541 /* not enough left */
1546 match = memcmp( left.bv_val,
1547 sub->sa_any[i].bv_val,
1548 sub->sa_any[i].bv_len );
1556 left.bv_val += sub->sa_any[i].bv_len;
1557 left.bv_len -= sub->sa_any[i].bv_len;
1559 priorspace = ASCII_SPACE(
1560 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1564 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1565 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1566 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1568 /* allow next space to match */
1573 if ( sub->sa_final.bv_len > left.bv_len ) {
1574 /* not enough left */
1579 match = memcmp( sub->sa_final.bv_val,
1580 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1581 sub->sa_final.bv_len );
1590 return LDAP_SUCCESS;
1593 #if defined(SLAPD_APPROX_INITIALS)
1594 # define SLAPD_APPROX_DELIMITER "._ "
1595 # define SLAPD_APPROX_WORDLEN 2
1597 # define SLAPD_APPROX_DELIMITER " "
1598 # define SLAPD_APPROX_WORDLEN 1
1607 struct berval *value,
1608 void *assertedValue )
1610 struct berval *nval, *assertv;
1611 char *val, **values, **words, *c;
1612 int i, count, len, nextchunk=0, nextavail=0;
1614 /* Yes, this is necessary */
1615 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1616 if( nval == NULL ) {
1618 return LDAP_SUCCESS;
1621 /* Yes, this is necessary */
1622 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1623 NULL, LDAP_UTF8_APPROX, NULL );
1624 if( assertv == NULL ) {
1627 return LDAP_SUCCESS;
1630 /* Isolate how many words there are */
1631 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1632 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1633 if ( c == NULL ) break;
1638 /* Get a phonetic copy of each word */
1639 words = (char **)ch_malloc( count * sizeof(char *) );
1640 values = (char **)ch_malloc( count * sizeof(char *) );
1641 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1643 values[i] = phonetic(c);
1646 /* Work through the asserted value's words, to see if at least some
1647 of the words are there, in the same order. */
1649 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1650 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1655 #if defined(SLAPD_APPROX_INITIALS)
1656 else if( len == 1 ) {
1657 /* Single letter words need to at least match one word's initial */
1658 for( i=nextavail; i<count; i++ )
1659 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1666 /* Isolate the next word in the asserted value and phonetic it */
1667 assertv->bv_val[nextchunk+len] = '\0';
1668 val = phonetic( assertv->bv_val + nextchunk );
1670 /* See if this phonetic chunk is in the remaining words of *value */
1671 for( i=nextavail; i<count; i++ ){
1672 if( !strcmp( val, values[i] ) ){
1680 /* This chunk in the asserted value was NOT within the *value. */
1686 /* Go on to the next word in the asserted value */
1690 /* If some of the words were seen, call it a match */
1691 if( nextavail > 0 ) {
1698 /* Cleanup allocs */
1699 ber_bvfree( assertv );
1700 for( i=0; i<count; i++ ) {
1701 ch_free( values[i] );
1707 return LDAP_SUCCESS;
1716 struct berval *prefix,
1722 int i,j, len, wordcount, keycount=0;
1723 struct berval *newkeys;
1724 BerVarray keys=NULL;
1726 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1727 struct berval val = BER_BVNULL;
1728 /* Yes, this is necessary */
1729 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1730 assert( !BER_BVISNULL( &val ) );
1732 /* Isolate how many words there are. There will be a key for each */
1733 for( wordcount = 0, c = val.bv_val; *c; c++) {
1734 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1735 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1737 if (*c == '\0') break;
1741 /* Allocate/increase storage to account for new keys */
1742 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1743 * sizeof(struct berval) );
1744 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1745 if( keys ) ch_free( keys );
1748 /* Get a phonetic copy of each word */
1749 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1751 if( len < SLAPD_APPROX_WORDLEN ) continue;
1752 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1757 ber_memfree( val.bv_val );
1759 BER_BVZERO( &keys[keycount] );
1762 return LDAP_SUCCESS;
1771 struct berval *prefix,
1772 void * assertedValue,
1781 /* Yes, this is necessary */
1782 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1783 NULL, LDAP_UTF8_APPROX, NULL );
1784 if( val == NULL || BER_BVISNULL( val ) ) {
1785 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1786 BER_BVZERO( &keys[0] );
1789 return LDAP_SUCCESS;
1792 /* Isolate how many words there are. There will be a key for each */
1793 for( count = 0,c = val->bv_val; *c; c++) {
1794 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1795 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1797 if (*c == '\0') break;
1801 /* Allocate storage for new keys */
1802 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1804 /* Get a phonetic copy of each word */
1805 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1807 if( len < SLAPD_APPROX_WORDLEN ) continue;
1808 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1814 BER_BVZERO( &keys[count] );
1817 return LDAP_SUCCESS;
1820 /* Remove all spaces and '-' characters */
1822 telephoneNumberNormalize(
1827 struct berval *normalized,
1832 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1834 /* validator should have refused an empty string */
1835 assert( !BER_BVISEMPTY( val ) );
1837 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1839 for( p = val->bv_val; *p; p++ ) {
1840 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1846 normalized->bv_len = q - normalized->bv_val;
1848 if( BER_BVISEMPTY( normalized ) ) {
1849 slap_sl_free( normalized->bv_val, ctx );
1850 BER_BVZERO( normalized );
1851 return LDAP_INVALID_SYNTAX;
1854 return LDAP_SUCCESS;
1862 struct berval val = *in;
1864 if( BER_BVISEMPTY( &val ) ) {
1865 /* disallow empty strings */
1866 return LDAP_INVALID_SYNTAX;
1869 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1870 if ( val.bv_len == 1 ) {
1871 return LDAP_SUCCESS;
1874 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1881 while ( OID_LEADCHAR( val.bv_val[0] )) {
1885 if ( val.bv_len == 0 ) {
1886 return LDAP_SUCCESS;
1890 if( !OID_SEPARATOR( val.bv_val[0] )) {
1898 return LDAP_INVALID_SYNTAX;
1907 struct berval val = *in;
1909 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1911 if ( val.bv_val[0] == '-' ) {
1915 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1916 return LDAP_INVALID_SYNTAX;
1919 if( val.bv_val[0] == '0' ) { /* "-0" */
1920 return LDAP_INVALID_SYNTAX;
1923 } else if ( val.bv_val[0] == '0' ) {
1924 if( val.bv_len > 1 ) { /* "0<more>" */
1925 return LDAP_INVALID_SYNTAX;
1928 return LDAP_SUCCESS;
1931 for( i=0; i < val.bv_len; i++ ) {
1932 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1933 return LDAP_INVALID_SYNTAX;
1937 return LDAP_SUCCESS;
1946 struct berval *value,
1947 void *assertedValue )
1949 struct berval *asserted = (struct berval *) assertedValue;
1950 int vsign = 1, asign = 1; /* default sign = '+' */
1955 if( v.bv_val[0] == '-' ) {
1961 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1964 if( a.bv_val[0] == '-' ) {
1970 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1972 match = vsign - asign;
1974 match = ( v.bv_len != a.bv_len
1975 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1976 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1977 if( vsign < 0 ) match = -match;
1981 return LDAP_SUCCESS;
1985 countryStringValidate(
1987 struct berval *val )
1989 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1991 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1992 return LDAP_INVALID_SYNTAX;
1994 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1995 return LDAP_INVALID_SYNTAX;
1998 return LDAP_SUCCESS;
2002 printableStringValidate(
2004 struct berval *val )
2008 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2010 for(i=0; i < val->bv_len; i++) {
2011 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2012 return LDAP_INVALID_SYNTAX;
2016 return LDAP_SUCCESS;
2020 printablesStringValidate(
2022 struct berval *val )
2026 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2028 for(i=0,len=0; i < val->bv_len; i++) {
2029 int c = val->bv_val[i];
2033 return LDAP_INVALID_SYNTAX;
2037 } else if ( SLAP_PRINTABLE(c) ) {
2040 return LDAP_INVALID_SYNTAX;
2045 return LDAP_INVALID_SYNTAX;
2048 return LDAP_SUCCESS;
2054 struct berval *val )
2058 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2060 for(i=0; i < val->bv_len; i++) {
2061 if( !LDAP_ASCII(val->bv_val[i]) ) {
2062 return LDAP_INVALID_SYNTAX;
2066 return LDAP_SUCCESS;
2075 struct berval *normalized,
2079 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2081 assert( !BER_BVISEMPTY( val ) );
2083 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2087 /* Ignore initial whitespace */
2088 while ( ASCII_SPACE( *p ) ) p++;
2090 normalized->bv_val = ber_strdup_x( p, ctx );
2091 p = q = normalized->bv_val;
2094 if ( ASCII_SPACE( *p ) ) {
2097 /* Ignore the extra whitespace */
2098 while ( ASCII_SPACE( *p ) ) {
2102 } else if ( casefold ) {
2103 /* Most IA5 rules require casefolding */
2104 *q++ = TOLOWER(*p); p++;
2111 assert( normalized->bv_val <= p );
2115 * If the string ended in space, backup the pointer one
2116 * position. One is enough because the above loop collapsed
2117 * all whitespace to a single space.
2119 if ( ASCII_SPACE( q[-1] ) ) --q;
2121 /* null terminate */
2124 normalized->bv_len = q - normalized->bv_val;
2125 if( BER_BVISEMPTY( normalized ) ) {
2126 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2127 normalized->bv_val[0] = ' ';
2128 normalized->bv_val[1] = '\0';
2129 normalized->bv_len = 1;
2132 return LDAP_SUCCESS;
2141 if( in->bv_len != 36 ) {
2142 return LDAP_INVALID_SYNTAX;
2145 for( i=0; i<36; i++ ) {
2151 if( in->bv_val[i] != '-' ) {
2152 return LDAP_INVALID_SYNTAX;
2156 if( !ASCII_HEX( in->bv_val[i]) ) {
2157 return LDAP_INVALID_SYNTAX;
2162 return LDAP_SUCCESS;
2171 struct berval *normalized,
2174 unsigned char octet = '\0';
2177 normalized->bv_len = 16;
2178 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2180 for( i=0, j=0; i<36; i++ ) {
2181 unsigned char nibble;
2182 if( val->bv_val[i] == '-' ) {
2185 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2186 nibble = val->bv_val[i] - '0';
2188 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2189 nibble = val->bv_val[i] - ('a'-10);
2191 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2192 nibble = val->bv_val[i] - ('A'-10);
2195 slap_sl_free( normalized->bv_val, ctx );
2196 return LDAP_INVALID_SYNTAX;
2201 normalized->bv_val[j>>1] = octet;
2203 octet = nibble << 4;
2208 normalized->bv_val[normalized->bv_len] = 0;
2209 return LDAP_SUCCESS;
2215 numericStringValidate(
2221 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2223 for(i=0; i < in->bv_len; i++) {
2224 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2225 return LDAP_INVALID_SYNTAX;
2229 return LDAP_SUCCESS;
2233 numericStringNormalize(
2238 struct berval *normalized,
2241 /* removal all spaces */
2244 assert( !BER_BVISEMPTY( val ) );
2246 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2249 q = normalized->bv_val;
2252 if ( ASCII_SPACE( *p ) ) {
2253 /* Ignore whitespace */
2260 /* we should have copied no more then is in val */
2261 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2263 /* null terminate */
2266 normalized->bv_len = q - normalized->bv_val;
2268 if( BER_BVISEMPTY( normalized ) ) {
2269 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2270 normalized->bv_val[0] = ' ';
2271 normalized->bv_val[1] = '\0';
2272 normalized->bv_len = 1;
2275 return LDAP_SUCCESS;
2279 * Integer conversion macros that will use the largest available
2282 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2283 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2284 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2285 # define SLAP_LONG_MAX LLONG_MAX
2286 # define SLAP_LONG_MIN LLONG_MIN
2287 # define SLAP_LONG long long
2289 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2290 # define SLAP_LONG_MAX LONG_MAX
2291 # define SLAP_LONG_MIN LONG_MIN
2292 # define SLAP_LONG long
2293 #endif /* HAVE_STRTOLL ... */
2301 struct berval *value,
2302 void *assertedValue )
2304 SLAP_LONG lValue, lAssertedValue;
2306 /* safe to assume integers are NUL terminated? */
2307 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2308 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2311 return LDAP_CONSTRAINT_VIOLATION;
2314 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2316 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2319 return LDAP_CONSTRAINT_VIOLATION;
2322 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2323 return LDAP_SUCCESS;
2332 struct berval *value,
2333 void *assertedValue )
2335 SLAP_LONG lValue, lAssertedValue;
2337 /* safe to assume integers are NUL terminated? */
2338 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2339 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2342 return LDAP_CONSTRAINT_VIOLATION;
2345 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2347 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2350 return LDAP_CONSTRAINT_VIOLATION;
2353 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2354 return LDAP_SUCCESS;
2358 serialNumberAndIssuerValidate(
2365 struct berval sn, i;
2366 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2368 i.bv_val = strchr( in->bv_val, '$' );
2369 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2371 sn.bv_val = in->bv_val;
2372 sn.bv_len = i.bv_val - in->bv_val;
2375 i.bv_len = in->bv_len - (sn.bv_len + 1);
2377 /* validate serial number (strict for now) */
2378 for( n=0; n < sn.bv_len; n++ ) {
2379 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2383 rc = dnValidate( NULL, &i );
2384 if( rc ) return LDAP_INVALID_SYNTAX;
2386 return LDAP_SUCCESS;
2390 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(
2474 struct berval sn, i, newi;
2479 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2480 val->bv_val, 0, 0 );
2482 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2484 i.bv_val = strchr( val->bv_val, '$' );
2485 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2487 sn.bv_val = val->bv_val;
2488 sn.bv_len = i.bv_val - val->bv_val;
2491 i.bv_len = val->bv_len - (sn.bv_len + 1);
2493 /* eat leading zeros */
2494 for( n=0; n < (sn.bv_len-1); n++ ) {
2495 if( sn.bv_val[n] != '0' ) break;
2500 for( n=0; n < sn.bv_len; n++ ) {
2501 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2502 return LDAP_INVALID_SYNTAX;
2507 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2508 if( rc ) return LDAP_INVALID_SYNTAX;
2510 /* make room from sn + "$" */
2511 out->bv_len = sn.bv_len + newi.bv_len + 1;
2512 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2514 if( BER_BVISNULL( out ) ) {
2515 slap_sl_free( newi.bv_val, ctx );
2519 /* push issuer over */
2520 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2521 /* insert sn and "$" */
2522 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2523 out->bv_val[sn.bv_len] = '$';
2525 out->bv_val[out->bv_len] = '\0';
2527 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2528 out->bv_val, 0, 0 );
2535 certificateExactNormalize(
2540 struct berval *normalized,
2543 int rc = LDAP_INVALID_SYNTAX;
2545 char *serial = NULL;
2546 ber_len_t seriallen;
2547 struct berval issuer_dn = BER_BVNULL;
2548 X509_NAME *name = NULL;
2549 ASN1_INTEGER *sn = NULL;
2552 if( BER_BVISEMPTY( val ) ) goto done;
2554 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2555 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2558 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2560 p = (unsigned char *)val->bv_val;
2561 xcert = d2i_X509( NULL, &p, val->bv_len);
2562 if( xcert == NULL ) goto done;
2564 sn=X509_get_serialNumber(xcert);
2565 if ( sn == NULL ) goto done;
2566 serial=i2s_ASN1_INTEGER(0, sn );
2567 if( serial == NULL ) goto done;
2568 seriallen=strlen(serial);
2570 name=X509_get_issuer_name(xcert);
2571 if( name == NULL ) goto done;
2572 rc = dnX509normalize( name, &issuer_dn );
2573 if( rc != LDAP_SUCCESS ) goto done;
2575 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2576 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2577 p = (unsigned char *)normalized->bv_val;
2578 AC_MEMCPY(p, serial, seriallen);
2581 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2582 p += issuer_dn.bv_len;
2585 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2586 normalized->bv_val, NULL, NULL );
2589 if (xcert) X509_free(xcert);
2590 if (serial) ch_free(serial);
2591 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2595 #endif /* HAVE_TLS */
2598 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2599 /* slight optimization - does not need the start parameter */
2600 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2605 check_time_syntax (struct berval *val,
2608 struct berval *fraction)
2611 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2612 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2613 * GeneralizedTime supports leap seconds, UTCTime does not.
2615 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2616 static const int mdays[2][12] = {
2617 /* non-leap years */
2618 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2620 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2623 int part, c, c1, c2, tzoffset, leapyear = 0;
2626 e = p + val->bv_len;
2628 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2629 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2631 for (part = start; part < 7 && p < e; part++) {
2633 if (!ASCII_DIGIT(c1)) {
2638 return LDAP_INVALID_SYNTAX;
2641 if (!ASCII_DIGIT(c)) {
2642 return LDAP_INVALID_SYNTAX;
2644 c += c1 * 10 - '0' * 11;
2645 if ((part | 1) == 3) {
2648 return LDAP_INVALID_SYNTAX;
2651 if (c >= ceiling[part]) {
2652 if (! (c == 60 && part == 6 && start == 0))
2653 return LDAP_INVALID_SYNTAX;
2657 if (part < 5 + start) {
2658 return LDAP_INVALID_SYNTAX;
2660 for (; part < 9; part++) {
2664 /* leapyear check for the Gregorian calendar (year>1581) */
2665 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2669 if (parts[3] >= mdays[leapyear][parts[2]]) {
2670 return LDAP_INVALID_SYNTAX;
2674 fraction->bv_val = p;
2675 fraction->bv_len = 0;
2676 if (p < e && (*p == '.' || *p == ',')) {
2678 while (++p < e && ASCII_DIGIT(*p)) {
2681 if (p - fraction->bv_val == 1) {
2682 return LDAP_INVALID_SYNTAX;
2684 for (end_num = p; end_num[-1] == '0'; --end_num) {
2687 c = end_num - fraction->bv_val;
2688 if (c != 1) fraction->bv_len = c;
2694 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2700 return LDAP_INVALID_SYNTAX;
2706 for (part = 7; part < 9 && p < e; part++) {
2708 if (!ASCII_DIGIT(c1)) {
2713 return LDAP_INVALID_SYNTAX;
2716 if (!ASCII_DIGIT(c2)) {
2717 return LDAP_INVALID_SYNTAX;
2719 parts[part] = c1 * 10 + c2 - '0' * 11;
2720 if (parts[part] >= ceiling[part]) {
2721 return LDAP_INVALID_SYNTAX;
2724 if (part < 8 + start) {
2725 return LDAP_INVALID_SYNTAX;
2728 if (tzoffset == '-') {
2729 /* negative offset to UTC, ie west of Greenwich */
2730 parts[4] += parts[7];
2731 parts[5] += parts[8];
2732 /* offset is just hhmm, no seconds */
2733 for (part = 6; --part >= 0; ) {
2737 c = mdays[leapyear][parts[2]];
2739 if (parts[part] >= c) {
2741 return LDAP_INVALID_SYNTAX;
2746 } else if (part != 5) {
2751 /* positive offset to UTC, ie east of Greenwich */
2752 parts[4] -= parts[7];
2753 parts[5] -= parts[8];
2754 for (part = 6; --part >= 0; ) {
2755 if (parts[part] < 0) {
2757 return LDAP_INVALID_SYNTAX;
2762 /* make first arg to % non-negative */
2763 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2768 } else if (part != 5) {
2775 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2778 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2785 struct berval *normalized )
2789 rc = check_time_syntax(val, 1, parts, NULL);
2790 if (rc != LDAP_SUCCESS) {
2794 normalized->bv_val = ch_malloc( 14 );
2795 if ( normalized->bv_val == NULL ) {
2796 return LBER_ERROR_MEMORY;
2799 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2800 parts[1], parts[2] + 1, parts[3] + 1,
2801 parts[4], parts[5], parts[6] );
2802 normalized->bv_len = 13;
2804 return LDAP_SUCCESS;
2814 return check_time_syntax(in, 1, parts, NULL);
2817 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2820 generalizedTimeValidate(
2825 struct berval fraction;
2826 return check_time_syntax(in, 0, parts, &fraction);
2830 generalizedTimeNormalize(
2835 struct berval *normalized,
2840 struct berval fraction;
2842 rc = check_time_syntax(val, 0, parts, &fraction);
2843 if (rc != LDAP_SUCCESS) {
2847 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2848 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2849 if ( BER_BVISNULL( normalized ) ) {
2850 return LBER_ERROR_MEMORY;
2853 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2854 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2855 parts[4], parts[5], parts[6] );
2856 if ( !BER_BVISEMPTY( &fraction ) ) {
2857 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2858 fraction.bv_val, fraction.bv_len );
2859 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2861 strcpy( normalized->bv_val + len-1, "Z" );
2862 normalized->bv_len = len;
2864 return LDAP_SUCCESS;
2868 generalizedTimeOrderingMatch(
2873 struct berval *value,
2874 void *assertedValue )
2876 struct berval *asserted = (struct berval *) assertedValue;
2877 ber_len_t v_len = value->bv_len;
2878 ber_len_t av_len = asserted->bv_len;
2880 /* ignore trailing 'Z' when comparing */
2881 int match = memcmp( value->bv_val, asserted->bv_val,
2882 (v_len < av_len ? v_len : av_len) - 1 );
2883 if ( match == 0 ) match = v_len - av_len;
2886 return LDAP_SUCCESS;
2889 /* Index generation function */
2890 int generalizedTimeIndexer(
2895 struct berval *prefix,
2904 BerValue bvtmp; /* 40 bit index */
2906 struct lutil_timet tt;
2908 bvtmp.bv_len = sizeof(tmp);
2910 for( i=0; values[i].bv_val != NULL; i++ ) {
2911 /* just count them */
2914 /* we should have at least one value at this point */
2917 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2919 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2920 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2921 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2922 /* Use 40 bits of time for key */
2923 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2924 lutil_tm2time( &tm, &tt );
2925 tmp[0] = tt.tt_gsec & 0xff;
2926 tmp[4] = tt.tt_sec & 0xff;
2928 tmp[3] = tt.tt_sec & 0xff;
2930 tmp[2] = tt.tt_sec & 0xff;
2932 tmp[1] = tt.tt_sec & 0xff;
2934 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2938 keys[j].bv_val = NULL;
2943 return LDAP_SUCCESS;
2946 /* Index generation function */
2947 int generalizedTimeFilter(
2952 struct berval *prefix,
2953 void * assertedValue,
2959 BerValue bvtmp; /* 40 bit index */
2960 BerValue *value = (BerValue *) assertedValue;
2962 struct lutil_timet tt;
2964 bvtmp.bv_len = sizeof(tmp);
2966 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2967 /* Use 40 bits of time for key */
2968 if ( value->bv_val && value->bv_len >= 10 &&
2969 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2971 lutil_tm2time( &tm, &tt );
2972 tmp[0] = tt.tt_gsec & 0xff;
2973 tmp[4] = tt.tt_sec & 0xff;
2975 tmp[3] = tt.tt_sec & 0xff;
2977 tmp[2] = tt.tt_sec & 0xff;
2979 tmp[1] = tt.tt_sec & 0xff;
2981 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2982 ber_dupbv_x(keys, &bvtmp, ctx );
2983 keys[1].bv_val = NULL;
2991 return LDAP_SUCCESS;
2995 deliveryMethodValidate(
2997 struct berval *val )
3000 #define LENOF(s) (sizeof(s)-1)
3001 struct berval tmp = *val;
3003 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3004 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3005 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3008 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3010 switch( tmp.bv_val[0] ) {
3013 if(( tmp.bv_len >= LENOF("any") ) &&
3014 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3016 tmp.bv_len -= LENOF("any");
3017 tmp.bv_val += LENOF("any");
3020 return LDAP_INVALID_SYNTAX;
3024 if(( tmp.bv_len >= LENOF("mhs") ) &&
3025 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3027 tmp.bv_len -= LENOF("mhs");
3028 tmp.bv_val += LENOF("mhs");
3031 return LDAP_INVALID_SYNTAX;
3035 if(( tmp.bv_len >= LENOF("physical") ) &&
3036 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3038 tmp.bv_len -= LENOF("physical");
3039 tmp.bv_val += LENOF("physical");
3042 return LDAP_INVALID_SYNTAX;
3045 case 'T': /* telex or teletex or telephone */
3046 if(( tmp.bv_len >= LENOF("telex") ) &&
3047 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3049 tmp.bv_len -= LENOF("telex");
3050 tmp.bv_val += LENOF("telex");
3053 if(( tmp.bv_len >= LENOF("teletex") ) &&
3054 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3056 tmp.bv_len -= LENOF("teletex");
3057 tmp.bv_val += LENOF("teletex");
3060 if(( tmp.bv_len >= LENOF("telephone") ) &&
3061 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3063 tmp.bv_len -= LENOF("telephone");
3064 tmp.bv_val += LENOF("telephone");
3067 return LDAP_INVALID_SYNTAX;
3070 case 'G': /* g3fax or g4fax */
3071 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3072 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3073 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3075 tmp.bv_len -= LENOF("g3fax");
3076 tmp.bv_val += LENOF("g3fax");
3079 return LDAP_INVALID_SYNTAX;
3083 if(( tmp.bv_len >= LENOF("ia5") ) &&
3084 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3086 tmp.bv_len -= LENOF("ia5");
3087 tmp.bv_val += LENOF("ia5");
3090 return LDAP_INVALID_SYNTAX;
3094 if(( tmp.bv_len >= LENOF("videotex") ) &&
3095 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3097 tmp.bv_len -= LENOF("videotex");
3098 tmp.bv_val += LENOF("videotex");
3101 return LDAP_INVALID_SYNTAX;
3104 return LDAP_INVALID_SYNTAX;
3107 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3109 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3113 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3117 return LDAP_INVALID_SYNTAX;
3119 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3128 nisNetgroupTripleValidate(
3130 struct berval *val )
3135 if ( BER_BVISEMPTY( val ) ) {
3136 return LDAP_INVALID_SYNTAX;
3139 p = (char *)val->bv_val;
3140 e = p + val->bv_len;
3142 if ( *p != '(' /*')'*/ ) {
3143 return LDAP_INVALID_SYNTAX;
3146 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3150 return LDAP_INVALID_SYNTAX;
3153 } else if ( !AD_CHAR( *p ) ) {
3154 return LDAP_INVALID_SYNTAX;
3158 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3159 return LDAP_INVALID_SYNTAX;
3165 return LDAP_INVALID_SYNTAX;
3168 return LDAP_SUCCESS;
3172 bootParameterValidate(
3174 struct berval *val )
3178 if ( BER_BVISEMPTY( val ) ) {
3179 return LDAP_INVALID_SYNTAX;
3182 p = (char *)val->bv_val;
3183 e = p + val->bv_len;
3186 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3187 if ( !AD_CHAR( *p ) ) {
3188 return LDAP_INVALID_SYNTAX;
3193 return LDAP_INVALID_SYNTAX;
3197 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3198 if ( !AD_CHAR( *p ) ) {
3199 return LDAP_INVALID_SYNTAX;
3204 return LDAP_INVALID_SYNTAX;
3208 for ( p++; p < e; p++ ) {
3209 if ( !SLAP_PRINTABLE( *p ) ) {
3210 return LDAP_INVALID_SYNTAX;
3214 return LDAP_SUCCESS;
3218 firstComponentNormalize(
3223 struct berval *normalized,
3230 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3231 ber_dupbv_x( normalized, val, ctx );
3232 return LDAP_SUCCESS;
3235 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3237 if( val->bv_val[0] != '(' /*')'*/ &&
3238 val->bv_val[0] != '{' /*'}'*/ )
3240 return LDAP_INVALID_SYNTAX;
3243 /* trim leading white space */
3245 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3251 /* grab next word */
3252 comp.bv_val = &val->bv_val[len];
3253 len = val->bv_len - len;
3254 for( comp.bv_len = 0;
3255 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3261 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3262 rc = numericoidValidate( NULL, &comp );
3263 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3264 rc = integerValidate( NULL, &comp );
3266 rc = LDAP_INVALID_SYNTAX;
3270 if( rc == LDAP_SUCCESS ) {
3271 ber_dupbv_x( normalized, &comp, ctx );
3278 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3279 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3281 static slap_syntax_defs_rec syntax_defs[] = {
3282 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3283 X_BINARY X_NOT_H_R ")",
3284 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3285 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3287 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3289 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3291 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3292 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3294 SLAP_SYNTAX_BER, berValidate, NULL},
3295 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3296 0, bitStringValidate, NULL },
3297 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3298 0, booleanValidate, NULL},
3299 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3300 X_BINARY X_NOT_H_R ")",
3301 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3302 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3303 X_BINARY X_NOT_H_R ")",
3304 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3305 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3306 X_BINARY X_NOT_H_R ")",
3307 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3308 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3309 0, countryStringValidate, NULL},
3310 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3311 0, dnValidate, dnPretty},
3312 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3313 0, rdnValidate, rdnPretty},
3314 #ifdef LDAP_COMP_MATCH
3315 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3316 0, allComponentsValidate, NULL},
3317 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3318 0, componentFilterValidate, NULL},
3320 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3322 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3323 0, deliveryMethodValidate, NULL},
3324 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3325 0, UTF8StringValidate, NULL},
3326 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3328 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3330 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3332 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3334 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3336 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3337 0, printablesStringValidate, NULL},
3338 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3339 SLAP_SYNTAX_BLOB, NULL, NULL},
3340 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3341 0, generalizedTimeValidate, NULL},
3342 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3344 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3345 0, IA5StringValidate, NULL},
3346 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3347 0, integerValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3349 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3350 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3352 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3354 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3356 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3358 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3360 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3361 0, nameUIDValidate, nameUIDPretty },
3362 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3364 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3365 0, numericStringValidate, NULL},
3366 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3368 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3369 0, numericoidValidate, NULL},
3370 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3371 0, IA5StringValidate, NULL},
3372 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3373 0, blobValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3375 0, UTF8StringValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3378 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3380 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3381 0, printableStringValidate, NULL},
3382 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3383 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3384 0, subtreeSpecificationValidate, NULL},
3385 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3386 X_BINARY X_NOT_H_R ")",
3387 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3388 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3389 0, printableStringValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3392 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3393 0, printablesStringValidate, NULL},
3394 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3395 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3396 0, utcTimeValidate, NULL},
3398 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3402 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3404 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3406 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3409 /* RFC 2307 NIS Syntaxes */
3410 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3411 0, nisNetgroupTripleValidate, NULL},
3412 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3413 0, bootParameterValidate, NULL},
3415 /* From PKIX *//* This OID is not published yet. */
3416 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3418 serialNumberAndIssuerValidate,
3419 serialNumberAndIssuerPretty},
3421 #ifdef SLAPD_ACI_ENABLED
3422 /* OpenLDAP Experimental Syntaxes */
3423 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3425 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3429 #ifdef SLAPD_AUTHPASSWD
3430 /* needs updating */
3431 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3432 SLAP_SYNTAX_HIDE, NULL, NULL},
3435 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3436 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3438 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3439 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3441 /* OpenLDAP Void Syntax */
3442 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3443 SLAP_SYNTAX_HIDE, inValidate, NULL},
3444 {NULL, 0, NULL, NULL}
3447 char *certificateExactMatchSyntaxes[] = {
3448 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3451 #ifdef LDAP_COMP_MATCH
3452 char *componentFilterMatchSyntaxes[] = {
3453 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3457 char *directoryStringSyntaxes[] = {
3458 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3461 char *integerFirstComponentMatchSyntaxes[] = {
3462 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3463 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3466 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3467 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3468 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3469 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3470 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3471 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3472 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3473 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3474 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3479 * Other matching rules in X.520 that we do not use (yet):
3481 * 2.5.13.25 uTCTimeMatch
3482 * 2.5.13.26 uTCTimeOrderingMatch
3483 * 2.5.13.31* directoryStringFirstComponentMatch
3484 * 2.5.13.32* wordMatch
3485 * 2.5.13.33* keywordMatch
3486 * 2.5.13.36 certificatePairExactMatch
3487 * 2.5.13.37 certificatePairMatch
3488 * 2.5.13.38 certificateListExactMatch
3489 * 2.5.13.39 certificateListMatch
3490 * 2.5.13.40 algorithmIdentifierMatch
3491 * 2.5.13.41* storedPrefixMatch
3492 * 2.5.13.42 attributeCertificateMatch
3493 * 2.5.13.43 readerAndKeyIDMatch
3494 * 2.5.13.44 attributeIntegrityMatch
3496 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3498 static slap_mrule_defs_rec mrule_defs[] = {
3500 * EQUALITY matching rules must be listed after associated APPROX
3501 * matching rules. So, we list all APPROX matching rules first.
3503 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3504 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3505 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3506 NULL, NULL, directoryStringApproxMatch,
3507 directoryStringApproxIndexer, directoryStringApproxFilter,
3510 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3511 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3512 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3513 NULL, NULL, IA5StringApproxMatch,
3514 IA5StringApproxIndexer, IA5StringApproxFilter,
3518 * Other matching rules
3521 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3522 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3523 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3524 NULL, NULL, octetStringMatch,
3525 octetStringIndexer, octetStringFilter,
3528 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3529 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3530 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3531 NULL, dnNormalize, dnMatch,
3532 octetStringIndexer, octetStringFilter,
3535 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3536 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3537 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3538 NULL, dnNormalize, dnRelativeMatch,
3542 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3543 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3544 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3545 NULL, dnNormalize, dnRelativeMatch,
3549 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3550 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3551 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3552 NULL, dnNormalize, dnRelativeMatch,
3556 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3557 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3558 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3559 NULL, dnNormalize, dnRelativeMatch,
3563 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3564 "SYNTAX 1.2.36.79672281.1.5.0 )",
3565 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3566 NULL, rdnNormalize, rdnMatch,
3567 octetStringIndexer, octetStringFilter,
3570 #ifdef LDAP_COMP_MATCH
3571 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3572 "SYNTAX 1.2.36.79672281.1.5.2 )",
3573 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3574 NULL, NULL , componentFilterMatch,
3575 octetStringIndexer, octetStringFilter,
3578 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3579 "SYNTAX 1.2.36.79672281.1.5.3 )",
3580 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3581 NULL, NULL , allComponentsMatch,
3582 octetStringIndexer, octetStringFilter,
3585 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3586 "SYNTAX 1.2.36.79672281.1.5.3 )",
3587 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3588 NULL, NULL , directoryComponentsMatch,
3589 octetStringIndexer, octetStringFilter,
3593 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3595 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3596 NULL, UTF8StringNormalize, octetStringMatch,
3597 octetStringIndexer, octetStringFilter,
3598 directoryStringApproxMatchOID },
3600 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3602 SLAP_MR_ORDERING, directoryStringSyntaxes,
3603 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3605 "caseIgnoreMatch" },
3607 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3609 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3610 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3611 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3612 "caseIgnoreMatch" },
3614 {"( 2.5.13.5 NAME 'caseExactMatch' "
3615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3616 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3617 NULL, UTF8StringNormalize, octetStringMatch,
3618 octetStringIndexer, octetStringFilter,
3619 directoryStringApproxMatchOID },
3621 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3623 SLAP_MR_ORDERING, directoryStringSyntaxes,
3624 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3628 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3629 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3630 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3631 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3632 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3635 {"( 2.5.13.8 NAME 'numericStringMatch' "
3636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3637 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3638 NULL, numericStringNormalize, octetStringMatch,
3639 octetStringIndexer, octetStringFilter,
3642 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3644 SLAP_MR_ORDERING, NULL,
3645 NULL, numericStringNormalize, octetStringOrderingMatch,
3647 "numericStringMatch" },
3649 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3651 SLAP_MR_SUBSTR, NULL,
3652 NULL, numericStringNormalize, octetStringSubstringsMatch,
3653 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3654 "numericStringMatch" },
3656 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3658 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3659 NULL, NULL, NULL, NULL, NULL, NULL },
3661 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3663 SLAP_MR_SUBSTR, NULL,
3664 NULL, NULL, NULL, NULL, NULL,
3665 "caseIgnoreListMatch" },
3667 {"( 2.5.13.13 NAME 'booleanMatch' "
3668 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3669 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3670 NULL, NULL, booleanMatch,
3671 octetStringIndexer, octetStringFilter,
3674 {"( 2.5.13.14 NAME 'integerMatch' "
3675 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3676 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3677 NULL, NULL, integerMatch,
3678 octetStringIndexer, octetStringFilter,
3681 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3683 SLAP_MR_ORDERING, NULL,
3684 NULL, NULL, integerMatch,
3688 {"( 2.5.13.16 NAME 'bitStringMatch' "
3689 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3690 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3691 NULL, NULL, octetStringMatch,
3692 octetStringIndexer, octetStringFilter,
3695 {"( 2.5.13.17 NAME 'octetStringMatch' "
3696 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3697 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3698 NULL, NULL, octetStringMatch,
3699 octetStringIndexer, octetStringFilter,
3702 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3703 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3704 SLAP_MR_ORDERING, NULL,
3705 NULL, NULL, octetStringOrderingMatch,
3707 "octetStringMatch" },
3709 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3710 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3711 SLAP_MR_SUBSTR, NULL,
3712 NULL, NULL, octetStringSubstringsMatch,
3713 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3714 "octetStringMatch" },
3716 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3717 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3718 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3720 telephoneNumberNormalize, octetStringMatch,
3721 octetStringIndexer, octetStringFilter,
3724 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3725 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3726 SLAP_MR_SUBSTR, NULL,
3727 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3728 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3729 "telephoneNumberMatch" },
3731 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3732 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3733 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3734 NULL, NULL, NULL, NULL, NULL, NULL },
3736 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3738 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3739 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3740 uniqueMemberIndexer, uniqueMemberFilter,
3743 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3745 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3746 NULL, NULL, NULL, NULL, NULL, NULL },
3748 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3750 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3751 NULL, generalizedTimeNormalize, octetStringMatch,
3752 generalizedTimeIndexer, generalizedTimeFilter,
3755 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3757 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3758 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3760 "generalizedTimeMatch" },
3762 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3763 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3764 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3765 integerFirstComponentMatchSyntaxes,
3766 NULL, firstComponentNormalize, integerMatch,
3767 octetStringIndexer, octetStringFilter,
3770 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3772 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3773 objectIdentifierFirstComponentMatchSyntaxes,
3774 NULL, firstComponentNormalize, octetStringMatch,
3775 octetStringIndexer, octetStringFilter,
3778 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3779 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3780 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3782 NULL, certificateExactNormalize, octetStringMatch,
3783 octetStringIndexer, octetStringFilter,
3785 NULL, NULL, NULL, NULL, NULL,
3789 {"( 2.5.13.35 NAME 'certificateMatch' "
3790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3791 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3793 NULL, NULL, octetStringMatch,
3794 octetStringIndexer, octetStringFilter,
3796 NULL, NULL, NULL, NULL, NULL,
3800 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3802 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3803 NULL, IA5StringNormalize, octetStringMatch,
3804 octetStringIndexer, octetStringFilter,
3805 IA5StringApproxMatchOID },
3807 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3809 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3810 NULL, IA5StringNormalize, octetStringMatch,
3811 octetStringIndexer, octetStringFilter,
3812 IA5StringApproxMatchOID },
3814 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3816 SLAP_MR_SUBSTR, NULL,
3817 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3818 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3819 "caseIgnoreIA5Match" },
3821 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3823 SLAP_MR_SUBSTR, NULL,
3824 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3825 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3826 "caseExactIA5Match" },
3828 #ifdef SLAPD_AUTHPASSWD
3829 /* needs updating */
3830 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3832 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3833 NULL, NULL, authPasswordMatch,
3838 #ifdef SLAPD_ACI_ENABLED
3839 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3840 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3841 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3842 NULL, NULL, OpenLDAPaciMatch,
3847 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3848 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3850 NULL, NULL, integerBitAndMatch,
3854 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3855 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3857 NULL, NULL, integerBitOrMatch,
3861 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3862 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3863 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3864 NULL, UUIDNormalize, octetStringMatch,
3865 octetStringIndexer, octetStringFilter,
3868 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3869 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3870 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3871 NULL, UUIDNormalize, octetStringOrderingMatch,
3872 octetStringIndexer, octetStringFilter,
3875 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3876 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3877 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3878 NULL, NULL, csnMatch,
3879 csnIndexer, csnFilter,
3882 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3883 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3884 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3885 NULL, NULL, csnOrderingMatch,
3889 {NULL, SLAP_MR_NONE, NULL,
3890 NULL, NULL, NULL, NULL, NULL,
3895 slap_schema_init( void )
3900 /* we should only be called once (from main) */
3901 assert( schema_init_done == 0 );
3903 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3904 res = register_syntax( &syntax_defs[i] );
3907 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3908 syntax_defs[i].sd_desc );
3913 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3914 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3915 mrule_defs[i].mrd_compat_syntaxes == NULL )
3918 "slap_schema_init: Ignoring unusable matching rule %s\n",
3919 mrule_defs[i].mrd_desc );
3923 res = register_matching_rule( &mrule_defs[i] );
3927 "slap_schema_init: Error registering matching rule %s\n",
3928 mrule_defs[i].mrd_desc );
3933 res = slap_schema_load();
3934 schema_init_done = 1;
3939 schema_destroy( void )