1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 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 /* 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 #ifdef SLAP_AUTHZ_SYNTAX
71 /* FIXME: temporary */
72 #define authzMatch octetStringMatch
73 #endif /* SLAP_AUTHZ_SYNTAX */
75 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
76 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
77 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
78 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
80 ldap_pvt_thread_mutex_t ad_undef_mutex;
81 ldap_pvt_thread_mutex_t oc_undef_mutex;
88 /* no value allowed */
89 return LDAP_INVALID_SYNTAX;
97 /* any value allowed */
101 #define berValidate blobValidate
108 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
109 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
116 static int certificateValidate( Syntax *syntax, struct berval *in )
119 unsigned char *p = (unsigned char *)in->bv_val;
121 xcert = d2i_X509(NULL, &p, in->bv_len);
122 if ( !xcert ) return LDAP_INVALID_SYNTAX;
127 #define certificateValidate sequenceValidate
136 struct berval *value,
137 void *assertedValue )
139 struct berval *asserted = (struct berval *) assertedValue;
140 int match = value->bv_len - asserted->bv_len;
143 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
151 octetStringOrderingMatch(
156 struct berval *value,
157 void *assertedValue )
159 struct berval *asserted = (struct berval *) assertedValue;
160 ber_len_t v_len = value->bv_len;
161 ber_len_t av_len = asserted->bv_len;
163 int match = memcmp( value->bv_val, asserted->bv_val,
164 (v_len < av_len ? v_len : av_len) );
166 if( match == 0 ) match = v_len - av_len;
174 HASH_CONTEXT *HASHcontext,
175 struct berval *prefix,
180 HASH_Init(HASHcontext);
181 if(prefix && prefix->bv_len > 0) {
182 HASH_Update(HASHcontext,
183 (unsigned char *)prefix->bv_val, prefix->bv_len);
185 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
186 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
187 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
193 HASH_CONTEXT *HASHcontext,
194 unsigned char *HASHdigest,
195 unsigned char *value,
198 HASH_CONTEXT ctx = *HASHcontext;
199 HASH_Update( &ctx, value, len );
200 HASH_Final( HASHdigest, &ctx );
203 /* Index generation function */
204 int octetStringIndexer(
209 struct berval *prefix,
217 HASH_CONTEXT HASHcontext;
218 unsigned char HASHdigest[HASH_BYTES];
219 struct berval digest;
220 digest.bv_val = (char *)HASHdigest;
221 digest.bv_len = sizeof(HASHdigest);
223 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
224 /* just count them */
227 /* we should have at least one value at this point */
230 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
232 slen = syntax->ssyn_oidlen;
233 mlen = mr->smr_oidlen;
235 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
236 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
237 hashIter( &HASHcontext, HASHdigest,
238 (unsigned char *)values[i].bv_val, values[i].bv_len );
239 ber_dupbv_x( &keys[i], &digest, ctx );
242 BER_BVZERO( &keys[i] );
249 /* Index generation function */
250 int octetStringFilter(
255 struct berval *prefix,
256 void * assertedValue,
262 HASH_CONTEXT HASHcontext;
263 unsigned char HASHdigest[HASH_BYTES];
264 struct berval *value = (struct berval *) assertedValue;
265 struct berval digest;
266 digest.bv_val = (char *)HASHdigest;
267 digest.bv_len = sizeof(HASHdigest);
269 slen = syntax->ssyn_oidlen;
270 mlen = mr->smr_oidlen;
272 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
274 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
275 hashIter( &HASHcontext, HASHdigest,
276 (unsigned char *)value->bv_val, value->bv_len );
278 ber_dupbv_x( keys, &digest, ctx );
279 BER_BVZERO( &keys[1] );
287 octetStringSubstringsMatch(
292 struct berval *value,
293 void *assertedValue )
296 SubstringsAssertion *sub = assertedValue;
297 struct berval left = *value;
301 /* Add up asserted input length */
302 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
303 inlen += sub->sa_initial.bv_len;
306 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
307 inlen += sub->sa_any[i].bv_len;
310 if ( !BER_BVISNULL( &sub->sa_final ) ) {
311 inlen += sub->sa_final.bv_len;
314 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
315 if ( inlen > left.bv_len ) {
320 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
321 sub->sa_initial.bv_len );
327 left.bv_val += sub->sa_initial.bv_len;
328 left.bv_len -= sub->sa_initial.bv_len;
329 inlen -= sub->sa_initial.bv_len;
332 if ( !BER_BVISNULL( &sub->sa_final ) ) {
333 if ( inlen > left.bv_len ) {
338 match = memcmp( sub->sa_final.bv_val,
339 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
340 sub->sa_final.bv_len );
346 left.bv_len -= sub->sa_final.bv_len;
347 inlen -= sub->sa_final.bv_len;
351 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
356 if ( inlen > left.bv_len ) {
357 /* not enough length */
362 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
366 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
373 idx = p - left.bv_val;
375 if ( idx >= left.bv_len ) {
376 /* this shouldn't happen */
383 if ( sub->sa_any[i].bv_len > left.bv_len ) {
384 /* not enough left */
389 match = memcmp( left.bv_val,
390 sub->sa_any[i].bv_val,
391 sub->sa_any[i].bv_len );
399 left.bv_val += sub->sa_any[i].bv_len;
400 left.bv_len -= sub->sa_any[i].bv_len;
401 inlen -= sub->sa_any[i].bv_len;
410 /* Substrings Index generation function */
412 octetStringSubstringsIndexer(
417 struct berval *prefix,
426 HASH_CONTEXT HCany, HCini, HCfin;
427 unsigned char HASHdigest[HASH_BYTES];
428 struct berval digest;
429 digest.bv_val = (char *)HASHdigest;
430 digest.bv_len = sizeof(HASHdigest);
434 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
435 /* count number of indices to generate */
436 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
437 if( values[i].bv_len >= index_substr_if_maxlen ) {
438 nkeys += index_substr_if_maxlen -
439 (index_substr_if_minlen - 1);
440 } else if( values[i].bv_len >= index_substr_if_minlen ) {
441 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
445 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
446 if( values[i].bv_len >= index_substr_any_len ) {
447 nkeys += values[i].bv_len - (index_substr_any_len - 1);
451 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
452 if( values[i].bv_len >= index_substr_if_maxlen ) {
453 nkeys += index_substr_if_maxlen -
454 (index_substr_if_minlen - 1);
455 } else if( values[i].bv_len >= index_substr_if_minlen ) {
456 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
462 /* no keys to generate */
467 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
469 slen = syntax->ssyn_oidlen;
470 mlen = mr->smr_oidlen;
472 if ( flags & SLAP_INDEX_SUBSTR_ANY )
473 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
474 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
475 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
476 if( flags & SLAP_INDEX_SUBSTR_FINAL )
477 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
480 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
483 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
484 ( values[i].bv_len >= index_substr_any_len ) )
486 max = values[i].bv_len - (index_substr_any_len - 1);
488 for( j=0; j<max; j++ ) {
489 hashIter( &HCany, HASHdigest,
490 (unsigned char *)&values[i].bv_val[j],
491 index_substr_any_len );
492 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
496 /* skip if too short */
497 if( values[i].bv_len < index_substr_if_minlen ) continue;
499 max = index_substr_if_maxlen < values[i].bv_len
500 ? index_substr_if_maxlen : values[i].bv_len;
502 for( j=index_substr_if_minlen; j<=max; j++ ) {
504 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
505 hashIter( &HCini, HASHdigest,
506 (unsigned char *)values[i].bv_val, j );
507 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
510 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
511 hashIter( &HCfin, HASHdigest,
512 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
513 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
520 BER_BVZERO( &keys[nkeys] );
531 octetStringSubstringsFilter (
536 struct berval *prefix,
537 void * assertedValue,
541 SubstringsAssertion *sa;
544 size_t slen, mlen, klen;
546 HASH_CONTEXT HASHcontext;
547 unsigned char HASHdigest[HASH_BYTES];
548 struct berval *value;
549 struct berval digest;
551 sa = (SubstringsAssertion *) assertedValue;
553 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
554 !BER_BVISNULL( &sa->sa_initial ) &&
555 sa->sa_initial.bv_len >= index_substr_if_minlen )
558 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
559 ( flags & SLAP_INDEX_SUBSTR_ANY ))
561 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
565 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
567 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
568 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
569 /* don't bother accounting with stepping */
570 nkeys += sa->sa_any[i].bv_len -
571 ( index_substr_any_len - 1 );
576 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
577 !BER_BVISNULL( &sa->sa_final ) &&
578 sa->sa_final.bv_len >= index_substr_if_minlen )
581 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
582 ( flags & SLAP_INDEX_SUBSTR_ANY ))
584 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
593 digest.bv_val = (char *)HASHdigest;
594 digest.bv_len = sizeof(HASHdigest);
596 slen = syntax->ssyn_oidlen;
597 mlen = mr->smr_oidlen;
599 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
602 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
603 !BER_BVISNULL( &sa->sa_initial ) &&
604 sa->sa_initial.bv_len >= index_substr_if_minlen )
606 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
607 value = &sa->sa_initial;
609 klen = index_substr_if_maxlen < value->bv_len
610 ? index_substr_if_maxlen : value->bv_len;
612 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
613 hashIter( &HASHcontext, HASHdigest,
614 (unsigned char *)value->bv_val, klen );
615 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
617 /* If initial is too long and we have subany indexed, use it
618 * to match the excess...
620 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
623 pre = SLAP_INDEX_SUBSTR_PREFIX;
624 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
625 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
627 hashIter( &HASHcontext, HASHdigest,
628 (unsigned char *)&value->bv_val[j], index_substr_any_len );
629 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
636 pre = SLAP_INDEX_SUBSTR_PREFIX;
637 klen = index_substr_any_len;
639 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
640 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
644 value = &sa->sa_any[i];
646 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
648 j <= value->bv_len - index_substr_any_len;
649 j += index_substr_any_step )
651 hashIter( &HASHcontext, HASHdigest,
652 (unsigned char *)&value->bv_val[j], klen );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
659 !BER_BVISNULL( &sa->sa_final ) &&
660 sa->sa_final.bv_len >= index_substr_if_minlen )
662 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
663 value = &sa->sa_final;
665 klen = index_substr_if_maxlen < value->bv_len
666 ? index_substr_if_maxlen : value->bv_len;
668 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
669 hashIter( &HASHcontext, HASHdigest,
670 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
671 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
673 /* If final is too long and we have subany indexed, use it
674 * to match the excess...
676 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
679 pre = SLAP_INDEX_SUBSTR_PREFIX;
680 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
681 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
683 hashIter( &HASHcontext, HASHdigest,
684 (unsigned char *)&value->bv_val[j], index_substr_any_len );
685 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
691 BER_BVZERO( &keys[nkeys] );
708 /* very unforgiving validation, requires no normalization
709 * before simplistic matching
711 if( in->bv_len < 3 ) {
712 return LDAP_INVALID_SYNTAX;
716 * RFC 2252 section 6.3 Bit String
717 * bitstring = "'" *binary-digit "'B"
718 * binary-digit = "0" / "1"
719 * example: '0101111101'B
722 if( in->bv_val[0] != '\'' ||
723 in->bv_val[in->bv_len - 2] != '\'' ||
724 in->bv_val[in->bv_len - 1] != 'B' )
726 return LDAP_INVALID_SYNTAX;
729 for( i = in->bv_len - 3; i > 0; i-- ) {
730 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
731 return LDAP_INVALID_SYNTAX;
739 * Syntax is [RFC2252]:
744 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
746 Values in this syntax are encoded according to the following BNF:
748 bitstring = "'" *binary-digit "'B"
750 binary-digit = "0" / "1"
754 6.21. Name And Optional UID
756 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
758 Values in this syntax are encoded according to the following BNF:
760 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
762 Although the '#' character may occur in a string representation of a
763 distinguished name, no additional special quoting is done. This
764 syntax has been added subsequent to RFC 1778.
768 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
771 * draft-ietf-ldapbis-syntaxes-xx.txt says:
776 A value of the Bit String syntax is a sequence of binary digits. The
777 LDAP-specific encoding of a value of this syntax is defined by the
780 BitString = SQUOTE *binary-digit SQUOTE "B"
782 binary-digit = "0" / "1"
784 The <SQUOTE> rule is defined in [MODELS].
789 The LDAP definition for the Bit String syntax is:
791 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
793 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
797 3.3.21. Name and Optional UID
799 A value of the Name and Optional UID syntax is the distinguished name
800 [MODELS] of an entity optionally accompanied by a unique identifier
801 that serves to differentiate the entity from others with an identical
804 The LDAP-specific encoding of a value of this syntax is defined by
807 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
809 The <BitString> rule is defined in Section 3.3.2. The
810 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
813 Note that although the '#' character may occur in the string
814 representation of a distinguished name, no additional escaping of
815 this character is performed when a <distinguishedName> is encoded in
816 a <NameAndOptionalUID>.
819 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
821 The LDAP definition for the Name and Optional UID syntax is:
823 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
825 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
829 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
832 1.4. Common ABNF Productions
835 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
837 SQUOTE = %x27 ; single quote ("'")
841 * Note: normalization strips any leading "0"s, unless the
842 * bit string is exactly "'0'B", so the normalized example,
843 * in slapd, would result in
845 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
847 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
848 * i.e. "#", doesn't have to be escaped except when at the
849 * beginning of a value, the definition of Name and Optional
850 * UID appears to be flawed, because there is no clear means
851 * to determine whether the UID part is present or not.
855 * cn=Someone,dc=example,dc=com#'1'B
857 * could be either a NameAndOptionalUID with trailing UID, i.e.
859 * DN = "cn=Someone,dc=example,dc=com"
862 * or a NameAndOptionalUID with no trailing UID, and the AVA
863 * in the last RDN made of
866 * attributeValue = com#'1'B
868 * in fact "com#'1'B" is a valid IA5 string.
870 * As a consequence, current slapd code assumes that the
871 * presence of portions of a BitString at the end of the string
872 * representation of a NameAndOptionalUID means a BitString
873 * is expected, and cause an error otherwise. This is quite
874 * arbitrary, and might change in the future.
884 struct berval dn, uid;
886 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
888 ber_dupbv( &dn, in );
889 if( !dn.bv_val ) return LDAP_OTHER;
891 /* if there's a "#", try bitStringValidate()... */
892 uid.bv_val = strrchr( dn.bv_val, '#' );
893 if ( !BER_BVISNULL( &uid ) ) {
895 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
897 rc = bitStringValidate( NULL, &uid );
898 if ( rc == LDAP_SUCCESS ) {
899 /* in case of success, trim the UID,
900 * otherwise treat it as part of the DN */
901 dn.bv_len -= uid.bv_len + 1;
902 uid.bv_val[-1] = '\0';
906 rc = dnValidate( NULL, &dn );
908 ber_memfree( dn.bv_val );
919 assert( val != NULL );
920 assert( out != NULL );
923 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
925 if( BER_BVISEMPTY( val ) ) {
926 ber_dupbv_x( out, val, ctx );
928 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
929 return LDAP_INVALID_SYNTAX;
933 struct berval dnval = *val;
934 struct berval uidval = BER_BVNULL;
936 uidval.bv_val = strrchr( val->bv_val, '#' );
937 if ( !BER_BVISNULL( &uidval ) ) {
939 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
941 rc = bitStringValidate( NULL, &uidval );
943 if ( rc == LDAP_SUCCESS ) {
944 ber_dupbv_x( &dnval, val, ctx );
945 dnval.bv_len -= uidval.bv_len + 1;
946 dnval.bv_val[dnval.bv_len] = '\0';
949 BER_BVZERO( &uidval );
953 rc = dnPretty( syntax, &dnval, out, ctx );
954 if ( dnval.bv_val != val->bv_val ) {
955 slap_sl_free( dnval.bv_val, ctx );
957 if( rc != LDAP_SUCCESS ) {
961 if( !BER_BVISNULL( &uidval ) ) {
965 tmp = slap_sl_realloc( out->bv_val, out->bv_len
966 + STRLENOF( "#" ) + uidval.bv_len + 1,
969 ber_memfree_x( out->bv_val, ctx );
973 out->bv_val[out->bv_len++] = '#';
974 out->bv_val[out->bv_len++] = '\'';
976 got1 = uidval.bv_len < sizeof("'0'B");
977 for( i = 1; i < uidval.bv_len - 2; i++ ) {
978 c = uidval.bv_val[i];
981 if( got1 ) out->bv_val[out->bv_len++] = c;
985 out->bv_val[out->bv_len++] = c;
990 out->bv_val[out->bv_len++] = '\'';
991 out->bv_val[out->bv_len++] = 'B';
992 out->bv_val[out->bv_len] = '\0';
996 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1002 uniqueMemberNormalize(
1007 struct berval *normalized,
1013 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1015 ber_dupbv_x( &out, val, ctx );
1016 if ( BER_BVISEMPTY( &out ) ) {
1020 struct berval uid = BER_BVNULL;
1022 uid.bv_val = strrchr( out.bv_val, '#' );
1023 if ( !BER_BVISNULL( &uid ) ) {
1025 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1027 rc = bitStringValidate( NULL, &uid );
1028 if ( rc == LDAP_SUCCESS ) {
1029 uid.bv_val[-1] = '\0';
1030 out.bv_len -= uid.bv_len + 1;
1036 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1038 if( rc != LDAP_SUCCESS ) {
1039 slap_sl_free( out.bv_val, ctx );
1040 return LDAP_INVALID_SYNTAX;
1043 if( !BER_BVISNULL( &uid ) ) {
1046 tmp = ch_realloc( normalized->bv_val,
1047 normalized->bv_len + uid.bv_len
1048 + STRLENOF("#") + 1 );
1049 if ( tmp == NULL ) {
1050 ber_memfree_x( normalized->bv_val, ctx );
1054 normalized->bv_val = tmp;
1056 /* insert the separator */
1057 normalized->bv_val[normalized->bv_len++] = '#';
1059 /* append the UID */
1060 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1061 uid.bv_val, uid.bv_len );
1062 normalized->bv_len += uid.bv_len;
1065 normalized->bv_val[normalized->bv_len] = '\0';
1068 slap_sl_free( out.bv_val, ctx );
1071 return LDAP_SUCCESS;
1080 struct berval *value,
1081 void *assertedValue )
1084 struct berval *asserted = (struct berval *) assertedValue;
1085 struct berval assertedDN = *asserted;
1086 struct berval assertedUID = BER_BVNULL;
1087 struct berval valueDN = *value;
1088 struct berval valueUID = BER_BVNULL;
1089 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1091 if ( !BER_BVISEMPTY( asserted ) ) {
1092 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1093 if ( !BER_BVISNULL( &assertedUID ) ) {
1094 assertedUID.bv_val++;
1095 assertedUID.bv_len = assertedDN.bv_len
1096 - ( assertedUID.bv_val - assertedDN.bv_val );
1098 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1099 assertedDN.bv_len -= assertedUID.bv_len + 1;
1102 BER_BVZERO( &assertedUID );
1107 if ( !BER_BVISEMPTY( value ) ) {
1109 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1110 if ( !BER_BVISNULL( &valueUID ) ) {
1112 valueUID.bv_len = valueDN.bv_len
1113 - ( valueUID.bv_val - valueDN.bv_val );
1115 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1116 valueDN.bv_len -= valueUID.bv_len + 1;
1119 BER_BVZERO( &valueUID );
1124 if( valueUID.bv_len && assertedUID.bv_len ) {
1125 match = valueUID.bv_len - assertedUID.bv_len;
1128 return LDAP_SUCCESS;
1131 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1134 return LDAP_SUCCESS;
1137 } else if ( !approx && valueUID.bv_len ) {
1140 return LDAP_SUCCESS;
1142 } else if ( !approx && assertedUID.bv_len ) {
1145 return LDAP_SUCCESS;
1148 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1152 uniqueMemberIndexer(
1157 struct berval *prefix,
1165 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1166 /* just count them */
1170 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1172 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1173 struct berval assertedDN = values[i];
1174 struct berval assertedUID = BER_BVNULL;
1176 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1177 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1178 if ( !BER_BVISNULL( &assertedUID ) ) {
1179 assertedUID.bv_val++;
1180 assertedUID.bv_len = assertedDN.bv_len
1181 - ( assertedUID.bv_val - assertedDN.bv_val );
1183 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1184 assertedDN.bv_len -= assertedUID.bv_len + 1;
1187 BER_BVZERO( &assertedUID );
1192 dnvalues[i] = assertedDN;
1194 BER_BVZERO( &dnvalues[i] );
1196 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1197 dnvalues, keysp, ctx );
1199 slap_sl_free( dnvalues, ctx );
1209 struct berval *prefix,
1210 void * assertedValue,
1214 struct berval *asserted = (struct berval *) assertedValue;
1215 struct berval assertedDN = *asserted;
1216 struct berval assertedUID = BER_BVNULL;
1218 if ( !BER_BVISEMPTY( asserted ) ) {
1219 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1220 if ( !BER_BVISNULL( &assertedUID ) ) {
1221 assertedUID.bv_val++;
1222 assertedUID.bv_len = assertedDN.bv_len
1223 - ( assertedUID.bv_val - assertedDN.bv_val );
1225 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1226 assertedDN.bv_len -= assertedUID.bv_len + 1;
1229 BER_BVZERO( &assertedUID );
1234 return octetStringFilter( use, flags, syntax, mr, prefix,
1235 &assertedDN, keysp, ctx );
1240 * Handling boolean syntax and matching is quite rigid.
1241 * A more flexible approach would be to allow a variety
1242 * of strings to be normalized and prettied into TRUE
1250 /* very unforgiving validation, requires no normalization
1251 * before simplistic matching
1254 if( in->bv_len == 4 ) {
1255 if( bvmatch( in, &slap_true_bv ) ) {
1256 return LDAP_SUCCESS;
1258 } else if( in->bv_len == 5 ) {
1259 if( bvmatch( in, &slap_false_bv ) ) {
1260 return LDAP_SUCCESS;
1264 return LDAP_INVALID_SYNTAX;
1273 struct berval *value,
1274 void *assertedValue )
1276 /* simplistic matching allowed by rigid validation */
1277 struct berval *asserted = (struct berval *) assertedValue;
1278 *matchp = value->bv_len != asserted->bv_len;
1279 return LDAP_SUCCESS;
1282 /*-------------------------------------------------------------------
1283 LDAP/X.500 string syntax / matching rules have a few oddities. This
1284 comment attempts to detail how slapd(8) treats them.
1287 StringSyntax X.500 LDAP Matching/Comments
1288 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1289 PrintableString subset subset i/e + ignore insignificant spaces
1290 PrintableString subset subset i/e + ignore insignificant spaces
1291 NumericString subset subset ignore all spaces
1292 IA5String ASCII ASCII i/e + ignore insignificant spaces
1293 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1295 TelephoneNumber subset subset i + ignore all spaces and "-"
1297 See draft-ietf-ldapbis-strpro for details (once published).
1301 In X.500(93), a directory string can be either a PrintableString,
1302 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1303 In later versions, more CHOICEs were added. In all cases the string
1306 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1307 A directory string cannot be zero length.
1309 For matching, there are both case ignore and exact rules. Both
1310 also require that "insignificant" spaces be ignored.
1311 spaces before the first non-space are ignored;
1312 spaces after the last non-space are ignored;
1313 spaces after a space are ignored.
1314 Note: by these rules (and as clarified in X.520), a string of only
1315 spaces is to be treated as if held one space, not empty (which
1316 would be a syntax error).
1319 In ASN.1, numeric string is just a string of digits and spaces
1320 and could be empty. However, in X.500, all attribute values of
1321 numeric string carry a non-empty constraint. For example:
1323 internationalISDNNumber ATTRIBUTE ::= {
1324 WITH SYNTAX InternationalISDNNumber
1325 EQUALITY MATCHING RULE numericStringMatch
1326 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1327 ID id-at-internationalISDNNumber }
1328 InternationalISDNNumber ::=
1329 NumericString (SIZE(1..ub-international-isdn-number))
1331 Unforunately, some assertion values are don't carry the same
1332 constraint (but its unclear how such an assertion could ever
1333 be true). In LDAP, there is one syntax (numericString) not two
1334 (numericString with constraint, numericString without constraint).
1335 This should be treated as numericString with non-empty constraint.
1336 Note that while someone may have no ISDN number, there are no ISDN
1337 numbers which are zero length.
1339 In matching, spaces are ignored.
1342 In ASN.1, Printable string is just a string of printable characters
1343 and can be empty. In X.500, semantics much like NumericString (see
1344 serialNumber for a like example) excepting uses insignificant space
1345 handling instead of ignore all spaces.
1348 Basically same as PrintableString. There are no examples in X.500,
1349 but same logic applies. So we require them to be non-empty as
1352 -------------------------------------------------------------------*/
1361 unsigned char *u = (unsigned char *)in->bv_val;
1363 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1364 /* directory strings cannot be empty */
1365 return LDAP_INVALID_SYNTAX;
1368 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1369 /* get the length indicated by the first byte */
1370 len = LDAP_UTF8_CHARLEN2( u, len );
1372 /* very basic checks */
1375 if( (u[5] & 0xC0) != 0x80 ) {
1376 return LDAP_INVALID_SYNTAX;
1379 if( (u[4] & 0xC0) != 0x80 ) {
1380 return LDAP_INVALID_SYNTAX;
1383 if( (u[3] & 0xC0) != 0x80 ) {
1384 return LDAP_INVALID_SYNTAX;
1387 if( (u[2] & 0xC0 )!= 0x80 ) {
1388 return LDAP_INVALID_SYNTAX;
1391 if( (u[1] & 0xC0) != 0x80 ) {
1392 return LDAP_INVALID_SYNTAX;
1395 /* CHARLEN already validated it */
1398 return LDAP_INVALID_SYNTAX;
1401 /* make sure len corresponds with the offset
1402 to the next character */
1403 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1407 return LDAP_INVALID_SYNTAX;
1410 return LDAP_SUCCESS;
1414 UTF8StringNormalize(
1419 struct berval *normalized,
1422 struct berval tmp, nvalue;
1426 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1428 if( BER_BVISNULL( val ) ) {
1429 /* assume we're dealing with a syntax (e.g., UTF8String)
1430 * which allows empty strings
1432 BER_BVZERO( normalized );
1433 return LDAP_SUCCESS;
1436 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1437 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1438 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1439 ? LDAP_UTF8_APPROX : 0;
1441 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1446 /* collapse spaces (in place) */
1448 nvalue.bv_val = tmp.bv_val;
1450 /* trim leading spaces? */
1451 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1452 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1454 for( i = 0; i < tmp.bv_len; i++) {
1455 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1456 if( wasspace++ == 0 ) {
1457 /* trim repeated spaces */
1458 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1462 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1466 if( !BER_BVISEMPTY( &nvalue ) ) {
1467 /* trim trailing space? */
1469 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1470 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1474 nvalue.bv_val[nvalue.bv_len] = '\0';
1477 /* string of all spaces is treated as one space */
1478 nvalue.bv_val[0] = ' ';
1479 nvalue.bv_val[1] = '\0';
1483 *normalized = nvalue;
1484 return LDAP_SUCCESS;
1488 directoryStringSubstringsMatch(
1493 struct berval *value,
1494 void *assertedValue )
1497 SubstringsAssertion *sub = assertedValue;
1498 struct berval left = *value;
1502 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1503 if ( sub->sa_initial.bv_len > left.bv_len ) {
1504 /* not enough left */
1509 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1510 sub->sa_initial.bv_len );
1516 left.bv_val += sub->sa_initial.bv_len;
1517 left.bv_len -= sub->sa_initial.bv_len;
1519 priorspace = ASCII_SPACE(
1520 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1523 if ( sub->sa_any ) {
1524 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1528 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1529 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1531 /* allow next space to match */
1538 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1542 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1543 /* not enough left */
1548 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1555 idx = p - left.bv_val;
1557 if ( idx >= left.bv_len ) {
1558 /* this shouldn't happen */
1565 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1566 /* not enough left */
1571 match = memcmp( left.bv_val,
1572 sub->sa_any[i].bv_val,
1573 sub->sa_any[i].bv_len );
1581 left.bv_val += sub->sa_any[i].bv_len;
1582 left.bv_len -= sub->sa_any[i].bv_len;
1584 priorspace = ASCII_SPACE(
1585 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1589 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1590 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1591 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1593 /* allow next space to match */
1598 if ( sub->sa_final.bv_len > left.bv_len ) {
1599 /* not enough left */
1604 match = memcmp( sub->sa_final.bv_val,
1605 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1606 sub->sa_final.bv_len );
1615 return LDAP_SUCCESS;
1618 #if defined(SLAPD_APPROX_INITIALS)
1619 # define SLAPD_APPROX_DELIMITER "._ "
1620 # define SLAPD_APPROX_WORDLEN 2
1622 # define SLAPD_APPROX_DELIMITER " "
1623 # define SLAPD_APPROX_WORDLEN 1
1632 struct berval *value,
1633 void *assertedValue )
1635 struct berval *nval, *assertv;
1636 char *val, **values, **words, *c;
1637 int i, count, len, nextchunk=0, nextavail=0;
1639 /* Yes, this is necessary */
1640 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1641 if( nval == NULL ) {
1643 return LDAP_SUCCESS;
1646 /* Yes, this is necessary */
1647 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1648 NULL, LDAP_UTF8_APPROX, NULL );
1649 if( assertv == NULL ) {
1652 return LDAP_SUCCESS;
1655 /* Isolate how many words there are */
1656 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1657 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1658 if ( c == NULL ) break;
1663 /* Get a phonetic copy of each word */
1664 words = (char **)ch_malloc( count * sizeof(char *) );
1665 values = (char **)ch_malloc( count * sizeof(char *) );
1666 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1668 values[i] = phonetic(c);
1671 /* Work through the asserted value's words, to see if at least some
1672 of the words are there, in the same order. */
1674 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1675 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1680 #if defined(SLAPD_APPROX_INITIALS)
1681 else if( len == 1 ) {
1682 /* Single letter words need to at least match one word's initial */
1683 for( i=nextavail; i<count; i++ )
1684 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1691 /* Isolate the next word in the asserted value and phonetic it */
1692 assertv->bv_val[nextchunk+len] = '\0';
1693 val = phonetic( assertv->bv_val + nextchunk );
1695 /* See if this phonetic chunk is in the remaining words of *value */
1696 for( i=nextavail; i<count; i++ ){
1697 if( !strcmp( val, values[i] ) ){
1705 /* This chunk in the asserted value was NOT within the *value. */
1711 /* Go on to the next word in the asserted value */
1715 /* If some of the words were seen, call it a match */
1716 if( nextavail > 0 ) {
1723 /* Cleanup allocs */
1724 ber_bvfree( assertv );
1725 for( i=0; i<count; i++ ) {
1726 ch_free( values[i] );
1732 return LDAP_SUCCESS;
1741 struct berval *prefix,
1747 int i,j, len, wordcount, keycount=0;
1748 struct berval *newkeys;
1749 BerVarray keys=NULL;
1751 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1752 struct berval val = BER_BVNULL;
1753 /* Yes, this is necessary */
1754 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1755 assert( !BER_BVISNULL( &val ) );
1757 /* Isolate how many words there are. There will be a key for each */
1758 for( wordcount = 0, c = val.bv_val; *c; c++) {
1759 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1760 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1762 if (*c == '\0') break;
1766 /* Allocate/increase storage to account for new keys */
1767 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1768 * sizeof(struct berval) );
1769 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1770 if( keys ) ch_free( keys );
1773 /* Get a phonetic copy of each word */
1774 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1776 if( len < SLAPD_APPROX_WORDLEN ) continue;
1777 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1782 ber_memfree( val.bv_val );
1784 BER_BVZERO( &keys[keycount] );
1787 return LDAP_SUCCESS;
1796 struct berval *prefix,
1797 void * assertedValue,
1806 /* Yes, this is necessary */
1807 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1808 NULL, LDAP_UTF8_APPROX, NULL );
1809 if( val == NULL || BER_BVISNULL( val ) ) {
1810 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1811 BER_BVZERO( &keys[0] );
1814 return LDAP_SUCCESS;
1817 /* Isolate how many words there are. There will be a key for each */
1818 for( count = 0,c = val->bv_val; *c; c++) {
1819 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1820 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1822 if (*c == '\0') break;
1826 /* Allocate storage for new keys */
1827 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1829 /* Get a phonetic copy of each word */
1830 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1832 if( len < SLAPD_APPROX_WORDLEN ) continue;
1833 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1839 BER_BVZERO( &keys[count] );
1842 return LDAP_SUCCESS;
1845 /* Remove all spaces and '-' characters */
1847 telephoneNumberNormalize(
1852 struct berval *normalized,
1857 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1859 /* validator should have refused an empty string */
1860 assert( !BER_BVISEMPTY( val ) );
1862 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1864 for( p = val->bv_val; *p; p++ ) {
1865 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1871 normalized->bv_len = q - normalized->bv_val;
1873 if( BER_BVISEMPTY( normalized ) ) {
1874 slap_sl_free( normalized->bv_val, ctx );
1875 BER_BVZERO( normalized );
1876 return LDAP_INVALID_SYNTAX;
1879 return LDAP_SUCCESS;
1887 struct berval val = *in;
1889 if( BER_BVISEMPTY( &val ) ) {
1890 /* disallow empty strings */
1891 return LDAP_INVALID_SYNTAX;
1894 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1895 if ( val.bv_len == 1 ) {
1896 return LDAP_SUCCESS;
1899 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1906 while ( OID_LEADCHAR( val.bv_val[0] )) {
1910 if ( val.bv_len == 0 ) {
1911 return LDAP_SUCCESS;
1915 if( !OID_SEPARATOR( val.bv_val[0] )) {
1923 return LDAP_INVALID_SYNTAX;
1932 struct berval val = *in;
1934 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1936 if ( val.bv_val[0] == '-' ) {
1940 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1941 return LDAP_INVALID_SYNTAX;
1944 if( val.bv_val[0] == '0' ) { /* "-0" */
1945 return LDAP_INVALID_SYNTAX;
1948 } else if ( val.bv_val[0] == '0' ) {
1949 if( val.bv_len > 1 ) { /* "0<more>" */
1950 return LDAP_INVALID_SYNTAX;
1953 return LDAP_SUCCESS;
1956 for( i=0; i < val.bv_len; i++ ) {
1957 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1958 return LDAP_INVALID_SYNTAX;
1962 return LDAP_SUCCESS;
1971 struct berval *value,
1972 void *assertedValue )
1974 struct berval *asserted = (struct berval *) assertedValue;
1975 int vsign = 1, asign = 1; /* default sign = '+' */
1980 if( v.bv_val[0] == '-' ) {
1986 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1989 if( a.bv_val[0] == '-' ) {
1995 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1997 match = vsign - asign;
1999 match = ( v.bv_len != a.bv_len
2000 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2001 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2002 if( vsign < 0 ) match = -match;
2006 return LDAP_SUCCESS;
2010 countryStringValidate(
2012 struct berval *val )
2014 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2016 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2017 return LDAP_INVALID_SYNTAX;
2019 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2020 return LDAP_INVALID_SYNTAX;
2023 return LDAP_SUCCESS;
2027 printableStringValidate(
2029 struct berval *val )
2033 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2035 for(i=0; i < val->bv_len; i++) {
2036 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2037 return LDAP_INVALID_SYNTAX;
2041 return LDAP_SUCCESS;
2045 printablesStringValidate(
2047 struct berval *val )
2051 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2053 for(i=0,len=0; i < val->bv_len; i++) {
2054 int c = val->bv_val[i];
2058 return LDAP_INVALID_SYNTAX;
2062 } else if ( SLAP_PRINTABLE(c) ) {
2065 return LDAP_INVALID_SYNTAX;
2070 return LDAP_INVALID_SYNTAX;
2073 return LDAP_SUCCESS;
2079 struct berval *val )
2083 for(i=0; i < val->bv_len; i++) {
2084 if( !LDAP_ASCII(val->bv_val[i]) ) {
2085 return LDAP_INVALID_SYNTAX;
2089 return LDAP_SUCCESS;
2098 struct berval *normalized,
2102 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2104 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2108 /* Ignore initial whitespace */
2109 while ( ASCII_SPACE( *p ) ) p++;
2111 normalized->bv_val = ber_strdup_x( p, ctx );
2112 p = q = normalized->bv_val;
2115 if ( ASCII_SPACE( *p ) ) {
2118 /* Ignore the extra whitespace */
2119 while ( ASCII_SPACE( *p ) ) {
2123 } else if ( casefold ) {
2124 /* Most IA5 rules require casefolding */
2125 *q++ = TOLOWER(*p); p++;
2132 assert( normalized->bv_val <= p );
2136 * If the string ended in space, backup the pointer one
2137 * position. One is enough because the above loop collapsed
2138 * all whitespace to a single space.
2140 if ( ASCII_SPACE( q[-1] ) ) --q;
2142 /* null terminate */
2145 normalized->bv_len = q - normalized->bv_val;
2147 return LDAP_SUCCESS;
2156 if( in->bv_len != 36 ) {
2157 return LDAP_INVALID_SYNTAX;
2160 for( i=0; i<36; i++ ) {
2166 if( in->bv_val[i] != '-' ) {
2167 return LDAP_INVALID_SYNTAX;
2171 if( !ASCII_HEX( in->bv_val[i]) ) {
2172 return LDAP_INVALID_SYNTAX;
2177 return LDAP_SUCCESS;
2188 int rc=LDAP_INVALID_SYNTAX;
2190 assert( in != NULL );
2191 assert( out != NULL );
2193 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2196 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2198 for( i=0; i<36; i++ ) {
2204 if( in->bv_val[i] != '-' ) {
2207 out->bv_val[i] = '-';
2211 if( !ASCII_HEX( in->bv_val[i]) ) {
2214 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2219 out->bv_val[ out->bv_len ] = '\0';
2223 slap_sl_free( out->bv_val, ctx );
2236 struct berval *normalized,
2239 unsigned char octet = '\0';
2242 normalized->bv_len = 16;
2243 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2245 for( i=0, j=0; i<36; i++ ) {
2246 unsigned char nibble;
2247 if( val->bv_val[i] == '-' ) {
2250 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2251 nibble = val->bv_val[i] - '0';
2253 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2254 nibble = val->bv_val[i] - ('a'-10);
2256 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2257 nibble = val->bv_val[i] - ('A'-10);
2260 slap_sl_free( normalized->bv_val, ctx );
2261 return LDAP_INVALID_SYNTAX;
2266 normalized->bv_val[j>>1] = octet;
2268 octet = nibble << 4;
2273 normalized->bv_val[normalized->bv_len] = 0;
2274 return LDAP_SUCCESS;
2280 numericStringValidate(
2286 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2288 for(i=0; i < in->bv_len; i++) {
2289 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2290 return LDAP_INVALID_SYNTAX;
2294 return LDAP_SUCCESS;
2298 numericStringNormalize(
2303 struct berval *normalized,
2306 /* removal all spaces */
2309 assert( !BER_BVISEMPTY( val ) );
2311 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2314 q = normalized->bv_val;
2317 if ( ASCII_SPACE( *p ) ) {
2318 /* Ignore whitespace */
2325 /* we should have copied no more then is in val */
2326 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2328 /* null terminate */
2331 normalized->bv_len = q - normalized->bv_val;
2333 if( BER_BVISEMPTY( normalized ) ) {
2334 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2335 normalized->bv_val[0] = ' ';
2336 normalized->bv_val[1] = '\0';
2337 normalized->bv_len = 1;
2340 return LDAP_SUCCESS;
2344 * Integer conversion macros that will use the largest available
2347 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2348 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2349 # define SLAP_LONG long long
2351 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2352 # define SLAP_LONG long
2353 #endif /* HAVE_STRTOLL ... */
2361 struct berval *value,
2362 void *assertedValue )
2364 SLAP_LONG lValue, lAssertedValue;
2367 /* safe to assume integers are NUL terminated? */
2368 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2369 if( errno == ERANGE )
2371 return LDAP_CONSTRAINT_VIOLATION;
2374 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2376 if( errno == ERANGE )
2378 return LDAP_CONSTRAINT_VIOLATION;
2381 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2382 return LDAP_SUCCESS;
2391 struct berval *value,
2392 void *assertedValue )
2394 SLAP_LONG lValue, lAssertedValue;
2397 /* safe to assume integers are NUL terminated? */
2398 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2399 if( errno == ERANGE )
2401 return LDAP_CONSTRAINT_VIOLATION;
2404 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2406 if( errno == ERANGE )
2408 return LDAP_CONSTRAINT_VIOLATION;
2411 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2412 return LDAP_SUCCESS;
2416 serialNumberAndIssuerValidate(
2422 struct berval sn, i;
2423 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2425 i.bv_val = ber_bvchr( in, '$' );
2426 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2428 sn.bv_val = in->bv_val;
2429 sn.bv_len = i.bv_val - in->bv_val;
2432 i.bv_len = in->bv_len - (sn.bv_len + 1);
2434 /* validate serial number (strict for now) */
2435 for( n=0; n < sn.bv_len; n++ ) {
2436 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2440 rc = dnValidate( NULL, &i );
2441 if( rc ) return LDAP_INVALID_SYNTAX;
2443 return LDAP_SUCCESS;
2447 serialNumberAndIssuerPretty(
2455 struct berval sn, i, newi;
2457 assert( val != NULL );
2458 assert( out != NULL );
2460 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2461 val->bv_val, 0, 0 );
2463 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2465 i.bv_val = ber_bvchr( val, '$' );
2466 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2468 sn.bv_val = val->bv_val;
2469 sn.bv_len = i.bv_val - val->bv_val;
2472 i.bv_len = val->bv_len - (sn.bv_len + 1);
2474 /* eat leading zeros */
2475 for( n=0; n < (sn.bv_len-1); n++ ) {
2476 if( sn.bv_val[n] != '0' ) break;
2481 for( n=0; n < sn.bv_len; n++ ) {
2482 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2486 rc = dnPretty( syntax, &i, &newi, ctx );
2487 if( rc ) return LDAP_INVALID_SYNTAX;
2489 /* make room from sn + "$" */
2490 out->bv_len = sn.bv_len + newi.bv_len + 1;
2491 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2493 if( out->bv_val == NULL ) {
2495 slap_sl_free( newi.bv_val, ctx );
2499 /* push issuer over */
2500 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2501 /* insert sn and "$" */
2502 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2503 out->bv_val[sn.bv_len] = '$';
2505 out->bv_val[out->bv_len] = '\0';
2507 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2508 out->bv_val, 0, 0 );
2510 return LDAP_SUCCESS;
2514 * This routine is called by certificateExactNormalize when
2515 * certificateExactNormalize receives a search string instead of
2516 * a certificate. This routine checks if the search value is valid
2517 * and then returns the normalized value
2520 serialNumberAndIssuerNormalize(
2530 struct berval sn, i, newi;
2532 assert( val != NULL );
2533 assert( out != NULL );
2535 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2536 val->bv_val, 0, 0 );
2538 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2540 i.bv_val = ber_bvchr( val, '$' );
2541 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2543 sn.bv_val = val->bv_val;
2544 sn.bv_len = i.bv_val - val->bv_val;
2547 i.bv_len = val->bv_len - (sn.bv_len + 1);
2549 /* eat leading zeros */
2550 for( n=0; n < (sn.bv_len-1); n++ ) {
2551 if( sn.bv_val[n] != '0' ) break;
2556 for( n=0; n < sn.bv_len; n++ ) {
2557 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2558 return LDAP_INVALID_SYNTAX;
2563 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2564 if( rc ) return LDAP_INVALID_SYNTAX;
2566 /* make room from sn + "$" */
2567 out->bv_len = sn.bv_len + newi.bv_len + 1;
2568 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2570 if( out->bv_val == NULL ) {
2572 slap_sl_free( newi.bv_val, ctx );
2576 /* push issuer over */
2577 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2578 /* insert sn and "$" */
2579 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2580 out->bv_val[sn.bv_len] = '$';
2582 out->bv_val[out->bv_len] = '\0';
2584 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2585 out->bv_val, 0, 0 );
2592 certificateExactNormalize(
2597 struct berval *normalized,
2600 int rc = LDAP_INVALID_SYNTAX;
2602 char *serial = NULL;
2603 ber_len_t seriallen;
2604 struct berval issuer_dn = BER_BVNULL;
2605 X509_NAME *name = NULL;
2606 ASN1_INTEGER *sn = NULL;
2609 if( BER_BVISEMPTY( val ) ) goto done;
2611 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2612 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2615 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2617 p = (unsigned char *)val->bv_val;
2618 xcert = d2i_X509( NULL, &p, val->bv_len);
2619 if( xcert == NULL ) goto done;
2621 sn=X509_get_serialNumber(xcert);
2622 if ( sn == NULL ) goto done;
2623 serial=i2s_ASN1_INTEGER(0, sn );
2624 if( serial == NULL ) goto done;
2625 seriallen=strlen(serial);
2627 name=X509_get_issuer_name(xcert);
2628 if( name == NULL ) goto done;
2629 rc = dnX509normalize( name, &issuer_dn );
2630 if( rc != LDAP_SUCCESS ) goto done;
2632 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2633 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2634 p = (unsigned char *)normalized->bv_val;
2635 AC_MEMCPY(p, serial, seriallen);
2638 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2639 p += issuer_dn.bv_len;
2642 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2643 normalized->bv_val, NULL, NULL );
2646 if (xcert) X509_free(xcert);
2647 if (serial) ch_free(serial);
2648 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2652 #endif /* HAVE_TLS */
2655 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2656 /* slight optimization - does not need the start parameter */
2657 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2662 check_time_syntax (struct berval *val,
2665 struct berval *fraction)
2668 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2669 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2670 * GeneralizedTime supports leap seconds, UTCTime does not.
2672 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2673 static const int mdays[2][12] = {
2674 /* non-leap years */
2675 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2677 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2680 int part, c, c1, c2, tzoffset, leapyear = 0;
2683 e = p + val->bv_len;
2685 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2686 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2688 for (part = start; part < 7 && p < e; part++) {
2690 if (!ASCII_DIGIT(c1)) {
2695 return LDAP_INVALID_SYNTAX;
2698 if (!ASCII_DIGIT(c)) {
2699 return LDAP_INVALID_SYNTAX;
2701 c += c1 * 10 - '0' * 11;
2702 if ((part | 1) == 3) {
2705 return LDAP_INVALID_SYNTAX;
2708 if (c >= ceiling[part]) {
2709 if (! (c == 60 && part == 6 && start == 0))
2710 return LDAP_INVALID_SYNTAX;
2714 if (part < 5 + start) {
2715 return LDAP_INVALID_SYNTAX;
2717 for (; part < 9; part++) {
2721 /* leapyear check for the Gregorian calendar (year>1581) */
2722 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2726 if (parts[3] >= mdays[leapyear][parts[2]]) {
2727 return LDAP_INVALID_SYNTAX;
2731 fraction->bv_val = p;
2732 fraction->bv_len = 0;
2733 if (p < e && (*p == '.' || *p == ',')) {
2735 while (++p < e && ASCII_DIGIT(*p)) {
2738 if (p - fraction->bv_val == 1) {
2739 return LDAP_INVALID_SYNTAX;
2741 for (end_num = p; end_num[-1] == '0'; --end_num) {
2744 c = end_num - fraction->bv_val;
2745 if (c != 1) fraction->bv_len = c;
2751 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2757 return LDAP_INVALID_SYNTAX;
2763 for (part = 7; part < 9 && p < e; part++) {
2765 if (!ASCII_DIGIT(c1)) {
2770 return LDAP_INVALID_SYNTAX;
2773 if (!ASCII_DIGIT(c2)) {
2774 return LDAP_INVALID_SYNTAX;
2776 parts[part] = c1 * 10 + c2 - '0' * 11;
2777 if (parts[part] >= ceiling[part]) {
2778 return LDAP_INVALID_SYNTAX;
2781 if (part < 8 + start) {
2782 return LDAP_INVALID_SYNTAX;
2785 if (tzoffset == '-') {
2786 /* negative offset to UTC, ie west of Greenwich */
2787 parts[4] += parts[7];
2788 parts[5] += parts[8];
2789 /* offset is just hhmm, no seconds */
2790 for (part = 6; --part >= 0; ) {
2794 c = mdays[leapyear][parts[2]];
2796 if (parts[part] >= c) {
2798 return LDAP_INVALID_SYNTAX;
2803 } else if (part != 5) {
2808 /* positive offset to UTC, ie east of Greenwich */
2809 parts[4] -= parts[7];
2810 parts[5] -= parts[8];
2811 for (part = 6; --part >= 0; ) {
2812 if (parts[part] < 0) {
2814 return LDAP_INVALID_SYNTAX;
2819 /* make first arg to % non-negative */
2820 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2825 } else if (part != 5) {
2832 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2835 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2842 struct berval *normalized )
2846 rc = check_time_syntax(val, 1, parts, NULL);
2847 if (rc != LDAP_SUCCESS) {
2851 normalized->bv_val = ch_malloc( 14 );
2852 if ( normalized->bv_val == NULL ) {
2853 return LBER_ERROR_MEMORY;
2856 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2857 parts[1], parts[2] + 1, parts[3] + 1,
2858 parts[4], parts[5], parts[6] );
2859 normalized->bv_len = 13;
2861 return LDAP_SUCCESS;
2871 return check_time_syntax(in, 1, parts, NULL);
2874 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2877 generalizedTimeValidate(
2882 struct berval fraction;
2883 return check_time_syntax(in, 0, parts, &fraction);
2887 generalizedTimeNormalize(
2892 struct berval *normalized,
2897 struct berval fraction;
2899 rc = check_time_syntax(val, 0, parts, &fraction);
2900 if (rc != LDAP_SUCCESS) {
2904 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2905 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2906 if ( BER_BVISNULL( normalized ) ) {
2907 return LBER_ERROR_MEMORY;
2910 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2911 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2912 parts[4], parts[5], parts[6] );
2913 if ( !BER_BVISEMPTY( &fraction ) ) {
2914 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2915 fraction.bv_val, fraction.bv_len );
2916 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2918 strcpy( normalized->bv_val + len-1, "Z" );
2919 normalized->bv_len = len;
2921 return LDAP_SUCCESS;
2925 generalizedTimeOrderingMatch(
2930 struct berval *value,
2931 void *assertedValue )
2933 struct berval *asserted = (struct berval *) assertedValue;
2934 ber_len_t v_len = value->bv_len;
2935 ber_len_t av_len = asserted->bv_len;
2937 /* ignore trailing 'Z' when comparing */
2938 int match = memcmp( value->bv_val, asserted->bv_val,
2939 (v_len < av_len ? v_len : av_len) - 1 );
2940 if ( match == 0 ) match = v_len - av_len;
2943 return LDAP_SUCCESS;
2946 /* Index generation function */
2947 int generalizedTimeIndexer(
2952 struct berval *prefix,
2960 BerValue bvtmp; /* 40 bit index */
2962 struct lutil_timet tt;
2964 bvtmp.bv_len = sizeof(tmp);
2966 for( i=0; values[i].bv_val != NULL; i++ ) {
2967 /* just count them */
2970 /* we should have at least one value at this point */
2973 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2975 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2976 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2977 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2978 /* Use 40 bits of time for key */
2979 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2980 lutil_tm2time( &tm, &tt );
2981 tmp[0] = tt.tt_gsec & 0xff;
2982 tmp[4] = tt.tt_sec & 0xff;
2984 tmp[3] = tt.tt_sec & 0xff;
2986 tmp[2] = tt.tt_sec & 0xff;
2988 tmp[1] = tt.tt_sec & 0xff;
2990 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2994 keys[j].bv_val = NULL;
2999 return LDAP_SUCCESS;
3002 /* Index generation function */
3003 int generalizedTimeFilter(
3008 struct berval *prefix,
3009 void * assertedValue,
3015 BerValue bvtmp; /* 40 bit index */
3016 BerValue *value = (BerValue *) assertedValue;
3018 struct lutil_timet tt;
3020 bvtmp.bv_len = sizeof(tmp);
3022 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3023 /* Use 40 bits of time for key */
3024 if ( value->bv_val && value->bv_len >= 10 &&
3025 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3027 lutil_tm2time( &tm, &tt );
3028 tmp[0] = tt.tt_gsec & 0xff;
3029 tmp[4] = tt.tt_sec & 0xff;
3031 tmp[3] = tt.tt_sec & 0xff;
3033 tmp[2] = tt.tt_sec & 0xff;
3035 tmp[1] = tt.tt_sec & 0xff;
3037 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3038 ber_dupbv_x(keys, &bvtmp, ctx );
3039 keys[1].bv_val = NULL;
3047 return LDAP_SUCCESS;
3051 deliveryMethodValidate(
3053 struct berval *val )
3056 #define LENOF(s) (sizeof(s)-1)
3057 struct berval tmp = *val;
3059 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3060 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3061 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3064 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3066 switch( tmp.bv_val[0] ) {
3069 if(( tmp.bv_len >= LENOF("any") ) &&
3070 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3072 tmp.bv_len -= LENOF("any");
3073 tmp.bv_val += LENOF("any");
3076 return LDAP_INVALID_SYNTAX;
3080 if(( tmp.bv_len >= LENOF("mhs") ) &&
3081 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3083 tmp.bv_len -= LENOF("mhs");
3084 tmp.bv_val += LENOF("mhs");
3087 return LDAP_INVALID_SYNTAX;
3091 if(( tmp.bv_len >= LENOF("physical") ) &&
3092 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3094 tmp.bv_len -= LENOF("physical");
3095 tmp.bv_val += LENOF("physical");
3098 return LDAP_INVALID_SYNTAX;
3101 case 'T': /* telex or teletex or telephone */
3102 if(( tmp.bv_len >= LENOF("telex") ) &&
3103 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3105 tmp.bv_len -= LENOF("telex");
3106 tmp.bv_val += LENOF("telex");
3109 if(( tmp.bv_len >= LENOF("teletex") ) &&
3110 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3112 tmp.bv_len -= LENOF("teletex");
3113 tmp.bv_val += LENOF("teletex");
3116 if(( tmp.bv_len >= LENOF("telephone") ) &&
3117 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3119 tmp.bv_len -= LENOF("telephone");
3120 tmp.bv_val += LENOF("telephone");
3123 return LDAP_INVALID_SYNTAX;
3126 case 'G': /* g3fax or g4fax */
3127 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3128 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3129 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3131 tmp.bv_len -= LENOF("g3fax");
3132 tmp.bv_val += LENOF("g3fax");
3135 return LDAP_INVALID_SYNTAX;
3139 if(( tmp.bv_len >= LENOF("ia5") ) &&
3140 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3142 tmp.bv_len -= LENOF("ia5");
3143 tmp.bv_val += LENOF("ia5");
3146 return LDAP_INVALID_SYNTAX;
3150 if(( tmp.bv_len >= LENOF("videotex") ) &&
3151 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3153 tmp.bv_len -= LENOF("videotex");
3154 tmp.bv_val += LENOF("videotex");
3157 return LDAP_INVALID_SYNTAX;
3160 return LDAP_INVALID_SYNTAX;
3163 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3165 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3169 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3173 return LDAP_INVALID_SYNTAX;
3175 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3184 nisNetgroupTripleValidate(
3186 struct berval *val )
3191 if ( BER_BVISEMPTY( val ) ) {
3192 return LDAP_INVALID_SYNTAX;
3195 p = (char *)val->bv_val;
3196 e = p + val->bv_len;
3198 if ( *p != '(' /*')'*/ ) {
3199 return LDAP_INVALID_SYNTAX;
3202 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3206 return LDAP_INVALID_SYNTAX;
3209 } else if ( !AD_CHAR( *p ) ) {
3210 return LDAP_INVALID_SYNTAX;
3214 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3215 return LDAP_INVALID_SYNTAX;
3221 return LDAP_INVALID_SYNTAX;
3224 return LDAP_SUCCESS;
3228 bootParameterValidate(
3230 struct berval *val )
3234 if ( BER_BVISEMPTY( val ) ) {
3235 return LDAP_INVALID_SYNTAX;
3238 p = (char *)val->bv_val;
3239 e = p + val->bv_len;
3242 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3243 if ( !AD_CHAR( *p ) ) {
3244 return LDAP_INVALID_SYNTAX;
3249 return LDAP_INVALID_SYNTAX;
3253 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3254 if ( !AD_CHAR( *p ) ) {
3255 return LDAP_INVALID_SYNTAX;
3260 return LDAP_INVALID_SYNTAX;
3264 for ( p++; p < e; p++ ) {
3265 if ( !SLAP_PRINTABLE( *p ) ) {
3266 return LDAP_INVALID_SYNTAX;
3270 return LDAP_SUCCESS;
3274 firstComponentNormalize(
3279 struct berval *normalized,
3286 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3287 ber_dupbv_x( normalized, val, ctx );
3288 return LDAP_SUCCESS;
3291 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3293 if( val->bv_val[0] != '(' /*')'*/ &&
3294 val->bv_val[0] != '{' /*'}'*/ )
3296 return LDAP_INVALID_SYNTAX;
3299 /* trim leading white space */
3301 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3307 /* grab next word */
3308 comp.bv_val = &val->bv_val[len];
3309 len = val->bv_len - len;
3310 for( comp.bv_len = 0;
3311 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3317 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3318 rc = numericoidValidate( NULL, &comp );
3319 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3320 rc = integerValidate( NULL, &comp );
3322 rc = LDAP_INVALID_SYNTAX;
3326 if( rc == LDAP_SUCCESS ) {
3327 ber_dupbv_x( normalized, &comp, ctx );
3334 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3335 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3337 static slap_syntax_defs_rec syntax_defs[] = {
3338 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3339 X_BINARY X_NOT_H_R ")",
3340 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3341 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3343 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3345 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3347 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3348 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3350 SLAP_SYNTAX_BER, berValidate, NULL},
3351 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3352 0, bitStringValidate, NULL },
3353 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3354 0, booleanValidate, NULL},
3355 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3356 X_BINARY X_NOT_H_R ")",
3357 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3358 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3359 X_BINARY X_NOT_H_R ")",
3360 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3361 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3362 X_BINARY X_NOT_H_R ")",
3363 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3364 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3365 0, countryStringValidate, NULL},
3366 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3367 0, dnValidate, dnPretty},
3368 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3369 0, rdnValidate, rdnPretty},
3370 #ifdef LDAP_COMP_MATCH
3371 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3372 0, allComponentsValidate, NULL},
3373 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3374 0, componentFilterValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3378 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3379 0, deliveryMethodValidate, NULL},
3380 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3381 0, UTF8StringValidate, NULL},
3382 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3384 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3386 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3388 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3390 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3392 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3393 0, printablesStringValidate, NULL},
3394 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3395 SLAP_SYNTAX_BLOB, NULL, NULL},
3396 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3397 0, generalizedTimeValidate, NULL},
3398 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3401 0, IA5StringValidate, NULL},
3402 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3403 0, integerValidate, NULL},
3404 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3405 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3406 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3408 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3410 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3412 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3414 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3416 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3417 0, nameUIDValidate, nameUIDPretty },
3418 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3420 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3421 0, numericStringValidate, NULL},
3422 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3424 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3425 0, numericoidValidate, NULL},
3426 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3427 0, IA5StringValidate, NULL},
3428 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3429 0, blobValidate, NULL},
3430 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3431 0, UTF8StringValidate, NULL},
3432 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3434 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3436 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3437 0, printableStringValidate, NULL},
3438 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3439 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3440 0, subtreeSpecificationValidate, NULL},
3441 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3442 X_BINARY X_NOT_H_R ")",
3443 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3444 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3445 0, printableStringValidate, NULL},
3446 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3448 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3449 0, printablesStringValidate, NULL},
3450 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3451 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3452 0, utcTimeValidate, NULL},
3454 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3456 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3458 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3460 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3462 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3465 /* RFC 2307 NIS Syntaxes */
3466 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3467 0, nisNetgroupTripleValidate, NULL},
3468 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3469 0, bootParameterValidate, NULL},
3471 /* From PKIX *//* This OID is not published yet. */
3472 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3474 serialNumberAndIssuerValidate,
3475 serialNumberAndIssuerPretty},
3477 #ifdef SLAPD_AUTHPASSWD
3478 /* needs updating */
3479 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3480 SLAP_SYNTAX_HIDE, NULL, NULL},
3483 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
3484 0, UUIDValidate, UUIDPretty},
3486 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3487 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3489 /* OpenLDAP Void Syntax */
3490 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3491 SLAP_SYNTAX_HIDE, inValidate, NULL},
3493 #ifdef SLAP_AUTHZ_SYNTAX
3494 /* FIXME: OID is unused, but not registered yet */
3495 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3496 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3497 #endif /* SLAP_AUTHZ_SYNTAX */
3499 {NULL, 0, NULL, NULL}
3502 char *certificateExactMatchSyntaxes[] = {
3503 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3506 #ifdef LDAP_COMP_MATCH
3507 char *componentFilterMatchSyntaxes[] = {
3508 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3512 char *directoryStringSyntaxes[] = {
3513 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3516 char *integerFirstComponentMatchSyntaxes[] = {
3517 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3518 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
3521 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3522 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3523 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3524 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
3525 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3526 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3527 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3528 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3529 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3534 * Other matching rules in X.520 that we do not use (yet):
3536 * 2.5.13.25 uTCTimeMatch
3537 * 2.5.13.26 uTCTimeOrderingMatch
3538 * 2.5.13.31* directoryStringFirstComponentMatch
3539 * 2.5.13.32* wordMatch
3540 * 2.5.13.33* keywordMatch
3541 * 2.5.13.36 certificatePairExactMatch
3542 * 2.5.13.37 certificatePairMatch
3543 * 2.5.13.38 certificateListExactMatch
3544 * 2.5.13.39 certificateListMatch
3545 * 2.5.13.40 algorithmIdentifierMatch
3546 * 2.5.13.41* storedPrefixMatch
3547 * 2.5.13.42 attributeCertificateMatch
3548 * 2.5.13.43 readerAndKeyIDMatch
3549 * 2.5.13.44 attributeIntegrityMatch
3551 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3553 static slap_mrule_defs_rec mrule_defs[] = {
3555 * EQUALITY matching rules must be listed after associated APPROX
3556 * matching rules. So, we list all APPROX matching rules first.
3558 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3560 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3561 NULL, NULL, directoryStringApproxMatch,
3562 directoryStringApproxIndexer, directoryStringApproxFilter,
3565 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3566 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3567 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3568 NULL, NULL, IA5StringApproxMatch,
3569 IA5StringApproxIndexer, IA5StringApproxFilter,
3573 * Other matching rules
3576 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3577 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3578 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3579 NULL, NULL, octetStringMatch,
3580 octetStringIndexer, octetStringFilter,
3583 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3584 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3585 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3586 NULL, dnNormalize, dnMatch,
3587 octetStringIndexer, octetStringFilter,
3590 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3591 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3592 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3593 NULL, dnNormalize, dnRelativeMatch,
3597 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3598 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3599 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3600 NULL, dnNormalize, dnRelativeMatch,
3604 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3605 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3606 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3607 NULL, dnNormalize, dnRelativeMatch,
3611 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3613 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3614 NULL, dnNormalize, dnRelativeMatch,
3618 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3619 "SYNTAX 1.2.36.79672281.1.5.0 )",
3620 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3621 NULL, rdnNormalize, rdnMatch,
3622 octetStringIndexer, octetStringFilter,
3625 #ifdef LDAP_COMP_MATCH
3626 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3627 "SYNTAX 1.2.36.79672281.1.5.2 )",
3628 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3629 NULL, NULL , componentFilterMatch,
3630 octetStringIndexer, octetStringFilter,
3633 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3634 "SYNTAX 1.2.36.79672281.1.5.3 )",
3635 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3636 NULL, NULL , allComponentsMatch,
3637 octetStringIndexer, octetStringFilter,
3640 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3641 "SYNTAX 1.2.36.79672281.1.5.3 )",
3642 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3643 NULL, NULL , directoryComponentsMatch,
3644 octetStringIndexer, octetStringFilter,
3648 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3649 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3650 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3651 NULL, UTF8StringNormalize, octetStringMatch,
3652 octetStringIndexer, octetStringFilter,
3653 directoryStringApproxMatchOID },
3655 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3656 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3657 SLAP_MR_ORDERING, directoryStringSyntaxes,
3658 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3660 "caseIgnoreMatch" },
3662 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3663 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3664 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3665 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3666 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3667 "caseIgnoreMatch" },
3669 {"( 2.5.13.5 NAME 'caseExactMatch' "
3670 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3671 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3672 NULL, UTF8StringNormalize, octetStringMatch,
3673 octetStringIndexer, octetStringFilter,
3674 directoryStringApproxMatchOID },
3676 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3678 SLAP_MR_ORDERING, directoryStringSyntaxes,
3679 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3683 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3685 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3686 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3687 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3690 {"( 2.5.13.8 NAME 'numericStringMatch' "
3691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3692 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3693 NULL, numericStringNormalize, octetStringMatch,
3694 octetStringIndexer, octetStringFilter,
3697 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3699 SLAP_MR_ORDERING, NULL,
3700 NULL, numericStringNormalize, octetStringOrderingMatch,
3702 "numericStringMatch" },
3704 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3706 SLAP_MR_SUBSTR, NULL,
3707 NULL, numericStringNormalize, octetStringSubstringsMatch,
3708 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3709 "numericStringMatch" },
3711 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3713 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3714 NULL, NULL, NULL, NULL, NULL, NULL },
3716 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3717 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3718 SLAP_MR_SUBSTR, NULL,
3719 NULL, NULL, NULL, NULL, NULL,
3720 "caseIgnoreListMatch" },
3722 {"( 2.5.13.13 NAME 'booleanMatch' "
3723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3724 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3725 NULL, NULL, booleanMatch,
3726 octetStringIndexer, octetStringFilter,
3729 {"( 2.5.13.14 NAME 'integerMatch' "
3730 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3731 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3732 NULL, NULL, integerMatch,
3733 octetStringIndexer, octetStringFilter,
3736 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3738 SLAP_MR_ORDERING, NULL,
3739 NULL, NULL, integerMatch,
3743 {"( 2.5.13.16 NAME 'bitStringMatch' "
3744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3745 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3746 NULL, NULL, octetStringMatch,
3747 octetStringIndexer, octetStringFilter,
3750 {"( 2.5.13.17 NAME 'octetStringMatch' "
3751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3752 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3753 NULL, NULL, octetStringMatch,
3754 octetStringIndexer, octetStringFilter,
3757 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3759 SLAP_MR_ORDERING, NULL,
3760 NULL, NULL, octetStringOrderingMatch,
3762 "octetStringMatch" },
3764 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3766 SLAP_MR_SUBSTR, NULL,
3767 NULL, NULL, octetStringSubstringsMatch,
3768 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3769 "octetStringMatch" },
3771 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3772 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3773 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3775 telephoneNumberNormalize, octetStringMatch,
3776 octetStringIndexer, octetStringFilter,
3779 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3780 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3781 SLAP_MR_SUBSTR, NULL,
3782 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3783 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3784 "telephoneNumberMatch" },
3786 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3787 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3788 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3789 NULL, NULL, NULL, NULL, NULL, NULL },
3791 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3792 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3793 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3794 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3795 uniqueMemberIndexer, uniqueMemberFilter,
3798 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3799 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3800 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3801 NULL, NULL, NULL, NULL, NULL, NULL },
3803 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3804 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3805 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3806 NULL, generalizedTimeNormalize, octetStringMatch,
3807 generalizedTimeIndexer, generalizedTimeFilter,
3810 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3811 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3812 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3813 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3815 "generalizedTimeMatch" },
3817 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3819 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3820 integerFirstComponentMatchSyntaxes,
3821 NULL, firstComponentNormalize, integerMatch,
3822 octetStringIndexer, octetStringFilter,
3825 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3827 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3828 objectIdentifierFirstComponentMatchSyntaxes,
3829 NULL, firstComponentNormalize, octetStringMatch,
3830 octetStringIndexer, octetStringFilter,
3833 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3834 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3835 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3837 NULL, certificateExactNormalize, octetStringMatch,
3838 octetStringIndexer, octetStringFilter,
3840 NULL, NULL, NULL, NULL, NULL,
3844 {"( 2.5.13.35 NAME 'certificateMatch' "
3845 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3846 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3848 NULL, NULL, octetStringMatch,
3849 octetStringIndexer, octetStringFilter,
3851 NULL, NULL, NULL, NULL, NULL,
3855 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3857 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3858 NULL, IA5StringNormalize, octetStringMatch,
3859 octetStringIndexer, octetStringFilter,
3860 IA5StringApproxMatchOID },
3862 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3865 NULL, IA5StringNormalize, octetStringMatch,
3866 octetStringIndexer, octetStringFilter,
3867 IA5StringApproxMatchOID },
3869 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3871 SLAP_MR_SUBSTR, NULL,
3872 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3873 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3874 "caseIgnoreIA5Match" },
3876 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3877 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3878 SLAP_MR_SUBSTR, NULL,
3879 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3880 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3881 "caseExactIA5Match" },
3883 #ifdef SLAPD_AUTHPASSWD
3884 /* needs updating */
3885 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3886 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3887 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3888 NULL, NULL, authPasswordMatch,
3893 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3896 NULL, NULL, integerBitAndMatch,
3900 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3901 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3903 NULL, NULL, integerBitOrMatch,
3907 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
3908 "SYNTAX 1.3.6.1.1.16.1 )",
3909 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
3910 NULL, UUIDNormalize, octetStringMatch,
3911 octetStringIndexer, octetStringFilter,
3914 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
3915 "SYNTAX 1.3.6.1.1.16.1 )",
3916 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
3917 NULL, UUIDNormalize, octetStringOrderingMatch,
3918 octetStringIndexer, octetStringFilter,
3921 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3922 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3923 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3924 NULL, NULL, csnMatch,
3925 csnIndexer, csnFilter,
3928 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3929 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3930 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3931 NULL, NULL, csnOrderingMatch,
3935 #ifdef SLAP_AUTHZ_SYNTAX
3936 /* FIXME: OID is unused, but not registered yet */
3937 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3938 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3939 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3940 NULL, authzNormalize, authzMatch,
3943 #endif /* SLAP_AUTHZ_SYNTAX */
3945 {NULL, SLAP_MR_NONE, NULL,
3946 NULL, NULL, NULL, NULL, NULL,
3951 slap_schema_init( void )
3956 /* we should only be called once (from main) */
3957 assert( schema_init_done == 0 );
3959 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3960 res = register_syntax( &syntax_defs[i] );
3963 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3964 syntax_defs[i].sd_desc );
3969 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3970 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3971 mrule_defs[i].mrd_compat_syntaxes == NULL )
3974 "slap_schema_init: Ignoring unusable matching rule %s\n",
3975 mrule_defs[i].mrd_desc );
3979 res = register_matching_rule( &mrule_defs[i] );
3983 "slap_schema_init: Error registering matching rule %s\n",
3984 mrule_defs[i].mrd_desc );
3989 res = slap_schema_load();
3990 schema_init_done = 1;
3995 schema_destroy( void )
4004 if( schema_init_done ) {
4005 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4006 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );