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 /* FIXME: temporary */
71 #define authzMatch octetStringMatch
73 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
74 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
75 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
76 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
78 ldap_pvt_thread_mutex_t ad_undef_mutex;
79 ldap_pvt_thread_mutex_t oc_undef_mutex;
86 /* no value allowed */
87 return LDAP_INVALID_SYNTAX;
95 /* any value allowed */
99 #define berValidate blobValidate
106 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
107 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
114 static int certificateValidate( Syntax *syntax, struct berval *in )
117 unsigned char *p = (unsigned char *)in->bv_val;
119 xcert = d2i_X509(NULL, &p, in->bv_len);
120 if ( !xcert ) return LDAP_INVALID_SYNTAX;
125 #define certificateValidate sequenceValidate
134 struct berval *value,
135 void *assertedValue )
137 struct berval *asserted = (struct berval *) assertedValue;
138 int match = value->bv_len - asserted->bv_len;
141 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
149 octetStringOrderingMatch(
154 struct berval *value,
155 void *assertedValue )
157 struct berval *asserted = (struct berval *) assertedValue;
158 ber_len_t v_len = value->bv_len;
159 ber_len_t av_len = asserted->bv_len;
161 int match = memcmp( value->bv_val, asserted->bv_val,
162 (v_len < av_len ? v_len : av_len) );
164 if( match == 0 ) match = v_len - av_len;
172 HASH_CONTEXT *HASHcontext,
173 struct berval *prefix,
178 HASH_Init(HASHcontext);
179 if(prefix && prefix->bv_len > 0) {
180 HASH_Update(HASHcontext,
181 (unsigned char *)prefix->bv_val, prefix->bv_len);
183 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
184 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
185 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
191 HASH_CONTEXT *HASHcontext,
192 unsigned char *HASHdigest,
193 unsigned char *value,
196 HASH_CONTEXT ctx = *HASHcontext;
197 HASH_Update( &ctx, value, len );
198 HASH_Final( HASHdigest, &ctx );
201 /* Index generation function */
202 int octetStringIndexer(
207 struct berval *prefix,
215 HASH_CONTEXT HASHcontext;
216 unsigned char HASHdigest[HASH_BYTES];
217 struct berval digest;
218 digest.bv_val = (char *)HASHdigest;
219 digest.bv_len = sizeof(HASHdigest);
221 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
222 /* just count them */
225 /* we should have at least one value at this point */
228 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
230 slen = syntax->ssyn_oidlen;
231 mlen = mr->smr_oidlen;
233 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
234 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
235 hashIter( &HASHcontext, HASHdigest,
236 (unsigned char *)values[i].bv_val, values[i].bv_len );
237 ber_dupbv_x( &keys[i], &digest, ctx );
240 BER_BVZERO( &keys[i] );
247 /* Index generation function */
248 int octetStringFilter(
253 struct berval *prefix,
254 void * assertedValue,
260 HASH_CONTEXT HASHcontext;
261 unsigned char HASHdigest[HASH_BYTES];
262 struct berval *value = (struct berval *) assertedValue;
263 struct berval digest;
264 digest.bv_val = (char *)HASHdigest;
265 digest.bv_len = sizeof(HASHdigest);
267 slen = syntax->ssyn_oidlen;
268 mlen = mr->smr_oidlen;
270 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
272 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
273 hashIter( &HASHcontext, HASHdigest,
274 (unsigned char *)value->bv_val, value->bv_len );
276 ber_dupbv_x( keys, &digest, ctx );
277 BER_BVZERO( &keys[1] );
285 octetStringSubstringsMatch(
290 struct berval *value,
291 void *assertedValue )
294 SubstringsAssertion *sub = assertedValue;
295 struct berval left = *value;
299 /* Add up asserted input length */
300 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
301 inlen += sub->sa_initial.bv_len;
304 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
305 inlen += sub->sa_any[i].bv_len;
308 if ( !BER_BVISNULL( &sub->sa_final ) ) {
309 inlen += sub->sa_final.bv_len;
312 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
313 if ( inlen > left.bv_len ) {
318 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
319 sub->sa_initial.bv_len );
325 left.bv_val += sub->sa_initial.bv_len;
326 left.bv_len -= sub->sa_initial.bv_len;
327 inlen -= sub->sa_initial.bv_len;
330 if ( !BER_BVISNULL( &sub->sa_final ) ) {
331 if ( inlen > left.bv_len ) {
336 match = memcmp( sub->sa_final.bv_val,
337 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
338 sub->sa_final.bv_len );
344 left.bv_len -= sub->sa_final.bv_len;
345 inlen -= sub->sa_final.bv_len;
349 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
354 if ( inlen > left.bv_len ) {
355 /* not enough length */
360 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
364 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
371 idx = p - left.bv_val;
373 if ( idx >= left.bv_len ) {
374 /* this shouldn't happen */
381 if ( sub->sa_any[i].bv_len > left.bv_len ) {
382 /* not enough left */
387 match = memcmp( left.bv_val,
388 sub->sa_any[i].bv_val,
389 sub->sa_any[i].bv_len );
397 left.bv_val += sub->sa_any[i].bv_len;
398 left.bv_len -= sub->sa_any[i].bv_len;
399 inlen -= sub->sa_any[i].bv_len;
408 /* Substrings Index generation function */
410 octetStringSubstringsIndexer(
415 struct berval *prefix,
424 HASH_CONTEXT HCany, HCini, HCfin;
425 unsigned char HASHdigest[HASH_BYTES];
426 struct berval digest;
427 digest.bv_val = (char *)HASHdigest;
428 digest.bv_len = sizeof(HASHdigest);
432 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
433 /* count number of indices to generate */
434 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
435 if( values[i].bv_len >= index_substr_if_maxlen ) {
436 nkeys += index_substr_if_maxlen -
437 (index_substr_if_minlen - 1);
438 } else if( values[i].bv_len >= index_substr_if_minlen ) {
439 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
443 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
444 if( values[i].bv_len >= index_substr_any_len ) {
445 nkeys += values[i].bv_len - (index_substr_any_len - 1);
449 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
450 if( values[i].bv_len >= index_substr_if_maxlen ) {
451 nkeys += index_substr_if_maxlen -
452 (index_substr_if_minlen - 1);
453 } else if( values[i].bv_len >= index_substr_if_minlen ) {
454 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
460 /* no keys to generate */
465 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
467 slen = syntax->ssyn_oidlen;
468 mlen = mr->smr_oidlen;
470 if ( flags & SLAP_INDEX_SUBSTR_ANY )
471 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
472 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
473 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
474 if( flags & SLAP_INDEX_SUBSTR_FINAL )
475 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
478 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
481 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
482 ( values[i].bv_len >= index_substr_any_len ) )
484 max = values[i].bv_len - (index_substr_any_len - 1);
486 for( j=0; j<max; j++ ) {
487 hashIter( &HCany, HASHdigest,
488 (unsigned char *)&values[i].bv_val[j],
489 index_substr_any_len );
490 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
494 /* skip if too short */
495 if( values[i].bv_len < index_substr_if_minlen ) continue;
497 max = index_substr_if_maxlen < values[i].bv_len
498 ? index_substr_if_maxlen : values[i].bv_len;
500 for( j=index_substr_if_minlen; j<=max; j++ ) {
502 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
503 hashIter( &HCini, HASHdigest,
504 (unsigned char *)values[i].bv_val, j );
505 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
508 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
509 hashIter( &HCfin, HASHdigest,
510 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
511 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
518 BER_BVZERO( &keys[nkeys] );
529 octetStringSubstringsFilter (
534 struct berval *prefix,
535 void * assertedValue,
539 SubstringsAssertion *sa;
542 size_t slen, mlen, klen;
544 HASH_CONTEXT HASHcontext;
545 unsigned char HASHdigest[HASH_BYTES];
546 struct berval *value;
547 struct berval digest;
549 sa = (SubstringsAssertion *) assertedValue;
551 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
552 !BER_BVISNULL( &sa->sa_initial ) &&
553 sa->sa_initial.bv_len >= index_substr_if_minlen )
556 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
557 ( flags & SLAP_INDEX_SUBSTR_ANY ))
559 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
563 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
565 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
566 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
567 /* don't bother accounting with stepping */
568 nkeys += sa->sa_any[i].bv_len -
569 ( index_substr_any_len - 1 );
574 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
575 !BER_BVISNULL( &sa->sa_final ) &&
576 sa->sa_final.bv_len >= index_substr_if_minlen )
579 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
580 ( flags & SLAP_INDEX_SUBSTR_ANY ))
582 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
591 digest.bv_val = (char *)HASHdigest;
592 digest.bv_len = sizeof(HASHdigest);
594 slen = syntax->ssyn_oidlen;
595 mlen = mr->smr_oidlen;
597 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
600 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
601 !BER_BVISNULL( &sa->sa_initial ) &&
602 sa->sa_initial.bv_len >= index_substr_if_minlen )
604 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
605 value = &sa->sa_initial;
607 klen = index_substr_if_maxlen < value->bv_len
608 ? index_substr_if_maxlen : value->bv_len;
610 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
611 hashIter( &HASHcontext, HASHdigest,
612 (unsigned char *)value->bv_val, klen );
613 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
615 /* If initial is too long and we have subany indexed, use it
616 * to match the excess...
618 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
621 pre = SLAP_INDEX_SUBSTR_PREFIX;
622 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
623 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
625 hashIter( &HASHcontext, HASHdigest,
626 (unsigned char *)&value->bv_val[j], index_substr_any_len );
627 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
632 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
634 pre = SLAP_INDEX_SUBSTR_PREFIX;
635 klen = index_substr_any_len;
637 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
638 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
642 value = &sa->sa_any[i];
644 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
646 j <= value->bv_len - index_substr_any_len;
647 j += index_substr_any_step )
649 hashIter( &HASHcontext, HASHdigest,
650 (unsigned char *)&value->bv_val[j], klen );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
657 !BER_BVISNULL( &sa->sa_final ) &&
658 sa->sa_final.bv_len >= index_substr_if_minlen )
660 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
661 value = &sa->sa_final;
663 klen = index_substr_if_maxlen < value->bv_len
664 ? index_substr_if_maxlen : value->bv_len;
666 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
667 hashIter( &HASHcontext, HASHdigest,
668 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
669 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
671 /* If final is too long and we have subany indexed, use it
672 * to match the excess...
674 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
677 pre = SLAP_INDEX_SUBSTR_PREFIX;
678 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
679 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
681 hashIter( &HASHcontext, HASHdigest,
682 (unsigned char *)&value->bv_val[j], index_substr_any_len );
683 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
689 BER_BVZERO( &keys[nkeys] );
706 /* very unforgiving validation, requires no normalization
707 * before simplistic matching
709 if( in->bv_len < 3 ) {
710 return LDAP_INVALID_SYNTAX;
714 * RFC 2252 section 6.3 Bit String
715 * bitstring = "'" *binary-digit "'B"
716 * binary-digit = "0" / "1"
717 * example: '0101111101'B
720 if( in->bv_val[0] != '\'' ||
721 in->bv_val[in->bv_len - 2] != '\'' ||
722 in->bv_val[in->bv_len - 1] != 'B' )
724 return LDAP_INVALID_SYNTAX;
727 for( i = in->bv_len - 3; i > 0; i-- ) {
728 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
729 return LDAP_INVALID_SYNTAX;
737 * Syntax is [RFC2252]:
742 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
744 Values in this syntax are encoded according to the following BNF:
746 bitstring = "'" *binary-digit "'B"
748 binary-digit = "0" / "1"
752 6.21. Name And Optional UID
754 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
756 Values in this syntax are encoded according to the following BNF:
758 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
760 Although the '#' character may occur in a string representation of a
761 distinguished name, no additional special quoting is done. This
762 syntax has been added subsequent to RFC 1778.
766 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
769 * draft-ietf-ldapbis-syntaxes-xx.txt says:
774 A value of the Bit String syntax is a sequence of binary digits. The
775 LDAP-specific encoding of a value of this syntax is defined by the
778 BitString = SQUOTE *binary-digit SQUOTE "B"
780 binary-digit = "0" / "1"
782 The <SQUOTE> rule is defined in [MODELS].
787 The LDAP definition for the Bit String syntax is:
789 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
791 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
795 3.3.21. Name and Optional UID
797 A value of the Name and Optional UID syntax is the distinguished name
798 [MODELS] of an entity optionally accompanied by a unique identifier
799 that serves to differentiate the entity from others with an identical
802 The LDAP-specific encoding of a value of this syntax is defined by
805 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
807 The <BitString> rule is defined in Section 3.3.2. The
808 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
811 Note that although the '#' character may occur in the string
812 representation of a distinguished name, no additional escaping of
813 this character is performed when a <distinguishedName> is encoded in
814 a <NameAndOptionalUID>.
817 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
819 The LDAP definition for the Name and Optional UID syntax is:
821 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
823 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
827 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
830 1.4. Common ABNF Productions
833 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
835 SQUOTE = %x27 ; single quote ("'")
839 * Note: normalization strips any leading "0"s, unless the
840 * bit string is exactly "'0'B", so the normalized example,
841 * in slapd, would result in
843 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
845 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
846 * i.e. "#", doesn't have to be escaped except when at the
847 * beginning of a value, the definition of Name and Optional
848 * UID appears to be flawed, because there is no clear means
849 * to determine whether the UID part is present or not.
853 * cn=Someone,dc=example,dc=com#'1'B
855 * could be either a NameAndOptionalUID with trailing UID, i.e.
857 * DN = "cn=Someone,dc=example,dc=com"
860 * or a NameAndOptionalUID with no trailing UID, and the AVA
861 * in the last RDN made of
864 * attributeValue = com#'1'B
866 * in fact "com#'1'B" is a valid IA5 string.
868 * As a consequence, current slapd code assumes that the
869 * presence of portions of a BitString at the end of the string
870 * representation of a NameAndOptionalUID means a BitString
871 * is expected, and cause an error otherwise. This is quite
872 * arbitrary, and might change in the future.
882 struct berval dn, uid;
884 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
886 ber_dupbv( &dn, in );
887 if( !dn.bv_val ) return LDAP_OTHER;
889 /* if there's a "#", try bitStringValidate()... */
890 uid.bv_val = strrchr( dn.bv_val, '#' );
891 if ( !BER_BVISNULL( &uid ) ) {
893 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
895 rc = bitStringValidate( NULL, &uid );
896 if ( rc == LDAP_SUCCESS ) {
897 /* in case of success, trim the UID,
898 * otherwise treat it as part of the DN */
899 dn.bv_len -= uid.bv_len + 1;
900 uid.bv_val[-1] = '\0';
904 rc = dnValidate( NULL, &dn );
906 ber_memfree( dn.bv_val );
917 assert( val != NULL );
918 assert( out != NULL );
921 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
923 if( BER_BVISEMPTY( val ) ) {
924 ber_dupbv_x( out, val, ctx );
926 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
927 return LDAP_INVALID_SYNTAX;
931 struct berval dnval = *val;
932 struct berval uidval = BER_BVNULL;
934 uidval.bv_val = strrchr( val->bv_val, '#' );
935 if ( !BER_BVISNULL( &uidval ) ) {
937 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
939 rc = bitStringValidate( NULL, &uidval );
941 if ( rc == LDAP_SUCCESS ) {
942 ber_dupbv_x( &dnval, val, ctx );
943 dnval.bv_len -= uidval.bv_len + 1;
944 dnval.bv_val[dnval.bv_len] = '\0';
947 BER_BVZERO( &uidval );
951 rc = dnPretty( syntax, &dnval, out, ctx );
952 if ( dnval.bv_val != val->bv_val ) {
953 slap_sl_free( dnval.bv_val, ctx );
955 if( rc != LDAP_SUCCESS ) {
959 if( !BER_BVISNULL( &uidval ) ) {
963 tmp = slap_sl_realloc( out->bv_val, out->bv_len
964 + STRLENOF( "#" ) + uidval.bv_len + 1,
967 ber_memfree_x( out->bv_val, ctx );
971 out->bv_val[out->bv_len++] = '#';
972 out->bv_val[out->bv_len++] = '\'';
974 got1 = uidval.bv_len < sizeof("'0'B");
975 for( i = 1; i < uidval.bv_len - 2; i++ ) {
976 c = uidval.bv_val[i];
979 if( got1 ) out->bv_val[out->bv_len++] = c;
983 out->bv_val[out->bv_len++] = c;
988 out->bv_val[out->bv_len++] = '\'';
989 out->bv_val[out->bv_len++] = 'B';
990 out->bv_val[out->bv_len] = '\0';
994 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1000 uniqueMemberNormalize(
1005 struct berval *normalized,
1011 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1013 ber_dupbv_x( &out, val, ctx );
1014 if ( BER_BVISEMPTY( &out ) ) {
1018 struct berval uid = BER_BVNULL;
1020 uid.bv_val = strrchr( out.bv_val, '#' );
1021 if ( !BER_BVISNULL( &uid ) ) {
1023 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1025 rc = bitStringValidate( NULL, &uid );
1026 if ( rc == LDAP_SUCCESS ) {
1027 uid.bv_val[-1] = '\0';
1028 out.bv_len -= uid.bv_len + 1;
1034 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1036 if( rc != LDAP_SUCCESS ) {
1037 slap_sl_free( out.bv_val, ctx );
1038 return LDAP_INVALID_SYNTAX;
1041 if( !BER_BVISNULL( &uid ) ) {
1044 tmp = ch_realloc( normalized->bv_val,
1045 normalized->bv_len + uid.bv_len
1046 + STRLENOF("#") + 1 );
1047 if ( tmp == NULL ) {
1048 ber_memfree_x( normalized->bv_val, ctx );
1052 normalized->bv_val = tmp;
1054 /* insert the separator */
1055 normalized->bv_val[normalized->bv_len++] = '#';
1057 /* append the UID */
1058 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1059 uid.bv_val, uid.bv_len );
1060 normalized->bv_len += uid.bv_len;
1063 normalized->bv_val[normalized->bv_len] = '\0';
1066 slap_sl_free( out.bv_val, ctx );
1069 return LDAP_SUCCESS;
1078 struct berval *value,
1079 void *assertedValue )
1082 struct berval *asserted = (struct berval *) assertedValue;
1083 struct berval assertedDN = *asserted;
1084 struct berval assertedUID = BER_BVNULL;
1085 struct berval valueDN = *value;
1086 struct berval valueUID = BER_BVNULL;
1087 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1089 if ( !BER_BVISEMPTY( asserted ) ) {
1090 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1091 if ( !BER_BVISNULL( &assertedUID ) ) {
1092 assertedUID.bv_val++;
1093 assertedUID.bv_len = assertedDN.bv_len
1094 - ( assertedUID.bv_val - assertedDN.bv_val );
1096 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1097 assertedDN.bv_len -= assertedUID.bv_len + 1;
1100 BER_BVZERO( &assertedUID );
1105 if ( !BER_BVISEMPTY( value ) ) {
1107 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1108 if ( !BER_BVISNULL( &valueUID ) ) {
1110 valueUID.bv_len = valueDN.bv_len
1111 - ( valueUID.bv_val - valueDN.bv_val );
1113 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1114 valueDN.bv_len -= valueUID.bv_len + 1;
1117 BER_BVZERO( &valueUID );
1122 if( valueUID.bv_len && assertedUID.bv_len ) {
1123 match = valueUID.bv_len - assertedUID.bv_len;
1126 return LDAP_SUCCESS;
1129 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1132 return LDAP_SUCCESS;
1135 } else if ( !approx && valueUID.bv_len ) {
1138 return LDAP_SUCCESS;
1140 } else if ( !approx && assertedUID.bv_len ) {
1143 return LDAP_SUCCESS;
1146 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1150 uniqueMemberIndexer(
1155 struct berval *prefix,
1163 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1164 /* just count them */
1168 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1170 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1171 struct berval assertedDN = values[i];
1172 struct berval assertedUID = BER_BVNULL;
1174 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1175 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1176 if ( !BER_BVISNULL( &assertedUID ) ) {
1177 assertedUID.bv_val++;
1178 assertedUID.bv_len = assertedDN.bv_len
1179 - ( assertedUID.bv_val - assertedDN.bv_val );
1181 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1182 assertedDN.bv_len -= assertedUID.bv_len + 1;
1185 BER_BVZERO( &assertedUID );
1190 dnvalues[i] = assertedDN;
1192 BER_BVZERO( &dnvalues[i] );
1194 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1195 dnvalues, keysp, ctx );
1197 slap_sl_free( dnvalues, ctx );
1207 struct berval *prefix,
1208 void * assertedValue,
1212 struct berval *asserted = (struct berval *) assertedValue;
1213 struct berval assertedDN = *asserted;
1214 struct berval assertedUID = BER_BVNULL;
1216 if ( !BER_BVISEMPTY( asserted ) ) {
1217 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1218 if ( !BER_BVISNULL( &assertedUID ) ) {
1219 assertedUID.bv_val++;
1220 assertedUID.bv_len = assertedDN.bv_len
1221 - ( assertedUID.bv_val - assertedDN.bv_val );
1223 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1224 assertedDN.bv_len -= assertedUID.bv_len + 1;
1227 BER_BVZERO( &assertedUID );
1232 return octetStringFilter( use, flags, syntax, mr, prefix,
1233 &assertedDN, keysp, ctx );
1238 * Handling boolean syntax and matching is quite rigid.
1239 * A more flexible approach would be to allow a variety
1240 * of strings to be normalized and prettied into TRUE
1248 /* very unforgiving validation, requires no normalization
1249 * before simplistic matching
1252 if( in->bv_len == 4 ) {
1253 if( bvmatch( in, &slap_true_bv ) ) {
1254 return LDAP_SUCCESS;
1256 } else if( in->bv_len == 5 ) {
1257 if( bvmatch( in, &slap_false_bv ) ) {
1258 return LDAP_SUCCESS;
1262 return LDAP_INVALID_SYNTAX;
1271 struct berval *value,
1272 void *assertedValue )
1274 /* simplistic matching allowed by rigid validation */
1275 struct berval *asserted = (struct berval *) assertedValue;
1276 *matchp = value->bv_len != asserted->bv_len;
1277 return LDAP_SUCCESS;
1280 /*-------------------------------------------------------------------
1281 LDAP/X.500 string syntax / matching rules have a few oddities. This
1282 comment attempts to detail how slapd(8) treats them.
1285 StringSyntax X.500 LDAP Matching/Comments
1286 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1287 PrintableString subset subset i/e + ignore insignificant spaces
1288 PrintableString subset subset i/e + ignore insignificant spaces
1289 NumericString subset subset ignore all spaces
1290 IA5String ASCII ASCII i/e + ignore insignificant spaces
1291 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1293 TelephoneNumber subset subset i + ignore all spaces and "-"
1295 See draft-ietf-ldapbis-strpro for details (once published).
1299 In X.500(93), a directory string can be either a PrintableString,
1300 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1301 In later versions, more CHOICEs were added. In all cases the string
1304 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1305 A directory string cannot be zero length.
1307 For matching, there are both case ignore and exact rules. Both
1308 also require that "insignificant" spaces be ignored.
1309 spaces before the first non-space are ignored;
1310 spaces after the last non-space are ignored;
1311 spaces after a space are ignored.
1312 Note: by these rules (and as clarified in X.520), a string of only
1313 spaces is to be treated as if held one space, not empty (which
1314 would be a syntax error).
1317 In ASN.1, numeric string is just a string of digits and spaces
1318 and could be empty. However, in X.500, all attribute values of
1319 numeric string carry a non-empty constraint. For example:
1321 internationalISDNNumber ATTRIBUTE ::= {
1322 WITH SYNTAX InternationalISDNNumber
1323 EQUALITY MATCHING RULE numericStringMatch
1324 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1325 ID id-at-internationalISDNNumber }
1326 InternationalISDNNumber ::=
1327 NumericString (SIZE(1..ub-international-isdn-number))
1329 Unforunately, some assertion values are don't carry the same
1330 constraint (but its unclear how such an assertion could ever
1331 be true). In LDAP, there is one syntax (numericString) not two
1332 (numericString with constraint, numericString without constraint).
1333 This should be treated as numericString with non-empty constraint.
1334 Note that while someone may have no ISDN number, there are no ISDN
1335 numbers which are zero length.
1337 In matching, spaces are ignored.
1340 In ASN.1, Printable string is just a string of printable characters
1341 and can be empty. In X.500, semantics much like NumericString (see
1342 serialNumber for a like example) excepting uses insignificant space
1343 handling instead of ignore all spaces.
1346 Basically same as PrintableString. There are no examples in X.500,
1347 but same logic applies. So we require them to be non-empty as
1350 -------------------------------------------------------------------*/
1359 unsigned char *u = (unsigned char *)in->bv_val;
1361 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1362 /* directory strings cannot be empty */
1363 return LDAP_INVALID_SYNTAX;
1366 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1367 /* get the length indicated by the first byte */
1368 len = LDAP_UTF8_CHARLEN2( u, len );
1370 /* very basic checks */
1373 if( (u[5] & 0xC0) != 0x80 ) {
1374 return LDAP_INVALID_SYNTAX;
1377 if( (u[4] & 0xC0) != 0x80 ) {
1378 return LDAP_INVALID_SYNTAX;
1381 if( (u[3] & 0xC0) != 0x80 ) {
1382 return LDAP_INVALID_SYNTAX;
1385 if( (u[2] & 0xC0 )!= 0x80 ) {
1386 return LDAP_INVALID_SYNTAX;
1389 if( (u[1] & 0xC0) != 0x80 ) {
1390 return LDAP_INVALID_SYNTAX;
1393 /* CHARLEN already validated it */
1396 return LDAP_INVALID_SYNTAX;
1399 /* make sure len corresponds with the offset
1400 to the next character */
1401 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1405 return LDAP_INVALID_SYNTAX;
1408 return LDAP_SUCCESS;
1412 UTF8StringNormalize(
1417 struct berval *normalized,
1420 struct berval tmp, nvalue;
1424 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1426 if( BER_BVISNULL( val ) ) {
1427 /* assume we're dealing with a syntax (e.g., UTF8String)
1428 * which allows empty strings
1430 BER_BVZERO( normalized );
1431 return LDAP_SUCCESS;
1434 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1435 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1436 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1437 ? LDAP_UTF8_APPROX : 0;
1439 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1444 /* collapse spaces (in place) */
1446 nvalue.bv_val = tmp.bv_val;
1448 /* trim leading spaces? */
1449 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1450 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1452 for( i = 0; i < tmp.bv_len; i++) {
1453 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1454 if( wasspace++ == 0 ) {
1455 /* trim repeated spaces */
1456 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1460 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1464 if( !BER_BVISEMPTY( &nvalue ) ) {
1465 /* trim trailing space? */
1467 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1468 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1472 nvalue.bv_val[nvalue.bv_len] = '\0';
1475 /* string of all spaces is treated as one space */
1476 nvalue.bv_val[0] = ' ';
1477 nvalue.bv_val[1] = '\0';
1481 *normalized = nvalue;
1482 return LDAP_SUCCESS;
1486 directoryStringSubstringsMatch(
1491 struct berval *value,
1492 void *assertedValue )
1495 SubstringsAssertion *sub = assertedValue;
1496 struct berval left = *value;
1500 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1501 if ( sub->sa_initial.bv_len > left.bv_len ) {
1502 /* not enough left */
1507 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1508 sub->sa_initial.bv_len );
1514 left.bv_val += sub->sa_initial.bv_len;
1515 left.bv_len -= sub->sa_initial.bv_len;
1517 priorspace = ASCII_SPACE(
1518 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1521 if ( sub->sa_any ) {
1522 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1526 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1527 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1529 /* allow next space to match */
1536 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1540 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1541 /* not enough left */
1546 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1553 idx = p - left.bv_val;
1555 if ( idx >= left.bv_len ) {
1556 /* this shouldn't happen */
1563 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1564 /* not enough left */
1569 match = memcmp( left.bv_val,
1570 sub->sa_any[i].bv_val,
1571 sub->sa_any[i].bv_len );
1579 left.bv_val += sub->sa_any[i].bv_len;
1580 left.bv_len -= sub->sa_any[i].bv_len;
1582 priorspace = ASCII_SPACE(
1583 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1587 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1588 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1589 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1591 /* allow next space to match */
1596 if ( sub->sa_final.bv_len > left.bv_len ) {
1597 /* not enough left */
1602 match = memcmp( sub->sa_final.bv_val,
1603 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1604 sub->sa_final.bv_len );
1613 return LDAP_SUCCESS;
1616 #if defined(SLAPD_APPROX_INITIALS)
1617 # define SLAPD_APPROX_DELIMITER "._ "
1618 # define SLAPD_APPROX_WORDLEN 2
1620 # define SLAPD_APPROX_DELIMITER " "
1621 # define SLAPD_APPROX_WORDLEN 1
1630 struct berval *value,
1631 void *assertedValue )
1633 struct berval *nval, *assertv;
1634 char *val, **values, **words, *c;
1635 int i, count, len, nextchunk=0, nextavail=0;
1637 /* Yes, this is necessary */
1638 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1639 if( nval == NULL ) {
1641 return LDAP_SUCCESS;
1644 /* Yes, this is necessary */
1645 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1646 NULL, LDAP_UTF8_APPROX, NULL );
1647 if( assertv == NULL ) {
1650 return LDAP_SUCCESS;
1653 /* Isolate how many words there are */
1654 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1655 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1656 if ( c == NULL ) break;
1661 /* Get a phonetic copy of each word */
1662 words = (char **)ch_malloc( count * sizeof(char *) );
1663 values = (char **)ch_malloc( count * sizeof(char *) );
1664 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1666 values[i] = phonetic(c);
1669 /* Work through the asserted value's words, to see if at least some
1670 of the words are there, in the same order. */
1672 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1673 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1678 #if defined(SLAPD_APPROX_INITIALS)
1679 else if( len == 1 ) {
1680 /* Single letter words need to at least match one word's initial */
1681 for( i=nextavail; i<count; i++ )
1682 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1689 /* Isolate the next word in the asserted value and phonetic it */
1690 assertv->bv_val[nextchunk+len] = '\0';
1691 val = phonetic( assertv->bv_val + nextchunk );
1693 /* See if this phonetic chunk is in the remaining words of *value */
1694 for( i=nextavail; i<count; i++ ){
1695 if( !strcmp( val, values[i] ) ){
1703 /* This chunk in the asserted value was NOT within the *value. */
1709 /* Go on to the next word in the asserted value */
1713 /* If some of the words were seen, call it a match */
1714 if( nextavail > 0 ) {
1721 /* Cleanup allocs */
1722 ber_bvfree( assertv );
1723 for( i=0; i<count; i++ ) {
1724 ch_free( values[i] );
1730 return LDAP_SUCCESS;
1739 struct berval *prefix,
1745 int i,j, len, wordcount, keycount=0;
1746 struct berval *newkeys;
1747 BerVarray keys=NULL;
1749 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1750 struct berval val = BER_BVNULL;
1751 /* Yes, this is necessary */
1752 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1753 assert( !BER_BVISNULL( &val ) );
1755 /* Isolate how many words there are. There will be a key for each */
1756 for( wordcount = 0, c = val.bv_val; *c; c++) {
1757 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1758 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1760 if (*c == '\0') break;
1764 /* Allocate/increase storage to account for new keys */
1765 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1766 * sizeof(struct berval) );
1767 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1768 if( keys ) ch_free( keys );
1771 /* Get a phonetic copy of each word */
1772 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1774 if( len < SLAPD_APPROX_WORDLEN ) continue;
1775 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1780 ber_memfree( val.bv_val );
1782 BER_BVZERO( &keys[keycount] );
1785 return LDAP_SUCCESS;
1794 struct berval *prefix,
1795 void * assertedValue,
1804 /* Yes, this is necessary */
1805 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1806 NULL, LDAP_UTF8_APPROX, NULL );
1807 if( val == NULL || BER_BVISNULL( val ) ) {
1808 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1809 BER_BVZERO( &keys[0] );
1812 return LDAP_SUCCESS;
1815 /* Isolate how many words there are. There will be a key for each */
1816 for( count = 0,c = val->bv_val; *c; c++) {
1817 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1818 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1820 if (*c == '\0') break;
1824 /* Allocate storage for new keys */
1825 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1827 /* Get a phonetic copy of each word */
1828 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1830 if( len < SLAPD_APPROX_WORDLEN ) continue;
1831 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1837 BER_BVZERO( &keys[count] );
1840 return LDAP_SUCCESS;
1843 /* Remove all spaces and '-' characters */
1845 telephoneNumberNormalize(
1850 struct berval *normalized,
1855 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1857 /* validator should have refused an empty string */
1858 assert( !BER_BVISEMPTY( val ) );
1860 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1862 for( p = val->bv_val; *p; p++ ) {
1863 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1869 normalized->bv_len = q - normalized->bv_val;
1871 if( BER_BVISEMPTY( normalized ) ) {
1872 slap_sl_free( normalized->bv_val, ctx );
1873 BER_BVZERO( normalized );
1874 return LDAP_INVALID_SYNTAX;
1877 return LDAP_SUCCESS;
1885 struct berval val = *in;
1887 if( BER_BVISEMPTY( &val ) ) {
1888 /* disallow empty strings */
1889 return LDAP_INVALID_SYNTAX;
1892 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1893 if ( val.bv_len == 1 ) {
1894 return LDAP_SUCCESS;
1897 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1904 while ( OID_LEADCHAR( val.bv_val[0] )) {
1908 if ( val.bv_len == 0 ) {
1909 return LDAP_SUCCESS;
1913 if( !OID_SEPARATOR( val.bv_val[0] )) {
1921 return LDAP_INVALID_SYNTAX;
1930 struct berval val = *in;
1932 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1934 if ( val.bv_val[0] == '-' ) {
1938 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1939 return LDAP_INVALID_SYNTAX;
1942 if( val.bv_val[0] == '0' ) { /* "-0" */
1943 return LDAP_INVALID_SYNTAX;
1946 } else if ( val.bv_val[0] == '0' ) {
1947 if( val.bv_len > 1 ) { /* "0<more>" */
1948 return LDAP_INVALID_SYNTAX;
1951 return LDAP_SUCCESS;
1954 for( i=0; i < val.bv_len; i++ ) {
1955 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1956 return LDAP_INVALID_SYNTAX;
1960 return LDAP_SUCCESS;
1969 struct berval *value,
1970 void *assertedValue )
1972 struct berval *asserted = (struct berval *) assertedValue;
1973 int vsign = 1, asign = 1; /* default sign = '+' */
1978 if( v.bv_val[0] == '-' ) {
1984 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1987 if( a.bv_val[0] == '-' ) {
1993 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1995 match = vsign - asign;
1997 match = ( v.bv_len != a.bv_len
1998 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1999 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2000 if( vsign < 0 ) match = -match;
2004 return LDAP_SUCCESS;
2008 countryStringValidate(
2010 struct berval *val )
2012 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2014 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2015 return LDAP_INVALID_SYNTAX;
2017 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2018 return LDAP_INVALID_SYNTAX;
2021 return LDAP_SUCCESS;
2025 printableStringValidate(
2027 struct berval *val )
2031 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2033 for(i=0; i < val->bv_len; i++) {
2034 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2035 return LDAP_INVALID_SYNTAX;
2039 return LDAP_SUCCESS;
2043 printablesStringValidate(
2045 struct berval *val )
2049 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2051 for(i=0,len=0; i < val->bv_len; i++) {
2052 int c = val->bv_val[i];
2056 return LDAP_INVALID_SYNTAX;
2060 } else if ( SLAP_PRINTABLE(c) ) {
2063 return LDAP_INVALID_SYNTAX;
2068 return LDAP_INVALID_SYNTAX;
2071 return LDAP_SUCCESS;
2077 struct berval *val )
2081 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2083 for(i=0; i < val->bv_len; i++) {
2084 if( !LDAP_ASCII(val->bv_val[i]) ) {
2085 return LDAP_INVALID_SYNTAX;
2089 return LDAP_SUCCESS;
2098 struct berval *normalized,
2102 int casefold = !SLAP_MR_ASSOCIATED( mr,
2103 slap_schema.si_mr_caseExactIA5Match );
2105 assert( !BER_BVISEMPTY( val ) );
2107 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2111 /* Ignore initial whitespace */
2112 while ( ASCII_SPACE( *p ) ) p++;
2114 normalized->bv_val = ber_strdup_x( p, ctx );
2115 p = q = normalized->bv_val;
2118 if ( ASCII_SPACE( *p ) ) {
2121 /* Ignore the extra whitespace */
2122 while ( ASCII_SPACE( *p ) ) {
2126 } else if ( casefold ) {
2127 /* Most IA5 rules require casefolding */
2128 *q++ = TOLOWER(*p); p++;
2135 assert( normalized->bv_val <= p );
2139 * If the string ended in space, backup the pointer one
2140 * position. One is enough because the above loop collapsed
2141 * all whitespace to a single space.
2143 if ( ASCII_SPACE( q[-1] ) ) --q;
2145 /* null terminate */
2148 normalized->bv_len = q - normalized->bv_val;
2149 if( BER_BVISEMPTY( normalized ) ) {
2150 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2151 normalized->bv_val[0] = ' ';
2152 normalized->bv_val[1] = '\0';
2153 normalized->bv_len = 1;
2156 return LDAP_SUCCESS;
2165 if( in->bv_len != 36 ) {
2166 return LDAP_INVALID_SYNTAX;
2169 for( i=0; i<36; i++ ) {
2175 if( in->bv_val[i] != '-' ) {
2176 return LDAP_INVALID_SYNTAX;
2180 if( !ASCII_HEX( in->bv_val[i]) ) {
2181 return LDAP_INVALID_SYNTAX;
2186 return LDAP_SUCCESS;
2197 int rc=LDAP_INVALID_SYNTAX;
2199 assert( in != NULL );
2200 assert( out != NULL );
2202 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2205 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2207 for( i=0; i<36; i++ ) {
2213 if( in->bv_val[i] != '-' ) {
2216 out->bv_val[i] = '-';
2220 if( !ASCII_HEX( in->bv_val[i]) ) {
2223 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2228 out->bv_val[ out->bv_len ] = '\0';
2232 slap_sl_free( out->bv_val, ctx );
2245 struct berval *normalized,
2248 unsigned char octet = '\0';
2251 normalized->bv_len = 16;
2252 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2254 for( i=0, j=0; i<36; i++ ) {
2255 unsigned char nibble;
2256 if( val->bv_val[i] == '-' ) {
2259 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2260 nibble = val->bv_val[i] - '0';
2262 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2263 nibble = val->bv_val[i] - ('a'-10);
2265 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2266 nibble = val->bv_val[i] - ('A'-10);
2269 slap_sl_free( normalized->bv_val, ctx );
2270 return LDAP_INVALID_SYNTAX;
2275 normalized->bv_val[j>>1] = octet;
2277 octet = nibble << 4;
2282 normalized->bv_val[normalized->bv_len] = 0;
2283 return LDAP_SUCCESS;
2289 numericStringValidate(
2295 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2297 for(i=0; i < in->bv_len; i++) {
2298 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2299 return LDAP_INVALID_SYNTAX;
2303 return LDAP_SUCCESS;
2307 numericStringNormalize(
2312 struct berval *normalized,
2315 /* removal all spaces */
2318 assert( !BER_BVISEMPTY( val ) );
2320 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2323 q = normalized->bv_val;
2326 if ( ASCII_SPACE( *p ) ) {
2327 /* Ignore whitespace */
2334 /* we should have copied no more then is in val */
2335 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2337 /* null terminate */
2340 normalized->bv_len = q - normalized->bv_val;
2342 if( BER_BVISEMPTY( normalized ) ) {
2343 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2344 normalized->bv_val[0] = ' ';
2345 normalized->bv_val[1] = '\0';
2346 normalized->bv_len = 1;
2349 return LDAP_SUCCESS;
2353 * Integer conversion macros that will use the largest available
2356 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2357 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2358 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2359 # define SLAP_LONG_MAX LLONG_MAX
2360 # define SLAP_LONG_MIN LLONG_MIN
2361 # define SLAP_LONG long long
2363 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2364 # define SLAP_LONG_MAX LONG_MAX
2365 # define SLAP_LONG_MIN LONG_MIN
2366 # define SLAP_LONG long
2367 #endif /* HAVE_STRTOLL ... */
2375 struct berval *value,
2376 void *assertedValue )
2378 SLAP_LONG lValue, lAssertedValue;
2380 /* safe to assume integers are NUL terminated? */
2381 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2382 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2385 return LDAP_CONSTRAINT_VIOLATION;
2388 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2390 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2393 return LDAP_CONSTRAINT_VIOLATION;
2396 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2397 return LDAP_SUCCESS;
2406 struct berval *value,
2407 void *assertedValue )
2409 SLAP_LONG lValue, lAssertedValue;
2411 /* safe to assume integers are NUL terminated? */
2412 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2413 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2416 return LDAP_CONSTRAINT_VIOLATION;
2419 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2421 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2424 return LDAP_CONSTRAINT_VIOLATION;
2427 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2428 return LDAP_SUCCESS;
2432 serialNumberAndIssuerValidate(
2438 struct berval sn, i;
2440 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2443 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2445 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2446 /* Parse old format */
2447 i.bv_val = ber_bvchr( in, '$' );
2448 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2450 sn.bv_val = in->bv_val;
2451 sn.bv_len = i.bv_val - in->bv_val;
2454 i.bv_len = in->bv_len - (sn.bv_len + 1);
2456 /* eat leading zeros */
2457 for( n=0; n < (sn.bv_len-1); n++ ) {
2458 if( sn.bv_val[n] != '0' ) break;
2463 for( n=0; n < sn.bv_len; n++ ) {
2464 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2468 /* Parse GSER format */
2469 int havesn=0,haveissuer=0;
2470 struct berval x = *in;
2474 /* eat leading spaces */
2475 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2479 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2480 return LDAP_INVALID_SYNTAX;
2483 /* should be at issuer or serialNumber NamedValue */
2484 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2486 x.bv_val += STRLENOF("issuer");
2487 x.bv_len -= STRLENOF("issuer");
2489 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2490 x.bv_val++; x.bv_len--;
2492 /* eat leading spaces */
2493 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2497 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2498 x.bv_val++; x.bv_len--;
2500 i.bv_val = x.bv_val;
2503 for( ; i.bv_len < x.bv_len; ) {
2504 if ( i.bv_val[i.bv_len] != '"' ) {
2508 if ( i.bv_val[i.bv_len+1] == '"' ) {
2515 x.bv_val += i.bv_len+1;
2516 x.bv_len -= i.bv_len+1;
2518 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2519 return LDAP_INVALID_SYNTAX;
2524 } else if( strncasecmp( x.bv_val, "serialNumber",
2525 STRLENOF("serialNumber")) == 0 )
2527 /* parse serialNumber */
2529 x.bv_val += STRLENOF("serialNumber");
2530 x.bv_len -= STRLENOF("serialNumber");
2532 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2533 x.bv_val++; x.bv_len--;
2535 /* eat leading spaces */
2536 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2540 sn.bv_val = x.bv_val;
2543 if( sn.bv_val[0] == '-' ) {
2548 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2549 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2552 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2553 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2554 return LDAP_INVALID_SYNTAX;
2557 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2559 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2560 return LDAP_INVALID_SYNTAX;
2565 } else return LDAP_INVALID_SYNTAX;
2567 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2568 x.bv_val++; x.bv_len--;
2571 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2575 /* should be at remaining NamedValue */
2576 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2577 STRLENOF("issuer" )) == 0 ))
2580 x.bv_val += STRLENOF("issuer");
2581 x.bv_len -= STRLENOF("issuer");
2583 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2584 x.bv_val++; x.bv_len--;
2586 /* eat leading spaces */
2587 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2591 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2592 x.bv_val++; x.bv_len--;
2594 i.bv_val = x.bv_val;
2597 for( ; i.bv_len < x.bv_len; ) {
2598 if ( i.bv_val[i.bv_len] != '"' ) {
2602 if ( i.bv_val[i.bv_len+1] == '"' ) {
2609 x.bv_val += i.bv_len+1;
2610 x.bv_len -= i.bv_len+1;
2612 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2613 STRLENOF("serialNumber")) == 0 ))
2615 /* parse serialNumber */
2617 x.bv_val += STRLENOF("serialNumber");
2618 x.bv_len -= STRLENOF("serialNumber");
2620 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2621 x.bv_val++; x.bv_len--;
2623 /* eat leading spaces */
2624 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2628 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2629 x.bv_val++; x.bv_len--;
2631 sn.bv_val = x.bv_val;
2634 if( sn.bv_val[0] == '-' ) {
2639 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2640 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2643 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2644 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2645 return LDAP_INVALID_SYNTAX;
2648 x.bv_val += sn.bv_len;
2649 x.bv_len -= sn.bv_len;
2651 } else return LDAP_INVALID_SYNTAX;
2653 /* eat trailing spaces */
2654 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2658 /* should have no characters left... */
2659 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2662 /* validate DN -- doesn't handle double dquote */
2663 rc = dnValidate( NULL, &i );
2664 if( rc ) return LDAP_INVALID_SYNTAX;
2666 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2668 return LDAP_SUCCESS;
2672 serialNumberAndIssuerPretty(
2680 struct berval sn, i, ni;
2682 assert( in != NULL );
2683 assert( out != NULL );
2685 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2688 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2690 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2691 /* Parse old format */
2692 i.bv_val = ber_bvchr( in, '$' );
2693 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2695 sn.bv_val = in->bv_val;
2696 sn.bv_len = i.bv_val - in->bv_val;
2699 i.bv_len = in->bv_len - (sn.bv_len + 1);
2701 /* eat leading zeros */
2702 for( n=0; n < (sn.bv_len-1); n++ ) {
2703 if( sn.bv_val[n] != '0' ) break;
2708 for( n=0; n < sn.bv_len; n++ ) {
2709 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2713 /* Parse GSER format */
2714 int havesn=0,haveissuer=0;
2715 struct berval x = *in;
2719 /* eat leading spaces */
2720 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2724 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2725 return LDAP_INVALID_SYNTAX;
2728 /* should be at issuer or serialNumber NamedValue */
2729 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2731 x.bv_val += STRLENOF("issuer");
2732 x.bv_len -= STRLENOF("issuer");
2734 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2735 x.bv_val++; x.bv_len--;
2737 /* eat leading spaces */
2738 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2742 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2743 x.bv_val++; x.bv_len--;
2745 i.bv_val = x.bv_val;
2748 for( ; i.bv_len < x.bv_len; ) {
2749 if ( i.bv_val[i.bv_len] != '"' ) {
2753 if ( i.bv_val[i.bv_len+1] == '"' ) {
2760 x.bv_val += i.bv_len+1;
2761 x.bv_len -= i.bv_len+1;
2763 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2764 return LDAP_INVALID_SYNTAX;
2769 } else if( strncasecmp( x.bv_val, "serialNumber",
2770 STRLENOF("serialNumber")) == 0 )
2772 /* parse serialNumber */
2774 x.bv_val += STRLENOF("serialNumber");
2775 x.bv_len -= STRLENOF("serialNumber");
2777 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2778 x.bv_val++; x.bv_len--;
2780 /* eat leading spaces */
2781 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2785 sn.bv_val = x.bv_val;
2788 if( sn.bv_val[0] == '-' ) {
2793 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2794 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2797 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2798 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2799 return LDAP_INVALID_SYNTAX;
2802 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2804 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2805 return LDAP_INVALID_SYNTAX;
2810 } else return LDAP_INVALID_SYNTAX;
2812 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2813 x.bv_val++; x.bv_len--;
2816 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2820 /* should be at remaining NamedValue */
2821 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2822 STRLENOF("issuer" )) == 0 ))
2825 x.bv_val += STRLENOF("issuer");
2826 x.bv_len -= STRLENOF("issuer");
2828 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2829 x.bv_val++; x.bv_len--;
2831 /* eat leading spaces */
2832 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2836 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2837 x.bv_val++; x.bv_len--;
2839 i.bv_val = x.bv_val;
2842 for( ; i.bv_len < x.bv_len; ) {
2843 if ( i.bv_val[i.bv_len] != '"' ) {
2847 if ( i.bv_val[i.bv_len+1] == '"' ) {
2854 x.bv_val += i.bv_len+1;
2855 x.bv_len -= i.bv_len+1;
2857 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2858 STRLENOF("serialNumber")) == 0 ))
2860 /* parse serialNumber */
2862 x.bv_val += STRLENOF("serialNumber");
2863 x.bv_len -= STRLENOF("serialNumber");
2865 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2866 x.bv_val++; x.bv_len--;
2868 /* eat leading spaces */
2869 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2873 sn.bv_val = x.bv_val;
2876 if( sn.bv_val[0] == '-' ) {
2881 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2882 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2885 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2886 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2887 return LDAP_INVALID_SYNTAX;
2890 x.bv_val += sn.bv_len;
2891 x.bv_len -= sn.bv_len;
2893 } else return LDAP_INVALID_SYNTAX;
2895 /* eat trailing spaces */
2896 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2900 /* should have no characters left... */
2901 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2903 ber_dupbv_x( &ni, &i, ctx );
2906 /* need to handle double dquotes here */
2909 rc = dnPretty( syntax, &i, &ni, ctx );
2911 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2912 slap_sl_free( i.bv_val, ctx );
2915 if( rc ) return LDAP_INVALID_SYNTAX;
2917 /* make room from sn + "$" */
2918 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2919 + sn.bv_len + ni.bv_len;
2920 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2922 if( out->bv_val == NULL ) {
2924 slap_sl_free( ni.bv_val, ctx );
2929 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2930 STRLENOF("{ serialNumber "));
2931 n = STRLENOF("{ serialNumber ");
2933 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2936 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2937 n += STRLENOF(", issuer \"");
2939 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2942 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2943 n += STRLENOF("\" }");
2945 out->bv_val[n] = '\0';
2947 assert( n == out->bv_len );
2949 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2950 out->bv_val, 0, 0 );
2952 slap_sl_free( ni.bv_val, ctx );
2954 return LDAP_SUCCESS;
2958 * This routine is called by certificateExactNormalize when
2959 * certificateExactNormalize receives a search string instead of
2960 * a certificate. This routine checks if the search value is valid
2961 * and then returns the normalized value
2964 serialNumberAndIssuerNormalize(
2974 struct berval sn, i, ni;
2976 assert( in != NULL );
2977 assert( out != NULL );
2979 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2982 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2984 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2985 /* Parse old format */
2986 i.bv_val = ber_bvchr( in, '$' );
2987 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2989 sn.bv_val = in->bv_val;
2990 sn.bv_len = i.bv_val - in->bv_val;
2993 i.bv_len = in->bv_len - (sn.bv_len + 1);
2995 /* eat leading zeros */
2996 for( n=0; n < (sn.bv_len-1); n++ ) {
2997 if( sn.bv_val[n] != '0' ) break;
3002 for( n=0; n < sn.bv_len; n++ ) {
3003 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3007 /* Parse GSER format */
3008 int havesn=0,haveissuer=0;
3009 struct berval x = *in;
3013 /* eat leading spaces */
3014 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3018 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3019 return LDAP_INVALID_SYNTAX;
3022 /* should be at issuer or serialNumber NamedValue */
3023 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3025 x.bv_val += STRLENOF("issuer");
3026 x.bv_len -= STRLENOF("issuer");
3028 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3029 x.bv_val++; x.bv_len--;
3031 /* eat leading spaces */
3032 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3036 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3037 x.bv_val++; x.bv_len--;
3039 i.bv_val = x.bv_val;
3042 for( ; i.bv_len < x.bv_len; ) {
3043 if ( i.bv_val[i.bv_len] != '"' ) {
3047 if ( i.bv_val[i.bv_len+1] == '"' ) {
3054 x.bv_val += i.bv_len+1;
3055 x.bv_len -= i.bv_len+1;
3057 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3058 return LDAP_INVALID_SYNTAX;
3063 } else if( strncasecmp( x.bv_val, "serialNumber",
3064 STRLENOF("serialNumber")) == 0 )
3066 /* parse serialNumber */
3068 x.bv_val += STRLENOF("serialNumber");
3069 x.bv_len -= STRLENOF("serialNumber");
3071 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3072 x.bv_val++; x.bv_len--;
3074 /* eat leading spaces */
3075 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3079 sn.bv_val = x.bv_val;
3082 if( sn.bv_val[0] == '-' ) {
3087 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3088 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3091 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3092 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3093 return LDAP_INVALID_SYNTAX;
3096 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3098 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3099 return LDAP_INVALID_SYNTAX;
3104 } else return LDAP_INVALID_SYNTAX;
3106 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3107 x.bv_val++; x.bv_len--;
3110 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3114 /* should be at remaining NamedValue */
3115 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3116 STRLENOF("issuer" )) == 0 ))
3119 x.bv_val += STRLENOF("issuer");
3120 x.bv_len -= STRLENOF("issuer");
3122 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3123 x.bv_val++; x.bv_len--;
3125 /* eat leading spaces */
3126 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3130 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3131 x.bv_val++; x.bv_len--;
3133 i.bv_val = x.bv_val;
3136 for( ; i.bv_len < x.bv_len; ) {
3137 if ( i.bv_val[i.bv_len] != '"' ) {
3141 if ( i.bv_val[i.bv_len+1] == '"' ) {
3148 x.bv_val += i.bv_len+1;
3149 x.bv_len -= i.bv_len+1;
3151 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3152 STRLENOF("serialNumber")) == 0 ))
3154 /* parse serialNumber */
3156 x.bv_val += STRLENOF("serialNumber");
3157 x.bv_len -= STRLENOF("serialNumber");
3159 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3160 x.bv_val++; x.bv_len--;
3162 /* eat leading spaces */
3163 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3167 sn.bv_val = x.bv_val;
3170 if( sn.bv_val[0] == '-' ) {
3175 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3176 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3179 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3180 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3181 return LDAP_INVALID_SYNTAX;
3184 x.bv_val += sn.bv_len;
3185 x.bv_len -= sn.bv_len;
3187 } else return LDAP_INVALID_SYNTAX;
3189 /* eat trailing spaces */
3190 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3194 /* should have no characters left... */
3195 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3197 ber_dupbv_x( &ni, &i, ctx );
3200 /* need to handle double dquotes here */
3203 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3205 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3206 slap_sl_free( i.bv_val, ctx );
3209 if( rc ) return LDAP_INVALID_SYNTAX;
3211 /* make room from sn + "$" */
3212 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3213 + sn.bv_len + ni.bv_len;
3214 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3216 if( out->bv_val == NULL ) {
3218 slap_sl_free( ni.bv_val, ctx );
3223 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3224 STRLENOF( "{ serialNumber " ));
3225 n = STRLENOF( "{ serialNumber " );
3227 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3230 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3231 n += STRLENOF( ", issuer \"" );
3233 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3236 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3237 n += STRLENOF( "\" }" );
3239 out->bv_val[n] = '\0';
3241 assert( n == out->bv_len );
3243 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3244 out->bv_val, 0, 0 );
3246 slap_sl_free( ni.bv_val, ctx );
3248 return LDAP_SUCCESS;
3253 certificateExactNormalize(
3258 struct berval *normalized,
3261 int rc = LDAP_INVALID_SYNTAX;
3263 char *serial = NULL;
3264 ber_len_t seriallen;
3265 struct berval issuer_dn = BER_BVNULL;
3266 X509_NAME *name = NULL;
3267 ASN1_INTEGER *sn = NULL;
3270 if( BER_BVISEMPTY( val ) ) goto done;
3272 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3273 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3276 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3278 p = (unsigned char *)val->bv_val;
3279 xcert = d2i_X509( NULL, &p, val->bv_len);
3280 if( xcert == NULL ) goto done;
3282 sn=X509_get_serialNumber(xcert);
3283 if ( sn == NULL ) goto done;
3284 serial=i2s_ASN1_INTEGER(0, sn );
3285 if( serial == NULL ) goto done;
3286 seriallen=strlen(serial);
3288 name=X509_get_issuer_name(xcert);
3289 if( name == NULL ) goto done;
3290 rc = dnX509normalize( name, &issuer_dn );
3291 if( rc != LDAP_SUCCESS ) goto done;
3293 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3294 + seriallen + issuer_dn.bv_len;
3295 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3297 p = (unsigned char *)normalized->bv_val;
3299 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3300 p += STRLENOF( "{ serialNumber " );
3302 AC_MEMCPY(p, serial, seriallen);
3305 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3306 p += STRLENOF( ", issuer \"" );
3308 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3309 p += issuer_dn.bv_len;
3311 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3312 p += STRLENOF( "\" }" );
3316 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3317 normalized->bv_val, NULL, NULL );
3322 if (xcert) X509_free(xcert);
3323 if (serial) ch_free(serial);
3324 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3328 #endif /* HAVE_TLS */
3331 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3332 /* slight optimization - does not need the start parameter */
3333 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3338 check_time_syntax (struct berval *val,
3341 struct berval *fraction)
3344 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3345 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3346 * GeneralizedTime supports leap seconds, UTCTime does not.
3348 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3349 static const int mdays[2][12] = {
3350 /* non-leap years */
3351 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3353 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3356 int part, c, c1, c2, tzoffset, leapyear = 0;
3359 e = p + val->bv_len;
3361 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3362 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3364 for (part = start; part < 7 && p < e; part++) {
3366 if (!ASCII_DIGIT(c1)) {
3371 return LDAP_INVALID_SYNTAX;
3374 if (!ASCII_DIGIT(c)) {
3375 return LDAP_INVALID_SYNTAX;
3377 c += c1 * 10 - '0' * 11;
3378 if ((part | 1) == 3) {
3381 return LDAP_INVALID_SYNTAX;
3384 if (c >= ceiling[part]) {
3385 if (! (c == 60 && part == 6 && start == 0))
3386 return LDAP_INVALID_SYNTAX;
3390 if (part < 5 + start) {
3391 return LDAP_INVALID_SYNTAX;
3393 for (; part < 9; part++) {
3397 /* leapyear check for the Gregorian calendar (year>1581) */
3398 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3402 if (parts[3] >= mdays[leapyear][parts[2]]) {
3403 return LDAP_INVALID_SYNTAX;
3407 fraction->bv_val = p;
3408 fraction->bv_len = 0;
3409 if (p < e && (*p == '.' || *p == ',')) {
3411 while (++p < e && ASCII_DIGIT(*p)) {
3414 if (p - fraction->bv_val == 1) {
3415 return LDAP_INVALID_SYNTAX;
3417 for (end_num = p; end_num[-1] == '0'; --end_num) {
3420 c = end_num - fraction->bv_val;
3421 if (c != 1) fraction->bv_len = c;
3427 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3433 return LDAP_INVALID_SYNTAX;
3439 for (part = 7; part < 9 && p < e; part++) {
3441 if (!ASCII_DIGIT(c1)) {
3446 return LDAP_INVALID_SYNTAX;
3449 if (!ASCII_DIGIT(c2)) {
3450 return LDAP_INVALID_SYNTAX;
3452 parts[part] = c1 * 10 + c2 - '0' * 11;
3453 if (parts[part] >= ceiling[part]) {
3454 return LDAP_INVALID_SYNTAX;
3457 if (part < 8 + start) {
3458 return LDAP_INVALID_SYNTAX;
3461 if (tzoffset == '-') {
3462 /* negative offset to UTC, ie west of Greenwich */
3463 parts[4] += parts[7];
3464 parts[5] += parts[8];
3465 /* offset is just hhmm, no seconds */
3466 for (part = 6; --part >= 0; ) {
3470 c = mdays[leapyear][parts[2]];
3472 if (parts[part] >= c) {
3474 return LDAP_INVALID_SYNTAX;
3479 } else if (part != 5) {
3484 /* positive offset to UTC, ie east of Greenwich */
3485 parts[4] -= parts[7];
3486 parts[5] -= parts[8];
3487 for (part = 6; --part >= 0; ) {
3488 if (parts[part] < 0) {
3490 return LDAP_INVALID_SYNTAX;
3495 /* make first arg to % non-negative */
3496 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3501 } else if (part != 5) {
3508 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3511 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3518 struct berval *normalized )
3522 rc = check_time_syntax(val, 1, parts, NULL);
3523 if (rc != LDAP_SUCCESS) {
3527 normalized->bv_val = ch_malloc( 14 );
3528 if ( normalized->bv_val == NULL ) {
3529 return LBER_ERROR_MEMORY;
3532 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3533 parts[1], parts[2] + 1, parts[3] + 1,
3534 parts[4], parts[5], parts[6] );
3535 normalized->bv_len = 13;
3537 return LDAP_SUCCESS;
3547 return check_time_syntax(in, 1, parts, NULL);
3550 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3553 generalizedTimeValidate(
3558 struct berval fraction;
3559 return check_time_syntax(in, 0, parts, &fraction);
3563 generalizedTimeNormalize(
3568 struct berval *normalized,
3573 struct berval fraction;
3575 rc = check_time_syntax(val, 0, parts, &fraction);
3576 if (rc != LDAP_SUCCESS) {
3580 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3581 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3582 if ( BER_BVISNULL( normalized ) ) {
3583 return LBER_ERROR_MEMORY;
3586 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3587 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3588 parts[4], parts[5], parts[6] );
3589 if ( !BER_BVISEMPTY( &fraction ) ) {
3590 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3591 fraction.bv_val, fraction.bv_len );
3592 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3594 strcpy( normalized->bv_val + len-1, "Z" );
3595 normalized->bv_len = len;
3597 return LDAP_SUCCESS;
3601 generalizedTimeOrderingMatch(
3606 struct berval *value,
3607 void *assertedValue )
3609 struct berval *asserted = (struct berval *) assertedValue;
3610 ber_len_t v_len = value->bv_len;
3611 ber_len_t av_len = asserted->bv_len;
3613 /* ignore trailing 'Z' when comparing */
3614 int match = memcmp( value->bv_val, asserted->bv_val,
3615 (v_len < av_len ? v_len : av_len) - 1 );
3616 if ( match == 0 ) match = v_len - av_len;
3619 return LDAP_SUCCESS;
3622 /* Index generation function */
3623 int generalizedTimeIndexer(
3628 struct berval *prefix,
3636 BerValue bvtmp; /* 40 bit index */
3638 struct lutil_timet tt;
3640 bvtmp.bv_len = sizeof(tmp);
3642 for( i=0; values[i].bv_val != NULL; i++ ) {
3643 /* just count them */
3646 /* we should have at least one value at this point */
3649 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3651 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3652 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3653 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3654 /* Use 40 bits of time for key */
3655 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3656 lutil_tm2time( &tm, &tt );
3657 tmp[0] = tt.tt_gsec & 0xff;
3658 tmp[4] = tt.tt_sec & 0xff;
3660 tmp[3] = tt.tt_sec & 0xff;
3662 tmp[2] = tt.tt_sec & 0xff;
3664 tmp[1] = tt.tt_sec & 0xff;
3666 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3670 keys[j].bv_val = NULL;
3675 return LDAP_SUCCESS;
3678 /* Index generation function */
3679 int generalizedTimeFilter(
3684 struct berval *prefix,
3685 void * assertedValue,
3691 BerValue bvtmp; /* 40 bit index */
3692 BerValue *value = (BerValue *) assertedValue;
3694 struct lutil_timet tt;
3696 bvtmp.bv_len = sizeof(tmp);
3698 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3699 /* Use 40 bits of time for key */
3700 if ( value->bv_val && value->bv_len >= 10 &&
3701 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3703 lutil_tm2time( &tm, &tt );
3704 tmp[0] = tt.tt_gsec & 0xff;
3705 tmp[4] = tt.tt_sec & 0xff;
3707 tmp[3] = tt.tt_sec & 0xff;
3709 tmp[2] = tt.tt_sec & 0xff;
3711 tmp[1] = tt.tt_sec & 0xff;
3713 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3714 ber_dupbv_x(keys, &bvtmp, ctx );
3715 keys[1].bv_val = NULL;
3723 return LDAP_SUCCESS;
3727 deliveryMethodValidate(
3729 struct berval *val )
3732 #define LENOF(s) (sizeof(s)-1)
3733 struct berval tmp = *val;
3735 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3736 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3737 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3740 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3742 switch( tmp.bv_val[0] ) {
3745 if(( tmp.bv_len >= LENOF("any") ) &&
3746 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3748 tmp.bv_len -= LENOF("any");
3749 tmp.bv_val += LENOF("any");
3752 return LDAP_INVALID_SYNTAX;
3756 if(( tmp.bv_len >= LENOF("mhs") ) &&
3757 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3759 tmp.bv_len -= LENOF("mhs");
3760 tmp.bv_val += LENOF("mhs");
3763 return LDAP_INVALID_SYNTAX;
3767 if(( tmp.bv_len >= LENOF("physical") ) &&
3768 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3770 tmp.bv_len -= LENOF("physical");
3771 tmp.bv_val += LENOF("physical");
3774 return LDAP_INVALID_SYNTAX;
3777 case 'T': /* telex or teletex or telephone */
3778 if(( tmp.bv_len >= LENOF("telex") ) &&
3779 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3781 tmp.bv_len -= LENOF("telex");
3782 tmp.bv_val += LENOF("telex");
3785 if(( tmp.bv_len >= LENOF("teletex") ) &&
3786 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3788 tmp.bv_len -= LENOF("teletex");
3789 tmp.bv_val += LENOF("teletex");
3792 if(( tmp.bv_len >= LENOF("telephone") ) &&
3793 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3795 tmp.bv_len -= LENOF("telephone");
3796 tmp.bv_val += LENOF("telephone");
3799 return LDAP_INVALID_SYNTAX;
3802 case 'G': /* g3fax or g4fax */
3803 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3804 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3805 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3807 tmp.bv_len -= LENOF("g3fax");
3808 tmp.bv_val += LENOF("g3fax");
3811 return LDAP_INVALID_SYNTAX;
3815 if(( tmp.bv_len >= LENOF("ia5") ) &&
3816 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3818 tmp.bv_len -= LENOF("ia5");
3819 tmp.bv_val += LENOF("ia5");
3822 return LDAP_INVALID_SYNTAX;
3826 if(( tmp.bv_len >= LENOF("videotex") ) &&
3827 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3829 tmp.bv_len -= LENOF("videotex");
3830 tmp.bv_val += LENOF("videotex");
3833 return LDAP_INVALID_SYNTAX;
3836 return LDAP_INVALID_SYNTAX;
3839 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3841 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3845 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3849 return LDAP_INVALID_SYNTAX;
3851 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3860 nisNetgroupTripleValidate(
3862 struct berval *val )
3867 if ( BER_BVISEMPTY( val ) ) {
3868 return LDAP_INVALID_SYNTAX;
3871 p = (char *)val->bv_val;
3872 e = p + val->bv_len;
3874 if ( *p != '(' /*')'*/ ) {
3875 return LDAP_INVALID_SYNTAX;
3878 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3882 return LDAP_INVALID_SYNTAX;
3885 } else if ( !AD_CHAR( *p ) ) {
3886 return LDAP_INVALID_SYNTAX;
3890 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3891 return LDAP_INVALID_SYNTAX;
3897 return LDAP_INVALID_SYNTAX;
3900 return LDAP_SUCCESS;
3904 bootParameterValidate(
3906 struct berval *val )
3910 if ( BER_BVISEMPTY( val ) ) {
3911 return LDAP_INVALID_SYNTAX;
3914 p = (char *)val->bv_val;
3915 e = p + val->bv_len;
3918 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3919 if ( !AD_CHAR( *p ) ) {
3920 return LDAP_INVALID_SYNTAX;
3925 return LDAP_INVALID_SYNTAX;
3929 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3930 if ( !AD_CHAR( *p ) ) {
3931 return LDAP_INVALID_SYNTAX;
3936 return LDAP_INVALID_SYNTAX;
3940 for ( p++; p < e; p++ ) {
3941 if ( !SLAP_PRINTABLE( *p ) ) {
3942 return LDAP_INVALID_SYNTAX;
3946 return LDAP_SUCCESS;
3950 firstComponentNormalize(
3955 struct berval *normalized,
3962 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3963 ber_dupbv_x( normalized, val, ctx );
3964 return LDAP_SUCCESS;
3967 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3969 if( val->bv_val[0] != '(' /*')'*/ &&
3970 val->bv_val[0] != '{' /*'}'*/ )
3972 return LDAP_INVALID_SYNTAX;
3975 /* trim leading white space */
3977 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3983 /* grab next word */
3984 comp.bv_val = &val->bv_val[len];
3985 len = val->bv_len - len;
3986 for( comp.bv_len = 0;
3987 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3993 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3994 rc = numericoidValidate( NULL, &comp );
3995 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3996 rc = integerValidate( NULL, &comp );
3998 rc = LDAP_INVALID_SYNTAX;
4002 if( rc == LDAP_SUCCESS ) {
4003 ber_dupbv_x( normalized, &comp, ctx );
4010 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4011 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4013 static slap_syntax_defs_rec syntax_defs[] = {
4014 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4015 X_BINARY X_NOT_H_R ")",
4016 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
4017 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4019 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4021 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4023 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4024 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4026 SLAP_SYNTAX_BER, berValidate, NULL},
4027 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4028 0, bitStringValidate, NULL },
4029 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4030 0, booleanValidate, NULL},
4031 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4032 X_BINARY X_NOT_H_R ")",
4033 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
4034 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4035 X_BINARY X_NOT_H_R ")",
4036 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4037 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4038 X_BINARY X_NOT_H_R ")",
4039 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4040 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4041 0, countryStringValidate, NULL},
4042 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4043 0, dnValidate, dnPretty},
4044 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4045 0, rdnValidate, rdnPretty},
4046 #ifdef LDAP_COMP_MATCH
4047 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4048 0, allComponentsValidate, NULL},
4049 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4050 0, componentFilterValidate, NULL},
4052 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4054 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4055 0, deliveryMethodValidate, NULL},
4056 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4057 0, UTF8StringValidate, NULL},
4058 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4060 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4062 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4064 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4066 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4068 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4069 0, printablesStringValidate, NULL},
4070 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4071 SLAP_SYNTAX_BLOB, NULL, NULL},
4072 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4073 0, generalizedTimeValidate, NULL},
4074 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4076 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4077 0, IA5StringValidate, NULL},
4078 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4079 0, integerValidate, NULL},
4080 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4081 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4082 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4084 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4086 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4088 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4090 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4092 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4093 0, nameUIDValidate, nameUIDPretty },
4094 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4096 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4097 0, numericStringValidate, NULL},
4098 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4100 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4101 0, numericoidValidate, NULL},
4102 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4103 0, IA5StringValidate, NULL},
4104 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4105 0, blobValidate, NULL},
4106 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4107 0, UTF8StringValidate, NULL},
4108 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4110 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4112 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4113 0, printableStringValidate, NULL},
4114 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4115 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4116 0, subtreeSpecificationValidate, NULL},
4117 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4118 X_BINARY X_NOT_H_R ")",
4119 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4120 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4121 0, printableStringValidate, NULL},
4122 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4124 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4125 0, printablesStringValidate, NULL},
4126 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4127 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4128 0, utcTimeValidate, NULL},
4130 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4132 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4134 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4136 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4138 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4141 /* RFC 2307 NIS Syntaxes */
4142 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4143 0, nisNetgroupTripleValidate, NULL},
4144 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4145 0, bootParameterValidate, NULL},
4147 /* draft-zeilenga-ldap-x509 */
4148 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4150 serialNumberAndIssuerValidate,
4151 serialNumberAndIssuerPretty},
4152 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4153 SLAP_SYNTAX_HIDE, NULL, NULL},
4154 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4155 SLAP_SYNTAX_HIDE, NULL, NULL},
4156 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4157 SLAP_SYNTAX_HIDE, NULL, NULL},
4158 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4159 SLAP_SYNTAX_HIDE, NULL, NULL},
4160 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4161 SLAP_SYNTAX_HIDE, NULL, NULL},
4162 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4163 SLAP_SYNTAX_HIDE, NULL, NULL},
4165 #ifdef SLAPD_AUTHPASSWD
4166 /* needs updating */
4167 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4168 SLAP_SYNTAX_HIDE, NULL, NULL},
4171 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4172 0, UUIDValidate, UUIDPretty},
4174 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4175 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4177 /* OpenLDAP Void Syntax */
4178 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4179 SLAP_SYNTAX_HIDE, inValidate, NULL},
4181 /* FIXME: OID is unused, but not registered yet */
4182 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4183 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4185 {NULL, 0, NULL, NULL}
4188 char *certificateExactMatchSyntaxes[] = {
4189 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4192 #ifdef LDAP_COMP_MATCH
4193 char *componentFilterMatchSyntaxes[] = {
4194 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4198 char *directoryStringSyntaxes[] = {
4199 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4202 char *integerFirstComponentMatchSyntaxes[] = {
4203 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4204 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4207 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4208 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4209 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4210 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4211 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4212 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4213 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4214 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4215 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4220 * Other matching rules in X.520 that we do not use (yet):
4222 * 2.5.13.25 uTCTimeMatch
4223 * 2.5.13.26 uTCTimeOrderingMatch
4224 * 2.5.13.31* directoryStringFirstComponentMatch
4225 * 2.5.13.32* wordMatch
4226 * 2.5.13.33* keywordMatch
4227 * 2.5.13.36+ certificatePairExactMatch
4228 * 2.5.13.37+ certificatePairMatch
4229 * 2.5.13.38+ certificateListExactMatch
4230 * 2.5.13.39+ certificateListMatch
4231 * 2.5.13.40+ algorithmIdentifierMatch
4232 * 2.5.13.41* storedPrefixMatch
4233 * 2.5.13.42 attributeCertificateMatch
4234 * 2.5.13.43 readerAndKeyIDMatch
4235 * 2.5.13.44 attributeIntegrityMatch
4237 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4238 * (+) described in draft-zeilenga-ldap-x509
4240 static slap_mrule_defs_rec mrule_defs[] = {
4242 * EQUALITY matching rules must be listed after associated APPROX
4243 * matching rules. So, we list all APPROX matching rules first.
4245 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4246 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4247 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4248 NULL, NULL, directoryStringApproxMatch,
4249 directoryStringApproxIndexer, directoryStringApproxFilter,
4252 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4253 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4254 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4255 NULL, NULL, IA5StringApproxMatch,
4256 IA5StringApproxIndexer, IA5StringApproxFilter,
4260 * Other matching rules
4263 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4264 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4265 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4266 NULL, NULL, octetStringMatch,
4267 octetStringIndexer, octetStringFilter,
4270 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4271 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4272 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4273 NULL, dnNormalize, dnMatch,
4274 octetStringIndexer, octetStringFilter,
4277 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4278 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4279 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4280 NULL, dnNormalize, dnRelativeMatch,
4284 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4285 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4286 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4287 NULL, dnNormalize, dnRelativeMatch,
4291 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4292 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4293 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4294 NULL, dnNormalize, dnRelativeMatch,
4298 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4299 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4300 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4301 NULL, dnNormalize, dnRelativeMatch,
4305 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4306 "SYNTAX 1.2.36.79672281.1.5.0 )",
4307 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4308 NULL, rdnNormalize, rdnMatch,
4309 octetStringIndexer, octetStringFilter,
4312 #ifdef LDAP_COMP_MATCH
4313 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4314 "SYNTAX 1.2.36.79672281.1.5.2 )",
4315 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4316 NULL, NULL , componentFilterMatch,
4317 octetStringIndexer, octetStringFilter,
4320 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4321 "SYNTAX 1.2.36.79672281.1.5.3 )",
4322 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4323 NULL, NULL , allComponentsMatch,
4324 octetStringIndexer, octetStringFilter,
4327 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4328 "SYNTAX 1.2.36.79672281.1.5.3 )",
4329 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4330 NULL, NULL , directoryComponentsMatch,
4331 octetStringIndexer, octetStringFilter,
4335 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4337 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4338 NULL, UTF8StringNormalize, octetStringMatch,
4339 octetStringIndexer, octetStringFilter,
4340 directoryStringApproxMatchOID },
4342 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4344 SLAP_MR_ORDERING, directoryStringSyntaxes,
4345 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4347 "caseIgnoreMatch" },
4349 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4350 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4351 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4352 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4353 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4354 "caseIgnoreMatch" },
4356 {"( 2.5.13.5 NAME 'caseExactMatch' "
4357 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4358 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4359 NULL, UTF8StringNormalize, octetStringMatch,
4360 octetStringIndexer, octetStringFilter,
4361 directoryStringApproxMatchOID },
4363 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4364 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4365 SLAP_MR_ORDERING, directoryStringSyntaxes,
4366 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4370 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4371 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4372 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4373 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4374 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4377 {"( 2.5.13.8 NAME 'numericStringMatch' "
4378 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4379 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4380 NULL, numericStringNormalize, octetStringMatch,
4381 octetStringIndexer, octetStringFilter,
4384 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4386 SLAP_MR_ORDERING, NULL,
4387 NULL, numericStringNormalize, octetStringOrderingMatch,
4389 "numericStringMatch" },
4391 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4393 SLAP_MR_SUBSTR, NULL,
4394 NULL, numericStringNormalize, octetStringSubstringsMatch,
4395 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4396 "numericStringMatch" },
4398 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4400 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4401 NULL, NULL, NULL, NULL, NULL, NULL },
4403 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4404 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4405 SLAP_MR_SUBSTR, NULL,
4406 NULL, NULL, NULL, NULL, NULL,
4407 "caseIgnoreListMatch" },
4409 {"( 2.5.13.13 NAME 'booleanMatch' "
4410 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4411 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4412 NULL, NULL, booleanMatch,
4413 octetStringIndexer, octetStringFilter,
4416 {"( 2.5.13.14 NAME 'integerMatch' "
4417 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4418 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4419 NULL, NULL, integerMatch,
4420 octetStringIndexer, octetStringFilter,
4423 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4425 SLAP_MR_ORDERING, NULL,
4426 NULL, NULL, integerMatch,
4430 {"( 2.5.13.16 NAME 'bitStringMatch' "
4431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4432 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4433 NULL, NULL, octetStringMatch,
4434 octetStringIndexer, octetStringFilter,
4437 {"( 2.5.13.17 NAME 'octetStringMatch' "
4438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4439 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4440 NULL, NULL, octetStringMatch,
4441 octetStringIndexer, octetStringFilter,
4444 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4446 SLAP_MR_ORDERING, NULL,
4447 NULL, NULL, octetStringOrderingMatch,
4449 "octetStringMatch" },
4451 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4453 SLAP_MR_SUBSTR, NULL,
4454 NULL, NULL, octetStringSubstringsMatch,
4455 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4456 "octetStringMatch" },
4458 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4462 telephoneNumberNormalize, octetStringMatch,
4463 octetStringIndexer, octetStringFilter,
4466 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4468 SLAP_MR_SUBSTR, NULL,
4469 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4470 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4471 "telephoneNumberMatch" },
4473 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4475 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4476 NULL, NULL, NULL, NULL, NULL, NULL },
4478 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4480 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4481 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4482 uniqueMemberIndexer, uniqueMemberFilter,
4485 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4487 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4488 NULL, NULL, NULL, NULL, NULL, NULL },
4490 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4492 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4493 NULL, generalizedTimeNormalize, octetStringMatch,
4494 generalizedTimeIndexer, generalizedTimeFilter,
4497 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4499 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4500 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4502 "generalizedTimeMatch" },
4504 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4505 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4506 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4507 integerFirstComponentMatchSyntaxes,
4508 NULL, firstComponentNormalize, integerMatch,
4509 octetStringIndexer, octetStringFilter,
4512 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4514 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4515 objectIdentifierFirstComponentMatchSyntaxes,
4516 NULL, firstComponentNormalize, octetStringMatch,
4517 octetStringIndexer, octetStringFilter,
4520 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4521 "SYNTAX 1.3.6.1.1.15.1 )",
4522 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4524 NULL, certificateExactNormalize, octetStringMatch,
4525 octetStringIndexer, octetStringFilter,
4527 NULL, NULL, NULL, NULL, NULL,
4531 {"( 2.5.13.35 NAME 'certificateMatch' "
4532 "SYNTAX 1.3.6.1.1.15.2 )",
4533 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4534 NULL, NULL, NULL, NULL, NULL,
4537 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4539 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4540 NULL, IA5StringNormalize, octetStringMatch,
4541 octetStringIndexer, octetStringFilter,
4542 IA5StringApproxMatchOID },
4544 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4546 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4547 NULL, IA5StringNormalize, octetStringMatch,
4548 octetStringIndexer, octetStringFilter,
4549 IA5StringApproxMatchOID },
4551 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4553 SLAP_MR_SUBSTR, NULL,
4554 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4555 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4556 "caseIgnoreIA5Match" },
4558 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4560 SLAP_MR_SUBSTR, NULL,
4561 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4562 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4563 "caseExactIA5Match" },
4565 #ifdef SLAPD_AUTHPASSWD
4566 /* needs updating */
4567 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4569 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4570 NULL, NULL, authPasswordMatch,
4575 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4578 NULL, NULL, integerBitAndMatch,
4582 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4585 NULL, NULL, integerBitOrMatch,
4589 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4590 "SYNTAX 1.3.6.1.1.16.1 )",
4591 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4592 NULL, UUIDNormalize, octetStringMatch,
4593 octetStringIndexer, octetStringFilter,
4596 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4597 "SYNTAX 1.3.6.1.1.16.1 )",
4598 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4599 NULL, UUIDNormalize, octetStringOrderingMatch,
4600 octetStringIndexer, octetStringFilter,
4603 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4604 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4605 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4606 NULL, NULL, csnMatch,
4607 csnIndexer, csnFilter,
4610 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4611 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4612 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4613 NULL, NULL, csnOrderingMatch,
4617 /* FIXME: OID is unused, but not registered yet */
4618 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4619 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4620 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4621 NULL, authzNormalize, authzMatch,
4625 {NULL, SLAP_MR_NONE, NULL,
4626 NULL, NULL, NULL, NULL, NULL,
4631 slap_schema_init( void )
4636 /* we should only be called once (from main) */
4637 assert( schema_init_done == 0 );
4639 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4640 res = register_syntax( &syntax_defs[i] );
4643 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4644 syntax_defs[i].sd_desc );
4649 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4650 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4651 mrule_defs[i].mrd_compat_syntaxes == NULL )
4654 "slap_schema_init: Ignoring unusable matching rule %s\n",
4655 mrule_defs[i].mrd_desc );
4659 res = register_matching_rule( &mrule_defs[i] );
4663 "slap_schema_init: Error registering matching rule %s\n",
4664 mrule_defs[i].mrd_desc );
4669 res = slap_schema_load();
4670 schema_init_done = 1;
4675 schema_destroy( void )
4684 if( schema_init_done ) {
4685 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4686 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );