1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2006 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,
2105 slap_schema.si_mr_caseExactIA5Match );
2107 assert( !BER_BVISEMPTY( val ) );
2109 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
2113 /* Ignore initial whitespace */
2114 while ( ASCII_SPACE( *p ) ) p++;
2116 normalized->bv_val = ber_strdup_x( p, ctx );
2117 p = q = normalized->bv_val;
2120 if ( ASCII_SPACE( *p ) ) {
2123 /* Ignore the extra whitespace */
2124 while ( ASCII_SPACE( *p ) ) {
2128 } else if ( casefold ) {
2129 /* Most IA5 rules require casefolding */
2130 *q++ = TOLOWER(*p); p++;
2137 assert( normalized->bv_val <= p );
2141 * If the string ended in space, backup the pointer one
2142 * position. One is enough because the above loop collapsed
2143 * all whitespace to a single space.
2145 if ( ASCII_SPACE( q[-1] ) ) --q;
2147 /* null terminate */
2150 normalized->bv_len = q - normalized->bv_val;
2151 if( BER_BVISEMPTY( normalized ) ) {
2152 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2153 normalized->bv_val[0] = ' ';
2154 normalized->bv_val[1] = '\0';
2155 normalized->bv_len = 1;
2158 return LDAP_SUCCESS;
2167 if( in->bv_len != 36 ) {
2168 return LDAP_INVALID_SYNTAX;
2171 for( i=0; i<36; i++ ) {
2177 if( in->bv_val[i] != '-' ) {
2178 return LDAP_INVALID_SYNTAX;
2182 if( !ASCII_HEX( in->bv_val[i]) ) {
2183 return LDAP_INVALID_SYNTAX;
2188 return LDAP_SUCCESS;
2199 int rc=LDAP_INVALID_SYNTAX;
2201 assert( in != NULL );
2202 assert( out != NULL );
2204 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2207 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2209 for( i=0; i<36; i++ ) {
2215 if( in->bv_val[i] != '-' ) {
2218 out->bv_val[i] = '-';
2222 if( !ASCII_HEX( in->bv_val[i]) ) {
2225 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2230 out->bv_val[ out->bv_len ] = '\0';
2234 slap_sl_free( out->bv_val, ctx );
2247 struct berval *normalized,
2250 unsigned char octet = '\0';
2253 normalized->bv_len = 16;
2254 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2256 for( i=0, j=0; i<36; i++ ) {
2257 unsigned char nibble;
2258 if( val->bv_val[i] == '-' ) {
2261 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2262 nibble = val->bv_val[i] - '0';
2264 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2265 nibble = val->bv_val[i] - ('a'-10);
2267 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2268 nibble = val->bv_val[i] - ('A'-10);
2271 slap_sl_free( normalized->bv_val, ctx );
2272 return LDAP_INVALID_SYNTAX;
2277 normalized->bv_val[j>>1] = octet;
2279 octet = nibble << 4;
2284 normalized->bv_val[normalized->bv_len] = 0;
2285 return LDAP_SUCCESS;
2291 numericStringValidate(
2297 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2299 for(i=0; i < in->bv_len; i++) {
2300 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2301 return LDAP_INVALID_SYNTAX;
2305 return LDAP_SUCCESS;
2309 numericStringNormalize(
2314 struct berval *normalized,
2317 /* removal all spaces */
2320 assert( !BER_BVISEMPTY( val ) );
2322 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2325 q = normalized->bv_val;
2328 if ( ASCII_SPACE( *p ) ) {
2329 /* Ignore whitespace */
2336 /* we should have copied no more then is in val */
2337 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2339 /* null terminate */
2342 normalized->bv_len = q - normalized->bv_val;
2344 if( BER_BVISEMPTY( normalized ) ) {
2345 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2346 normalized->bv_val[0] = ' ';
2347 normalized->bv_val[1] = '\0';
2348 normalized->bv_len = 1;
2351 return LDAP_SUCCESS;
2355 * Integer conversion macros that will use the largest available
2358 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2359 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2360 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2361 # define SLAP_LONG_MAX LLONG_MAX
2362 # define SLAP_LONG_MIN LLONG_MIN
2363 # define SLAP_LONG long long
2365 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2366 # define SLAP_LONG_MAX LONG_MAX
2367 # define SLAP_LONG_MIN LONG_MIN
2368 # define SLAP_LONG long
2369 #endif /* HAVE_STRTOLL ... */
2377 struct berval *value,
2378 void *assertedValue )
2380 SLAP_LONG lValue, lAssertedValue;
2382 /* safe to assume integers are NUL terminated? */
2383 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2384 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2387 return LDAP_CONSTRAINT_VIOLATION;
2390 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2392 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2395 return LDAP_CONSTRAINT_VIOLATION;
2398 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2399 return LDAP_SUCCESS;
2408 struct berval *value,
2409 void *assertedValue )
2411 SLAP_LONG lValue, lAssertedValue;
2413 /* safe to assume integers are NUL terminated? */
2414 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2415 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2418 return LDAP_CONSTRAINT_VIOLATION;
2421 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2423 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2426 return LDAP_CONSTRAINT_VIOLATION;
2429 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2430 return LDAP_SUCCESS;
2434 serialNumberAndIssuerValidate(
2440 struct berval sn, i;
2442 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2445 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2447 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2448 /* Parse old format */
2449 i.bv_val = ber_bvchr( in, '$' );
2450 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2452 sn.bv_val = in->bv_val;
2453 sn.bv_len = i.bv_val - in->bv_val;
2456 i.bv_len = in->bv_len - (sn.bv_len + 1);
2458 /* eat leading zeros */
2459 for( n=0; n < (sn.bv_len-1); n++ ) {
2460 if( sn.bv_val[n] != '0' ) break;
2465 for( n=0; n < sn.bv_len; n++ ) {
2466 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2470 /* Parse GSER format */
2471 int havesn=0,haveissuer=0;
2472 struct berval x = *in;
2476 /* eat leading spaces */
2477 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2481 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2482 return LDAP_INVALID_SYNTAX;
2485 /* should be at issuer or serialNumber NamedValue */
2486 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2488 x.bv_val += STRLENOF("issuer");
2489 x.bv_len -= STRLENOF("issuer");
2491 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2492 x.bv_val++; x.bv_len--;
2494 /* eat leading spaces */
2495 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2499 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2500 x.bv_val++; x.bv_len--;
2502 i.bv_val = x.bv_val;
2505 for( ; i.bv_len < x.bv_len; ) {
2506 if ( i.bv_val[i.bv_len] != '"' ) {
2510 if ( i.bv_val[i.bv_len+1] == '"' ) {
2517 x.bv_val += i.bv_len+1;
2518 x.bv_len -= i.bv_len+1;
2520 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2521 return LDAP_INVALID_SYNTAX;
2526 } else if( strncasecmp( x.bv_val, "serialNumber",
2527 STRLENOF("serialNumber")) == 0 )
2529 /* parse serialNumber */
2531 x.bv_val += STRLENOF("serialNumber");
2532 x.bv_len -= STRLENOF("serialNumber");
2534 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2535 x.bv_val++; x.bv_len--;
2537 /* eat leading spaces */
2538 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2542 sn.bv_val = x.bv_val;
2545 if( sn.bv_val[0] == '-' ) {
2550 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2551 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2554 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2555 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2556 return LDAP_INVALID_SYNTAX;
2559 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2561 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2562 return LDAP_INVALID_SYNTAX;
2567 } else return LDAP_INVALID_SYNTAX;
2569 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2570 x.bv_val++; x.bv_len--;
2573 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2577 /* should be at remaining NamedValue */
2578 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2579 STRLENOF("issuer" )) == 0 ))
2582 x.bv_val += STRLENOF("issuer");
2583 x.bv_len -= STRLENOF("issuer");
2585 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2586 x.bv_val++; x.bv_len--;
2588 /* eat leading spaces */
2589 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2593 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2594 x.bv_val++; x.bv_len--;
2596 i.bv_val = x.bv_val;
2599 for( ; i.bv_len < x.bv_len; ) {
2600 if ( i.bv_val[i.bv_len] != '"' ) {
2604 if ( i.bv_val[i.bv_len+1] == '"' ) {
2611 x.bv_val += i.bv_len+1;
2612 x.bv_len -= i.bv_len+1;
2614 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2615 STRLENOF("serialNumber")) == 0 ))
2617 /* parse serialNumber */
2619 x.bv_val += STRLENOF("serialNumber");
2620 x.bv_len -= STRLENOF("serialNumber");
2622 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2623 x.bv_val++; x.bv_len--;
2625 /* eat leading spaces */
2626 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2630 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2631 x.bv_val++; x.bv_len--;
2633 sn.bv_val = x.bv_val;
2636 if( sn.bv_val[0] == '-' ) {
2641 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2642 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2645 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2646 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2647 return LDAP_INVALID_SYNTAX;
2650 x.bv_val += sn.bv_len;
2651 x.bv_len -= sn.bv_len;
2653 } else return LDAP_INVALID_SYNTAX;
2655 /* eat trailing spaces */
2656 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2660 /* should have no characters left... */
2661 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2664 /* validate DN -- doesn't handle double dquote */
2665 rc = dnValidate( NULL, &i );
2666 if( rc ) return LDAP_INVALID_SYNTAX;
2668 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2670 return LDAP_SUCCESS;
2674 serialNumberAndIssuerPretty(
2682 struct berval sn, i, ni;
2684 assert( in != NULL );
2685 assert( out != NULL );
2687 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2690 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2692 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2693 /* Parse old format */
2694 i.bv_val = ber_bvchr( in, '$' );
2695 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2697 sn.bv_val = in->bv_val;
2698 sn.bv_len = i.bv_val - in->bv_val;
2701 i.bv_len = in->bv_len - (sn.bv_len + 1);
2703 /* eat leading zeros */
2704 for( n=0; n < (sn.bv_len-1); n++ ) {
2705 if( sn.bv_val[n] != '0' ) break;
2710 for( n=0; n < sn.bv_len; n++ ) {
2711 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2715 /* Parse GSER format */
2716 int havesn=0,haveissuer=0;
2717 struct berval x = *in;
2721 /* eat leading spaces */
2722 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2726 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2727 return LDAP_INVALID_SYNTAX;
2730 /* should be at issuer or serialNumber NamedValue */
2731 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2733 x.bv_val += STRLENOF("issuer");
2734 x.bv_len -= STRLENOF("issuer");
2736 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2737 x.bv_val++; x.bv_len--;
2739 /* eat leading spaces */
2740 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2744 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2745 x.bv_val++; x.bv_len--;
2747 i.bv_val = x.bv_val;
2750 for( ; i.bv_len < x.bv_len; ) {
2751 if ( i.bv_val[i.bv_len] != '"' ) {
2755 if ( i.bv_val[i.bv_len+1] == '"' ) {
2762 x.bv_val += i.bv_len+1;
2763 x.bv_len -= i.bv_len+1;
2765 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2766 return LDAP_INVALID_SYNTAX;
2771 } else if( strncasecmp( x.bv_val, "serialNumber",
2772 STRLENOF("serialNumber")) == 0 )
2774 /* parse serialNumber */
2776 x.bv_val += STRLENOF("serialNumber");
2777 x.bv_len -= STRLENOF("serialNumber");
2779 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2780 x.bv_val++; x.bv_len--;
2782 /* eat leading spaces */
2783 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2787 sn.bv_val = x.bv_val;
2790 if( sn.bv_val[0] == '-' ) {
2795 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2796 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2799 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2800 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2801 return LDAP_INVALID_SYNTAX;
2804 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2806 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2807 return LDAP_INVALID_SYNTAX;
2812 } else return LDAP_INVALID_SYNTAX;
2814 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2815 x.bv_val++; x.bv_len--;
2818 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2822 /* should be at remaining NamedValue */
2823 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2824 STRLENOF("issuer" )) == 0 ))
2827 x.bv_val += STRLENOF("issuer");
2828 x.bv_len -= STRLENOF("issuer");
2830 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2831 x.bv_val++; x.bv_len--;
2833 /* eat leading spaces */
2834 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2838 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2839 x.bv_val++; x.bv_len--;
2841 i.bv_val = x.bv_val;
2844 for( ; i.bv_len < x.bv_len; ) {
2845 if ( i.bv_val[i.bv_len] != '"' ) {
2849 if ( i.bv_val[i.bv_len+1] == '"' ) {
2856 x.bv_val += i.bv_len+1;
2857 x.bv_len -= i.bv_len+1;
2859 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2860 STRLENOF("serialNumber")) == 0 ))
2862 /* parse serialNumber */
2864 x.bv_val += STRLENOF("serialNumber");
2865 x.bv_len -= STRLENOF("serialNumber");
2867 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2868 x.bv_val++; x.bv_len--;
2870 /* eat leading spaces */
2871 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2875 sn.bv_val = x.bv_val;
2878 if( sn.bv_val[0] == '-' ) {
2883 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2884 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2887 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2888 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2889 return LDAP_INVALID_SYNTAX;
2892 x.bv_val += sn.bv_len;
2893 x.bv_len -= sn.bv_len;
2895 } else return LDAP_INVALID_SYNTAX;
2897 /* eat trailing spaces */
2898 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2902 /* should have no characters left... */
2903 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2905 ber_dupbv_x( &ni, &i, ctx );
2908 /* need to handle double dquotes here */
2911 rc = dnPretty( syntax, &i, &ni, ctx );
2913 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2914 slap_sl_free( i.bv_val, ctx );
2917 if( rc ) return LDAP_INVALID_SYNTAX;
2919 /* make room from sn + "$" */
2920 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2921 + sn.bv_len + ni.bv_len;
2922 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2924 if( out->bv_val == NULL ) {
2926 slap_sl_free( ni.bv_val, ctx );
2931 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2932 STRLENOF("{ serialNumber "));
2933 n = STRLENOF("{ serialNumber ");
2935 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2938 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2939 n += STRLENOF(", issuer \"");
2941 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2944 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2945 n += STRLENOF("\" }");
2947 out->bv_val[n] = '\0';
2949 assert( n == out->bv_len );
2951 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2952 out->bv_val, 0, 0 );
2954 slap_sl_free( ni.bv_val, ctx );
2956 return LDAP_SUCCESS;
2960 * This routine is called by certificateExactNormalize when
2961 * certificateExactNormalize receives a search string instead of
2962 * a certificate. This routine checks if the search value is valid
2963 * and then returns the normalized value
2966 serialNumberAndIssuerNormalize(
2976 struct berval sn, i, ni;
2978 assert( in != NULL );
2979 assert( out != NULL );
2981 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2984 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2986 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2987 /* Parse old format */
2988 i.bv_val = ber_bvchr( in, '$' );
2989 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2991 sn.bv_val = in->bv_val;
2992 sn.bv_len = i.bv_val - in->bv_val;
2995 i.bv_len = in->bv_len - (sn.bv_len + 1);
2997 /* eat leading zeros */
2998 for( n=0; n < (sn.bv_len-1); n++ ) {
2999 if( sn.bv_val[n] != '0' ) break;
3004 for( n=0; n < sn.bv_len; n++ ) {
3005 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3009 /* Parse GSER format */
3010 int havesn=0,haveissuer=0;
3011 struct berval x = *in;
3015 /* eat leading spaces */
3016 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3020 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3021 return LDAP_INVALID_SYNTAX;
3024 /* should be at issuer or serialNumber NamedValue */
3025 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3027 x.bv_val += STRLENOF("issuer");
3028 x.bv_len -= STRLENOF("issuer");
3030 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3031 x.bv_val++; x.bv_len--;
3033 /* eat leading spaces */
3034 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3038 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3039 x.bv_val++; x.bv_len--;
3041 i.bv_val = x.bv_val;
3044 for( ; i.bv_len < x.bv_len; ) {
3045 if ( i.bv_val[i.bv_len] != '"' ) {
3049 if ( i.bv_val[i.bv_len+1] == '"' ) {
3056 x.bv_val += i.bv_len+1;
3057 x.bv_len -= i.bv_len+1;
3059 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3060 return LDAP_INVALID_SYNTAX;
3065 } else if( strncasecmp( x.bv_val, "serialNumber",
3066 STRLENOF("serialNumber")) == 0 )
3068 /* parse serialNumber */
3070 x.bv_val += STRLENOF("serialNumber");
3071 x.bv_len -= STRLENOF("serialNumber");
3073 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3074 x.bv_val++; x.bv_len--;
3076 /* eat leading spaces */
3077 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3081 sn.bv_val = x.bv_val;
3084 if( sn.bv_val[0] == '-' ) {
3089 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3090 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3093 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3094 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3095 return LDAP_INVALID_SYNTAX;
3098 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3100 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3101 return LDAP_INVALID_SYNTAX;
3106 } else return LDAP_INVALID_SYNTAX;
3108 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3109 x.bv_val++; x.bv_len--;
3112 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3116 /* should be at remaining NamedValue */
3117 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3118 STRLENOF("issuer" )) == 0 ))
3121 x.bv_val += STRLENOF("issuer");
3122 x.bv_len -= STRLENOF("issuer");
3124 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3125 x.bv_val++; x.bv_len--;
3127 /* eat leading spaces */
3128 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3132 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3133 x.bv_val++; x.bv_len--;
3135 i.bv_val = x.bv_val;
3138 for( ; i.bv_len < x.bv_len; ) {
3139 if ( i.bv_val[i.bv_len] != '"' ) {
3143 if ( i.bv_val[i.bv_len+1] == '"' ) {
3150 x.bv_val += i.bv_len+1;
3151 x.bv_len -= i.bv_len+1;
3153 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3154 STRLENOF("serialNumber")) == 0 ))
3156 /* parse serialNumber */
3158 x.bv_val += STRLENOF("serialNumber");
3159 x.bv_len -= STRLENOF("serialNumber");
3161 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3162 x.bv_val++; x.bv_len--;
3164 /* eat leading spaces */
3165 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3169 sn.bv_val = x.bv_val;
3172 if( sn.bv_val[0] == '-' ) {
3177 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3178 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3181 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3182 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3183 return LDAP_INVALID_SYNTAX;
3186 x.bv_val += sn.bv_len;
3187 x.bv_len -= sn.bv_len;
3189 } else return LDAP_INVALID_SYNTAX;
3191 /* eat trailing spaces */
3192 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3196 /* should have no characters left... */
3197 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3199 ber_dupbv_x( &ni, &i, ctx );
3202 /* need to handle double dquotes here */
3205 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3207 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3208 slap_sl_free( i.bv_val, ctx );
3211 if( rc ) return LDAP_INVALID_SYNTAX;
3213 /* make room from sn + "$" */
3214 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3215 + sn.bv_len + ni.bv_len;
3216 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3218 if( out->bv_val == NULL ) {
3220 slap_sl_free( ni.bv_val, ctx );
3225 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3226 STRLENOF( "{ serialNumber " ));
3227 n = STRLENOF( "{ serialNumber " );
3229 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3232 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3233 n += STRLENOF( ", issuer \"" );
3235 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3238 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3239 n += STRLENOF( "\" }" );
3241 out->bv_val[n] = '\0';
3243 assert( n == out->bv_len );
3245 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3246 out->bv_val, 0, 0 );
3248 slap_sl_free( ni.bv_val, ctx );
3250 return LDAP_SUCCESS;
3255 certificateExactNormalize(
3260 struct berval *normalized,
3263 int rc = LDAP_INVALID_SYNTAX;
3265 char *serial = NULL;
3266 ber_len_t seriallen;
3267 struct berval issuer_dn = BER_BVNULL;
3268 X509_NAME *name = NULL;
3269 ASN1_INTEGER *sn = NULL;
3272 if( BER_BVISEMPTY( val ) ) goto done;
3274 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3275 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3278 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
3280 p = (unsigned char *)val->bv_val;
3281 xcert = d2i_X509( NULL, &p, val->bv_len);
3282 if( xcert == NULL ) goto done;
3284 sn=X509_get_serialNumber(xcert);
3285 if ( sn == NULL ) goto done;
3286 serial=i2s_ASN1_INTEGER(0, sn );
3287 if( serial == NULL ) goto done;
3288 seriallen=strlen(serial);
3290 name=X509_get_issuer_name(xcert);
3291 if( name == NULL ) goto done;
3292 rc = dnX509normalize( name, &issuer_dn );
3293 if( rc != LDAP_SUCCESS ) goto done;
3295 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3296 + seriallen + issuer_dn.bv_len;
3297 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3299 p = (unsigned char *)normalized->bv_val;
3301 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3302 p += STRLENOF( "{ serialNumber " );
3304 AC_MEMCPY(p, serial, seriallen);
3307 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3308 p += STRLENOF( ", issuer \"" );
3310 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3311 p += issuer_dn.bv_len;
3313 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3314 p += STRLENOF( "\" }" );
3318 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3319 normalized->bv_val, NULL, NULL );
3324 if (xcert) X509_free(xcert);
3325 if (serial) ch_free(serial);
3326 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3330 #endif /* HAVE_TLS */
3333 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3334 /* slight optimization - does not need the start parameter */
3335 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3340 check_time_syntax (struct berval *val,
3343 struct berval *fraction)
3346 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3347 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3348 * GeneralizedTime supports leap seconds, UTCTime does not.
3350 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3351 static const int mdays[2][12] = {
3352 /* non-leap years */
3353 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3355 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3358 int part, c, c1, c2, tzoffset, leapyear = 0;
3361 e = p + val->bv_len;
3363 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3364 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3366 for (part = start; part < 7 && p < e; part++) {
3368 if (!ASCII_DIGIT(c1)) {
3373 return LDAP_INVALID_SYNTAX;
3376 if (!ASCII_DIGIT(c)) {
3377 return LDAP_INVALID_SYNTAX;
3379 c += c1 * 10 - '0' * 11;
3380 if ((part | 1) == 3) {
3383 return LDAP_INVALID_SYNTAX;
3386 if (c >= ceiling[part]) {
3387 if (! (c == 60 && part == 6 && start == 0))
3388 return LDAP_INVALID_SYNTAX;
3392 if (part < 5 + start) {
3393 return LDAP_INVALID_SYNTAX;
3395 for (; part < 9; part++) {
3399 /* leapyear check for the Gregorian calendar (year>1581) */
3400 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3404 if (parts[3] >= mdays[leapyear][parts[2]]) {
3405 return LDAP_INVALID_SYNTAX;
3409 fraction->bv_val = p;
3410 fraction->bv_len = 0;
3411 if (p < e && (*p == '.' || *p == ',')) {
3413 while (++p < e && ASCII_DIGIT(*p)) {
3416 if (p - fraction->bv_val == 1) {
3417 return LDAP_INVALID_SYNTAX;
3419 for (end_num = p; end_num[-1] == '0'; --end_num) {
3422 c = end_num - fraction->bv_val;
3423 if (c != 1) fraction->bv_len = c;
3429 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3435 return LDAP_INVALID_SYNTAX;
3441 for (part = 7; part < 9 && p < e; part++) {
3443 if (!ASCII_DIGIT(c1)) {
3448 return LDAP_INVALID_SYNTAX;
3451 if (!ASCII_DIGIT(c2)) {
3452 return LDAP_INVALID_SYNTAX;
3454 parts[part] = c1 * 10 + c2 - '0' * 11;
3455 if (parts[part] >= ceiling[part]) {
3456 return LDAP_INVALID_SYNTAX;
3459 if (part < 8 + start) {
3460 return LDAP_INVALID_SYNTAX;
3463 if (tzoffset == '-') {
3464 /* negative offset to UTC, ie west of Greenwich */
3465 parts[4] += parts[7];
3466 parts[5] += parts[8];
3467 /* offset is just hhmm, no seconds */
3468 for (part = 6; --part >= 0; ) {
3472 c = mdays[leapyear][parts[2]];
3474 if (parts[part] >= c) {
3476 return LDAP_INVALID_SYNTAX;
3481 } else if (part != 5) {
3486 /* positive offset to UTC, ie east of Greenwich */
3487 parts[4] -= parts[7];
3488 parts[5] -= parts[8];
3489 for (part = 6; --part >= 0; ) {
3490 if (parts[part] < 0) {
3492 return LDAP_INVALID_SYNTAX;
3497 /* make first arg to % non-negative */
3498 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3503 } else if (part != 5) {
3510 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3513 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3520 struct berval *normalized )
3524 rc = check_time_syntax(val, 1, parts, NULL);
3525 if (rc != LDAP_SUCCESS) {
3529 normalized->bv_val = ch_malloc( 14 );
3530 if ( normalized->bv_val == NULL ) {
3531 return LBER_ERROR_MEMORY;
3534 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3535 parts[1], parts[2] + 1, parts[3] + 1,
3536 parts[4], parts[5], parts[6] );
3537 normalized->bv_len = 13;
3539 return LDAP_SUCCESS;
3549 return check_time_syntax(in, 1, parts, NULL);
3552 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3555 generalizedTimeValidate(
3560 struct berval fraction;
3561 return check_time_syntax(in, 0, parts, &fraction);
3565 generalizedTimeNormalize(
3570 struct berval *normalized,
3575 struct berval fraction;
3577 rc = check_time_syntax(val, 0, parts, &fraction);
3578 if (rc != LDAP_SUCCESS) {
3582 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3583 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3584 if ( BER_BVISNULL( normalized ) ) {
3585 return LBER_ERROR_MEMORY;
3588 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3589 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3590 parts[4], parts[5], parts[6] );
3591 if ( !BER_BVISEMPTY( &fraction ) ) {
3592 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3593 fraction.bv_val, fraction.bv_len );
3594 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3596 strcpy( normalized->bv_val + len-1, "Z" );
3597 normalized->bv_len = len;
3599 return LDAP_SUCCESS;
3603 generalizedTimeOrderingMatch(
3608 struct berval *value,
3609 void *assertedValue )
3611 struct berval *asserted = (struct berval *) assertedValue;
3612 ber_len_t v_len = value->bv_len;
3613 ber_len_t av_len = asserted->bv_len;
3615 /* ignore trailing 'Z' when comparing */
3616 int match = memcmp( value->bv_val, asserted->bv_val,
3617 (v_len < av_len ? v_len : av_len) - 1 );
3618 if ( match == 0 ) match = v_len - av_len;
3621 return LDAP_SUCCESS;
3624 /* Index generation function */
3625 int generalizedTimeIndexer(
3630 struct berval *prefix,
3638 BerValue bvtmp; /* 40 bit index */
3640 struct lutil_timet tt;
3642 bvtmp.bv_len = sizeof(tmp);
3644 for( i=0; values[i].bv_val != NULL; i++ ) {
3645 /* just count them */
3648 /* we should have at least one value at this point */
3651 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3653 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3654 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3655 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3656 /* Use 40 bits of time for key */
3657 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3658 lutil_tm2time( &tm, &tt );
3659 tmp[0] = tt.tt_gsec & 0xff;
3660 tmp[4] = tt.tt_sec & 0xff;
3662 tmp[3] = tt.tt_sec & 0xff;
3664 tmp[2] = tt.tt_sec & 0xff;
3666 tmp[1] = tt.tt_sec & 0xff;
3668 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3672 keys[j].bv_val = NULL;
3677 return LDAP_SUCCESS;
3680 /* Index generation function */
3681 int generalizedTimeFilter(
3686 struct berval *prefix,
3687 void * assertedValue,
3693 BerValue bvtmp; /* 40 bit index */
3694 BerValue *value = (BerValue *) assertedValue;
3696 struct lutil_timet tt;
3698 bvtmp.bv_len = sizeof(tmp);
3700 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3701 /* Use 40 bits of time for key */
3702 if ( value->bv_val && value->bv_len >= 10 &&
3703 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3705 lutil_tm2time( &tm, &tt );
3706 tmp[0] = tt.tt_gsec & 0xff;
3707 tmp[4] = tt.tt_sec & 0xff;
3709 tmp[3] = tt.tt_sec & 0xff;
3711 tmp[2] = tt.tt_sec & 0xff;
3713 tmp[1] = tt.tt_sec & 0xff;
3715 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3716 ber_dupbv_x(keys, &bvtmp, ctx );
3717 keys[1].bv_val = NULL;
3725 return LDAP_SUCCESS;
3729 deliveryMethodValidate(
3731 struct berval *val )
3734 #define LENOF(s) (sizeof(s)-1)
3735 struct berval tmp = *val;
3737 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3738 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3739 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3742 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3744 switch( tmp.bv_val[0] ) {
3747 if(( tmp.bv_len >= LENOF("any") ) &&
3748 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3750 tmp.bv_len -= LENOF("any");
3751 tmp.bv_val += LENOF("any");
3754 return LDAP_INVALID_SYNTAX;
3758 if(( tmp.bv_len >= LENOF("mhs") ) &&
3759 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3761 tmp.bv_len -= LENOF("mhs");
3762 tmp.bv_val += LENOF("mhs");
3765 return LDAP_INVALID_SYNTAX;
3769 if(( tmp.bv_len >= LENOF("physical") ) &&
3770 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3772 tmp.bv_len -= LENOF("physical");
3773 tmp.bv_val += LENOF("physical");
3776 return LDAP_INVALID_SYNTAX;
3779 case 'T': /* telex or teletex or telephone */
3780 if(( tmp.bv_len >= LENOF("telex") ) &&
3781 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3783 tmp.bv_len -= LENOF("telex");
3784 tmp.bv_val += LENOF("telex");
3787 if(( tmp.bv_len >= LENOF("teletex") ) &&
3788 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3790 tmp.bv_len -= LENOF("teletex");
3791 tmp.bv_val += LENOF("teletex");
3794 if(( tmp.bv_len >= LENOF("telephone") ) &&
3795 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3797 tmp.bv_len -= LENOF("telephone");
3798 tmp.bv_val += LENOF("telephone");
3801 return LDAP_INVALID_SYNTAX;
3804 case 'G': /* g3fax or g4fax */
3805 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3806 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3807 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3809 tmp.bv_len -= LENOF("g3fax");
3810 tmp.bv_val += LENOF("g3fax");
3813 return LDAP_INVALID_SYNTAX;
3817 if(( tmp.bv_len >= LENOF("ia5") ) &&
3818 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3820 tmp.bv_len -= LENOF("ia5");
3821 tmp.bv_val += LENOF("ia5");
3824 return LDAP_INVALID_SYNTAX;
3828 if(( tmp.bv_len >= LENOF("videotex") ) &&
3829 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3831 tmp.bv_len -= LENOF("videotex");
3832 tmp.bv_val += LENOF("videotex");
3835 return LDAP_INVALID_SYNTAX;
3838 return LDAP_INVALID_SYNTAX;
3841 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3843 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3847 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3851 return LDAP_INVALID_SYNTAX;
3853 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3862 nisNetgroupTripleValidate(
3864 struct berval *val )
3869 if ( BER_BVISEMPTY( val ) ) {
3870 return LDAP_INVALID_SYNTAX;
3873 p = (char *)val->bv_val;
3874 e = p + val->bv_len;
3876 if ( *p != '(' /*')'*/ ) {
3877 return LDAP_INVALID_SYNTAX;
3880 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3884 return LDAP_INVALID_SYNTAX;
3887 } else if ( !AD_CHAR( *p ) ) {
3888 return LDAP_INVALID_SYNTAX;
3892 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3893 return LDAP_INVALID_SYNTAX;
3899 return LDAP_INVALID_SYNTAX;
3902 return LDAP_SUCCESS;
3906 bootParameterValidate(
3908 struct berval *val )
3912 if ( BER_BVISEMPTY( val ) ) {
3913 return LDAP_INVALID_SYNTAX;
3916 p = (char *)val->bv_val;
3917 e = p + val->bv_len;
3920 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3921 if ( !AD_CHAR( *p ) ) {
3922 return LDAP_INVALID_SYNTAX;
3927 return LDAP_INVALID_SYNTAX;
3931 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3932 if ( !AD_CHAR( *p ) ) {
3933 return LDAP_INVALID_SYNTAX;
3938 return LDAP_INVALID_SYNTAX;
3942 for ( p++; p < e; p++ ) {
3943 if ( !SLAP_PRINTABLE( *p ) ) {
3944 return LDAP_INVALID_SYNTAX;
3948 return LDAP_SUCCESS;
3952 firstComponentNormalize(
3957 struct berval *normalized,
3964 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3965 ber_dupbv_x( normalized, val, ctx );
3966 return LDAP_SUCCESS;
3969 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3971 if( val->bv_val[0] != '(' /*')'*/ &&
3972 val->bv_val[0] != '{' /*'}'*/ )
3974 return LDAP_INVALID_SYNTAX;
3977 /* trim leading white space */
3979 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3985 /* grab next word */
3986 comp.bv_val = &val->bv_val[len];
3987 len = val->bv_len - len;
3988 for( comp.bv_len = 0;
3989 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3995 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3996 rc = numericoidValidate( NULL, &comp );
3997 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3998 rc = integerValidate( NULL, &comp );
4000 rc = LDAP_INVALID_SYNTAX;
4004 if( rc == LDAP_SUCCESS ) {
4005 ber_dupbv_x( normalized, &comp, ctx );
4012 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4013 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4015 static slap_syntax_defs_rec syntax_defs[] = {
4016 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4017 X_BINARY X_NOT_H_R ")",
4018 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
4019 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4021 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4023 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4025 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4026 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4028 SLAP_SYNTAX_BER, berValidate, NULL},
4029 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4030 0, bitStringValidate, NULL },
4031 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4032 0, booleanValidate, NULL},
4033 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4034 X_BINARY X_NOT_H_R ")",
4035 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
4036 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4037 X_BINARY X_NOT_H_R ")",
4038 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4039 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4040 X_BINARY X_NOT_H_R ")",
4041 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4042 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4043 0, countryStringValidate, NULL},
4044 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4045 0, dnValidate, dnPretty},
4046 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4047 0, rdnValidate, rdnPretty},
4048 #ifdef LDAP_COMP_MATCH
4049 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4050 0, allComponentsValidate, NULL},
4051 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4052 0, componentFilterValidate, NULL},
4054 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4056 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4057 0, deliveryMethodValidate, NULL},
4058 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4059 0, UTF8StringValidate, NULL},
4060 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4062 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4064 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4066 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4068 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4070 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4071 0, printablesStringValidate, NULL},
4072 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4073 SLAP_SYNTAX_BLOB, NULL, NULL},
4074 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4075 0, generalizedTimeValidate, NULL},
4076 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4078 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4079 0, IA5StringValidate, NULL},
4080 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4081 0, integerValidate, NULL},
4082 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4083 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4084 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4086 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4088 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4090 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4092 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4094 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4095 0, nameUIDValidate, nameUIDPretty },
4096 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4098 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4099 0, numericStringValidate, NULL},
4100 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4102 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4103 0, numericoidValidate, NULL},
4104 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4105 0, IA5StringValidate, NULL},
4106 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4107 0, blobValidate, NULL},
4108 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4109 0, UTF8StringValidate, NULL},
4110 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4112 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4114 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4115 0, printableStringValidate, NULL},
4116 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4117 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4118 0, subtreeSpecificationValidate, NULL},
4119 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4120 X_BINARY X_NOT_H_R ")",
4121 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4122 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4123 0, printableStringValidate, NULL},
4124 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4126 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4127 0, printablesStringValidate, NULL},
4128 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4129 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4130 0, utcTimeValidate, NULL},
4132 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4134 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4136 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4138 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4140 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4143 /* RFC 2307 NIS Syntaxes */
4144 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4145 0, nisNetgroupTripleValidate, NULL},
4146 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4147 0, bootParameterValidate, NULL},
4149 /* draft-zeilenga-ldap-x509 */
4150 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4152 serialNumberAndIssuerValidate,
4153 serialNumberAndIssuerPretty},
4154 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4155 SLAP_SYNTAX_HIDE, NULL, NULL},
4156 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4157 SLAP_SYNTAX_HIDE, NULL, NULL},
4158 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4159 SLAP_SYNTAX_HIDE, NULL, NULL},
4160 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4161 SLAP_SYNTAX_HIDE, NULL, NULL},
4162 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4163 SLAP_SYNTAX_HIDE, NULL, NULL},
4164 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4165 SLAP_SYNTAX_HIDE, NULL, NULL},
4167 #ifdef SLAPD_AUTHPASSWD
4168 /* needs updating */
4169 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4170 SLAP_SYNTAX_HIDE, NULL, NULL},
4173 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4174 0, UUIDValidate, UUIDPretty},
4176 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4177 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4179 /* OpenLDAP Void Syntax */
4180 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4181 SLAP_SYNTAX_HIDE, inValidate, NULL},
4183 #ifdef SLAP_AUTHZ_SYNTAX
4184 /* FIXME: OID is unused, but not registered yet */
4185 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4186 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4187 #endif /* SLAP_AUTHZ_SYNTAX */
4189 {NULL, 0, NULL, NULL}
4192 char *certificateExactMatchSyntaxes[] = {
4193 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4196 #ifdef LDAP_COMP_MATCH
4197 char *componentFilterMatchSyntaxes[] = {
4198 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4202 char *directoryStringSyntaxes[] = {
4203 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4206 char *integerFirstComponentMatchSyntaxes[] = {
4207 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4208 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4211 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4212 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4213 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4214 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4215 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4216 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4217 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4218 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4219 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4224 * Other matching rules in X.520 that we do not use (yet):
4226 * 2.5.13.25 uTCTimeMatch
4227 * 2.5.13.26 uTCTimeOrderingMatch
4228 * 2.5.13.31* directoryStringFirstComponentMatch
4229 * 2.5.13.32* wordMatch
4230 * 2.5.13.33* keywordMatch
4231 * 2.5.13.36+ certificatePairExactMatch
4232 * 2.5.13.37+ certificatePairMatch
4233 * 2.5.13.38+ certificateListExactMatch
4234 * 2.5.13.39+ certificateListMatch
4235 * 2.5.13.40+ algorithmIdentifierMatch
4236 * 2.5.13.41* storedPrefixMatch
4237 * 2.5.13.42 attributeCertificateMatch
4238 * 2.5.13.43 readerAndKeyIDMatch
4239 * 2.5.13.44 attributeIntegrityMatch
4241 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4242 * (+) described in draft-zeilenga-ldap-x509
4244 static slap_mrule_defs_rec mrule_defs[] = {
4246 * EQUALITY matching rules must be listed after associated APPROX
4247 * matching rules. So, we list all APPROX matching rules first.
4249 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4250 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4251 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4252 NULL, NULL, directoryStringApproxMatch,
4253 directoryStringApproxIndexer, directoryStringApproxFilter,
4256 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4257 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4258 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4259 NULL, NULL, IA5StringApproxMatch,
4260 IA5StringApproxIndexer, IA5StringApproxFilter,
4264 * Other matching rules
4267 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4269 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4270 NULL, NULL, octetStringMatch,
4271 octetStringIndexer, octetStringFilter,
4274 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4275 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4276 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4277 NULL, dnNormalize, dnMatch,
4278 octetStringIndexer, octetStringFilter,
4281 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4282 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4283 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4284 NULL, dnNormalize, dnRelativeMatch,
4288 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4289 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4290 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4291 NULL, dnNormalize, dnRelativeMatch,
4295 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4296 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4297 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4298 NULL, dnNormalize, dnRelativeMatch,
4302 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4303 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4304 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4305 NULL, dnNormalize, dnRelativeMatch,
4309 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4310 "SYNTAX 1.2.36.79672281.1.5.0 )",
4311 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4312 NULL, rdnNormalize, rdnMatch,
4313 octetStringIndexer, octetStringFilter,
4316 #ifdef LDAP_COMP_MATCH
4317 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4318 "SYNTAX 1.2.36.79672281.1.5.2 )",
4319 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4320 NULL, NULL , componentFilterMatch,
4321 octetStringIndexer, octetStringFilter,
4324 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4325 "SYNTAX 1.2.36.79672281.1.5.3 )",
4326 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4327 NULL, NULL , allComponentsMatch,
4328 octetStringIndexer, octetStringFilter,
4331 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4332 "SYNTAX 1.2.36.79672281.1.5.3 )",
4333 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4334 NULL, NULL , directoryComponentsMatch,
4335 octetStringIndexer, octetStringFilter,
4339 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4340 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4341 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4342 NULL, UTF8StringNormalize, octetStringMatch,
4343 octetStringIndexer, octetStringFilter,
4344 directoryStringApproxMatchOID },
4346 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4347 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4348 SLAP_MR_ORDERING, directoryStringSyntaxes,
4349 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4351 "caseIgnoreMatch" },
4353 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4354 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4355 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4356 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4357 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4358 "caseIgnoreMatch" },
4360 {"( 2.5.13.5 NAME 'caseExactMatch' "
4361 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4362 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4363 NULL, UTF8StringNormalize, octetStringMatch,
4364 octetStringIndexer, octetStringFilter,
4365 directoryStringApproxMatchOID },
4367 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4368 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4369 SLAP_MR_ORDERING, directoryStringSyntaxes,
4370 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4374 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4375 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4376 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4377 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4378 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4381 {"( 2.5.13.8 NAME 'numericStringMatch' "
4382 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4383 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4384 NULL, numericStringNormalize, octetStringMatch,
4385 octetStringIndexer, octetStringFilter,
4388 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4389 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4390 SLAP_MR_ORDERING, NULL,
4391 NULL, numericStringNormalize, octetStringOrderingMatch,
4393 "numericStringMatch" },
4395 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4396 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4397 SLAP_MR_SUBSTR, NULL,
4398 NULL, numericStringNormalize, octetStringSubstringsMatch,
4399 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4400 "numericStringMatch" },
4402 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4403 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4404 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4405 NULL, NULL, NULL, NULL, NULL, NULL },
4407 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4408 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4409 SLAP_MR_SUBSTR, NULL,
4410 NULL, NULL, NULL, NULL, NULL,
4411 "caseIgnoreListMatch" },
4413 {"( 2.5.13.13 NAME 'booleanMatch' "
4414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4415 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4416 NULL, NULL, booleanMatch,
4417 octetStringIndexer, octetStringFilter,
4420 {"( 2.5.13.14 NAME 'integerMatch' "
4421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4422 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4423 NULL, NULL, integerMatch,
4424 octetStringIndexer, octetStringFilter,
4427 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4428 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4429 SLAP_MR_ORDERING, NULL,
4430 NULL, NULL, integerMatch,
4434 {"( 2.5.13.16 NAME 'bitStringMatch' "
4435 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4436 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4437 NULL, NULL, octetStringMatch,
4438 octetStringIndexer, octetStringFilter,
4441 {"( 2.5.13.17 NAME 'octetStringMatch' "
4442 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4443 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4444 NULL, NULL, octetStringMatch,
4445 octetStringIndexer, octetStringFilter,
4448 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4449 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4450 SLAP_MR_ORDERING, NULL,
4451 NULL, NULL, octetStringOrderingMatch,
4453 "octetStringMatch" },
4455 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4456 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4457 SLAP_MR_SUBSTR, NULL,
4458 NULL, NULL, octetStringSubstringsMatch,
4459 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4460 "octetStringMatch" },
4462 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4463 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4464 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4466 telephoneNumberNormalize, octetStringMatch,
4467 octetStringIndexer, octetStringFilter,
4470 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4471 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4472 SLAP_MR_SUBSTR, NULL,
4473 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4474 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4475 "telephoneNumberMatch" },
4477 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4478 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4479 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4480 NULL, NULL, NULL, NULL, NULL, NULL },
4482 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4484 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4485 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4486 uniqueMemberIndexer, uniqueMemberFilter,
4489 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4490 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4491 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4492 NULL, NULL, NULL, NULL, NULL, NULL },
4494 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4496 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4497 NULL, generalizedTimeNormalize, octetStringMatch,
4498 generalizedTimeIndexer, generalizedTimeFilter,
4501 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4503 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4504 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4506 "generalizedTimeMatch" },
4508 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4510 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4511 integerFirstComponentMatchSyntaxes,
4512 NULL, firstComponentNormalize, integerMatch,
4513 octetStringIndexer, octetStringFilter,
4516 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4518 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4519 objectIdentifierFirstComponentMatchSyntaxes,
4520 NULL, firstComponentNormalize, octetStringMatch,
4521 octetStringIndexer, octetStringFilter,
4524 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4525 "SYNTAX 1.3.6.1.1.15.1 )",
4526 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4528 NULL, certificateExactNormalize, octetStringMatch,
4529 octetStringIndexer, octetStringFilter,
4531 NULL, NULL, NULL, NULL, NULL,
4535 {"( 2.5.13.35 NAME 'certificateMatch' "
4536 "SYNTAX 1.3.6.1.1.15.2 )",
4537 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4538 NULL, NULL, NULL, NULL, NULL,
4541 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4542 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4543 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4544 NULL, IA5StringNormalize, octetStringMatch,
4545 octetStringIndexer, octetStringFilter,
4546 IA5StringApproxMatchOID },
4548 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4549 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4550 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4551 NULL, IA5StringNormalize, octetStringMatch,
4552 octetStringIndexer, octetStringFilter,
4553 IA5StringApproxMatchOID },
4555 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4556 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4557 SLAP_MR_SUBSTR, NULL,
4558 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4559 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4560 "caseIgnoreIA5Match" },
4562 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4563 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4564 SLAP_MR_SUBSTR, NULL,
4565 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4566 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4567 "caseExactIA5Match" },
4569 #ifdef SLAPD_AUTHPASSWD
4570 /* needs updating */
4571 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4573 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4574 NULL, NULL, authPasswordMatch,
4579 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4580 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4582 NULL, NULL, integerBitAndMatch,
4586 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4587 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4589 NULL, NULL, integerBitOrMatch,
4593 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4594 "SYNTAX 1.3.6.1.1.16.1 )",
4595 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4596 NULL, UUIDNormalize, octetStringMatch,
4597 octetStringIndexer, octetStringFilter,
4600 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4601 "SYNTAX 1.3.6.1.1.16.1 )",
4602 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4603 NULL, UUIDNormalize, octetStringOrderingMatch,
4604 octetStringIndexer, octetStringFilter,
4607 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4608 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4609 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4610 NULL, NULL, csnMatch,
4611 csnIndexer, csnFilter,
4614 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4615 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4616 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4617 NULL, NULL, csnOrderingMatch,
4621 #ifdef SLAP_AUTHZ_SYNTAX
4622 /* FIXME: OID is unused, but not registered yet */
4623 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4624 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4625 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4626 NULL, authzNormalize, authzMatch,
4629 #endif /* SLAP_AUTHZ_SYNTAX */
4631 {NULL, SLAP_MR_NONE, NULL,
4632 NULL, NULL, NULL, NULL, NULL,
4637 slap_schema_init( void )
4642 /* we should only be called once (from main) */
4643 assert( schema_init_done == 0 );
4645 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4646 res = register_syntax( &syntax_defs[i] );
4649 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4650 syntax_defs[i].sd_desc );
4655 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4656 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4657 mrule_defs[i].mrd_compat_syntaxes == NULL )
4660 "slap_schema_init: Ignoring unusable matching rule %s\n",
4661 mrule_defs[i].mrd_desc );
4665 res = register_matching_rule( &mrule_defs[i] );
4669 "slap_schema_init: Error registering matching rule %s\n",
4670 mrule_defs[i].mrd_desc );
4675 res = slap_schema_load();
4676 schema_init_done = 1;
4681 schema_destroy( void )
4690 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4691 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );