1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
46 #include "lutil_hash.h"
47 #define HASH_BYTES LUTIL_HASH_BYTES
48 #define HASH_CONTEXT lutil_HASH_CTX
49 #define HASH_Init(c) lutil_HASHInit(c)
50 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
51 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
53 /* 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;
2196 struct berval *normalized,
2199 unsigned char octet = '\0';
2202 normalized->bv_len = 16;
2203 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2205 for( i=0, j=0; i<36; i++ ) {
2206 unsigned char nibble;
2207 if( val->bv_val[i] == '-' ) {
2210 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2211 nibble = val->bv_val[i] - '0';
2213 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2214 nibble = val->bv_val[i] - ('a'-10);
2216 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2217 nibble = val->bv_val[i] - ('A'-10);
2220 slap_sl_free( normalized->bv_val, ctx );
2221 return LDAP_INVALID_SYNTAX;
2226 normalized->bv_val[j>>1] = octet;
2228 octet = nibble << 4;
2233 normalized->bv_val[normalized->bv_len] = 0;
2234 return LDAP_SUCCESS;
2240 numericStringValidate(
2246 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2248 for(i=0; i < in->bv_len; i++) {
2249 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2250 return LDAP_INVALID_SYNTAX;
2254 return LDAP_SUCCESS;
2258 numericStringNormalize(
2263 struct berval *normalized,
2266 /* removal all spaces */
2269 assert( !BER_BVISEMPTY( val ) );
2271 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2274 q = normalized->bv_val;
2277 if ( ASCII_SPACE( *p ) ) {
2278 /* Ignore whitespace */
2285 /* we should have copied no more then is in val */
2286 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2288 /* null terminate */
2291 normalized->bv_len = q - normalized->bv_val;
2293 if( BER_BVISEMPTY( normalized ) ) {
2294 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2295 normalized->bv_val[0] = ' ';
2296 normalized->bv_val[1] = '\0';
2297 normalized->bv_len = 1;
2300 return LDAP_SUCCESS;
2304 * Integer conversion macros that will use the largest available
2307 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2308 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2309 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2310 # define SLAP_LONG_MAX LLONG_MAX
2311 # define SLAP_LONG_MIN LLONG_MIN
2312 # define SLAP_LONG long long
2314 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2315 # define SLAP_LONG_MAX LONG_MAX
2316 # define SLAP_LONG_MIN LONG_MIN
2317 # define SLAP_LONG long
2318 #endif /* HAVE_STRTOLL ... */
2326 struct berval *value,
2327 void *assertedValue )
2329 SLAP_LONG lValue, lAssertedValue;
2331 /* safe to assume integers are NUL terminated? */
2332 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2333 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2336 return LDAP_CONSTRAINT_VIOLATION;
2339 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2341 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2344 return LDAP_CONSTRAINT_VIOLATION;
2347 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2348 return LDAP_SUCCESS;
2357 struct berval *value,
2358 void *assertedValue )
2360 SLAP_LONG lValue, lAssertedValue;
2362 /* safe to assume integers are NUL terminated? */
2363 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2364 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2367 return LDAP_CONSTRAINT_VIOLATION;
2370 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2372 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2375 return LDAP_CONSTRAINT_VIOLATION;
2378 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2379 return LDAP_SUCCESS;
2383 serialNumberAndIssuerValidate(
2389 struct berval sn, i;
2390 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2392 i.bv_val = ber_bvchr( in, '$' );
2393 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2395 sn.bv_val = in->bv_val;
2396 sn.bv_len = i.bv_val - in->bv_val;
2399 i.bv_len = in->bv_len - (sn.bv_len + 1);
2401 /* validate serial number (strict for now) */
2402 for( n=0; n < sn.bv_len; n++ ) {
2403 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2407 rc = dnValidate( NULL, &i );
2408 if( rc ) return LDAP_INVALID_SYNTAX;
2410 return LDAP_SUCCESS;
2414 serialNumberAndIssuerPretty(
2422 struct berval sn, i, newi;
2424 assert( val != NULL );
2425 assert( out != NULL );
2427 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2428 val->bv_val, 0, 0 );
2430 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2432 i.bv_val = ber_bvchr( val, '$' );
2433 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2435 sn.bv_val = val->bv_val;
2436 sn.bv_len = i.bv_val - val->bv_val;
2439 i.bv_len = val->bv_len - (sn.bv_len + 1);
2441 /* eat leading zeros */
2442 for( n=0; n < (sn.bv_len-1); n++ ) {
2443 if( sn.bv_val[n] != '0' ) break;
2448 for( n=0; n < sn.bv_len; n++ ) {
2449 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2453 rc = dnPretty( syntax, &i, &newi, ctx );
2454 if( rc ) return LDAP_INVALID_SYNTAX;
2456 /* make room from sn + "$" */
2457 out->bv_len = sn.bv_len + newi.bv_len + 1;
2458 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2460 if( out->bv_val == NULL ) {
2462 slap_sl_free( newi.bv_val, ctx );
2466 /* push issuer over */
2467 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2468 /* insert sn and "$" */
2469 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2470 out->bv_val[sn.bv_len] = '$';
2472 out->bv_val[out->bv_len] = '\0';
2474 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2475 out->bv_val, 0, 0 );
2477 return LDAP_SUCCESS;
2481 * This routine is called by certificateExactNormalize when
2482 * certificateExactNormalize receives a search string instead of
2483 * a certificate. This routine checks if the search value is valid
2484 * and then returns the normalized value
2487 serialNumberAndIssuerNormalize(
2497 struct berval sn, i, newi;
2499 assert( val != NULL );
2500 assert( out != NULL );
2502 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2503 val->bv_val, 0, 0 );
2505 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2507 i.bv_val = ber_bvchr( val, '$' );
2508 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2510 sn.bv_val = val->bv_val;
2511 sn.bv_len = i.bv_val - val->bv_val;
2514 i.bv_len = val->bv_len - (sn.bv_len + 1);
2516 /* eat leading zeros */
2517 for( n=0; n < (sn.bv_len-1); n++ ) {
2518 if( sn.bv_val[n] != '0' ) break;
2523 for( n=0; n < sn.bv_len; n++ ) {
2524 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2525 return LDAP_INVALID_SYNTAX;
2530 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2531 if( rc ) return LDAP_INVALID_SYNTAX;
2533 /* make room from sn + "$" */
2534 out->bv_len = sn.bv_len + newi.bv_len + 1;
2535 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2537 if( out->bv_val == NULL ) {
2539 slap_sl_free( newi.bv_val, ctx );
2543 /* push issuer over */
2544 AC_MEMCPY( &out->bv_val[sn.bv_len+1], out->bv_val, newi.bv_len );
2545 /* insert sn and "$" */
2546 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2547 out->bv_val[sn.bv_len] = '$';
2549 out->bv_val[out->bv_len] = '\0';
2551 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2552 out->bv_val, 0, 0 );
2559 certificateExactNormalize(
2564 struct berval *normalized,
2567 int rc = LDAP_INVALID_SYNTAX;
2569 char *serial = NULL;
2570 ber_len_t seriallen;
2571 struct berval issuer_dn = BER_BVNULL;
2572 X509_NAME *name = NULL;
2573 ASN1_INTEGER *sn = NULL;
2576 if( BER_BVISEMPTY( val ) ) goto done;
2578 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2579 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2582 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2584 p = (unsigned char *)val->bv_val;
2585 xcert = d2i_X509( NULL, &p, val->bv_len);
2586 if( xcert == NULL ) goto done;
2588 sn=X509_get_serialNumber(xcert);
2589 if ( sn == NULL ) goto done;
2590 serial=i2s_ASN1_INTEGER(0, sn );
2591 if( serial == NULL ) goto done;
2592 seriallen=strlen(serial);
2594 name=X509_get_issuer_name(xcert);
2595 if( name == NULL ) goto done;
2596 rc = dnX509normalize( name, &issuer_dn );
2597 if( rc != LDAP_SUCCESS ) goto done;
2599 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2600 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2601 p = (unsigned char *)normalized->bv_val;
2602 AC_MEMCPY(p, serial, seriallen);
2605 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2606 p += issuer_dn.bv_len;
2609 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2610 normalized->bv_val, NULL, NULL );
2613 if (xcert) X509_free(xcert);
2614 if (serial) ch_free(serial);
2615 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2619 #endif /* HAVE_TLS */
2622 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2623 /* slight optimization - does not need the start parameter */
2624 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2629 check_time_syntax (struct berval *val,
2632 struct berval *fraction)
2635 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2636 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2637 * GeneralizedTime supports leap seconds, UTCTime does not.
2639 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2640 static const int mdays[2][12] = {
2641 /* non-leap years */
2642 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2644 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2647 int part, c, c1, c2, tzoffset, leapyear = 0;
2650 e = p + val->bv_len;
2652 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2653 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2655 for (part = start; part < 7 && p < e; part++) {
2657 if (!ASCII_DIGIT(c1)) {
2662 return LDAP_INVALID_SYNTAX;
2665 if (!ASCII_DIGIT(c)) {
2666 return LDAP_INVALID_SYNTAX;
2668 c += c1 * 10 - '0' * 11;
2669 if ((part | 1) == 3) {
2672 return LDAP_INVALID_SYNTAX;
2675 if (c >= ceiling[part]) {
2676 if (! (c == 60 && part == 6 && start == 0))
2677 return LDAP_INVALID_SYNTAX;
2681 if (part < 5 + start) {
2682 return LDAP_INVALID_SYNTAX;
2684 for (; part < 9; part++) {
2688 /* leapyear check for the Gregorian calendar (year>1581) */
2689 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2693 if (parts[3] >= mdays[leapyear][parts[2]]) {
2694 return LDAP_INVALID_SYNTAX;
2698 fraction->bv_val = p;
2699 fraction->bv_len = 0;
2700 if (p < e && (*p == '.' || *p == ',')) {
2702 while (++p < e && ASCII_DIGIT(*p)) {
2705 if (p - fraction->bv_val == 1) {
2706 return LDAP_INVALID_SYNTAX;
2708 for (end_num = p; end_num[-1] == '0'; --end_num) {
2711 c = end_num - fraction->bv_val;
2712 if (c != 1) fraction->bv_len = c;
2718 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2724 return LDAP_INVALID_SYNTAX;
2730 for (part = 7; part < 9 && p < e; part++) {
2732 if (!ASCII_DIGIT(c1)) {
2737 return LDAP_INVALID_SYNTAX;
2740 if (!ASCII_DIGIT(c2)) {
2741 return LDAP_INVALID_SYNTAX;
2743 parts[part] = c1 * 10 + c2 - '0' * 11;
2744 if (parts[part] >= ceiling[part]) {
2745 return LDAP_INVALID_SYNTAX;
2748 if (part < 8 + start) {
2749 return LDAP_INVALID_SYNTAX;
2752 if (tzoffset == '-') {
2753 /* negative offset to UTC, ie west of Greenwich */
2754 parts[4] += parts[7];
2755 parts[5] += parts[8];
2756 /* offset is just hhmm, no seconds */
2757 for (part = 6; --part >= 0; ) {
2761 c = mdays[leapyear][parts[2]];
2763 if (parts[part] >= c) {
2765 return LDAP_INVALID_SYNTAX;
2770 } else if (part != 5) {
2775 /* positive offset to UTC, ie east of Greenwich */
2776 parts[4] -= parts[7];
2777 parts[5] -= parts[8];
2778 for (part = 6; --part >= 0; ) {
2779 if (parts[part] < 0) {
2781 return LDAP_INVALID_SYNTAX;
2786 /* make first arg to % non-negative */
2787 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2792 } else if (part != 5) {
2799 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2802 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2809 struct berval *normalized )
2813 rc = check_time_syntax(val, 1, parts, NULL);
2814 if (rc != LDAP_SUCCESS) {
2818 normalized->bv_val = ch_malloc( 14 );
2819 if ( normalized->bv_val == NULL ) {
2820 return LBER_ERROR_MEMORY;
2823 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2824 parts[1], parts[2] + 1, parts[3] + 1,
2825 parts[4], parts[5], parts[6] );
2826 normalized->bv_len = 13;
2828 return LDAP_SUCCESS;
2838 return check_time_syntax(in, 1, parts, NULL);
2841 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2844 generalizedTimeValidate(
2849 struct berval fraction;
2850 return check_time_syntax(in, 0, parts, &fraction);
2854 generalizedTimeNormalize(
2859 struct berval *normalized,
2864 struct berval fraction;
2866 rc = check_time_syntax(val, 0, parts, &fraction);
2867 if (rc != LDAP_SUCCESS) {
2871 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2872 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2873 if ( BER_BVISNULL( normalized ) ) {
2874 return LBER_ERROR_MEMORY;
2877 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2878 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2879 parts[4], parts[5], parts[6] );
2880 if ( !BER_BVISEMPTY( &fraction ) ) {
2881 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2882 fraction.bv_val, fraction.bv_len );
2883 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2885 strcpy( normalized->bv_val + len-1, "Z" );
2886 normalized->bv_len = len;
2888 return LDAP_SUCCESS;
2892 generalizedTimeOrderingMatch(
2897 struct berval *value,
2898 void *assertedValue )
2900 struct berval *asserted = (struct berval *) assertedValue;
2901 ber_len_t v_len = value->bv_len;
2902 ber_len_t av_len = asserted->bv_len;
2904 /* ignore trailing 'Z' when comparing */
2905 int match = memcmp( value->bv_val, asserted->bv_val,
2906 (v_len < av_len ? v_len : av_len) - 1 );
2907 if ( match == 0 ) match = v_len - av_len;
2910 return LDAP_SUCCESS;
2913 /* Index generation function */
2914 int generalizedTimeIndexer(
2919 struct berval *prefix,
2927 BerValue bvtmp; /* 40 bit index */
2929 struct lutil_timet tt;
2931 bvtmp.bv_len = sizeof(tmp);
2933 for( i=0; values[i].bv_val != NULL; i++ ) {
2934 /* just count them */
2937 /* we should have at least one value at this point */
2940 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2942 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2943 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2944 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2945 /* Use 40 bits of time for key */
2946 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2947 lutil_tm2time( &tm, &tt );
2948 tmp[0] = tt.tt_gsec & 0xff;
2949 tmp[4] = tt.tt_sec & 0xff;
2951 tmp[3] = tt.tt_sec & 0xff;
2953 tmp[2] = tt.tt_sec & 0xff;
2955 tmp[1] = tt.tt_sec & 0xff;
2957 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2961 keys[j].bv_val = NULL;
2966 return LDAP_SUCCESS;
2969 /* Index generation function */
2970 int generalizedTimeFilter(
2975 struct berval *prefix,
2976 void * assertedValue,
2982 BerValue bvtmp; /* 40 bit index */
2983 BerValue *value = (BerValue *) assertedValue;
2985 struct lutil_timet tt;
2987 bvtmp.bv_len = sizeof(tmp);
2989 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2990 /* Use 40 bits of time for key */
2991 if ( value->bv_val && value->bv_len >= 10 &&
2992 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2994 lutil_tm2time( &tm, &tt );
2995 tmp[0] = tt.tt_gsec & 0xff;
2996 tmp[4] = tt.tt_sec & 0xff;
2998 tmp[3] = tt.tt_sec & 0xff;
3000 tmp[2] = tt.tt_sec & 0xff;
3002 tmp[1] = tt.tt_sec & 0xff;
3004 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3005 ber_dupbv_x(keys, &bvtmp, ctx );
3006 keys[1].bv_val = NULL;
3014 return LDAP_SUCCESS;
3018 deliveryMethodValidate(
3020 struct berval *val )
3023 #define LENOF(s) (sizeof(s)-1)
3024 struct berval tmp = *val;
3026 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3027 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3028 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3031 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3033 switch( tmp.bv_val[0] ) {
3036 if(( tmp.bv_len >= LENOF("any") ) &&
3037 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3039 tmp.bv_len -= LENOF("any");
3040 tmp.bv_val += LENOF("any");
3043 return LDAP_INVALID_SYNTAX;
3047 if(( tmp.bv_len >= LENOF("mhs") ) &&
3048 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3050 tmp.bv_len -= LENOF("mhs");
3051 tmp.bv_val += LENOF("mhs");
3054 return LDAP_INVALID_SYNTAX;
3058 if(( tmp.bv_len >= LENOF("physical") ) &&
3059 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3061 tmp.bv_len -= LENOF("physical");
3062 tmp.bv_val += LENOF("physical");
3065 return LDAP_INVALID_SYNTAX;
3068 case 'T': /* telex or teletex or telephone */
3069 if(( tmp.bv_len >= LENOF("telex") ) &&
3070 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3072 tmp.bv_len -= LENOF("telex");
3073 tmp.bv_val += LENOF("telex");
3076 if(( tmp.bv_len >= LENOF("teletex") ) &&
3077 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3079 tmp.bv_len -= LENOF("teletex");
3080 tmp.bv_val += LENOF("teletex");
3083 if(( tmp.bv_len >= LENOF("telephone") ) &&
3084 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3086 tmp.bv_len -= LENOF("telephone");
3087 tmp.bv_val += LENOF("telephone");
3090 return LDAP_INVALID_SYNTAX;
3093 case 'G': /* g3fax or g4fax */
3094 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3095 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3096 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3098 tmp.bv_len -= LENOF("g3fax");
3099 tmp.bv_val += LENOF("g3fax");
3102 return LDAP_INVALID_SYNTAX;
3106 if(( tmp.bv_len >= LENOF("ia5") ) &&
3107 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3109 tmp.bv_len -= LENOF("ia5");
3110 tmp.bv_val += LENOF("ia5");
3113 return LDAP_INVALID_SYNTAX;
3117 if(( tmp.bv_len >= LENOF("videotex") ) &&
3118 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3120 tmp.bv_len -= LENOF("videotex");
3121 tmp.bv_val += LENOF("videotex");
3124 return LDAP_INVALID_SYNTAX;
3127 return LDAP_INVALID_SYNTAX;
3130 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3132 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3136 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3140 return LDAP_INVALID_SYNTAX;
3142 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3151 nisNetgroupTripleValidate(
3153 struct berval *val )
3158 if ( BER_BVISEMPTY( val ) ) {
3159 return LDAP_INVALID_SYNTAX;
3162 p = (char *)val->bv_val;
3163 e = p + val->bv_len;
3165 if ( *p != '(' /*')'*/ ) {
3166 return LDAP_INVALID_SYNTAX;
3169 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3173 return LDAP_INVALID_SYNTAX;
3176 } else if ( !AD_CHAR( *p ) ) {
3177 return LDAP_INVALID_SYNTAX;
3181 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3182 return LDAP_INVALID_SYNTAX;
3188 return LDAP_INVALID_SYNTAX;
3191 return LDAP_SUCCESS;
3195 bootParameterValidate(
3197 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;
3209 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3210 if ( !AD_CHAR( *p ) ) {
3211 return LDAP_INVALID_SYNTAX;
3216 return LDAP_INVALID_SYNTAX;
3220 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3221 if ( !AD_CHAR( *p ) ) {
3222 return LDAP_INVALID_SYNTAX;
3227 return LDAP_INVALID_SYNTAX;
3231 for ( p++; p < e; p++ ) {
3232 if ( !SLAP_PRINTABLE( *p ) ) {
3233 return LDAP_INVALID_SYNTAX;
3237 return LDAP_SUCCESS;
3241 firstComponentNormalize(
3246 struct berval *normalized,
3253 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3254 ber_dupbv_x( normalized, val, ctx );
3255 return LDAP_SUCCESS;
3258 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3260 if( val->bv_val[0] != '(' /*')'*/ &&
3261 val->bv_val[0] != '{' /*'}'*/ )
3263 return LDAP_INVALID_SYNTAX;
3266 /* trim leading white space */
3268 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3274 /* grab next word */
3275 comp.bv_val = &val->bv_val[len];
3276 len = val->bv_len - len;
3277 for( comp.bv_len = 0;
3278 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3284 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3285 rc = numericoidValidate( NULL, &comp );
3286 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3287 rc = integerValidate( NULL, &comp );
3289 rc = LDAP_INVALID_SYNTAX;
3293 if( rc == LDAP_SUCCESS ) {
3294 ber_dupbv_x( normalized, &comp, ctx );
3301 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3302 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3304 static slap_syntax_defs_rec syntax_defs[] = {
3305 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3306 X_BINARY X_NOT_H_R ")",
3307 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3308 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3310 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3312 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3314 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3315 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3317 SLAP_SYNTAX_BER, berValidate, NULL},
3318 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3319 0, bitStringValidate, NULL },
3320 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3321 0, booleanValidate, NULL},
3322 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3323 X_BINARY X_NOT_H_R ")",
3324 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3325 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3326 X_BINARY X_NOT_H_R ")",
3327 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3328 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3329 X_BINARY X_NOT_H_R ")",
3330 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3331 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3332 0, countryStringValidate, NULL},
3333 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3334 0, dnValidate, dnPretty},
3335 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3336 0, rdnValidate, rdnPretty},
3337 #ifdef LDAP_COMP_MATCH
3338 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3339 0, allComponentsValidate, NULL},
3340 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3341 0, componentFilterValidate, NULL},
3343 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3345 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3346 0, deliveryMethodValidate, NULL},
3347 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3348 0, UTF8StringValidate, NULL},
3349 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3351 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3353 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3355 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3357 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3359 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3360 0, printablesStringValidate, NULL},
3361 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3362 SLAP_SYNTAX_BLOB, NULL, NULL},
3363 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3364 0, generalizedTimeValidate, NULL},
3365 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3367 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3368 0, IA5StringValidate, NULL},
3369 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3370 0, integerValidate, NULL},
3371 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3372 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3373 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3375 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3377 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3379 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3381 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3383 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3384 0, nameUIDValidate, nameUIDPretty },
3385 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3387 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3388 0, numericStringValidate, NULL},
3389 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3391 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3392 0, numericoidValidate, NULL},
3393 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3394 0, IA5StringValidate, NULL},
3395 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3396 0, blobValidate, NULL},
3397 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3398 0, UTF8StringValidate, NULL},
3399 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3401 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3403 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3404 0, printableStringValidate, NULL},
3405 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3406 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3407 0, subtreeSpecificationValidate, NULL},
3408 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3409 X_BINARY X_NOT_H_R ")",
3410 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3411 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3412 0, printableStringValidate, NULL},
3413 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3415 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3416 0, printablesStringValidate, NULL},
3417 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3418 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3419 0, utcTimeValidate, NULL},
3421 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3423 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3425 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3427 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3429 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3432 /* RFC 2307 NIS Syntaxes */
3433 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3434 0, nisNetgroupTripleValidate, NULL},
3435 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3436 0, bootParameterValidate, NULL},
3438 /* From PKIX *//* This OID is not published yet. */
3439 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3441 serialNumberAndIssuerValidate,
3442 serialNumberAndIssuerPretty},
3444 #ifdef SLAPD_AUTHPASSWD
3445 /* needs updating */
3446 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3447 SLAP_SYNTAX_HIDE, NULL, NULL},
3450 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
3451 0, UUIDValidate, NULL},
3453 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3454 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3456 /* OpenLDAP Void Syntax */
3457 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3458 SLAP_SYNTAX_HIDE, inValidate, NULL},
3460 #ifdef SLAP_AUTHZ_SYNTAX
3461 /* FIXME: OID is unused, but not registered yet */
3462 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
3463 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
3464 #endif /* SLAP_AUTHZ_SYNTAX */
3466 {NULL, 0, NULL, NULL}
3469 char *certificateExactMatchSyntaxes[] = {
3470 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3473 #ifdef LDAP_COMP_MATCH
3474 char *componentFilterMatchSyntaxes[] = {
3475 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3479 char *directoryStringSyntaxes[] = {
3480 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3483 char *integerFirstComponentMatchSyntaxes[] = {
3484 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3485 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3488 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3489 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3490 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3491 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3492 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3493 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3494 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3495 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3496 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3501 * Other matching rules in X.520 that we do not use (yet):
3503 * 2.5.13.25 uTCTimeMatch
3504 * 2.5.13.26 uTCTimeOrderingMatch
3505 * 2.5.13.31* directoryStringFirstComponentMatch
3506 * 2.5.13.32* wordMatch
3507 * 2.5.13.33* keywordMatch
3508 * 2.5.13.36 certificatePairExactMatch
3509 * 2.5.13.37 certificatePairMatch
3510 * 2.5.13.38 certificateListExactMatch
3511 * 2.5.13.39 certificateListMatch
3512 * 2.5.13.40 algorithmIdentifierMatch
3513 * 2.5.13.41* storedPrefixMatch
3514 * 2.5.13.42 attributeCertificateMatch
3515 * 2.5.13.43 readerAndKeyIDMatch
3516 * 2.5.13.44 attributeIntegrityMatch
3518 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3520 static slap_mrule_defs_rec mrule_defs[] = {
3522 * EQUALITY matching rules must be listed after associated APPROX
3523 * matching rules. So, we list all APPROX matching rules first.
3525 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3527 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3528 NULL, NULL, directoryStringApproxMatch,
3529 directoryStringApproxIndexer, directoryStringApproxFilter,
3532 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3534 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3535 NULL, NULL, IA5StringApproxMatch,
3536 IA5StringApproxIndexer, IA5StringApproxFilter,
3540 * Other matching rules
3543 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3545 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3546 NULL, NULL, octetStringMatch,
3547 octetStringIndexer, octetStringFilter,
3550 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3552 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3553 NULL, dnNormalize, dnMatch,
3554 octetStringIndexer, octetStringFilter,
3557 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3559 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3560 NULL, dnNormalize, dnRelativeMatch,
3564 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3566 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3567 NULL, dnNormalize, dnRelativeMatch,
3571 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3573 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3574 NULL, dnNormalize, dnRelativeMatch,
3578 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3580 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3581 NULL, dnNormalize, dnRelativeMatch,
3585 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3586 "SYNTAX 1.2.36.79672281.1.5.0 )",
3587 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3588 NULL, rdnNormalize, rdnMatch,
3589 octetStringIndexer, octetStringFilter,
3592 #ifdef LDAP_COMP_MATCH
3593 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3594 "SYNTAX 1.2.36.79672281.1.5.2 )",
3595 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3596 NULL, NULL , componentFilterMatch,
3597 octetStringIndexer, octetStringFilter,
3600 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3601 "SYNTAX 1.2.36.79672281.1.5.3 )",
3602 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3603 NULL, NULL , allComponentsMatch,
3604 octetStringIndexer, octetStringFilter,
3607 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3608 "SYNTAX 1.2.36.79672281.1.5.3 )",
3609 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3610 NULL, NULL , directoryComponentsMatch,
3611 octetStringIndexer, octetStringFilter,
3615 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3617 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3618 NULL, UTF8StringNormalize, octetStringMatch,
3619 octetStringIndexer, octetStringFilter,
3620 directoryStringApproxMatchOID },
3622 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3624 SLAP_MR_ORDERING, directoryStringSyntaxes,
3625 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3627 "caseIgnoreMatch" },
3629 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3631 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3632 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3633 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3634 "caseIgnoreMatch" },
3636 {"( 2.5.13.5 NAME 'caseExactMatch' "
3637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3638 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3639 NULL, UTF8StringNormalize, octetStringMatch,
3640 octetStringIndexer, octetStringFilter,
3641 directoryStringApproxMatchOID },
3643 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3645 SLAP_MR_ORDERING, directoryStringSyntaxes,
3646 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3650 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3652 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3653 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3654 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3657 {"( 2.5.13.8 NAME 'numericStringMatch' "
3658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3659 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3660 NULL, numericStringNormalize, octetStringMatch,
3661 octetStringIndexer, octetStringFilter,
3664 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3665 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3666 SLAP_MR_ORDERING, NULL,
3667 NULL, numericStringNormalize, octetStringOrderingMatch,
3669 "numericStringMatch" },
3671 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3673 SLAP_MR_SUBSTR, NULL,
3674 NULL, numericStringNormalize, octetStringSubstringsMatch,
3675 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3676 "numericStringMatch" },
3678 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3679 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3681 NULL, NULL, NULL, NULL, NULL, NULL },
3683 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3685 SLAP_MR_SUBSTR, NULL,
3686 NULL, NULL, NULL, NULL, NULL,
3687 "caseIgnoreListMatch" },
3689 {"( 2.5.13.13 NAME 'booleanMatch' "
3690 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3691 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3692 NULL, NULL, booleanMatch,
3693 octetStringIndexer, octetStringFilter,
3696 {"( 2.5.13.14 NAME 'integerMatch' "
3697 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3698 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3699 NULL, NULL, integerMatch,
3700 octetStringIndexer, octetStringFilter,
3703 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3704 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3705 SLAP_MR_ORDERING, NULL,
3706 NULL, NULL, integerMatch,
3710 {"( 2.5.13.16 NAME 'bitStringMatch' "
3711 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3712 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3713 NULL, NULL, octetStringMatch,
3714 octetStringIndexer, octetStringFilter,
3717 {"( 2.5.13.17 NAME 'octetStringMatch' "
3718 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3719 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3720 NULL, NULL, octetStringMatch,
3721 octetStringIndexer, octetStringFilter,
3724 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3725 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3726 SLAP_MR_ORDERING, NULL,
3727 NULL, NULL, octetStringOrderingMatch,
3729 "octetStringMatch" },
3731 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3732 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3733 SLAP_MR_SUBSTR, NULL,
3734 NULL, NULL, octetStringSubstringsMatch,
3735 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3736 "octetStringMatch" },
3738 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3739 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3740 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3742 telephoneNumberNormalize, octetStringMatch,
3743 octetStringIndexer, octetStringFilter,
3746 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3747 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3748 SLAP_MR_SUBSTR, NULL,
3749 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3750 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3751 "telephoneNumberMatch" },
3753 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3755 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3756 NULL, NULL, NULL, NULL, NULL, NULL },
3758 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3760 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3761 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3762 uniqueMemberIndexer, uniqueMemberFilter,
3765 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3767 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3768 NULL, NULL, NULL, NULL, NULL, NULL },
3770 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3772 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3773 NULL, generalizedTimeNormalize, octetStringMatch,
3774 generalizedTimeIndexer, generalizedTimeFilter,
3777 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3778 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3779 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3780 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3782 "generalizedTimeMatch" },
3784 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3785 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3786 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3787 integerFirstComponentMatchSyntaxes,
3788 NULL, firstComponentNormalize, integerMatch,
3789 octetStringIndexer, octetStringFilter,
3792 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3793 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3794 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3795 objectIdentifierFirstComponentMatchSyntaxes,
3796 NULL, firstComponentNormalize, octetStringMatch,
3797 octetStringIndexer, octetStringFilter,
3800 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3801 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3802 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3804 NULL, certificateExactNormalize, octetStringMatch,
3805 octetStringIndexer, octetStringFilter,
3807 NULL, NULL, NULL, NULL, NULL,
3811 {"( 2.5.13.35 NAME 'certificateMatch' "
3812 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3813 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3815 NULL, NULL, octetStringMatch,
3816 octetStringIndexer, octetStringFilter,
3818 NULL, NULL, NULL, NULL, NULL,
3822 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3823 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3824 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3825 NULL, IA5StringNormalize, octetStringMatch,
3826 octetStringIndexer, octetStringFilter,
3827 IA5StringApproxMatchOID },
3829 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3830 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3831 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3832 NULL, IA5StringNormalize, octetStringMatch,
3833 octetStringIndexer, octetStringFilter,
3834 IA5StringApproxMatchOID },
3836 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3838 SLAP_MR_SUBSTR, NULL,
3839 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3840 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3841 "caseIgnoreIA5Match" },
3843 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3845 SLAP_MR_SUBSTR, NULL,
3846 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3847 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3848 "caseExactIA5Match" },
3850 #ifdef SLAPD_AUTHPASSWD
3851 /* needs updating */
3852 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3853 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3854 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3855 NULL, NULL, authPasswordMatch,
3860 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3861 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3863 NULL, NULL, integerBitAndMatch,
3867 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3870 NULL, NULL, integerBitOrMatch,
3874 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
3875 "SYNTAX 1.3.6.1.1.16.1 )",
3876 SLAP_MR_EQUALITY, NULL,
3877 NULL, UUIDNormalize, octetStringMatch,
3878 octetStringIndexer, octetStringFilter,
3881 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
3882 "SYNTAX 1.3.6.1.1.16.1 )",
3883 SLAP_MR_ORDERING, NULL,
3884 NULL, UUIDNormalize, octetStringOrderingMatch,
3885 octetStringIndexer, octetStringFilter,
3888 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3889 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3890 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3891 NULL, NULL, csnMatch,
3892 csnIndexer, csnFilter,
3895 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3896 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3897 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3898 NULL, NULL, csnOrderingMatch,
3902 #ifdef SLAP_AUTHZ_SYNTAX
3903 /* FIXME: OID is unused, but not registered yet */
3904 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
3905 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
3906 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3907 NULL, authzNormalize, authzMatch,
3910 #endif /* SLAP_AUTHZ_SYNTAX */
3912 {NULL, SLAP_MR_NONE, NULL,
3913 NULL, NULL, NULL, NULL, NULL,
3918 slap_schema_init( void )
3923 /* we should only be called once (from main) */
3924 assert( schema_init_done == 0 );
3926 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3927 res = register_syntax( &syntax_defs[i] );
3930 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3931 syntax_defs[i].sd_desc );
3936 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3937 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3938 mrule_defs[i].mrd_compat_syntaxes == NULL )
3941 "slap_schema_init: Ignoring unusable matching rule %s\n",
3942 mrule_defs[i].mrd_desc );
3946 res = register_matching_rule( &mrule_defs[i] );
3950 "slap_schema_init: Error registering matching rule %s\n",
3951 mrule_defs[i].mrd_desc );
3956 res = slap_schema_load();
3957 schema_init_done = 1;
3962 schema_destroy( void )
3971 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
3972 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );