1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 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 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2085 for(i=0; i < val->bv_len; i++) {
2086 if( !LDAP_ASCII(val->bv_val[i]) ) {
2087 return LDAP_INVALID_SYNTAX;
2091 return LDAP_SUCCESS;
2100 struct berval *normalized,
2104 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
2106 assert( !BER_BVISEMPTY( val ) );
2108 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2112 /* Ignore initial whitespace */
2113 while ( ASCII_SPACE( *p ) ) p++;
2115 normalized->bv_val = ber_strdup_x( p, ctx );
2116 p = q = normalized->bv_val;
2119 if ( ASCII_SPACE( *p ) ) {
2122 /* Ignore the extra whitespace */
2123 while ( ASCII_SPACE( *p ) ) {
2127 } else if ( casefold ) {
2128 /* Most IA5 rules require casefolding */
2129 *q++ = TOLOWER(*p); p++;
2136 assert( normalized->bv_val <= p );
2140 * If the string ended in space, backup the pointer one
2141 * position. One is enough because the above loop collapsed
2142 * all whitespace to a single space.
2144 if ( ASCII_SPACE( q[-1] ) ) --q;
2146 /* null terminate */
2149 normalized->bv_len = q - normalized->bv_val;
2150 if( BER_BVISEMPTY( normalized ) ) {
2151 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2152 normalized->bv_val[0] = ' ';
2153 normalized->bv_val[1] = '\0';
2154 normalized->bv_len = 1;
2157 return LDAP_SUCCESS;
2166 if( in->bv_len != 36 ) {
2167 return LDAP_INVALID_SYNTAX;
2170 for( i=0; i<36; i++ ) {
2176 if( in->bv_val[i] != '-' ) {
2177 return LDAP_INVALID_SYNTAX;
2181 if( !ASCII_HEX( in->bv_val[i]) ) {
2182 return LDAP_INVALID_SYNTAX;
2187 return LDAP_SUCCESS;
2198 int rc=LDAP_INVALID_SYNTAX;
2200 assert( in != NULL );
2201 assert( out != NULL );
2203 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2206 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2208 for( i=0; i<36; i++ ) {
2214 if( in->bv_val[i] != '-' ) {
2217 out->bv_val[i] = '-';
2221 if( !ASCII_HEX( in->bv_val[i]) ) {
2224 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2229 out->bv_val[ out->bv_len ] = '\0';
2233 slap_sl_free( out->bv_val, ctx );
2246 struct berval *normalized,
2249 unsigned char octet = '\0';
2252 normalized->bv_len = 16;
2253 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2255 for( i=0, j=0; i<36; i++ ) {
2256 unsigned char nibble;
2257 if( val->bv_val[i] == '-' ) {
2260 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2261 nibble = val->bv_val[i] - '0';
2263 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2264 nibble = val->bv_val[i] - ('a'-10);
2266 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2267 nibble = val->bv_val[i] - ('A'-10);
2270 slap_sl_free( normalized->bv_val, ctx );
2271 return LDAP_INVALID_SYNTAX;
2276 normalized->bv_val[j>>1] = octet;
2278 octet = nibble << 4;
2283 normalized->bv_val[normalized->bv_len] = 0;
2284 return LDAP_SUCCESS;
2290 numericStringValidate(
2296 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2298 for(i=0; i < in->bv_len; i++) {
2299 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2300 return LDAP_INVALID_SYNTAX;
2304 return LDAP_SUCCESS;
2308 numericStringNormalize(
2313 struct berval *normalized,
2316 /* removal all spaces */
2319 assert( !BER_BVISEMPTY( val ) );
2321 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2324 q = normalized->bv_val;
2327 if ( ASCII_SPACE( *p ) ) {
2328 /* Ignore whitespace */
2335 /* we should have copied no more then is in val */
2336 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2338 /* null terminate */
2341 normalized->bv_len = q - normalized->bv_val;
2343 if( BER_BVISEMPTY( normalized ) ) {
2344 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2345 normalized->bv_val[0] = ' ';
2346 normalized->bv_val[1] = '\0';
2347 normalized->bv_len = 1;
2350 return LDAP_SUCCESS;
2354 * Integer conversion macros that will use the largest available
2357 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2358 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2359 # define SLAP_LONG long long
2361 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2362 # define SLAP_LONG long
2363 #endif /* HAVE_STRTOLL ... */
2371 struct berval *value,
2372 void *assertedValue )
2374 SLAP_LONG lValue, lAssertedValue;
2377 /* safe to assume integers are NUL terminated? */
2378 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2379 if( errno == ERANGE )
2381 return LDAP_CONSTRAINT_VIOLATION;
2384 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2386 if( errno == ERANGE )
2388 return LDAP_CONSTRAINT_VIOLATION;
2391 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2392 return LDAP_SUCCESS;
2401 struct berval *value,
2402 void *assertedValue )
2404 SLAP_LONG lValue, lAssertedValue;
2407 /* safe to assume integers are NUL terminated? */
2408 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2409 if( errno == ERANGE )
2411 return LDAP_CONSTRAINT_VIOLATION;
2414 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2416 if( errno == ERANGE )
2418 return LDAP_CONSTRAINT_VIOLATION;
2421 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2422 return LDAP_SUCCESS;
2426 serialNumberAndIssuerValidate(
2432 struct berval sn, i;
2433 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2435 i.bv_val = ber_bvchr( in, '$' );
2436 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2438 sn.bv_val = in->bv_val;
2439 sn.bv_len = i.bv_val - in->bv_val;
2442 i.bv_len = in->bv_len - (sn.bv_len + 1);
2444 /* validate serial number (strict for now) */
2445 for( n=0; n < sn.bv_len; n++ ) {
2446 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2450 rc = dnValidate( NULL, &i );
2451 if( rc ) return LDAP_INVALID_SYNTAX;
2453 return LDAP_SUCCESS;
2457 serialNumberAndIssuerPretty(
2465 struct berval sn, i, newi;
2467 assert( val != NULL );
2468 assert( out != NULL );
2470 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2471 val->bv_val, 0, 0 );
2473 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2475 i.bv_val = ber_bvchr( val, '$' );
2476 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2478 sn.bv_val = val->bv_val;
2479 sn.bv_len = i.bv_val - val->bv_val;
2482 i.bv_len = val->bv_len - (sn.bv_len + 1);
2484 /* eat leading zeros */
2485 for( n=0; n < (sn.bv_len-1); n++ ) {
2486 if( sn.bv_val[n] != '0' ) break;
2491 for( n=0; n < sn.bv_len; n++ ) {
2492 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2496 rc = dnPretty( syntax, &i, &newi, ctx );
2497 if( rc ) return LDAP_INVALID_SYNTAX;
2499 /* make room from sn + "$" */
2500 out->bv_len = sn.bv_len + newi.bv_len + 1;
2501 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2503 if( out->bv_val == NULL ) {
2505 slap_sl_free( newi.bv_val, ctx );
2509 /* push issuer over */
2510 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2511 /* insert sn and "$" */
2512 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2513 out->bv_val[sn.bv_len] = '$';
2515 out->bv_val[out->bv_len] = '\0';
2517 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2518 out->bv_val, 0, 0 );
2520 return LDAP_SUCCESS;
2524 * This routine is called by certificateExactNormalize when
2525 * certificateExactNormalize receives a search string instead of
2526 * a certificate. This routine checks if the search value is valid
2527 * and then returns the normalized value
2530 serialNumberAndIssuerNormalize(
2540 struct berval sn, i, newi;
2542 assert( val != NULL );
2543 assert( out != NULL );
2545 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2546 val->bv_val, 0, 0 );
2548 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2550 i.bv_val = ber_bvchr( val, '$' );
2551 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2553 sn.bv_val = val->bv_val;
2554 sn.bv_len = i.bv_val - val->bv_val;
2557 i.bv_len = val->bv_len - (sn.bv_len + 1);
2559 /* eat leading zeros */
2560 for( n=0; n < (sn.bv_len-1); n++ ) {
2561 if( sn.bv_val[n] != '0' ) break;
2566 for( n=0; n < sn.bv_len; n++ ) {
2567 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2568 return LDAP_INVALID_SYNTAX;
2573 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2574 if( rc ) return LDAP_INVALID_SYNTAX;
2576 /* make room from sn + "$" */
2577 out->bv_len = sn.bv_len + newi.bv_len + 1;
2578 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2580 if( out->bv_val == NULL ) {
2582 slap_sl_free( newi.bv_val, ctx );
2586 /* push issuer over */
2587 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2588 /* insert sn and "$" */
2589 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2590 out->bv_val[sn.bv_len] = '$';
2592 out->bv_val[out->bv_len] = '\0';
2594 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2595 out->bv_val, 0, 0 );
2602 certificateExactNormalize(
2607 struct berval *normalized,
2610 int rc = LDAP_INVALID_SYNTAX;
2612 char *serial = NULL;
2613 ber_len_t seriallen;
2614 struct berval issuer_dn = BER_BVNULL;
2615 X509_NAME *name = NULL;
2616 ASN1_INTEGER *sn = NULL;
2619 if( BER_BVISEMPTY( val ) ) goto done;
2621 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2622 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2625 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2627 p = (unsigned char *)val->bv_val;
2628 xcert = d2i_X509( NULL, &p, val->bv_len);
2629 if( xcert == NULL ) goto done;
2631 sn=X509_get_serialNumber(xcert);
2632 if ( sn == NULL ) goto done;
2633 serial=i2s_ASN1_INTEGER(0, sn );
2634 if( serial == NULL ) goto done;
2635 seriallen=strlen(serial);
2637 name=X509_get_issuer_name(xcert);
2638 if( name == NULL ) goto done;
2639 rc = dnX509normalize( name, &issuer_dn );
2640 if( rc != LDAP_SUCCESS ) goto done;
2642 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2643 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2644 p = (unsigned char *)normalized->bv_val;
2645 AC_MEMCPY(p, serial, seriallen);
2648 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2649 p += issuer_dn.bv_len;
2652 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2653 normalized->bv_val, NULL, NULL );
2656 if (xcert) X509_free(xcert);
2657 if (serial) ch_free(serial);
2658 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2662 #endif /* HAVE_TLS */
2665 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2666 /* slight optimization - does not need the start parameter */
2667 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2672 check_time_syntax (struct berval *val,
2675 struct berval *fraction)
2678 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2679 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2680 * GeneralizedTime supports leap seconds, UTCTime does not.
2682 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2683 static const int mdays[2][12] = {
2684 /* non-leap years */
2685 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2687 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2690 int part, c, c1, c2, tzoffset, leapyear = 0;
2693 e = p + val->bv_len;
2695 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2696 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2698 for (part = start; part < 7 && p < e; part++) {
2700 if (!ASCII_DIGIT(c1)) {
2705 return LDAP_INVALID_SYNTAX;
2708 if (!ASCII_DIGIT(c)) {
2709 return LDAP_INVALID_SYNTAX;
2711 c += c1 * 10 - '0' * 11;
2712 if ((part | 1) == 3) {
2715 return LDAP_INVALID_SYNTAX;
2718 if (c >= ceiling[part]) {
2719 if (! (c == 60 && part == 6 && start == 0))
2720 return LDAP_INVALID_SYNTAX;
2724 if (part < 5 + start) {
2725 return LDAP_INVALID_SYNTAX;
2727 for (; part < 9; part++) {
2731 /* leapyear check for the Gregorian calendar (year>1581) */
2732 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2736 if (parts[3] >= mdays[leapyear][parts[2]]) {
2737 return LDAP_INVALID_SYNTAX;
2741 fraction->bv_val = p;
2742 fraction->bv_len = 0;
2743 if (p < e && (*p == '.' || *p == ',')) {
2745 while (++p < e && ASCII_DIGIT(*p)) {
2748 if (p - fraction->bv_val == 1) {
2749 return LDAP_INVALID_SYNTAX;
2751 for (end_num = p; end_num[-1] == '0'; --end_num) {
2754 c = end_num - fraction->bv_val;
2755 if (c != 1) fraction->bv_len = c;
2761 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2767 return LDAP_INVALID_SYNTAX;
2773 for (part = 7; part < 9 && p < e; part++) {
2775 if (!ASCII_DIGIT(c1)) {
2780 return LDAP_INVALID_SYNTAX;
2783 if (!ASCII_DIGIT(c2)) {
2784 return LDAP_INVALID_SYNTAX;
2786 parts[part] = c1 * 10 + c2 - '0' * 11;
2787 if (parts[part] >= ceiling[part]) {
2788 return LDAP_INVALID_SYNTAX;
2791 if (part < 8 + start) {
2792 return LDAP_INVALID_SYNTAX;
2795 if (tzoffset == '-') {
2796 /* negative offset to UTC, ie west of Greenwich */
2797 parts[4] += parts[7];
2798 parts[5] += parts[8];
2799 /* offset is just hhmm, no seconds */
2800 for (part = 6; --part >= 0; ) {
2804 c = mdays[leapyear][parts[2]];
2806 if (parts[part] >= c) {
2808 return LDAP_INVALID_SYNTAX;
2813 } else if (part != 5) {
2818 /* positive offset to UTC, ie east of Greenwich */
2819 parts[4] -= parts[7];
2820 parts[5] -= parts[8];
2821 for (part = 6; --part >= 0; ) {
2822 if (parts[part] < 0) {
2824 return LDAP_INVALID_SYNTAX;
2829 /* make first arg to % non-negative */
2830 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2835 } else if (part != 5) {
2842 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2845 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2852 struct berval *normalized )
2856 rc = check_time_syntax(val, 1, parts, NULL);
2857 if (rc != LDAP_SUCCESS) {
2861 normalized->bv_val = ch_malloc( 14 );
2862 if ( normalized->bv_val == NULL ) {
2863 return LBER_ERROR_MEMORY;
2866 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2867 parts[1], parts[2] + 1, parts[3] + 1,
2868 parts[4], parts[5], parts[6] );
2869 normalized->bv_len = 13;
2871 return LDAP_SUCCESS;
2881 return check_time_syntax(in, 1, parts, NULL);
2884 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2887 generalizedTimeValidate(
2892 struct berval fraction;
2893 return check_time_syntax(in, 0, parts, &fraction);
2897 generalizedTimeNormalize(
2902 struct berval *normalized,
2907 struct berval fraction;
2909 rc = check_time_syntax(val, 0, parts, &fraction);
2910 if (rc != LDAP_SUCCESS) {
2914 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2915 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2916 if ( BER_BVISNULL( normalized ) ) {
2917 return LBER_ERROR_MEMORY;
2920 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2921 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2922 parts[4], parts[5], parts[6] );
2923 if ( !BER_BVISEMPTY( &fraction ) ) {
2924 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2925 fraction.bv_val, fraction.bv_len );
2926 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2928 strcpy( normalized->bv_val + len-1, "Z" );
2929 normalized->bv_len = len;
2931 return LDAP_SUCCESS;
2935 generalizedTimeOrderingMatch(
2940 struct berval *value,
2941 void *assertedValue )
2943 struct berval *asserted = (struct berval *) assertedValue;
2944 ber_len_t v_len = value->bv_len;
2945 ber_len_t av_len = asserted->bv_len;
2947 /* ignore trailing 'Z' when comparing */
2948 int match = memcmp( value->bv_val, asserted->bv_val,
2949 (v_len < av_len ? v_len : av_len) - 1 );
2950 if ( match == 0 ) match = v_len - av_len;
2953 return LDAP_SUCCESS;
2956 /* Index generation function */
2957 int generalizedTimeIndexer(
2962 struct berval *prefix,
2970 BerValue bvtmp; /* 40 bit index */
2972 struct lutil_timet tt;
2974 bvtmp.bv_len = sizeof(tmp);
2976 for( i=0; values[i].bv_val != NULL; i++ ) {
2977 /* just count them */
2980 /* we should have at least one value at this point */
2983 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2985 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2986 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2987 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2988 /* Use 40 bits of time for key */
2989 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2990 lutil_tm2time( &tm, &tt );
2991 tmp[0] = tt.tt_gsec & 0xff;
2992 tmp[4] = tt.tt_sec & 0xff;
2994 tmp[3] = tt.tt_sec & 0xff;
2996 tmp[2] = tt.tt_sec & 0xff;
2998 tmp[1] = tt.tt_sec & 0xff;
3000 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3004 keys[j].bv_val = NULL;
3009 return LDAP_SUCCESS;
3012 /* Index generation function */
3013 int generalizedTimeFilter(
3018 struct berval *prefix,
3019 void * assertedValue,
3025 BerValue bvtmp; /* 40 bit index */
3026 BerValue *value = (BerValue *) assertedValue;
3028 struct lutil_timet tt;
3030 bvtmp.bv_len = sizeof(tmp);
3032 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3033 /* Use 40 bits of time for key */
3034 if ( value->bv_val && value->bv_len >= 10 &&
3035 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3037 lutil_tm2time( &tm, &tt );
3038 tmp[0] = tt.tt_gsec & 0xff;
3039 tmp[4] = tt.tt_sec & 0xff;
3041 tmp[3] = tt.tt_sec & 0xff;
3043 tmp[2] = tt.tt_sec & 0xff;
3045 tmp[1] = tt.tt_sec & 0xff;
3047 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3048 ber_dupbv_x(keys, &bvtmp, ctx );
3049 keys[1].bv_val = NULL;
3057 return LDAP_SUCCESS;
3061 deliveryMethodValidate(
3063 struct berval *val )
3066 #define LENOF(s) (sizeof(s)-1)
3067 struct berval tmp = *val;
3069 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3070 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3071 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3074 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3076 switch( tmp.bv_val[0] ) {
3079 if(( tmp.bv_len >= LENOF("any") ) &&
3080 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3082 tmp.bv_len -= LENOF("any");
3083 tmp.bv_val += LENOF("any");
3086 return LDAP_INVALID_SYNTAX;
3090 if(( tmp.bv_len >= LENOF("mhs") ) &&
3091 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3093 tmp.bv_len -= LENOF("mhs");
3094 tmp.bv_val += LENOF("mhs");
3097 return LDAP_INVALID_SYNTAX;
3101 if(( tmp.bv_len >= LENOF("physical") ) &&
3102 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3104 tmp.bv_len -= LENOF("physical");
3105 tmp.bv_val += LENOF("physical");
3108 return LDAP_INVALID_SYNTAX;
3111 case 'T': /* telex or teletex or telephone */
3112 if(( tmp.bv_len >= LENOF("telex") ) &&
3113 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3115 tmp.bv_len -= LENOF("telex");
3116 tmp.bv_val += LENOF("telex");
3119 if(( tmp.bv_len >= LENOF("teletex") ) &&
3120 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3122 tmp.bv_len -= LENOF("teletex");
3123 tmp.bv_val += LENOF("teletex");
3126 if(( tmp.bv_len >= LENOF("telephone") ) &&
3127 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3129 tmp.bv_len -= LENOF("telephone");
3130 tmp.bv_val += LENOF("telephone");
3133 return LDAP_INVALID_SYNTAX;
3136 case 'G': /* g3fax or g4fax */
3137 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3138 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3139 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3141 tmp.bv_len -= LENOF("g3fax");
3142 tmp.bv_val += LENOF("g3fax");
3145 return LDAP_INVALID_SYNTAX;
3149 if(( tmp.bv_len >= LENOF("ia5") ) &&
3150 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3152 tmp.bv_len -= LENOF("ia5");
3153 tmp.bv_val += LENOF("ia5");
3156 return LDAP_INVALID_SYNTAX;
3160 if(( tmp.bv_len >= LENOF("videotex") ) &&
3161 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3163 tmp.bv_len -= LENOF("videotex");
3164 tmp.bv_val += LENOF("videotex");
3167 return LDAP_INVALID_SYNTAX;
3170 return LDAP_INVALID_SYNTAX;
3173 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3175 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3179 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3183 return LDAP_INVALID_SYNTAX;
3185 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3194 nisNetgroupTripleValidate(
3196 struct berval *val )
3201 if ( BER_BVISEMPTY( val ) ) {
3202 return LDAP_INVALID_SYNTAX;
3205 p = (char *)val->bv_val;
3206 e = p + val->bv_len;
3208 if ( *p != '(' /*')'*/ ) {
3209 return LDAP_INVALID_SYNTAX;
3212 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3216 return LDAP_INVALID_SYNTAX;
3219 } else if ( !AD_CHAR( *p ) ) {
3220 return LDAP_INVALID_SYNTAX;
3224 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3225 return LDAP_INVALID_SYNTAX;
3231 return LDAP_INVALID_SYNTAX;
3234 return LDAP_SUCCESS;
3238 bootParameterValidate(
3240 struct berval *val )
3244 if ( BER_BVISEMPTY( val ) ) {
3245 return LDAP_INVALID_SYNTAX;
3248 p = (char *)val->bv_val;
3249 e = p + val->bv_len;
3252 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3253 if ( !AD_CHAR( *p ) ) {
3254 return LDAP_INVALID_SYNTAX;
3259 return LDAP_INVALID_SYNTAX;
3263 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3264 if ( !AD_CHAR( *p ) ) {
3265 return LDAP_INVALID_SYNTAX;
3270 return LDAP_INVALID_SYNTAX;
3274 for ( p++; p < e; p++ ) {
3275 if ( !SLAP_PRINTABLE( *p ) ) {
3276 return LDAP_INVALID_SYNTAX;
3280 return LDAP_SUCCESS;
3284 firstComponentNormalize(
3289 struct berval *normalized,
3296 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3297 ber_dupbv_x( normalized, val, ctx );
3298 return LDAP_SUCCESS;
3301 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3303 if( val->bv_val[0] != '(' /*')'*/ &&
3304 val->bv_val[0] != '{' /*'}'*/ )
3306 return LDAP_INVALID_SYNTAX;
3309 /* trim leading white space */
3311 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3317 /* grab next word */
3318 comp.bv_val = &val->bv_val[len];
3319 len = val->bv_len - len;
3320 for( comp.bv_len = 0;
3321 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3327 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3328 rc = numericoidValidate( NULL, &comp );
3329 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3330 rc = integerValidate( NULL, &comp );
3332 rc = LDAP_INVALID_SYNTAX;
3336 if( rc == LDAP_SUCCESS ) {
3337 ber_dupbv_x( normalized, &comp, ctx );
3344 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3345 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3347 static slap_syntax_defs_rec syntax_defs[] = {
3348 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3349 X_BINARY X_NOT_H_R ")",
3350 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3351 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3353 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3355 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3357 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3358 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3360 SLAP_SYNTAX_BER, berValidate, NULL},
3361 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3362 0, bitStringValidate, NULL },
3363 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3364 0, booleanValidate, NULL},
3365 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3366 X_BINARY X_NOT_H_R ")",
3367 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3368 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3369 X_BINARY X_NOT_H_R ")",
3370 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3371 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3372 X_BINARY X_NOT_H_R ")",
3373 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3374 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3375 0, countryStringValidate, NULL},
3376 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3377 0, dnValidate, dnPretty},
3378 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3379 0, rdnValidate, rdnPretty},
3380 #ifdef LDAP_COMP_MATCH
3381 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3382 0, allComponentsValidate, NULL},
3383 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3384 0, componentFilterValidate, NULL},
3386 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3388 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3389 0, deliveryMethodValidate, NULL},
3390 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3391 0, UTF8StringValidate, NULL},
3392 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3394 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3396 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3398 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3400 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3402 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3403 0, printablesStringValidate, NULL},
3404 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3405 SLAP_SYNTAX_BLOB, NULL, NULL},
3406 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3407 0, generalizedTimeValidate, NULL},
3408 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3410 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3411 0, IA5StringValidate, NULL},
3412 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3413 0, integerValidate, NULL},
3414 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3415 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3416 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3418 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3420 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3422 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3424 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3426 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3427 0, nameUIDValidate, nameUIDPretty },
3428 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3430 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3431 0, numericStringValidate, NULL},
3432 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3434 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3435 0, numericoidValidate, NULL},
3436 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3437 0, IA5StringValidate, NULL},
3438 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3439 0, blobValidate, NULL},
3440 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3441 0, UTF8StringValidate, NULL},
3442 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3444 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3446 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3447 0, printableStringValidate, NULL},
3448 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3449 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3450 0, subtreeSpecificationValidate, NULL},
3451 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3452 X_BINARY X_NOT_H_R ")",
3453 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3454 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3455 0, printableStringValidate, NULL},
3456 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3458 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3459 0, printablesStringValidate, NULL},
3460 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3461 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3462 0, utcTimeValidate, NULL},
3464 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3466 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3468 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3470 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3472 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3475 /* RFC 2307 NIS Syntaxes */
3476 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3477 0, nisNetgroupTripleValidate, NULL},
3478 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3479 0, bootParameterValidate, NULL},
3481 /* From PKIX *//* This OID is not published yet. */
3482 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3484 serialNumberAndIssuerValidate,
3485 serialNumberAndIssuerPretty},
3487 #ifdef SLAPD_AUTHPASSWD
3488 /* needs updating */
3489 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3490 SLAP_SYNTAX_HIDE, NULL, NULL},
3493 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
3494 0, UUIDValidate, UUIDPretty},
3496 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3497 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3499 /* OpenLDAP Void Syntax */
3500 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3501 SLAP_SYNTAX_HIDE, inValidate, NULL},
3503 #ifdef SLAP_AUTHZ_SYNTAX
3504 /* FIXME: OID is unused, but not registered yet */
3505 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3506 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3507 #endif /* SLAP_AUTHZ_SYNTAX */
3509 {NULL, 0, NULL, NULL}
3512 char *certificateExactMatchSyntaxes[] = {
3513 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3516 #ifdef LDAP_COMP_MATCH
3517 char *componentFilterMatchSyntaxes[] = {
3518 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3522 char *directoryStringSyntaxes[] = {
3523 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3526 char *integerFirstComponentMatchSyntaxes[] = {
3527 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3528 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
3531 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3532 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3533 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3534 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
3535 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3536 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3537 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3538 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3539 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3544 * Other matching rules in X.520 that we do not use (yet):
3546 * 2.5.13.25 uTCTimeMatch
3547 * 2.5.13.26 uTCTimeOrderingMatch
3548 * 2.5.13.31* directoryStringFirstComponentMatch
3549 * 2.5.13.32* wordMatch
3550 * 2.5.13.33* keywordMatch
3551 * 2.5.13.36 certificatePairExactMatch
3552 * 2.5.13.37 certificatePairMatch
3553 * 2.5.13.38 certificateListExactMatch
3554 * 2.5.13.39 certificateListMatch
3555 * 2.5.13.40 algorithmIdentifierMatch
3556 * 2.5.13.41* storedPrefixMatch
3557 * 2.5.13.42 attributeCertificateMatch
3558 * 2.5.13.43 readerAndKeyIDMatch
3559 * 2.5.13.44 attributeIntegrityMatch
3561 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3563 static slap_mrule_defs_rec mrule_defs[] = {
3565 * EQUALITY matching rules must be listed after associated APPROX
3566 * matching rules. So, we list all APPROX matching rules first.
3568 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3570 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3571 NULL, NULL, directoryStringApproxMatch,
3572 directoryStringApproxIndexer, directoryStringApproxFilter,
3575 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3577 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3578 NULL, NULL, IA5StringApproxMatch,
3579 IA5StringApproxIndexer, IA5StringApproxFilter,
3583 * Other matching rules
3586 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3587 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3588 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3589 NULL, NULL, octetStringMatch,
3590 octetStringIndexer, octetStringFilter,
3593 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3595 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3596 NULL, dnNormalize, dnMatch,
3597 octetStringIndexer, octetStringFilter,
3600 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3602 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3603 NULL, dnNormalize, dnRelativeMatch,
3607 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3609 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3610 NULL, dnNormalize, dnRelativeMatch,
3614 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3616 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3617 NULL, dnNormalize, dnRelativeMatch,
3621 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3623 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3624 NULL, dnNormalize, dnRelativeMatch,
3628 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3629 "SYNTAX 1.2.36.79672281.1.5.0 )",
3630 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3631 NULL, rdnNormalize, rdnMatch,
3632 octetStringIndexer, octetStringFilter,
3635 #ifdef LDAP_COMP_MATCH
3636 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3637 "SYNTAX 1.2.36.79672281.1.5.2 )",
3638 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3639 NULL, NULL , componentFilterMatch,
3640 octetStringIndexer, octetStringFilter,
3643 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3644 "SYNTAX 1.2.36.79672281.1.5.3 )",
3645 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3646 NULL, NULL , allComponentsMatch,
3647 octetStringIndexer, octetStringFilter,
3650 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3651 "SYNTAX 1.2.36.79672281.1.5.3 )",
3652 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3653 NULL, NULL , directoryComponentsMatch,
3654 octetStringIndexer, octetStringFilter,
3658 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3660 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3661 NULL, UTF8StringNormalize, octetStringMatch,
3662 octetStringIndexer, octetStringFilter,
3663 directoryStringApproxMatchOID },
3665 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3667 SLAP_MR_ORDERING, directoryStringSyntaxes,
3668 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3670 "caseIgnoreMatch" },
3672 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3674 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3675 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3676 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3677 "caseIgnoreMatch" },
3679 {"( 2.5.13.5 NAME 'caseExactMatch' "
3680 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3681 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3682 NULL, UTF8StringNormalize, octetStringMatch,
3683 octetStringIndexer, octetStringFilter,
3684 directoryStringApproxMatchOID },
3686 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3688 SLAP_MR_ORDERING, directoryStringSyntaxes,
3689 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3693 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3695 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3696 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3697 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3700 {"( 2.5.13.8 NAME 'numericStringMatch' "
3701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3702 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3703 NULL, numericStringNormalize, octetStringMatch,
3704 octetStringIndexer, octetStringFilter,
3707 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3709 SLAP_MR_ORDERING, NULL,
3710 NULL, numericStringNormalize, octetStringOrderingMatch,
3712 "numericStringMatch" },
3714 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3716 SLAP_MR_SUBSTR, NULL,
3717 NULL, numericStringNormalize, octetStringSubstringsMatch,
3718 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3719 "numericStringMatch" },
3721 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3723 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3724 NULL, NULL, NULL, NULL, NULL, NULL },
3726 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3728 SLAP_MR_SUBSTR, NULL,
3729 NULL, NULL, NULL, NULL, NULL,
3730 "caseIgnoreListMatch" },
3732 {"( 2.5.13.13 NAME 'booleanMatch' "
3733 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3734 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3735 NULL, NULL, booleanMatch,
3736 octetStringIndexer, octetStringFilter,
3739 {"( 2.5.13.14 NAME 'integerMatch' "
3740 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3741 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3742 NULL, NULL, integerMatch,
3743 octetStringIndexer, octetStringFilter,
3746 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3747 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3748 SLAP_MR_ORDERING, NULL,
3749 NULL, NULL, integerMatch,
3753 {"( 2.5.13.16 NAME 'bitStringMatch' "
3754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3755 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3756 NULL, NULL, octetStringMatch,
3757 octetStringIndexer, octetStringFilter,
3760 {"( 2.5.13.17 NAME 'octetStringMatch' "
3761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3762 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3763 NULL, NULL, octetStringMatch,
3764 octetStringIndexer, octetStringFilter,
3767 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3768 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3769 SLAP_MR_ORDERING, NULL,
3770 NULL, NULL, octetStringOrderingMatch,
3772 "octetStringMatch" },
3774 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3776 SLAP_MR_SUBSTR, NULL,
3777 NULL, NULL, octetStringSubstringsMatch,
3778 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3779 "octetStringMatch" },
3781 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3783 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3785 telephoneNumberNormalize, octetStringMatch,
3786 octetStringIndexer, octetStringFilter,
3789 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3791 SLAP_MR_SUBSTR, NULL,
3792 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3793 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3794 "telephoneNumberMatch" },
3796 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3797 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3798 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3799 NULL, NULL, NULL, NULL, NULL, NULL },
3801 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3802 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3803 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3804 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3805 uniqueMemberIndexer, uniqueMemberFilter,
3808 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3809 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3810 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3811 NULL, NULL, NULL, NULL, NULL, NULL },
3813 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3814 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3815 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3816 NULL, generalizedTimeNormalize, octetStringMatch,
3817 generalizedTimeIndexer, generalizedTimeFilter,
3820 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3821 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3822 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3823 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3825 "generalizedTimeMatch" },
3827 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3828 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3829 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3830 integerFirstComponentMatchSyntaxes,
3831 NULL, firstComponentNormalize, integerMatch,
3832 octetStringIndexer, octetStringFilter,
3835 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3837 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3838 objectIdentifierFirstComponentMatchSyntaxes,
3839 NULL, firstComponentNormalize, octetStringMatch,
3840 octetStringIndexer, octetStringFilter,
3843 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3844 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3845 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3847 NULL, certificateExactNormalize, octetStringMatch,
3848 octetStringIndexer, octetStringFilter,
3850 NULL, NULL, NULL, NULL, NULL,
3854 {"( 2.5.13.35 NAME 'certificateMatch' "
3855 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3856 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3858 NULL, NULL, octetStringMatch,
3859 octetStringIndexer, octetStringFilter,
3861 NULL, NULL, NULL, NULL, NULL,
3865 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3867 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3868 NULL, IA5StringNormalize, octetStringMatch,
3869 octetStringIndexer, octetStringFilter,
3870 IA5StringApproxMatchOID },
3872 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3874 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3875 NULL, IA5StringNormalize, octetStringMatch,
3876 octetStringIndexer, octetStringFilter,
3877 IA5StringApproxMatchOID },
3879 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3880 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3881 SLAP_MR_SUBSTR, NULL,
3882 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3883 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3884 "caseIgnoreIA5Match" },
3886 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3887 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3888 SLAP_MR_SUBSTR, NULL,
3889 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3890 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3891 "caseExactIA5Match" },
3893 #ifdef SLAPD_AUTHPASSWD
3894 /* needs updating */
3895 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3896 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3897 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3898 NULL, NULL, authPasswordMatch,
3903 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3906 NULL, NULL, integerBitAndMatch,
3910 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3913 NULL, NULL, integerBitOrMatch,
3917 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
3918 "SYNTAX 1.3.6.1.1.16.1 )",
3919 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
3920 NULL, UUIDNormalize, octetStringMatch,
3921 octetStringIndexer, octetStringFilter,
3924 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
3925 "SYNTAX 1.3.6.1.1.16.1 )",
3926 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
3927 NULL, UUIDNormalize, octetStringOrderingMatch,
3928 octetStringIndexer, octetStringFilter,
3931 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3932 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3933 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3934 NULL, NULL, csnMatch,
3935 csnIndexer, csnFilter,
3938 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3939 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3940 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3941 NULL, NULL, csnOrderingMatch,
3945 #ifdef SLAP_AUTHZ_SYNTAX
3946 /* FIXME: OID is unused, but not registered yet */
3947 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3948 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3949 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3950 NULL, authzNormalize, authzMatch,
3953 #endif /* SLAP_AUTHZ_SYNTAX */
3955 {NULL, SLAP_MR_NONE, NULL,
3956 NULL, NULL, NULL, NULL, NULL,
3961 slap_schema_init( void )
3966 /* we should only be called once (from main) */
3967 assert( schema_init_done == 0 );
3969 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3970 res = register_syntax( &syntax_defs[i] );
3973 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3974 syntax_defs[i].sd_desc );
3979 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3980 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3981 mrule_defs[i].mrd_compat_syntaxes == NULL )
3984 "slap_schema_init: Ignoring unusable matching rule %s\n",
3985 mrule_defs[i].mrd_desc );
3989 res = register_matching_rule( &mrule_defs[i] );
3993 "slap_schema_init: Error registering matching rule %s\n",
3994 mrule_defs[i].mrd_desc );
3999 res = slap_schema_load();
4000 schema_init_done = 1;
4005 schema_destroy( void )
4014 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4015 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );